I'm trying to detect and fine-locate some objects in images from contours. The contours that I get often include some noise (maybe form the background, I don't know). The objects should look similar to rectangles or squares like:
I get very good results with shape matching (cv::matchShapes
) to detect contours with those objects in them, with and without noise, but I have problems with the fine-location in case of noise.
Noise looks like:
My idea was to find convexity defects and if they become too strong, somehow crop away the part that leads to concavity. Detecting the defects is ok, typically I get two defects per "unwanted structure", but I'm stuck on how to decide what and where I should remove points from the contours.
Here are some contours, their masks (so you can extract the contours easily) and the convex hull including thresholded convexity defects:
Could I just walk through the contour and locally decide whether a "left turn" is performed by the contour (if walking clockwise) and if so, remove contour points until the next left turn is taken? Maybe starting at a convexity defect?
I'm looking for algorithms or code, programming language should not be important, algorithm is more important.
This approach works only on points. You don't need to create masks for this.
The main idea is:
I get the following results. As you can see, it has some drawbacks for smooth defects (e.g. 7th image), but works pretty good for clearly visible defects. I don't know if this will solve your problem, but can be a starting point. In practice should be quite fast (you can surely optimize the code below, specially the
removeFromContour
function). Also, the only parameter of this approach is the amount of the convexity defect, so it works well with both small and big defecting blobs.UPDATE
Working on an approximated contour (e.g. using
CHAIN_APPROX_SIMPLE
infindContours
) may be faster, but the length of contours must be computed usingarcLength()
.This is the snippet to replace in the swapping part of
removeFromContour
: