separating image after watershed using emgu.cv - c#

i have a blood image and i applied watershed on it .. its works and determines the cells but i don't know how to put each cell in a separate image .. i'm working with emgu.cv can i get some help
here i segment the picture using my watershed method and then put the marker on the original image
Image<Gray, Int32> boundaryImage = watershedSegmenter.Process(image);
Image<Gray, Byte> test = watershedSegmenter.GetWatersheds(); Image<Bgr, byte>dest=new Image<Bgr, byte>(image.Width, image.Height);
dest = image.And(image, test);
pictureBox1.Width = boundaryImage.ToBitmap().Width;
pictureBox1.Height = boundaryImage.ToBitmap().Height;
pictureBox1.BackgroundImage = boundaryImage.ToBitmap();

It seems like EMGUcv cvWatershed() is having some bugs which is not yet resolved. The Marker Image is always returning white image. Can you share your 1st stage output images?
I'm not able to view any images by using this code.
Image<Bgr, Byte> image = Img_Source_Bgr.Copy();
Image<Gray, Int32> marker = new Image<Gray, Int32>(image.Width, image.Height);
Rectangle rect = image.ROI;
marker.Draw(
new CircleF(
new PointF(rect.Left + rect.Width / 2.0f, rect.Top + rect.Height / 2.0f),
/*(float)(Math.Min(image.Width, image.Height) / 20.0f)*/ 5.0f),
new Gray(255),
0);
Image<Bgr, Byte> result = image.ConcateHorizontal(marker.Convert<Bgr, byte>());
Image<Gray, Byte> mask = new Image<Gray, byte>(image.Size);
CvInvoke.cvWatershed(image, marker);
CvInvoke.cvCmpS(marker, 0.10, mask, CMP_TYPE.CV_CMP_GT);
imageBox1.Image = mask;

Related

EmguCV C# Contour detection

I need help in this part of code. I need to make my contours visible on black Background when Check Box is checked. But, when I set a tick in Check Box, my contours are disappear. Code and Screen shot below. [That's my screenshot][1]
private Image<Bgr, byte> Find(Image<Bgr, byte> image)
{
Image<Gray, byte> outputImage = image.Convert<Gray, byte>().ThresholdBinary(new Gray(100), new Gray(255)); //перевод изображения в серый цвет и уменьшение шума
VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
Mat hierarchy = new Mat();
CvInvoke.FindContours(outputImage, contours, hierarchy, Emgu.CV.CvEnum.RetrType.Tree, Emgu.CV.CvEnum.ChainApproxMethod.ChainApproxSimple);
if (checkBox1.Checked)
{
Image<Gray, byte> blackBackground = new Image<Gray, byte>(outputImage.Width, outputImage.Height, new Gray(0));
CvInvoke.DrawContours(blackBackground, contours, -1, new MCvScalar(255, 0, 0));
pictureBox2.Image = blackBackground.Bitmap;
}
else
{
CvInvoke.DrawContours(image, contours, -1, new MCvScalar(255, 0, 0));
pictureBox2.Image = image.Bitmap;
}
return image;
}
[1]: https://i.stack.imgur.com/BdtUb.png
Why don't you create a copy of the bitmap and assign to the picturebox like this?
pictureBox2.Image = blackBackground.ToBitmap();
or
pictureBox2.Image = image.ToBitmap();

Difference between two images using emgu

I'm coding in C# and I need help with the difference between two images. I'm using the emgu to help me with this part. The problem here is that as long as there is a diff in the pixel, it will be shown in the resulted pic.
However, what I need is if the pixel for the RefImg is higher than the CompImg, the color should be red and if it is lesser it should be green.
The code should take a minimal amount of time to execute too.
The code below is what I'm using now.
Image<Bgr, Byte> RefImg = new Image<Bgr, Byte>(new Bitmap(refImg));
Image<Bgr, Byte> CompImg = new Image<Bgr, Byte>(new Bitmap(compImg));
Image<Bgr, Byte> Difference; //Difference
double Threshold = 5;
Difference = RefImg.AbsDiff(CompImg);
Difference = Difference.ThresholdBinary(new Bgr(Threshold, Threshold, Threshold), new Bgr(0, 255, 0));
Using Abs diff allow you to find différences but not the sign due to absolute value operator.
To find greater and lower pixels value you must use cmp function.
Image<Bgr, Byte> RefImg = new Image<Bgr, Byte>(...);
Image<Bgr, Byte> CompImg = new Image<Bgr, Byte>(...);
//Convert to gray levels or split channels
Image<Gray, Byte> RefImgGray = RefImg.Convert<Gray, byte>();
Image<Gray, Byte> CompImgGray = CompImg.Convert<Gray, byte>();
//Compare image and build mask
Image<Gray, Byte> MaskDifferenceHigh = RefImgGray.Cmp(CompImgGray, CmpType.GreaterThan);
Image<Gray, Byte> MaskDifferenceLow = RefImgGray.Cmp(CompImgGray, CmpType.LessThan);
//Draw result
Image<Bgr, byte> result = RefImg.CopyBlank();
result.SetValue(new Bgr(Color.Red),MaskDifferenceHigh);
result.SetValue(new Bgr(Color.Green), MaskDifferenceLow);
Hope it helps.

Get position of objects using kinect and C#

I got a kinect mount in the ceiling pointing down to a table (that is roughly 2 to 3 meters of the kinect) and my objective is using the kinect depth stream, locate the objects and get their position to late send to unity. So for that i am using c sharp and opencv (emgu wrapper), i first use canny to get the edges and then use BoundingRect to create a box around the object.
The result is the as follows:
Original:
As you can see the stationary objects are no problem but the box around the hands (the first was a flyer on it) is to big and sometimes is even worse. Is there any other way (using opencv ) of getting the positions of the objects?
The objective is then to send the position and dimension (of the object) to unity (trough tcp/ip), so preferably the shapes have to squares or rectangles to easy manipulation on unity.
The code I have so far is:
Image<Bgr, Byte> grayImage = new Image<Bgr, Byte>("C:\\Users\\Pedro\\Desktop\\imgRva\\KinectSnapshot-03-48-01.png");
Image<Gray, Byte> gray = grayImage.Convert<Gray, Byte>().PyrDown().PyrUp();
CvInvoke.cvShowImage("texto", gray);
CvInvoke.cvWaitKey(0);
Image<Gray, Byte> bin = gray.ThresholdBinary(new Gray(40), new Gray(255));
Image<Gray, Byte> cannyEdges = bin.Canny(300, 300);
CvInvoke.cvShowImage("texto", cannyEdges);
CvInvoke.cvWaitKey(0);
Image<Gray, Byte> canny = new Image<Gray, byte>(cannyEdges.Size);
using (MemStorage storage = new MemStorage())
for (Contour<Point> contours = cannyEdges.FindContours(Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_NONE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_TREE, storage); contours != null; contours = contours.HNext)
{
CvInvoke.cvDrawContours(canny, contours, new MCvScalar(255), new MCvScalar(255), -1, 1, Emgu.CV.CvEnum.LINE_TYPE.EIGHT_CONNECTED, new Point(0, 0));
}
using (MemStorage store = new MemStorage())
for (Contour<Point> contours1 = cannyEdges.FindContours(Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_NONE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_TREE, store); contours1 != null; contours1 = contours1.HNext)
{
Rectangle r = CvInvoke.cvBoundingRect(contours1, 1);
canny.Draw(r, new Gray(255), 1);
Debug.WriteLine(r.Location + " x " + r.Width + " y " + r.Height);
}
CvInvoke.cvShowImage("texto", canny);
CvInvoke.cvWaitKey(0);
Ty

what is the function to find otsu threshold in emgu cv?

I don't need the thresholded image. I want the threshold. I found this in OpenCV.
cv::threshold( orig_img, thres_img, 0, 255, CV_THRESH_BINARY+CV_THRESH_OTSU );
Is there an equivalent in EmguCv. Thanks in advance.
PS. I need to use this threshold for canny edge detector
You can refer this code for Auto Canny Edge detector!
Image<Gray, byte> Img_Source_Gray = Img_Org_Gray.Copy();
Image<Gray, byte> Img_Egde_Gray = Img_Source_Gray.CopyBlank();
Image<Gray, byte> Img_SourceSmoothed_Gray = Img_Source_Gray.CopyBlank();
Image<Gray, byte> Img_Otsu_Gray = Img_Org_Gray.CopyBlank();
Img_SourceSmoothed_Gray = Img_Source_Gray.SmoothGaussian(3);
double CannyAccThresh = CvInvoke.cvThreshold(Img_EgdeNR_Gray.Ptr, Img_Otsu_Gray.Ptr, 0, 255, Emgu.CV.CvEnum.THRESH.CV_THRESH_OTSU | Emgu.CV.CvEnum.THRESH.CV_THRESH_BINARY);
double CannyThresh = 0.1 * CannyAccThresh;
Img_Otsu_Gray.Dispose();
Img_Egde_Gray = Img_SourceSmoothed_Gray.Canny(CannyThresh, CannyAccThresh);
imageBox2.Image = Img_Egde_Gray;

Value range for Image HSV for color extraction EMGUCV

In the following,
Image<Hsv, Byte> hsvimg = img.Convert<Hsv, Byte>();
Image<Gray, Byte>[] channels = hsvimg.Split();
Image<Gray, Byte> imghue = channels[0];
Image<Gray, Byte> imgsat = channels[1];
Image<Gray, Byte> imgval = channels[2];
Image<Gray, byte> huefilter = imghue.InRange(new Gray(?), new Gray(?));
Image<Gray, byte> satfilter = imghue.InRange(new Gray(?), new Gray(?));
Image<Gray, byte> valfilter = imgval.InRange(new Gray(?), new Gray(?));
What is the range value of different channel (h, s, v) for different color extraction? Is it 0-255 or 0-128. I want to detect Orange, Black and Sky blue object for an image.
Can you try something like this for orange
Image<Gray, byte> huefilter =
imghue.InRange(new Gray(Color.Orange.GetHue() - 10),
new Gray(Color.Orange.GetHue() + 10));
-10 and +10 is just a guess and could be broad. just play with it and see what works.
for satfilter you can use Color.Orange.GetSaturation()
and for the third one, I'm assuming you can use Color.Orange.GetBrightness()

Categories

Resources