I'm programming in C# and I use EmguCV (3.1). I use Canny edge detector from CvInvoke class. My problem is this algorithm do not find some edges. My OpenCL = true. Here is my problem:
The input image:
And the result:
As you see, rectangles that are not rotated, miss their top edges. My questions are:
1- Is it normal?
2- In case of NO how can I fix it?
HERE IS MY CODE:
CvInvoke.UseOpenCL = true;
Bitmap bm = new Bitmap(pictureBox1.Image);
Image<Gray, byte> im = new Image<Gray, byte>(bm);
UMat u = im.ToUMat();
CvInvoke.Canny(u, u, 150, 50);
pictureBox1.Image = u.Bitmap;
Related
I'm new with image processing and stuck on matching different angled images.
I'm trying to detect selected template image in captured camera image. If template image and are exactly same angle everything goes well. When both image angles different, image matching fails.
I used EmguCV to match 2 images.
what i need to use to match two image when different angle?
This is both image same angled. https://imgur.com/K6bUAZp
This is both image different angled. https://imgur.com/qatg2CV
Image<Bgr, byte> source = new Image<Bgr, byte>(grayMain); // Camera image
Image<Bgr, byte> template = new Image<Bgr, byte>(FrameImage); // Template image
Image<Bgr, byte> lastImage = source.Copy();
using (Image<Gray, float> result = source.MatchTemplate(template, TemplateMatchingType.CcoeffNormed))
{
double[] minVal, maxVal;
System.Drawing.Point[] minLocations, maxLocations;
result.MinMax(out minVal, out maxVal, out minLocations, out maxLocations);
if (maxVal[0] > 0.75)
{
Rectangle match = new Rectangle(maxLocations[0], template.Size);
lastImage.Draw(match, new Bgr(Color.Red), 3);
}
}
pictureBox.Image = lastImage.Bitmap;
I solved my problem with serch rectangle in camera image and crop this image with detected rectangle using AForge.QuadrilateralTransformation. And then using last images (template and cropped image) for matching.
This is after crop image -> https://imgur.com/5JqAL5J
After croping red rectangle and doing image matching resulted this image -> https://imgur.com/Sva3MzO
Hope this help.
I'm very new to Emgucv, so need a little help?
The code below is mainly taken from various places from Google. It will take a jpg file (which has a green background) and allow, from a separate form to change the values of h1 and h2 settings so as to create (reveal) a mask.
Now what I want to be able to do with this mask is to turn it transparent.
At the moment it will just display a black background around a person (for example), and then saves to file.
I need to know how to turn the black background transparent, if this is the correct way to approach this?
Thanks in advance.
What I have so far is in C# :
imgInput = new Image<Bgr, byte>(FileName);
Image<Hsv, Byte> hsvimg = imgInput.Convert<Hsv, Byte>();
//extract the hue and value channels
Image<Gray, Byte>[] channels = hsvimg.Split(); // split into components
Image<Gray, Byte> imghue = channels[0]; // hsv, so channels[0] is hue.
Image<Gray, Byte> imgval = channels[2]; // hsv, so channels[2] is value.
//filter out all but "the color you want"...seems to be 0 to 128 (64, 72) ?
Image<Gray, Byte> huefilter = imghue.InRange(new Gray(h1), new Gray(h2));
// TURN IT TRANSPARENT somewhere around here?
pictureBox2.Image = imgInput.Copy(mask).Bitmap;
imgInput.Copy(mask).Save("changedImage.png");
I am not sure I really understand what you are trying to do. But a mask is a binary object. A mask is usually black for what you do not want and white for what you do. As far as I know, there is no transparent mask, as to me that makes no sense. Masks are used to extract parts of an image by masking out the rest.
Maybe you could elaborate on what it is you want to do?
Doug
I think I may have the solution I was looking for. I found some code on stackoverflow which I've tweaked a little :
public Image<Bgra, Byte> MakeTransparent(Image<Bgr, Byte> image, double r1, double r2)
{
Mat imageMat = image.Mat;
Mat finalMat = new Mat(imageMat.Rows, imageMat.Cols, DepthType.Cv8U, 4);
Mat tmp = new Mat(imageMat.Rows, imageMat.Cols, DepthType.Cv8U, 1);
Mat alpha = new Mat(imageMat.Rows, imageMat.Cols, DepthType.Cv8U, 1);
CvInvoke.CvtColor(imageMat, tmp, ColorConversion.Bgr2Gray);
CvInvoke.Threshold(tmp, alpha, (int)r1, (int)r2, ThresholdType.Binary);
VectorOfMat rgb = new VectorOfMat(3);
CvInvoke.Split(imageMat, rgb);
Mat[] rgba = { rgb[0], rgb[1], rgb[2], alpha };
VectorOfMat vector = new VectorOfMat(rgba);
CvInvoke.Merge(vector, finalMat);
return finalMat.ToImage<Bgra, Byte>();
}
I'm now looking at adding SmoothGaussian to the mask to create a kind on blend, where the two images are layered, rather than a sharp cut-out.
My task is to recognize eye borders (not pupil but whole eye).
I can't take the white part of image even using HSV filtering.
I use filtering by hue and saturation and get no result:
Image<Gray, byte> huefilter = imghue.InRange(new Gray(Color.White.GetHue()-10), new Gray(Color.White.GetHue() + 10));
Image<Gray, byte> saturationfilter = imgsaturation.InRange(new Gray(Color.White.GetSaturation() - 10), new Gray(Color.White.GetSaturation() + 10));
Image<Gray, byte> resultImg = huefilter.And(saturationfilter);
Sample images:One Two Three
Please give an advise how to get the light zone around pupil with help of c# EmguCV.
I'm using EmguCV 2.4 in C# for edge detection and ellipse fitting of ellipsoid objects in a picture (e.g. laser spot).
EmguCV has implemented functions for fitting an ellipse to a point cloud using the least squares method, but the ellipses do not fit very well to the ellipsoids, depending on their angle.
Here's a basic code, I'm using:
CHAIN_APPROX_METHOD approxMethod = CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_NONE;
RETR_TYPE RetrType = RETR_TYPE.CV_RETR_LIST;
Bitmap Bmp = new Bitmap(#"C:\Users\pernizki\Downloads\binary2.bmp"); // read Bitmap
Image<Bgr, byte> ImgIn = new Image<Bgr, byte>(Bmp); // Convert to Image<>
Image<Gray, byte> ImgBin = ImgIn.Convert<Gray, byte>(); // convert Bgr to Gray
ImgBin = ImgBin.ThresholdBinary(new Gray(140), new Gray(120)).PyrDown().PyrUp(); // convert to binary and reduce noise
ImgBin = ImgBin.Canny(100, 120); // detect the edges from binary image
Contour<Point> Contour = ImgBin.FindContours(approxMethod, RetrType); // Get Contour from binary Image
int cntr = 0;
PointF[] ContourPts = new PointF[Contour.Total];
// Convert Contour to PointF Array
foreach(Point p in Contour)
{
ContourPts[cntr++] = new PointF(p.X, p.Y);
}
Ellipse fittedEllipse = PointCollection.EllipseLeastSquareFitting(ContourPts);
ImgIn.Draw(Contour, new Bgr(Color.Green), 2);
ImgIn.Draw(fittedEllipse, new Bgr(Color.Tomato), 2);
CvInvoke.cvShowImage("Fitted Ellipse", ImgIn.Ptr);
When I have vertical or horizontal ellipse as an input image, the fitted ellipse is always 90° rotated to the input shape. If the angle is something between 0° and 90° the fitted ellipse is still rotated, but at different angle.
I understand, that this problem is fundamental to the least square method. But are there more robust algorithms to fit an ellipse, that is enclosing all of the points?
The picture in the EmguCV tutorial for fitting an ellipse seems to be exactly, what I'm looking for. Unfortunately, that's not how the function works.
Here's an example image, that I've used.
(sorry for having only one, as I don't have enough reputation for more)
rotated Ellipse
i need to compare two images and identify differences on them as percentage. "Absdiff" function on emgucv doesn't help with that. i already done that compare example on emgucv wiki. what i exactly want is how to get two image difference in numerical format?
//emgucv wiki compare example
//acquire the frame
Frame = capture.RetrieveBgrFrame(); //aquire a frame
Difference = Previous_Frame.AbsDiff(Frame);
//what i want is
double differenceValue=Previous_Frame."SOMETHING";
if you need more detail plz ask.
Thanks in advance.
EmguCV MatchTemplate based comparison
Bitmap inputMap = //bitmap source image
Image<Gray, Byte> sourceImage = new Image<Gray, Byte>(inputMap);
Bitmap tempBitmap = //Bitmap template image
Image<Gray, Byte> templateImage = new Image<Gray, Byte>(tempBitmap);
Image<Gray, float> resultImage = sourceImage.MatchTemplate(templateImage, Emgu.CV.CvEnum.TemplateMatchingType.CcoeffNormed);
double[] minValues, maxValues;
Point[] minLocations, maxLocations;
resultImage.MinMax(out minValues, out maxValues, out minLocations, out maxLocations);
double percentage = maxValues[0] * 100; //this will be percentage of difference of two images
The two images need to have the same width and height or MatchTemplate will throw an exception. In case if we want to have an exact match.
Or
The template image should be smaller than the source image to get a number of occurrence of the template image on the source image
EmguCV AbsDiff based comparison
Bitmap inputMap = //bitmap source image
Image<Gray, Byte> sourceImage = new Image<Gray, Byte>(inputMap);
Bitmap tempBitmap = //Bitmap template image
Image<Gray, Byte> templateImage = new Image<Gray, Byte>(tempBitmap);
Image<Gray, byte> resultImage = new Image<Gray, byte>(templateImage.Width,
templateImage.Height);
CvInvoke.AbsDiff(sourceImage, templateImage, resultImage);
double diff = CvInvoke.CountNonZero(resultImage);
diff = (diff / (templateImage.Width * templateImage.Height)) * 100; // this will give you the difference in percentage
As per my experience, this is the best method compared to MatchTemplate based comparison. Match template failed to capture very minimal changes in two images.
But AbsDiff will be able to capture very small difference as well