EMGU CV Face Recognition from Image - c#

I've been working with OpenCV before for C++ work and It was working great. Now, I'm developing a C# project and using EMGU CV for gender recognition. I've got problem with predict function. Every time I ran it, program crashed on Predict function, when I erased predict line, it is running. Here's my code:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
FaceRecognizer face = new FisherFaceRecognizer(0, 3500);
face.Load("colorFisherFaceModel.yml");
Image<Bgr, Byte> img1 = new Image<Bgr, Byte>("C:\\Users\\sguthesis\\Pictures\\me.jpg");
cascade = new CascadeClassifier("C:\\Users\\sguthesis\\documents\\visual studio 2013\\Projects\\EmguCV FFR with Image\\EmguCV FFR with Image\\haarcascade_frontalface_alt_tree.xml");
FaceRecognizer.PredictionResult predictedLabel = face.Predict(img1);
}
Also, I want to get an output, 1 or 2. 1 for male and 2 for female. I have trained many data that saved on colorFisherFaceModel.yml. It was run well on OpenCV. But I don't know how to use it in EMGU CV.

I'm also working on EmguCV, so I guess I can point few things here,
So first thing is you load "yml" file, Is this file you saved after recognizer is trained or you obtained from somewhere. Because my understanding is first you have to train your Recognizer, what is the structure of the yml file. Why do you load the cascade, where are you going to use it? (normally this is used to detect the face)
If you're saying that program crashed most probably because there are no items in the trained set. (in this case i guess it would be yml file) or as what I've read you need minimum of two faces in training set in order to use Fisher recognizer.

this happens because the FaceRecognizer wants to be trained before the Predict method can be called.
You can even load an existing xml Training file by the face.Load(yourTrainingFile.xml) method or by face.Train(yourImages.ToArray, imageIds.ToArray()) method.
Place your FaceRecognizer.PredictionResult predictedLabel = face.Predict(img1); code part within a trycatch block the the debugger wont close and you will catch the error message.
PS : if the number of pictures have been changed since the last Training.xml file has been created, then it's recommended to call the face.Train method instead of face.Load method!

Related

How to read text from 'simple' screenshot fast and effectively?

I'm working on a small personal application that should read some text (2 sentences at most) from a really simple Android screenshot. The text is always the same size, same font, and in approx. the same location. The background is very plain, usually a few shades of 1 color (think like bright orange fading into a little darker orange). I'm trying to figure out what would be the best way (and most importantly, the fastest way) to do this.
My first attempt involved the IronOcr C# library, and to be fair, it worked quite well! But I've noticed a few issues with it:
It's not 100% accurate
Despite having a community/trial version, it sometimes throws exceptions telling you to get a license
It takes ~400ms to read a ~600x300 pixel image, which in the case of my simple image, I consider to be rather long
As strange as it sounds, I have a feeling that libraries like IronOcr and Tesseract may just be too advanced for my needs. To improve speeds I have even written a piece of code to "treshold" my image first, making it completely black and white.
My current IronOcr settings look like this:
ImageReader = new AdvancedOcr()
{
CleanBackgroundNoise = false,
EnhanceContrast = false,
EnhanceResolution = false,
Strategy = AdvancedOcr.OcrStrategy.Fast,
ColorSpace = AdvancedOcr.OcrColorSpace.GrayScale,
DetectWhiteTextOnDarkBackgrounds = true,
InputImageType = AdvancedOcr.InputTypes.Snippet,
RotateAndStraighten = false,
ReadBarCodes = false,
ColorDepth = 1
};
And I could totally live with the results I've been getting using IronOcr, but the licensing exceptions ruin it. I also don't have $399 USD to spend on a private hobby project that won't even leave my own PC :(
But my main goal with this question is to find a better, faster or more efficient way to do this. It doesn't necessarily have to be an existing library, I'd be more than willing to make my own kind of letter-detection code that would work (only?) for screenshots like mine if someone can point me in the right direction.
I have researched about this topic and the best solution which I could find is Azure cognitive services. You can use Computer vision API to read text from an image. Here is the complete document.
How fast does it have to be?
If you are using C# I recommend the Google Cloud Vision API. You pay per request but the first 1000 per month are free (check pricing here). However, it does require a web request but I find it to be very quick
using Google.Cloud.Vision.V1;
using System;
namespace GoogleCloudSamples
{
public class QuickStart
{
public static void Main(string[] args)
{
// Instantiates a client
var client = ImageAnnotatorClient.Create();
// Load the image file into memory
var image = Image.FromFile("wakeupcat.jpg");
// Performs label detection on the image file
var response = client.DetectText(image);
foreach (var annotation in response)
{
if (annotation.Description != null)
Console.WriteLine(annotation.Description);
}
}
}
}
I find it works well for pictures and scanned documents so it should work perfectly for your situation. The SDK is also available in other languages too like Java, Python, and Node

Stand alone ".exe" matlab file not saving images

I'm trying to create an ".exe" file that will read some sort of data(for a known path), and will plot it one time as "bplot" and the other time as "histogram".
The code works fine as I run it from the editor, and even after I've made an ".exe" file. The problem begins when I try to run it from a "C#" code with the command "Process.Start(#"my_path.exe")". It seems like it runs the code and I can see the figures that are made, but it doesn't save the pictures.
My matlab code is:
clear
clc
P = csvread('my_path\test_csv.csv');
SP = bplot(P);
pause (3);
saveas(figure(1),[pwd '\picture1.jpeg']);
pause (3)
B = csvread('my_path\test2_csv.csv');
histogram(B);
pause (3)
saveas(figure(1),[pwd '\picture2.jpeg']);
pause (3)
close
clear
clc
The "bplot" is an external function that I downloaded.
Any ideas how to save it in other way so the stand alone application will save the images when I call it from C# code?
Try using the syntax with ProcessStartInfo parameter (see here), rather than syntax with the path the file directly.
Indeed if not setting ProcessStartInfo.WorkingDirectory, it will be considered to be %SYSTEMROOT%\System32 (for which you don't have write access as normal user)
var startInfo = new ProcessStartInfo(#"my_path.exe");
startInfo.WorkingDirectory= .... you exe dir or something else....;
Process.Start(startInfo);

Why is PictureBox.Load locking image on some systems?

(Please see the edit on the bottom of the question, if you do not want to read the whole story.)
Hi,
I am new to stackoverflow. Don’t get me wrong, I use it quite often. But up until now I never actually posted something. This is because I did not have something new/useful to say and my English is not that good. The first thing (might have) changed, the latter did not.
I ran into a problem at a customer's Windows 7 system quite recently. I was shipping a C# .Net 4.0 Windows Forms application via ClickOnce. Basically, it is an application that creates a bitmap file and shows it to the user. If the bitmap exists prior to the creation, the existing file gets deleted first. After that the new file is created and loaded by a PictureBox.
The following thing occurred at the customer’s system: After starting the application the first creation succeeds – the second and all following ones do not. The file cannot be deleted, because some process is blocking it. This process is the application itself.
System.IO.IOException: The process cannot access the file “filename” because it is being used by another process.
Well, of course that is nothing unusual. The thing is I tested the application on several systems. None showed this exception. And until now I am unable to see an code error.
So I looked a little bit closer on the customer’s system: The only difference I could find is, that they changed the users folder so that they are not located on the windows partition, but on a different one (C:\Users --> D:\Users). I searched for an instruction on the internet and did the same thing on one of my test systems. To my surprise I got the same exception when I ran my application on it.
With that I could change my code so that the exception does not occur anymore. But I do not understand why that is. So maybe there is something wrong with my code and the error just reveals itself under that special circumstances. Or maybe the code is okay and the reason lies somewhere else. I just hoped that you might be able to help me.
So here is some code I put together, that shows the same behavior. I used 3 buttons, an OpenFileDialog and a PictureBox on a Form. First thing to do is to choose an image file. By pressing one of the two remaining buttons it gets copied into the main folder of the application. After being copied it is shown by the PictureBox. By the way, it does not seem to matter if it is a ClickOnce-application or a “normal” one.
String m_FileName;
private void btnChooseFile_Click(object sender, EventArgs e) {
if(openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK) { // If file was chosen, set file name for later use and activate buttons.
m_FileName = "Test" + Path.GetExtension(openFileDialog1.FileName);
}
}
private void button1_Click(object sender, EventArgs e) {
// This is not working.
if(this.pictureBox1.Image != null) {
//Image img = this.pictureBox1.Image; // I was not sure, if maybe the pictureBox somehow prevents the disposing of the image, as long as it's assigned to it.
//this.pictureBox1.ImageLocation = null; // So I set them null, both the image and the image location.
//this.pictureBox1.Image = null;
//img.Dispose(); // Then I disposed the image.
this.pictureBox1.Image.Dispose(); // The short version. It is not working either way.
this.pictureBox1.Image = null;
}
(new FileInfo(openFileDialog1.FileName)).CopyTo(m_FileName, true); // But still this is where the Exception occurs.
this.pictureBox1.Load(m_FileName);
}
private void button2_Click(object sender, EventArgs e) {
//This is working.
if(this.pictureBox1.Image != null) {
//Image img = this.pictureBox1.Image;
//this.pictureBox1.Image = null;
//img.Dispose();
this.pictureBox1.Image.Dispose();
this.pictureBox1.Image = null;
}
(new FileInfo(openFileDialog1.FileName)).CopyTo(m_FileName, true);
pictureBox1.Image = Image.FromFile(m_FileName);
}
What happens now is the following: If I start the application and click button1 twice, I will get the exception (on the second click). If I start it and click button2 twice, I will not. If I start the application and click buttons1 first and after that button2, I will get the exception. So, the Picture.Load-Function somehow blocks the file, even if I dispose it.
When I searched on the internet, I found an article from microsoft: http://support.microsoft.com/kb/309482/en-us. But it does not hit the bull's eye.
Take into account, that both versions are working on all my test machines. I just get the exception when I change the users folder to a non-windows-partition.
Why is that? And where is the difference in the presented versions?
Edit
Okay, because of the first and only reaction so far, it seems to me, that it is still not clear, what really happens: If I take the above code, put it in a Windows Forms application, compile it and run it on different computers (at work, at home, does not matter) it works - both button1 and button2 (with the Click-functions linked to them) can be used as often as I like - no exception thrown. If I run the application on a computer, where I changed the users folder, and click button1 the second time - bam - IOException, file locked by process. Button2 works as long as I do not press button1.
The first answer implies, that I should get the locking on every system. But I DO NOT (as long as I do not change the users folder)! I tested it on every single computer I could get my hands on - no IOException. I set up a new system, just to rule out some special changes to the systems in my company - both buttonx_Click functions worked - no exception either. I even compiled the program on another computer - same behavior. The only three systems to throw that exception were the ones with the changed users folder.
So far I have no clue, why this difference in behavior occurs. Can somebody help me?
Anybody?
Yes, this is normal. Happens on any operating system, doesn't have anything to do with the Users folder location. The PictureBox.Load() method was intented to be used to load images from locations other than the file system. Like a web site. Which is slow, it avoids freezing the UI while the download is taking place.
It internally uses a FileStream when it discovers that the url you pass is actually a file and not a website name. This FileStream does not get disposed until the PictureBox itself is disposed or you call the Load() method again. A requirement because Image.FromStream() requires the stream to remain readable until the image is no longer used. It is this FileStream that keeps a lock on the file. Disposing the PictureBox.Image is not enough to also dispose the FileStream, the Image object doesn't know that it is being displayed inside a picture box.
There are several ways to solve this problem:
Use the Image property instead of Load(), assign it from Image.FromFile(). Disposing the Image now also releases the lock on the file. As you found out
Keep a dummy image around, one that perhaps displays a "Loading..." bitmap. Load() it first to release the lock on the file
Dispose the PictureBox and recreate it.
This works and unlocks the file
Image img= Image.FromFile(mypath);
Graphics g = pictureBox1.CreateGraphics();
g.DrawImage(img,0,0);
img.Dispose();

Canon EDSDK Command TakePicture blocks everything after focus error

I'm using the Canon SDK 2.1 and i am trying to take a picture at the camera from C# code.
I started a session (EdsOpenSession) and everything works fine with this line of code:
EDSDK.EdsSendCommand(cameraDev, EDSDK.CameraCommand_TakePicture, 0);
the camera takes a picture and stores it on memory card.
The problem is here: if there is an AF error (e.g. the lens cap is on), the camera gets 'BUSY' and never gets back.
Also if i try to shut down the EDSDK with the functions EdsCloseSession or EdsTerminateSDK, they blocks. The only thing to get it up again is to restart the application and the camera.
I'm using an EOS 100D.
What can i do to get ignore these AF error and try to take another picture?
I have also just had this issue.
I have solved it by Sending a half button press to focus followed by a full button press to take the photo if that succeeds.
try
{
EDSDK.EdsSendCommand(cameraDev, EDSDK.CameraCommand_PressShutterButton, 1); // Half
EDSDK.EdsSendCommand(cameraDev, EDSDK.CameraCommand_PressShutterButton, 3); // Completely
}
finally
{
EDSDK.EdsSendCommand(cameraDev, EDSDK.CameraCommand_PressShutterButton, 0); // Off
}
I have the same problem with Canon EOS 1100D, but I've found http://digicamcontrol.com which is open source. They've managed to make autofocus working, but I haven't found what exactly they did. Maybe you can find it. I if you do, please share the solution.

Webcams, C#, and a reliable wrapper

I'm in dire need of a replacement for a wrapper being used in a C# application. Basically, what we need to do is attach a webcam feed to one of two picture boxes. This will be used to take still images at the push of a button, which may detach the camera feed and attach the still image to that picture box, then reattach the camera feed later. We had previously found some free code to utilize with a CaptureDevice.cs file and Pinvoke.dll to tie it into avicap32.dll. Unfortunately, this seems to have random, intermittent errors that cannot be reliably reproduced. It's just too flaky. At some random point, one of those picture boxes may go black and won't show the feed until the picture is taken, at which point the proper picture is attached to the picture box. Then, even if there's only one webcam attached, it'll keep prompting for the webcam to be selected, something it wouldn't do otherwise.
Quite frankly, I'm surprised and dismayed that Microsoft hasn't included anything in .NET to cover webcam video feeds. I'm looking for something reliable and relatively simple to implement to replace this buggy webcam system.
It is time to use MediaCapture object. Use this sample for MS Windows 10 https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/CameraStarterKit/
And read this article as well http://www.codepool.biz/csharp-camera-api-video-frame.html
May I suggest
http://www.emgu.com/wiki/index.php/Main_Page
I have used OpenCV in many C++ libraries and it seems to work very well for webcams from other things I've tried. Emgu is just a C# wrapper for OpenCV.
Here is a sample project to try it out on. It's very basic and simple, but should work right away.
http://dl.dropbox.com/u/18919663/vs%20samples/OpenCVCSharpTest.zip (just uploaded)
Sample:
using Emgu.CV;
using Emgu.CV.Structure;
...
public partial class Form1 : Form
{
public Capture cvWebCam;
public Form1()
{
InitializeComponent();
try
{
cvWebCam = new Capture();
timer1.Start();
}
catch
{
Console.WriteLine("Default camera not found or could not start");
}
}
private void timer1_Tick(object sender, EventArgs e)
{
if (cvWebCam != null)
using (Emgu.CV.Image<Bgr, byte> frame = cvWebCam.QueryFrame())
{
pictureBox1.BackgroundImage = frame.ToBitmap();
}
}
}
Try DirectShow.net- it's a free wrapper library to access DirectShow functionality from .NET:
http://directshownet.sourceforge.net
Its code samples contain a sample app for capturing video from webcams, too:
http://sourceforge.net/projects/directshownet/files/DirectShowSamples/

Categories