I am trying to use an binarize images similar to the following image:
Basically, I want all non white to become black but threshold in OpenCV is giving fringing (JPEG Artifacts). I even tried Otsu thresholding but some parts of the colors don't work so well.
Is there any simple way of doing this binarization properly?
Turn to greyscale, apply 5x5 blur filter, and binarize? The blur will smooth the ringing artifacts.
After quite some trial and error, turns out Morphological Closing before thresholding using a large value turns out to be most suitable for the next stage of what I am working on. But it does cause some loss of shape info.
Given that you have to use JPEG for this project, the one thing you can do use all one quantization tables. That is usually done through "quality" settings. You want an encoder that will allow you to do no quantization.
Related
I am using OpenCV to blend a set of pre-warped images. As input I have some 4-channel images (*.png or *.tif) from where I can extract a bgr image and an alpha mask with the region related to the image (white) and the background (black). Both image and mask are the inputs of the Blender module cv::detail::Blender::blend.
When I use feather (alpha) blending the result is ok, however, I would like to avoid ghosting effects. When I use multi-band, some artifacts are appearing on the edges of the images:
The problem is similar to the one raised here, and solved here. The thing is, if the solution is creating a binary mask (that I already extract from the alpha channel), it does not work for me. If I add padding to the ovelap between both images, it takes pixels from the background and messes up even more the result.
I guess that probably it has to do with the functions pyrUp and pyrDown, because maybe the blurring to create the Gaussian and Laplacian pyramids is applied to the whole image, and not only to the positive alpha region. In any case, I don't know how to fix the problem using these functions, and I cannot find another efficient solution.
When I use another implementation of multiresolution blending, it works perfectly, however, I am very interested in integrating the multi-band implementation of OpenCV. Any idea of how to fix this issue?
Issue has been already reported and solved here:
http://answers.opencv.org/question/89028/blending-artifacts-in-opencv-image-stitching/
I'm trying to do OCR to some forms that, however, have some texture as follows:
This texture causes the OCR programs to ignore it tagging it as an image region.
I considered using morphology. A closing operation with a star ends up as follows:
This result is still not good enough for the OCR.
When I manually erase the 'pepper' and do adaptive thresholding an image as follows gives good results on the OCR:
Do you have any other ideas for the problem?
thanks
For the given image, a 5x5 median filter does a little better than the closing. From there, binarization with an adaptive threshold can remove more of the background.
Anyway, the resulting quality will depend a lot on the images and perfect results can't be achieved.
Maybe have a look at this: https://code.google.com/p/ocropus/source/browse/DIRS?repo=ocroold (see ocr-doc-clean).
Considering that you know the font size, you could also consider using connected component filtering, perhaps in combination with a morphological operation. To be able to retain the commas, just be careful if a smaller connected component is near one that has a size similar to the characters that you are trying to read.
The background pattern is very regular and directionnal, so filtering in the Fourier domain must do some pretty good job here. Try for example the Butterworth filter
A concrete example of such filtering using gimp can be found here
I'm working with Infra Red image that is an output of a 3D sensor. This sensors project a Infra Red pattern in order to draw a depth map, and, because of this, the IR image has a lot of white spots that reduce its quality. So, I want to process this image to make it smoother in order to make it possible to detect objects laying in the surface.
The original image looks like this:
My objective is to have something like this (which I obtained by blocking the IR projecter with my hand) :
An "open" morphological operation does remove some noise, but I think first there should be some noise removal operation that addresses the white dots.
Any ideas?
I should mention that the algorithm to reduce the noise has to run on real time.
A median filter would be my first attempt .... possibly followed by a Gaussian blur. It really depends what you want to do with it afterwards.
For example, here's your original image after a 5x5 median filter and 5x5 Gaussian blur:
The main difficulty in your images is the large radius of the white dots.
Median and morphologic filters should be of little help here.
Usually I'm not a big fan of these algorithms, but you seem to have a perfect use case for a decomposition of your images on a functional space with a sketch and an oscillatary component.
Basically, these algorithms aim at solving for the cartoon-like image X that approaches the observed image, and that differs from Y only through the removal of some oscillatory texture.
You can find a list of related papers and algorithms here.
(Disclaimer: I'm not Jérôme Gilles, but I know him, and I know that
most of his algorithms were implemented in plain C, so I think most of
them are practical to implement with OpenCV.)
What you can try otherwise, if you want to try simpler implementations first:
taking the difference between the input image and a blurred version to see if it emphasizes the dots, in which case you have an easy way to find and mark them. The output of this part may be enough, but you may also want to fill the previous place of the dots using inpainting,
or applying anisotropic diffusion (like the Rudin-Osher-Fatemi equation) to see if the dots disappear. Despite its apparent complexity, this diffusion can be implemented easily and efficiently in OpenCV by applying the algorithms in this paper. TV diffusion can also be used for the inpainting step of the previous item.
My main point on the noise removal was to have a cleaner image so it would be easier to detect objects. However, as I tried to find a solution for the problem, I realized that it was unrealistic to remove all noise from the image using on-the-fly noise removal algorithms, since most of the image is actually noise.. So I had to find the objects despite those conditions. Here is my aproach
1 - Initial image
2 - Background subtraction followed by opening operation to smooth noise
3 - Binary threshold
4 - Morphological operation close to make sure object has no edge discontinuities (necessary for thin objects)
5 - Fill holes + opening morphological operations to remove small noise blobs
6 - Detection
Is the IR projected pattern fixed or changes over time?
In the second case, you could try to take advantage of the movement of the dots.
For instance, you could acquire a sequence of images and assign each pixel of the result image to the minimum (or a very low percentile) value of the sequence.
Edit: here is a Python script you might want to try
I wish to recreate characters and graphics primitives from JPEG images. Although the JPEG tranformation is lossy, because the original is (probably) monochrome with well defined primitives it can be largely reconstructed. I would like algorithms or heuristics that could enhance the signal to noise. This is a typical example:
I have applied the Canny edge detection algorithm and get good recognition of the edges of the numbers but this also includes noise:
I have tried to eliminate the background by binning into black and white at half-intensity which gives:
with the background removed but poorer outlines.
I can try heuristic solutions but this will take time and be arbitrary and so I would like to know if there are already solutions.
NOTE: A similar but not duplicate question relates to subpixel rendering which requires a completely different approach.
Ok, not strictly an answer, but just showing an example of what I mean by removing noise before edge detection.
The following sequence uses your original image and by using ImageJ, with auto-selection of parameters, I did the following:
Converted RGB original to 8-bit greyscale (removed most background).
Auto-threshold of greyscale equivalent.
Convert to binary.
Trace outline and invert result.
Maybe this would be a better starting point - the sequence below shows your original, the output from step 2 and the output from step 4:
What's the best set of image preprocessing operations to apply to images for text recognition in EmguCV?
I've included two sample images here.
Applying a low or high pass filter won't be suitable, as the text may be of any size. I've tried median and bilateral filters, but they don't seem to affect the image much.
The ideal result would be a binary image with all the text white, and most of the rest black. This image would then be sent to the OCR engine.
Thanks
There's nothing like the best set. Keep in mind that digital images can be acquired by different capture devices and each device can embed its own preprocessing system (filters) and other characteristics that can drastically change the image and even add noises to them. So every case would have to be treated (preprocessed) differently.
However, there are commmon operations that can be used to improve the detection, for instance, a very basic one would be to convert the image to grayscale and apply a threshold to binarize the image. Another technique I've used before is the bounding box, which allows you to detect the text region. To remove noises from images you might be interested in erode/dilate operations. I demonstrate some of these operations on this post.
Also, there are other interesting posts about OCR and OpenCV that you should take a look:
Simple Digit Recognition OCR in OpenCV-Python
Basic OCR in OpenCV
Now, just to show you a simple approach that can be used with your sample image, this is the result of inverting the color and applying a threshold:
cv::Mat new_img = cv::imread(argv[1]);
cv::bitwise_not(new_img, new_img);
double thres = 100;
double color = 255;
cv::threshold(new_img, new_img, thres, color, CV_THRESH_BINARY);
cv::imwrite("inv_thres.png", new_img);
Try morphological image processing. Have a look at this. However, it works only on binary images - so you will have to binarize the image( threshold?). Although, it is simple, it is dependent on font size, so one structure element will not work for all font sizes. If you want a generic solution, there are a number of papers for text detection in images - A search of this term in google scholar should provide you with some useful publications.