EmguCv EigenObjectRecognizer creating instance - c#

My application gets closed when it reaches at creating the recognizer object of EigenObjectRecognizer class without giving any error or warning , am I passing wrong parameters or there is some other problem ? Here is my code
string[] allFaces = Directory.GetFiles(savepath);
if (allFaces != null)
{
Image<Gray, Byte>[] trainingImages = new Image<Gray, Byte>[allFaces.Length];
string[] labels = new String[allFaces.Length];
for (int i = 0; i < allFaces.Length; i++)
{
trainingImages[i] = new Image<Gray, byte>(new Bitmap(allFaces[i]));
labels[i] = allFaces[i].Substring(allFaces[i].LastIndexOf("\\")+1);
}
MCvTermCriteria termCrit = new MCvTermCriteria(allFaces.Length, 0.001);
EigenObjectRecognizer recognizer = new EigenObjectRecognizer(
trainingImages,
labels,
1000,
ref termCrit);
Image<Gray, Byte> testImage = new Image<Gray, Byte>(#"C:\..test\1");
string label = recognizer.Recognize(testImage).Label;
MessageBox.Show(label);
}

Solved the problem by getting an error from raw run of the compiled exe which gave an error of input of not same size from opencv instead of emgucv . When I looked at my training images they were of different size. Hope it helps others

Related

Is there any way to compare two faces using emguCV in C#?

I need to compare just two faces if it is for the same person or not ...
I convert this project Face detection and recognition in runtime to compare two faces but the method always return true .
int ImagesCount = 0;
CascadeClassifier faceDetector = new CascadeClassifier("haarcascade_frontalface_alt.xml");
List<Mat> TrainedFaces = new List<Mat>();
List<int> PersonsLabes = new List<int>();
Mat image1 = img1.ToImage<Gray, byte>().Mat;
Mat image1Temp = img1.ToImage<Bgr, byte>().Mat;
foreach (Rectangle face in faceDetector.DetectMultiScale(image1, 1.2, 10, new Size(50, 50), Size.Empty))
{
Image<Gray, byte> trainedImage = ImageClass.CropImage(image1.ToBitmap(), face).ToImage<Gray, byte>().Resize(200, 200, Inter.Cubic);
CvInvoke.EqualizeHist(trainedImage, trainedImage);
TrainedFaces.Add(trainedImage.Mat);
PersonsLabes.Add(ImagesCount);
ImagesCount++;
}
EigenFaceRecognizer recognizer = new EigenFaceRecognizer(ImagesCount, 2000);
recognizer.Train(TrainedFaces.ToArray(), PersonsLabes.ToArray());
Mat image2 = img2.ToImage<Gray, byte>().Mat;
Rectangle[] rect = faceDetector.DetectMultiScale(image2, 1.2, 10, new Size(50, 50), Size.Empty);
if (rect.Length == 1)
{
Image<Gray, Byte> grayFaceResult = ImageClass.CropImage(image2.ToBitmap(), rect[0]).ToImage<Gray, byte>().Resize(200, 200, Inter.Cubic);
CvInvoke.EqualizeHist(grayFaceResult, grayFaceResult);
var result = recognizer.Predict(grayFaceResult);
if (result.Label != -1 && result.Distance < 2000)
{
return true;
}
}
return false;
Note: The first image may contain more than one picture of the same person and the second image should always contain one picture of the another or same person but always give me 0 ( Always return true Although I tried two pictures of two different people ) and I used emguCv 4.3
I searched a lot but I didn't found any thing can resolve me problem
Is there anyone who can know my mistake in this code or can give me a link for another solution for compare two faces ?
(Note: I am new to this field)
If you can deploy a python application on your server, you might adopt deepface. It has a verify function and you should send the base64 encoded images as inputs to those functions.
Endpoint: http://127.0.0.1:5000/verify
Body:
{
"model_name": "VGG-Face",
"img": [
{
"img1": "data:image/jpeg;base64,..."
, "img2": "data:image/jpeg;base64,..."
}
]
}

How to find the max occurred color in the picture using EMGU CV in C#?

I have an image of a "windows control" lets say a Text-box and I want to get background color of the text written within the text box by finding max color occurred in that picture by pixel color comparison.
I searched in google and I found that every one is talking about histogram and also some code is given to find out histogram of an image but no one described the procedure after finding histogram.
the code I found on some sites is like
// Create a grayscale image
Image<Gray, Byte> img = new Image<Gray, byte>(bmp);
// Fill image with random values
img.SetRandUniform(new MCvScalar(), new MCvScalar(255));
// Create and initialize histogram
DenseHistogram hist = new DenseHistogram(256, new RangeF(0.0f, 255.0f));
// Histogram Computing
hist.Calculate<Byte>(new Image<Gray, byte>[] { img }, true, null);
Currently I have used the code which takes a line segment from the image and finds the max color but which is not the right way to do it.
the currently used code is as follows
Image<Bgr, byte> image = new Image<Bgr, byte>(temp);
int height = temp.Height / 2;
Dictionary<Bgr, int> colors = new Dictionary<Bgr, int>();
for (int i = 0; i < (image.Width); i++)
{
Bgr pixel = new Bgr();
pixel = image[height, i];
if (colors.ContainsKey(pixel))
colors[pixel] += 1;
else
colors.Add(pixel, 1);
}
Bgr result = colors.FirstOrDefault(x => x.Value == colors.Values.Max()).Key;
please help me if any one knows how to get it. Take this image as input ==>
Emgu.CV's DenseHistogram exposes the method MinMax() which finds the maximum and minimum bin of the histogram.
So after computing your histogram like in your first code snippet:
// Create a grayscale image
Image<Gray, Byte> img = new Image<Gray, byte>(bmp);
// Fill image with random values
img.SetRandUniform(new MCvScalar(), new MCvScalar(255));
// Create and initialize histogram
DenseHistogram hist = new DenseHistogram(256, new RangeF(0.0f, 255.0f));
// Histogram Computing
hist.Calculate<Byte>(new Image<Gray, byte>[] { img }, true, null);
...find the peak of the histogram with this method:
float minValue, maxValue;
Point[] minLocation;
Point[] maxLocation;
hist.MinMax(out minValue, out maxValue, out minLocation, out maxLocation);
// This is the value you are looking for (the bin representing the highest peak in your
// histogram is the also the main color of your image).
var mainColor = maxLocation[0].Y;
I found a code snippet in stackoverflow which does my work.
code goes like this
int BlueHist;
int GreenHist;
int RedHist;
Image<Bgr, Byte> img = new Image<Bgr, byte>(bmp);
DenseHistogram Histo = new DenseHistogram(255, new RangeF(0, 255));
Image<Gray, Byte> img2Blue = img[0];
Image<Gray, Byte> img2Green = img[1];
Image<Gray, Byte> img2Red = img[2];
Histo.Calculate(new Image<Gray, Byte>[] { img2Blue }, true, null);
double[] minV, maxV;
Point[] minL, maxL;
Histo.MinMax(out minV, out maxV, out minL, out maxL);
BlueHist = maxL[0].Y;
Histo.Clear();
Histo.Calculate(new Image<Gray, Byte>[] { img2Green }, true, null);
Histo.MinMax(out minV, out maxV, out minL, out maxL);
GreenHist = maxL[0].Y;
Histo.Clear();
Histo.Calculate(new Image<Gray, Byte>[] { img2Red }, true, null);
Histo.MinMax(out minV, out maxV, out minL, out maxL);
RedHist = maxL[0].Y;

Detecting Text Regions from image using EmguCV

I am new to EmguCV and OpenCV. I want to detect the text Regions from an Image using EmguCV.
There are already some solutions posted on Stack using OpenCV.
Extracting text OpenCV
But unable to convert that OpenCV code to EmguCV.
Here is a direct conversion of the accepted answer in the link you provided into c# with EMGU. You might have to make some alterations since its a slightly different implementation but it should get you started. I also doubt it is a very robust so depending on your specific use it might not be suitable. Best of luck.
public List<Rectangle> detectLetters(Image<Bgr, Byte> img)
{
List<Rectangle> rects = new List<Rectangle>();
Image<Gray, Single> img_sobel;
Image<Gray, Byte> img_gray, img_threshold;
img_gray = img.Convert<Gray, Byte>();
img_sobel = img_gray.Sobel(1,0,3);
img_threshold = new Image<Gray, byte>(img_sobel.Size);
CvInvoke.cvThreshold(img_sobel.Convert<Gray, Byte>(), img_threshold, 0, 255, Emgu.CV.CvEnum.THRESH.CV_THRESH_OTSU);
StructuringElementEx element = new StructuringElementEx(3, 17, 1, 6, Emgu.CV.CvEnum.CV_ELEMENT_SHAPE.CV_SHAPE_RECT);
CvInvoke.cvMorphologyEx(img_threshold, img_threshold, IntPtr.Zero, element, Emgu.CV.CvEnum.CV_MORPH_OP.CV_MOP_CLOSE, 1);
for (Contour<System.Drawing.Point> contours = img_threshold.FindContours(); contours != null; contours = contours.HNext)
{
if (contours.Area > 100)
{
Contour<System.Drawing.Point> contours_poly = contours.ApproxPoly(3);
rects.Add(new Rectangle(contours_poly.BoundingRectangle.X, contours_poly.BoundingRectangle.Y, contours_poly.BoundingRectangle.Width, contours_poly.BoundingRectangle.Height));
}
}
return rects;
}
Usage:
Image<Bgr, Byte> img = new Image<Bgr, Byte>("VfDfJ.png");
List<Rectangle> rects = detectLetters(img);
for (int i=0;i<rects.Count();i++)
img.Draw(rects.ElementAt<Rectangle>(i),new Bgr(0,255,0),3);
CvInvoke.cvShowImage("Display", img.Ptr);
CvInvoke.cvWaitKey(0);
CvInvoke.cvDestroyWindow("Display");

Face Recognizer using EigenObjectRecognizer

Image<Gray, Byte>[] trainingImages = new Image<Gray,Byte>[5];
trainingImages[0] = new Image<Gray, byte>("MyPic.jpg");
String[] labels = new String[] { "mine"}
MCvTermCriteria termCrit = new MCvTermCriteria(1, 0.001);
EigenObjectRecognizer recognizer = new EigenObjectRecognizer(
trainingImages,
labels,
1000,
ref termCrit);
Image<Gray,Byte> testImage = new Image<Gray,Byte>("sample_photo.jpg");
var result= recognizer.Recognize(testImage);
result.label always returns string "mine"(label of the training image) for every face it detects.
result.label must be the returned when the detected faces are same in the two images, instead it returns same label for every face.
What is the problem with my code.

How to draw histogram using EmguCV and C#

I need to draw two types of histogram, namely monodimensional and tridimensional.
I'm a newbie to EMGU and all of the samples I found on the net are in C++ or C. Are there any samples using C# and Emgucv?
Thanks for helping.
The following code will segment the RED GREEN and BLUE Histogram data and put them in an array of floats for whatever use you want.
float[] BlueHist;
float[] GreenHist;
float[] RedHist;
Image<Bgr, Byte> img = new Image<Bgr, byte>("ImageFileName");
DenseHistogram Histo = new DenseHistogram(255, new RangeF(0, 255));
Image<Gray, Byte> img2Blue = img[0];
Image<Gray, Byte> img2Green = img[1];
Image<Gray, Byte> img2Red = img[2];
Histo.Calculate(new Image<Gray, Byte>[] { img2Blue }, true, null);
//The data is here
//Histo.MatND.ManagedArray
BlueHist = new float[256];
Histo.MatND.ManagedArray.CopyTo(BlueHist, 0);
Histo.Clear();
Histo.Calculate(new Image<Gray, Byte>[] { img2Green }, true, null);
GreenHist = new float[256];
Histo.MatND.ManagedArray.CopyTo(GreenHist, 0);
Histo.Clear();
Histo.Calculate(new Image<Gray, Byte>[] { img2Red }, true, null);
RedHist = new float[256];
Histo.MatND.ManagedArray.CopyTo(RedHist, 0);
and this will do the greyscale histogram:
float[] GrayHist;
Image<Gray, Byte> img_gray = new Image<Gray, byte>("ImageFileName");
Histo.Calculate(new Image<Gray, Byte>[] { img_gray }, true, null);
//The data is here
//Histo.MatND.ManagedArray
GrayHist = new float[256];
Histo.MatND.ManagedArray.CopyTo(GrayHist, 0);
Hope this helps,
Cheers,
Chris
[Edit]
To draw the histogram you will need to use either you own or a designed controls such as Zedgraph (This is supplied with with EMGU) here is a very good article on codeproject that shows it's use.
http://www.codeproject.com/KB/graphics/zedgraph.aspx
Cheers
Chris
Displaying Histograms in Emgu is super easy and fun. Just make a histogramBox control on your form, then call this in your loop and you are done.
histogramBox1.ClearHistogram();
histogramBox1.GenerateHistograms(frame, 256);
histogramBox1.Refresh();
Tridimensional histogram
Image<Bgr, Byte>[] inp = new Image<Bgr, byte>("fileName.jpg");
int nBins = 256;
DenseHistogram hist = new DenseHistogram(new int[] { nBins, nBins, nBins }, new RangeF[] { new RangeF(0, 255), new RangeF(0, 255), new RangeF(0, 255) });
hist.Calculate(inp.Split(), false, null);
// To get value of single bin
int b = 255; int g = 0; int r = 0; //blue
int count = Convert.ToInt32(hist.MatND.ManagedArray.GetValue(b, g, r)); //count = no of pixels in color Bgr(b,g,r)
//To get all values in a single array
List<Tuple<Bgr, int>> histVal = new List<Tuple<Bgr, int>>(nBins * nBins * nBins);
for (int i = 0; i < nBins; i++)
for (int j = 0; j < nBins; j++)
for (int k = 0; k < nBins; k++)
histVal.Add(new Tuple<Bgr, int>(new Bgr(i, j, k), Convert.ToInt32(hist.MatND.ManagedArray.GetValue(i, j, k))));
Monodimensional histogram
int nBins = 256;
float[] valHist = new float[nBins];
Image<Gray, Byte>[] inp = new Image<Gray, byte>("fileName.jpg");
DenseHistogram hist = new DenseHistogram(nBins, new RangeF(0, 255));
hist.Calculate(new Image<Gray, Byte>[] { inp }, true, null);
hist.MatND.ManagedArray.CopyTo(valHist,0);
It is important to follow the procedure to add the Emgu.CV.UI.dll to your toolbox in Windows Forms in order to use all of the Windows Forms controls that Emgu CV provides (HistogramBox included.)
First of all you need to open your form in designer view. From Toolbox, right click in the empty space of 'General' column. This should pop up a selection menu, where 'Choose Items' selection is available, see image below.
Afterwards, click on 'Choose Items'; you will see a 'Choose Toolbox Item' Dialog. From there click the 'Browse..' button on the lower right corner of the dialog.
Select 'Emgu.CV.UI.dll' file from 'Open' dialog, click the 'Open' button.
Now you should notice the ImageBox control has been added to the 'Choose Toolbox Items' dialog. Click 'Ok'. Then you should note the following controls added to your Toolbox (Applies for version 3.10 of Emgu. Some other versions of Emgu may have other controls or lack the controls mentioned below.)
HistogramBox
ImageBox
MatrixBox
PanAndZoomPictureBox.
Then you should be able to drag and drop to your form as you see fit the Windows Forms controls that Emgu CV has built-it. Or you should be able to use them programmatically:
Form frm = new Form();
var img = CvInvoke.Imread(this.PictureBox.ImageLocation, Emgu.CV.CvEnum.LoadImageType.Grayscale).ToImage<Gray, Byte>();
HistogramBox histo = new HistogramBox();
histo.ClearHistogram();
histo.GenerateHistograms(img, 256);
histo.Dock = DockStyle.Fill;
histo.Refresh();
frm.Controls.Add(histo);
frm.ShowDialog();
This answer was inspired in the Add Image Box Control tutorial.

Categories

Resources