More accurate houghline OpenCV - c++

I have been working with houghlines in OpenCV and I cant seem to get a more accurate line reading, sometimes there are two duplicate lines on top of each other. I have looked at tutorial on the opencv website but it gives a similar result.

To remove those duplicate lines, there are two things that may help you:
Double edges may appear that may lead to duplicate lines. A sequence of blurring/dilating the input image would solve these issues.
Close lines that have almost same slope can be removed by using lower angle resolutions for the theta argument of Hough Line method. For example using π/180 would result in finding lines that differ only by one degree in their slope. You may use 5*π/180 to find lines in 5 degree resolution.
As an example, the following lines are detected by using the raw image and a 1-degree resolution:
After a bit of blurring and using a 3-degree resolution you can get a result like the following:
By changing the threshold, you can get more or less lines.
About fitting curves you pointed in the comments section, yes you can fit curves, but not with hough lines method. You need to find a parametric definition of that shape and try to run the voting procedure in hough transform yourself. The only other shape that opencv helps you to find is circle.

Related

OpenCV Detect "Splotchy" Lines

I am attempting to use OpenCV to detect "splotchy" lines in a binary image. I have an image like the one below and would like to robustly detect the three roughly vertical lines of splotches. HoughLines does a decent job, but often fails if only a few of the white pixels in the splotches are perfectly colinear. I've also tried Generalized Hough transform functions, but they aren't much better.
What I would like to be able to do is have HoughLines perform the Hough transform and give me the image in the Hough space (where each pixel value represents the votes for a particular rho and theta). That way I could look for high density regions instead of peaks, as those regions may better represent the lines I'm looking for.
I can't seem to find a way to get the raw Hough space image however. Is it possible?
Are there better ways to detect splotchy lines like this?
As a side note, I would like to do this all on a GPU, so functions with a 'cv::cuda::` api would be best.

Detecting the locations of circles and crosses in an image

I'm new to OpenCV and was wondering if anybody could direct me to the most suitable algorithm(s) to tackle the challenge of identifying the locations of circles and crosses in images that look like the following . .
[
Sometimes there are lines connecting . .
[
They might even be hand drawn like this one . .
So far I have looked at the template matching example, but it is probably not the correct approach, and it doesn't scale the sizes of the templates to the images.
So given the following observations . . .
The crosses and circles may overlap.
If the diagram is in colour,
the colours will be identical for crosses and identical for circles.
Sometimes they will be joined by lines, sometimes not.
There may be other shape symbols in the plots
They symbols will be of similar size and shape, but might not be computer generated, so will not necessarily be identical.
Where should I begin my adventure?
Not an easy task.
For the colored case, you should start by separating the color planes. There is some chance that you can get the markers apart.
But for the b&w case, there is no escape, you must go deeper.
I would try to detect the grid lines first, for example using a Hough line detector, as accurately as possible. Then erase those lines.
Then try to find the crosses, which are short oblique line segments (most of the time broken by the previous operations).
The circles might be detected by a Hough circle detector, using a small range of radii.
Alternatively, a rige or edge detector can be used to get short segments and short curved arcs. You may have to add some filtering criteria to avoid the joining lines.
Like said, it's not a easy task.
One of possible way could be machine learning. I think of cascade classifier (aka Viola Jones method) that pretty nice for detection of object. It's pretty easy to implement with openCV but it need to understand how it works and a large amount of sample.
You can try to use couple of ideas:
1) FFT can help to remove grid. Something like this.
2) Markers (crosses and circles) are the objects with angle of gradient, that differs from right angles. It may help to localize them.

OpenCV: finding the coordinates of intersections of lines in the photo

I'm just starting to learn OpenCV programming. I would like to know if it is possible to get coordinates of intersections of lines (veins) from this photo.
http://mormometricanalysis.wu.cz/photo.JPG
In the photo there are marked needed points with the red colour. I want to calculate angles between lines, length of lines and area - examples below.
http://mormometricanalysis.wu.cz/
I have done some research about this problematic. But mostly the examples were about finding lines in a binary image - I don't know if I can make quality binary image from this photo in OpenCV. Computation of coordinates of points should be as precise as it can be.
Is there any function in OpenCV to do that? Do you have any idea how to solve this?
Thank you in advance for your answers.
I have to pass on the finding intersections part, but in order to get a binary image, your first step should be the following:
Treshold the image. This should work fine, if the contrast is always as high as in the example. Alternatively try edge detection.
As for finding lines that fit the veins I have a vague idea. Let me try to put it in words:
Try to find an area of high density in the binary image and determine the center [x1,y1].
Define a line with one fixed point in the center of this area f(x-x1) = m*x + y1
Rotate the line by varying m and optimize for a maximum correlation between the binary image of the line and the binary image of the veins
When you found the maximum of the correlation, cut the section of the line, that actually overlaps with a vein
Repeat with the next center of high density
This might/should give you a bunch of parametrically defined lines where you can easily determine the intersections and angles.

What is the simplest *correct* method to detect rectangles in an image?

I am trying to think of the best method to detect rectangles in an image.
My initial thought is to use the Hough transform for lines, and to select combinations of lines where you have two lines intersected at both the lower portion and upper portion by the same two lines, but this is not sufficient.
Would using a corner detector along with the Hough transform work?
Check out /samples/c/squares.c in your OpenCV distribution. This example provides a square detector, and it should be a pretty good start.
My answer here also applies.
I don't think that currently there exists a simple and robust method to detect rectangles in an image. You have to deal with many problems such as the rectangles not being exactly rectangular but only approximately, partial occlusions, lighting changes, etc.
One possible direction is to do a segmentation of the image and then check how close each segment is to being a rectangle. Since you can't trust your segmentation algorithm, you can run it multiple times with different parameters.
Another direction is to try to parametrically fit a rectangle to the image such that the image gradient magnitude along the contour will be maximized.
If you choose to work on a parametric approach, notice that while the trivial way to parameterize a rectangle is by the locations of it's four corners, which is 8 parameters, there are a few other representations that require less parameters.
There is an extension of Hough that can be useful.
http://en.wikipedia.org/wiki/Generalised_Hough_transform

Detecting curves in OpenCV

I am just starting to use OpenCV to detect specific curves in an image. First, I want to verify if there is a curve, and next, I would like to identify the type of curve according to vertical or horizontal convex or concave curve. Is there an available function in OpenCV? If not, can you give me some ideas about how can I possibly write such a function? Thanks! By the way, I'm using C++.
Template matching is not a robust way to solve this problem (its like looking at an object from a small pinhole) and edge detectors don't necessarily return you the true edges in the image; false edges such as those due to shadows are returned too. Further, you have to deal with the problem of incomplete edges and other problems that scales up with the complexity of the scene in your image.
The problem you posed, in general, is a very challenging one and, except for toy examples, there are no good solutions.
A rough attempt could be to first try to detect plausible edges using an edge detector (e.g. the canny edge detector suggested). Next, use RANSAC to try to fit a subset of the points in the detected edges to your curve model.
For e.g. let's say you are trying to detect a curve of the following form f(x) = ax^2 + bx + c. RANSAC will basically try to find from among the points in the detected edges, a subset of them that would best fit this curve model. To detect different curves, change f(x) accordingly and run RANSAC for each of them. You can then try to determine if the curve represented by f(x) really exists in your image using some heuristic applied to from the points that were assigned to it by RANSAC (e.g. if too few points were fitted to the model it is likely that the curve is not there. But how to determine a good threshold for the number of points?). You model will get more complex when you have to account for allowable transformation such as rotation etc.
The problem with this approach is you are basically trying fit what you think should be in the image to the points and sometimes, even if what you are looking for is not there, it will return you the "best possible" fit. For e.g. you have a whole bunch of points detected from a concentric circle. If you try to detect straight lines from these points, RANSAC will return you the best fit line! In fact, it could give you many different lines from different runs depending on which points it selected during its random initialization stage.
For more details on how to use RANSAC on this sort of problem, have a look at RANSAC for Dummies by Marco Zuliani. He also has a nice MATLAB toolbox to accompany this tech report, which you can probably port to the language of your choice.
Unless you know what you background looks like, or if you are in control of it e.g. by forcing a clean background, this is a very difficult problem to solve.