I am trying to find and display the contours after canny edge detection.
My code is working but I only see a black screen - and not the contours.
What is wrong?
If I remove the related part for finding contours, I succesfully see canny detected edges.
private void Device_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
video = (Bitmap)eventArgs.Frame.Clone();
Bitmap video2 = (Bitmap)eventArgs.Frame.Clone();
if (mode == 1)
{
Grayscale gray = new Grayscale(0.2125, 0.7154, 0.0721);
Bitmap video3 = gray.Apply(video2);
CannyEdgeDetector canny = new CannyEdgeDetector(0, 10);
canny.ApplyInPlace(video3);
//pic.Image = video3;
//Image<Gray, byte> imgOutput = video3.Convert<Gray, byte>().ThresholdBinary(new Gray(100), new Gray(255));
Mat hier = new Mat();
Emgu.CV.Util.VectorOfVectorOfPoint contours = new Emgu.CV.Util.VectorOfVectorOfPoint();
Image<Gray, byte> imgout = new Image<Gray, byte>(video.Width, video.Height, new Gray(0));
CvInvoke.FindContours(imgout, contours, hier, Emgu.CV.CvEnum.RetrType.External, Emgu.CV.CvEnum.ChainApproxMethod.ChainApproxSimple);
CvInvoke.DrawContours(imgout, contours, -1, new MCvScalar(255, 0, 0));
pic.Image = imgout.Bitmap;
}
else
pic.Image = video;
}
Related
I'm trying to recognize a text in an image. I'm using Emgu.CV in C#.
I think the image is clear enough to get the text but I don't get 100%.(Attached two images
)
Can I do something with the image to obtain a better result?
I have used "eng" too but the result is the same.
Emgu.CV.OCR.Tesseract _ocr=new Emgu.CV.OCR.Tesseract(#"./tessdata", "spa", OcrEngineMode.Default);
Emgu.CV.Image<Bgr, Byte> original = new Emgu.CV.Image<Bgr, Byte>(fi.FullName);
Rectangle rec = new Rectangle(105, 132, 50, 25);
original.ROI = rec;
Emgu.CV.Image<Bgr, Byte> crop = new Emgu.CV.Image<Bgr, Byte>(original.Width, original.Height);
CvInvoke.cvCopy(original, crop, IntPtr.Zero);
CvInvoke.Normalize(crop, crop, 0, 255, NormType.MinMax, DepthType.Default);
Emgu.CV.OCR.Pix pix = new Emgu.CV.OCR.Pix(crop.Mat);
_ocr.SetImage(pix);
_ocr.Recognize();
var words = _ocr.GetCharacters();
Get "AS000"
Get "AO800"
I try this
Emgu.CV.OCR.Tesseract _ocr = new
Emgu.CV.OCR.Tesseract(#"./tessdata", "spa", OcrEngineMode.LstmOnly);
_ocr.SetVariable("tessedit_char_whitelist","abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
_ocr.SetVariable("tessedit_pageseg_mode", "6");
Emgu.CV.Image<Bgr, Byte> original = new Emgu.CV.Image<Bgr, Byte>(fi.FullName);
Rectangle rec = new Rectangle(105, 132, 100, 25);
original.ROI = rec;
Emgu.CV.Image<Bgr, Byte> crop = new Emgu.CV.Image<Bgr, Byte>(original.Width, original.Height);
CvInvoke.cvCopy(original, crop, IntPtr.Zero);
Mat gray = new Mat();
gray = crop.Mat;
CvInvoke.CvtColor(crop, crop, ColorConversion.Bgr2Gray);
CvInvoke.Resize(crop, crop, new Size(crop.Cols*10, crop.Rows*10)); //for DPI
CvInvoke.Threshold(crop, crop, 0, 255, ThresholdType.Binary | ThresholdType.Otsu); //for Binarize
CvInvoke.GaussianBlur(crop, crop, new Size(1, 1), 0);
Emgu.CV.OCR.Pix pix = new Emgu.CV.OCR.Pix(crop.Mat);
_ocr.SetImage(pix);
_ocr.Recognize();
The result is better but not 100%.
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();
I'm trying to detect contour of an ellipse-like water droplet with Emgu CV. I wrote code for contour detection:
public List<int> GetDiameters()
{
string inputFile = #"path.jpg";
Image<Bgr, byte> imageInput = new Image<Bgr, byte>(inputFile);
Image<Gray, byte> grayImage = imageInput.Convert<Gray, byte>();
Image<Gray, byte> bluredImage = grayImage;
CvInvoke.MedianBlur(grayImage, bluredImage, 9);
Image<Gray, byte> edgedImage = bluredImage;
CvInvoke.Canny(bluredImage, edgedImage, 50, 5);
Image<Gray, byte> closedImage = edgedImage;
Mat kernel = CvInvoke.GetStructuringElement(Emgu.CV.CvEnum.ElementShape.Ellipse, new System.Drawing.Size { Height = 100, Width = 250}, new System.Drawing.Point(-1, -1));
CvInvoke.MorphologyEx(edgedImage, closedImage, Emgu.CV.CvEnum.MorphOp.Close, kernel, new System.Drawing.Point(-1, -1), 0, Emgu.CV.CvEnum.BorderType.Replicate, new MCvScalar());
System.Drawing.Point(100, 250), 10000, Emgu.CV.CvEnum.BorderType.Default, new MCvScalar()
Image<Gray, byte> contoursImage = closedImage;
Image<Bgr, byte> imageOut = imageInput;
VectorOfVectorOfPoint rescontours1 = new VectorOfVectorOfPoint();
using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint())
{
CvInvoke.FindContours(contoursImage, contours, null, Emgu.CV.CvEnum.RetrType.List,
Emgu.CV.CvEnum.ChainApproxMethod.LinkRuns);
MCvScalar color = new MCvScalar(0, 0, 255);
int count = contours.Size;
for (int i = 0; i < count; i++)
{
using (VectorOfPoint contour = contours[i])
using (VectorOfPoint approxContour = new VectorOfPoint())
{
CvInvoke.ApproxPolyDP(contour, approxContour,
0.01 * CvInvoke.ArcLength(contour, true), true);
var area = CvInvoke.ContourArea(contour);
if (area > 0 && approxContour.Size > 10)
{
rescontours1.Push(approxContour);
}
CvInvoke.DrawContours(imageOut, rescontours1, -1, color, 2);
}
}
}
}
result so far:
I think there is a problem with approximation. How to get rid of internal lines and close external contour?
I might need some more information to exactly pinpoint your issue, but it might be something to do with your median blur. I would see if you are blurring enough that EmguCV things the blur is enough that you can canny edge detection. Another method that you could use is Dilate. Try Dialating your Canny edge detection and see if you get any better results.
EDIT
Here is the code below
public List<int> GetDiameters()
{
//List to hold output diameters
List<int> diametors = new List<int>();
//File path to where the image is located
string inputFile = #"C:\Users\jones\Desktop\Image Folder\water.JPG";
//Read in the image and store it as a mat object
Mat img = CvInvoke.Imread(inputFile, Emgu.CV.CvEnum.ImreadModes.AnyColor);
//Mat object that will hold the output of the gaussian blur
Mat gaussianBlur = new Mat();
//Blur the image
CvInvoke.GaussianBlur(img, gaussianBlur, new System.Drawing.Size(21, 21), 20, 20, Emgu.CV.CvEnum.BorderType.Default);
//Mat object that will hold the output of the canny
Mat canny = new Mat();
//Canny the image
CvInvoke.Canny(gaussianBlur, canny, 40, 40);
//Mat object that will hold the output of the dilate
Mat dilate = new Mat();
//Dilate the canny image
CvInvoke.Dilate(canny, dilate, null, new System.Drawing.Point(-1, -1), 6, Emgu.CV.CvEnum.BorderType.Default, new MCvScalar(0, 0, 0));
//Vector that will hold all found contours
VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
//Find the contours and draw them on the image
CvInvoke.FindContours(dilate, contours, null, Emgu.CV.CvEnum.RetrType.External, Emgu.CV.CvEnum.ChainApproxMethod.ChainApproxSimple);
CvInvoke.DrawContours(img, contours, -1, new MCvScalar(255, 0, 0), 5, Emgu.CV.CvEnum.LineType.FourConnected);
//Variables to hold relevent info on what is the biggest contour
int biggest = 0;
int index = 0;
//Find the biggest contour
for (int i = 0; i < contours.Size; i++)
{
if (contours.Size > biggest)
{
biggest = contours.Size;
index = i;
}
}
//Once all contours have been looped over, add the biggest contour's index to the list
diametors.Add(index);
//Return the list
return diametors;
}
The first thing you do is blur the image.
Then you canny the image.
Then you dilate the image, as to make the final output contours more uniform.
Then you just find contours.
I know the final contours are a little bigger than the water droplet, but this is the best that I could come up with. You can probably fiddle around with some of the settings and the code above to make the result a little cleaner.
INPUT IMAGE
Hi I am try to learn EmguCV 3.3 and I have a question about blob counting.As you see in INPUT IMAGE I have black uneven blobs.
I am try to do something like this.
OUTPUT IMAGE
I need to draw rectangle around blobs and count them.
I tryied some approches but non of it work.
I need Help();
You can use FindCountours() or SimpleBlobDetection() to achieve that, here is an example code uses the first one:
Image<Gray, Byte> grayImage = new Image<Gray,Byte>(mRGrc.jpg);
Image<Gray, Byte> canny = new Image<Gray, byte>(grayImage.Size);
int counter = 0;
using (MemStorage storage = new MemStorage())
for (Contour<Point> contours = grayImage.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)
{
contours.ApproxPoly(contours.Perimeter * 0.05, storage);
CvInvoke.cvDrawContours(canny, contours, new MCvScalar(255), new MCvScalar(255), -1, 1, Emgu.CV.CvEnum.LINE_TYPE.EIGHT_CONNECTED, new Point(0, 0));
counter++;
}
using (MemStorage store = new MemStorage())
for (Contour<Point> contours1= grayImage.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);
}
Console.Writeline("Number of blobs: " + counter);
I'm doing a project to process brain injuries using Image Processing. In order to improve its accuracy, I need to extract only the brain matter from the skull.
Using EmguCV I was able to identify the inner and outer contours (Blue and Dark blue). Is there anyway to extract these identified contours into another image?
Image<Gray, byte> grayImage = new Image<Gray, byte>(bitmap);
Image<Bgr, byte> color = new Image<Bgr, byte>(bitmap);
grayImage = grayImage.ThresholdBinary(new Gray(220), new Gray(255));
using (MemStorage storage = new MemStorage())
{
for (Contour<Point> contours = grayImage.FindContours(
Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_TREE, storage); contours != null; contours = contours.HNext)
{
Contour<Point> currentContour = contours.ApproxPoly(contours.Perimeter * 0.015, storage);
if (currentContour.BoundingRectangle.Width > 20)
{
CvInvoke.cvDrawContours(color, contours, new MCvScalar(100), new MCvScalar(255), -1, 2, Emgu.CV.CvEnum.LINE_TYPE.EIGHT_CONNECTED, new Point(0, 0));
}
}
}
EmguCV 2.2.2
Expected output: