Convert raster images to vector graphics using OpenCV? - opencv

I'm looking for a possibility to convert raster images to vector data using OpenCV. There I found a function cv::findContours() which seems to be a bit primitive (more probably I did not understand it fully):
It seems to use b/w images only (no greyscale and no coloured images) and does not seem to accept any filtering/error suppresion parameters that could be helpful in noisy images, to avoid very short vector lines or to avoid uneven polylines where one single, straight line would be the better result.
So my question: is there a OpenCV possibility to vectorise coloured raster images where the colour-information is assigned to the resulting polylinbes afterwards? And how can I apply noise reduction and error suppression to such a algorithm?
Thanks!

If you want to raster image by color than I recommend you to clusterize image on some group of colors (or quantalize it) and after this extract contours of each color and convert to needed format. There are no ready vectorizing methods in OpenCV.

Related

Sensible way to remove irregular noise from images which does not have proper baseline

I am trying to remove noise from a medical image file. The noise pattern in the image file is irregular. It is also hindering with the data pattern of the original image.The image shown below is in .jpeg format and it is here
in .tif format.
The noise pattern in this image is muddled with the actual data pattern which happens to the white streaks of data points in the above image. My goal is to extract the white streams of data points from the noise pool. One of the way to do so is to convert the image in to the signal domain and then masking out specific noise signal.
The image below shows the fourier transform of the image. The problem is the noise pattern is highly irregular and I am having a hard time using gaussian filter. It is not easy for me to distinguish whether I am masking actual data points or the noise patterns. Does anybody has any sort of pointers on how to use filters when the noise pattern is not defined clearly from the data points.Thanks.
Edit:
The white stream/trail of data points in red circles:

Does OpenCV have functions to handle non-linearities in sRGB color space?

I am wondering whether OpenCV has functions to handle the non-linearities in the sRGB color space.
Say I want to convert an JPEG image from sRGB color space into XYZ color space. As specified in this Wiki page, one needs to first undo the nonlinearities to convert to linear RGB space, and then multiply with the 3x3 color transform matrix. However, I couldn't find any such discussions in the cvtColor documentation. Did I miss something?
Thanks a lot in advance!
It's not explicitly stated in the documentation, so you're not missing anything, but OpenCV does not perform gamma correction in its RGB2XYZ/BGR2XYZ color conversions. You can confirm this by looking at the source code for cvtColor in
<OpenCV_dir>/modules/imgproc/src/color.cpp
If you look at the RGB <-> XYZ section you'll see that the input RGB values are simply multiplied by the coefficient matrix.
I have also not found any existing method to perform gamma correction on an RGB image.
Interestingly, a custom RGB -> XYZ conversion is done as a preliminary step for converting to both L*a*b* and L*u*v*, and in both cases it performs gamma correction.
Unfortunately, this isn't accessible from RGB2XYZ code, but you might be able to reuse it in your own code. I've also seen several code samples on the web, mostly using look-up tables for CV_8U depth images.

Sharpening image using OpenCV OCR

I've been trying to work on an image processing script /OCR that will allow me to extract the letters (using tesseract) from the boxes found in the image below.
Following alot of processing, I was able to get the picture to look like this
In order to remove the noise I inverted the image followed by floodfilling and gaussian blurring to remove noise. This is what I ended up with next.
After running it through some threholding and erosion to remove the noise (erosion being the step that distorted the text) I was able to get the image to look like this before running it through tesseract
This, while a pretty good rendering, allows for fairly accurate results through tesseract. Though it sometimes fails because it reads the hash (#) as a H or W. This leads me to my question!
Is there a way using opencv, skimage, PIL (opencv preferably) I can sharpen this image in order to increase my chances of tesseract properly reading my image? OR Is there a way I can get from the third to final image WITHOUT having to use erosion which ultimately distorted the text in the image.
Any help would be greatly appreciated!
OpenCV does has functions like filter2D that convolves arbitrary kernel with given image. In particular you can use kernels that are used for image sharpening. The main question is whether this will improve the results of your OCR library or not. The image is already pretty sharp and the noise in the image is not a result of blur. I never worked with teseract myself, but I am fairly sure that it already does all the noise reduction it could. And 'helping' him in this process may actually have opposite effect. For example any sharpening process tends to amplify noise (as opposite to noise reduction processes that usually are blurring images). Most of computer vision libraries give better results when provided with raw (unprocessed) images.
Edit (after question update):
There multiple ways to do so. The first one that I would test is this: Your first binary image is pretty clean and sharp. Instead of of using morphological operations that reduce quality of letters switch to filtering contours. Use findContours function to find all contours in the image and store their hierarchy (i.e. which contour is inside which). From all the found contours you actually need only the contours on first and second levels, i.e. outer and inner contours of each letter (contours at zero level are the outermost contours). Other contours can be discarded. Among the contours that do belong to first level you can discard those whose bounding box is too small to be a real letter. After those two discarding procedures I would expect that most of the remaining contours are the ones that are parts of the letters. Draw them on white image and run OCR. (If you want white letters on black background you will need to invert the order of vertices in the contours).

reconstructing line diagrams from JPEGs

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:

OpenCV floor detection by segmentation

I'm working on a way to detect the floor in an image. I'm trying to accomplish this by reducing the image to areas of color and then assuming that the largest area is the floor. (We get to make some pretty extensive assumptions about the environment the robot will operate in)
What I'm looking for is some recommendations on algorithms that would be suited to this problem. Any help would be greatly appreciated.
Edit: specifically I am looking for an image segmentation algorithm that can reliably extract one area. Everything I've tried (mainly PyrSegmentation) seems to work by reducing the image to N colors. This is causing false positives when the camera is looking at an empty area.
Since floor detection is the main aim, I'd say instead of segmenting by color, you could try separation by texture.
The Eigen transform paper describes a single-value descriptor of texture "roughness" using the average of eigenvalues over a grayscale window in the image/video frame. On pg. 78 of the paper they apply the mean-shift segmentation on the eigen-transform output image, effectively separating it into different textures.
Since your images are from a video feed, there can be a lot of variations in lighting so color segmentation might pose a few problems (unless you're working with HSV and other color spaces as mentioned above). The calculation of the eigenvalues is very simple and fast in OpenCV with the cvSVD() function.
If you can make the assumption about colour constancy your main issue is going to be changes in lighting that will throw off your colour detection.
To that end, convert your input image to HSV, HSL, cie-Lab, YUV or some other luminance-separated colourspace and segment your image based on just the colour part (leave out the luminance value, V, L, L and Y in the examples above). This will help you overcome the obstacle of shadows and variations in lighting.

Resources