How to get Vector data in skeletonization? - opencv

i am using opencv to track the edge of a hand on an image. Using skin color is not that reliable so we can't use contour. Using Canny edge detection match what we need because it can get most of the outline correctly. Now i want to make the information to vector so that i can improve it in the vector way. I can't use HoughLinesP because the lines are usually not straight. Dilating it gives lots of unwant random lines. I can do thinning but i don't know what next step i should do. the thinned image is still image. I need the vector data. So how do i do it?

Related

Get polygons from edges in OpenCV

I have an image I want to extract lines from (a vascular network), using the Hough line algorithm. First I preprocess the image, then use Canny edge detection to generate the binary image.
I want to get a polygon/an array of joined line segments representing the shape of the vascular network. However applying the Hough line transform directly on this image yields mediocre results, partly because edge detection means each vessel is represented by two lines on each side, instead of a single line.
I'm new to OpenCV and image processing in general, so I'm probably going about this the wrong way. Any suggestions, or any recommended literature?
I suggest not using Canny edge detection.
Instead, first use a binary threshold to get a binary image of the vascular network (see http://docs.opencv.org/3.1.0/d7/d4d/tutorial_py_thresholding.html#gsc.tab=0 for applying a binary threshold). Then, pixels that are "on" should be points inside the network and those that are "off" should be outside.
Then use the findContours method:
http://opencvexamples.blogspot.com/2013/09/find-contour.html
This method gives you an array of contours, each of which is a list of points. A list of points will represent the list of line segments you are looking for (it will represent a contour, and if you are lucky it might be a polygon!).
Hough may not be the best tool for this job. Hough will give you straight lines or other geometric shapes. It is not designed to follow a detailed pattern like this.
Given the image, I would read research papers which already solve this. Here are a few examples from a search on Google Scholar. If they don't work for you, look up the citations as they should lead you down other paths.
https://scholar.google.com/scholar?hl=en&q=retina+computer+vision+vascular
http://ijesat.org/Volumes/2012_Vol_02_Iss_04/IJESAT_2012_02_04_25.pdf
http://www.vision.cs.rpiscrews.us/publications/pdfs/shen_itbm_submitted.pdf

Detect non-closed contour on opencv

I'm doing computer vision project for automatic card detection.
I need to separate the card from the background. I have applied the canny edge detection, using automatic parameter settings from this
Automatic calculation of low and high thresholds for the Canny operation in opencv
The result is excellent. However, sometimes the canny is not perfect like this
I have applied cvFindContour to detect the box. However, due to "hole" on the upper side, opencv failed to detect the contour.
How do I tune the cvFindContour to detect the contour or should I tune the canny edge instead?
There are multiple possible solutions.
The simplest one may be:
if FindContours does not find a closed contour, repeat the canny filter with a slightly decreased low_threshold, until you find a closed contour. If the closed contour has roughly the right size and shape, it is a card. The answer linked by Haris explains how to check whether a contour is closed
Another rather simple solution:
Don't apply Canny to the image at all. Execute findContours on the otsu thresholded image. Optionally use morphological opening and closing on the thresholded image to remove noise before findContours
FindContours does not need an edge image, it is usually executed with a thresholded image. I don't know your source image, so I cannot say how good this would work, but you would definitely avoid the problem of holes in the shape.
If the source image does not allow this, then the following may help:
use watershed to separate the card from the background. Use a high threshold to get some seed pixels that are definitely foreground and a low threshold to get pixels that are definitely background, then grow those two seeds using cv:watershed().
If the background in that image is the same color as the card, then the previous two methods may not work so well. In that case, your best bet may be the solution suggested by Micka:
use hough transform to find the 4 most prominent lines in the image. Form a rectangle with these 4 lines.

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).

trapezoid fitting in OpenCV

I am using OpenCV to do segmentation using methods like grabcut, watershed. Then use findContours to obtain the contour. The actual contour I would like to obtain is a trapezoid and the functions approxPolyDP and convexHull cannot do this. Can somebody give me some hits? Maybe there are other methods rather than segmentation to obtain it? I can think of edge detection using methods like Canny but the result is not good because of unconstrained background. A lot of segments have to be connected and it is kind of hard.
The sample image is also attached (the first one--human shoulder). I would like to find the contour and the location of where the contour/edge changes its direction, that is the human shoulders. As in the second image, the right corner point can change resulting in a trapezoid.
1.jpg: original image
2.jpg: the contour is labelled by hand
3.jpg: fitted lines
https://drive.google.com/folderview?id=0ByQ8kRZEPlqXUUZyaGtpSkJDeXc&usp=sharing
Thanks.

Finding a grid in an image

Having a match-3 game screenshot (for example http://www.gameplay3.com/images/games/jewel-quest-ii-01S.jpg), what would be the correct way to find the bound box for the grid (table with tiles)? The board doesn't have to be a perfect rectangle (as can be seen in the screenshot), but each cell is completely square.
I've tried several games, and found that there are some per-game image transformations that can be done to enhance the tiles inside the grid (for example in this game it's enough to take the V channel out of HSV color space). Then I can enlarge the tiles so that they overlap, find the largest contour of the image and get the bound box from it.
The problem with above approach is that every game (or even level inside the same game) may need a different transformation to get hold of the tiles. So the question is - is there a standard way to enhance either tiles inside the grid or grid's lines (I've tried finding lines with Hough transform, but, although the grid seems pretty visible to the eye, Hough doesn't find it)?
Also, what if the screenshot is obtained using the phone camera instead of taking a screenshot of a desktop? From my experience, captured images have less defined colors (which depends on lighting), and also can be distorted a little, as there is no way to hold the phone exactly in front of the screen.
I would go with the following approach for a screenshot:
Find corners in the image using for example a canny like edge detector.
Perform a hough line transform. This should work quite nicely on the edge image.
If you have some information about size of the tiles you could eliminate false positive lines using some sort of spatial model of the grid (eg. lines only having a small angle to x/y axis of the image and/or distance/angle of tile borders.
Identifiy tile borders under the found hough lines by looking for edges found by canny under/next to the lines.
Which implementation of the hough transform did you use? How did you preprocess the image?
Another approach would be to use some sort of machine learning approach. As you are working in OpenCV you could use either a Haar like feature detector. An example for face detection using Haar like features can be found here:
OpenCV Haar Face Detector example
Another machine learning approach would be to follow a Histogram of Oriented Gradients (Hog) approach in combination with a Support Vector Machine (SVM). An example is located here:
HOG example
You can find general information about HoG detection at:
Hog detection

Resources