I am using a console app and very basic Tesseract to perform digit recognition. I have copied an image from google and tried to find the digits only.
Bitmap image = new Bitmap("1.png");
TesseractEngine t = new TesseractEngine("./tessdata", "eng", EngineMode.Default);
t.SetVariable("tessedit_char_whitelist", "01234567890");
var r = t.Process(image, PageSegMode.SingleBlock);
Console.WriteLine("Result: " + r.GetText());
Console.ReadLine();
The image is
The result are different depending on the pageSegMode, but none of them are close to the image.
What is the best way to use Tesseract to identify digits from such pics?
Tesseract won't work well with an image like that unless you somehow train it specifically for that case, but I don't think you have to if you can transform the image right
Your goal should be feeding it a black and white picture with black digits and white background, you should do this processing before OCRing the image, there are many libraries for this, most people use OpenCV.
Tesseract already does some image processing but it's not great and probably doesn't help much with an image like that. You can view the auto processed result with tessedit_write_images to see what's actually being OCRed.
Here's some useful links:
https://github.com/tesseract-ocr/tesseract/wiki/ImproveQuality#image-processing
Using tesseract to recognize license plates
Related
My aim is to detect multiple datamatrices on a larger image like this (the four big):
Based on several code samples, I made a small test program:
Bitmap image = getImage();
DataMatrixReader reader = new DataMatrixReader();
GenericMultipleBarcodeReader genericReader = new genericMultipleBarcodeReader(reader);
Dictionary<DecodeHintType, object> hints = new Dictionary<DecodeHintType,object>();
hints.Add(DecodeHintType.TRY_HARDER, true);
BitmapLuminanceSource source = new BitmapLuminanceSource(image);
HybridBinarizer binarizer = new HybridBinarizer(source);
BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);
Result[] results = genericReader.decodeMultiple(binaryBitmap,hints);
show(results);
It could'nt detect any code on the large image.
But it can detect the code, when its cropped like that:
After that I merged two generated data matrices, and it failed too:
Last I ran two more test with slightly cropped images, both failed:
So it seems this library is not robust at all, or maybe I use it wrong.
Any idea how to improve my results? (including other libraries and preprocessing)
It can't be said that the library is not robust but there are two key factors affecting you here:
Zxing's data-matrix detection algorithm assumes that the barcode is centered. Or more precisely, that the center of the image is inside the data-matrix.
Zxing's multiple reader specially fails when barcodes are grid-aligned.
My recommendation is to implement your own MultipleBarcodeReader taking into account what I've mentioned.
A naive approach could be to take sample images centered over a grid of points spaced so every data-matrix (no matter its position within the image) contain at least one of the points inside. You just have to make sure to exclude duplicated codes.
I need to capture an area within my desktop. But I need this area to be very high resolution (like, at least few thousand's pixels horizontal, same goes for vertical). Is it possible to get a screen capture that has high density of pixels? How can I do this? I tried capturing the screen with some AutoIt script, and got some very good results (images that were 350MB big), now I would like to do the same using C#.
Edit:
I am doing my read/write of a .tif file like that, and it already loses most of the data:
using (Bitmap bitmap = (Bitmap)Image.FromFile(#"ScreenShot.tif")) //this file has 350MB
{
using (Bitmap newBitmap = new Bitmap(bitmap))
{
newBitmap.Save("TESTRES.TIF", ImageFormat.Tiff); //now this file has about 60MB, Why?
}
}
I am trying to capture my screen like that, but the best I can get from this is few megabytes (nowhere near 350MB):
using (var bmpScreenCapture = new Bitmap(window[2], window[3], PixelFormat.Format32bppArgb))
{
using (var i = Graphics.FromImage(bmpScreenCapture))
{
i.InterpolationMode = InterpolationMode.High;
i.CopyFromScreen(window[0], window[1], 0, 0, bmpScreenCapture.Size, CopyPixelOperation.SourceCopy);
}
bmpScreenCapture.Save("test2.tif", ImageFormat.Tiff);
}
You can't gather more information than the source has.
This is a basic truth and it does apply here, too.
So you can't capture more the your 1920x1080 pixels at their color depth.
OTOH, since you want to feed the captured image into OCR, there a few more things to consider and in fact to do..
OCR is very happy if you help it by optimizing the image. This should involve
reducing colors and adding contrast
enlarging to the recommended dpi resolution
adding even more contrast
Funnily, this will help OCR although the real information cannot increase above the original source. But a good resizing algorithm will add invented data and these often will be just what the OCR software needs.
You should also take care to use a good i.e. non lossy format when you store the image to a file like png or tif and never jpg.
The best way will have to be adjusted by trial and error until the OCR results are good enough.
Hint: Due to font antialiasing most text on screenshots is surrounded by a halo of colorful pixels. Getting rid of it by the reducing or even removing saturation is one way; maybe you want to turn it off in your display properties? (Check out ClearType!)
Im developing an image skin detection app.
But there is a problem with my camera, that try to compensate the light and the result image is bad, in most of cases i have a cold or warm effect on the image.
When i use photoshop there is the AutoTone function that normalize an image and reduce this problem.
With aforge i want to use HistogramEqualization() filter but the result is very bad:
// create filter
HistogramEqualization filter = new HistogramEqualization( );
// process image
filter.ApplyInPlace( sourceImage );
So my question is:
There is a function in Accord or Aforge to have the same result of the autotone of Photoshop?
If not, there is some library or script that let to do this?
Thank you all.
I use the LevelsLinear filter and base it on image stats:
ImageStatistics stats = new ImageStatistics(sourceImage);
LevelsLinear levelsLinear = new LevelsLinear {
InRed = stats.Red.GetRange( 0.90 ),
InGreen = stats.Green.GetRange( 0.90 ),
InBlue = stats.Blue.GetRange( 0.90 )
};
levelsLinear.ApplyInPlace(sourceImage);
You can play with the range to tweak the result.
You probably don't want to equalize the histogram, because as you see, a photo that wouldn't normally have much red, would have alot of red created and make it look nasty. Instead you probably want to examine for a bias to a hue that occurs almost everywhere. For example, your original photo probably had a bias towards blue in almost every pixel, and thus probably shouldn't be there. Look for a minimum bias and remove that amount everywhere.
A more practical solution is to experiment with the white balance setting on your camera to see what gives you the best result. Choosing the right preset, will leverage an algorithm that's probably as good as what you would write by hand. But maybe you are doing this as a learning experience.
I have 2 bmp images.
ImageA is a screenshot (example)
ImageB is a subset of that. Say for example, an icon.
I want to find the X,Y coordinates of ImageB within ImageA (if it exists).
Any idea how I would do that?
Here's a quick sample but it is slow take around 4-6 seconds, but it does exactly what you looking for and i know this post is old but if anyone else visiting this post recently
you can look this thing
you need .NET AForge namespace or framework google it and install it
include AForge name space in your project and that's it
it finds the pictiure with another and gives out the coordinates.
System.Drawing.Bitmap sourceImage = (Bitmap)Bitmap.FromFile(#"C:\SavedBMPs\1.jpg");
System.Drawing.Bitmap template = (Bitmap)Bitmap.FromFile(#"C:\SavedBMPs\2.jpg");
// create template matching algorithm's instance
// (set similarity threshold to 92.1%)
ExhaustiveTemplateMatching tm = new ExhaustiveTemplateMatching(0.921f);
// find all matchings with specified above similarity
TemplateMatch[] matchings = tm.ProcessImage(sourceImage, template);
// highlight found matchings
BitmapData data = sourceImage.LockBits(
new Rectangle(0, 0, sourceImage.Width, sourceImage.Height),
ImageLockMode.ReadWrite, sourceImage.PixelFormat);
foreach (TemplateMatch m in matchings)
{
Drawing.Rectangle(data, m.Rectangle, Color.White);
MessageBox.Show(m.Rectangle.Location.ToString());
// do something else with matching
}
sourceImage.UnlockBits(data);
So is there any warping of ImageB in ImageA?
How "exact" are the images, as in, pixel-for-pixel they will be the same?
How much computational power do you have for this?
If the answers to the first two questions are No and Yes, then you have a simple problem. It also helps to know the answer to Q3.
Update:
The basic idea's this: instead of matching a window around every pixel in imageB with every pixel in imageA and checking the correlation, let's identify points of interest (or features) in both images which will be trackable. So it looks like corners are really trackable since the area around it is kinda similar (not going into details) - hence, let's find some really strong corners in both images and search for corners which look most similar.
This reduces the problem of searching every pixel in B with A to searching for, say, 500 corners in B with a 1000 corners in A (or something like that) - much faster.
And the awesome thing is you have several such corner detectors at your disposal in OpenCV. If you don't feel using emguCV (C# varriant), then use the FAST detector to find matching corners and thus locate multiple features between your images. Once you have that, you can find the location of the top-left corner of the image.
If image B is an exact subset of image A (meaning, the pixel values are exactly the same), this is not an image processing problem, it's just string matching in 2D. In 99% of the cases, taking a line form the middle of B and matching it against each line of A will do what you want, and super fast &mdhas; I guess C# has a function for that. After you get your matches (normally, a few of them), just check the whole of B against the appropriate part of A.
The only problem I can see with this is that in some cases you can get too many matches. E.g. if A is your desktop, B is an icon, and you are unlucky enough to pick a line in B consisting of background only. This problem is easy to solve (you have to choose lines from B a bit more carefully), but this depends on the specifics of your problem.
Finding sub images in an imageFind an image in an ImageCheck if an image exists within another image
How do I compare two images & recognize the pattern in an image irrespective of its size and pattern size, and using .Net C#? Also, which algorithms are used for doing so from Image Processing?
See Scale-invariant feature transform, template matching, and Hough transform. A quick and inaccurate guess may be to make a histogram of color and compare it. If the image is complicated enough, you might be able to distinguish between several sets of images.
To make the matter simple, assume we have three buckets for R, G, and B. A completely white image would have (100%, 100%, 100%) for (R, G, B). A completely red image would have (100%, 0%, 0%). A complicated image might have something like (23%, 53%, 34%). If you take the distance between the points in that (R, G, B) space, you can compare which one is "closer".
look up pattern recognition. I known very little about it other than the name.
Warning: If that is what you want, it is one of the hardest "real world" programming problems known.
I am no expert in image recognition by I once stummbeled upon the AForge library which is written in C# and does image recognition. Maybe it can help...
Techniques for image matching and image recognition can be very different. For the first task, you may make use of SIFT or hand craft your own distance function, based on RGB or otherwise. For recognition, there a vast amount of machine learning techniques that you can use, more popular techniques involves Adaboost, SVM and other hybrid neural networks method. There are no lack of related research papers in this field. Google is your friend.
Jinmala, you've asked a question here that is extremely broad. There are literally thousands of papers in the literature about these topics. There is no correct answer, and there are many unsolved issues in the comparison of images, so you really probably can't hope for a simple solution that just works (unless your situation is quite simple and constrained)
If you narrow things down, I might be able to help.
You might be looking for this
System.Drawing.Bitmap sourceImage = (Bitmap)Bitmap.FromFile(#"C:\SavedBMPs\1.jpg");
System.Drawing.Bitmap template = (Bitmap)Bitmap.FromFile(#"C:\SavedBMPs\2.jpg");
// create template matching algorithm's instance
// (set similarity threshold to 92.5%)
ExhaustiveTemplateMatching tm = new ExhaustiveTemplateMatching(0.921f);
// find all matchings with specified above similarity
TemplateMatch[] matchings = tm.ProcessImage(sourceImage, template);
// highlight found matchings
BitmapData data = sourceImage.LockBits(
new Rectangle(0, 0, sourceImage.Width, sourceImage.Height),
ImageLockMode.ReadWrite, sourceImage.PixelFormat);
foreach (TemplateMatch m in matchings)
{
Drawing.Rectangle(data, m.Rectangle, Color.White);
MessageBox.Show(m.Rectangle.Location.ToString());
// do something else with matching
}
sourceImage.UnlockBits(data);
I warn you it is quite slow takes around 6 seconds to process image of 1024x768 finding in it pciture with the size of 50x50.enter code here
template matching, you can do this with EmguCV ,OpendotnetCV,Aforge.net
Scale-invariant feature transform (SIFT) might be what you're looking for. It's not simple to understand or implement, however.