1

I'm trying to extract the sub-images in this image

Binary Thresholding at 250 image

Contours image

As you can see, it's not prefect and it is picking up some things that aren't square shaped. Here is the code:

Mat src; Mat src_gray;
int thresh = 250;
int max_thresh = 255;
RNG rng(12345);

/// Function header
void thresh_callback(int, void*);

 /** @function main */
int main(int argc, char** argv)
{
/// Load source image and convert it to gray
src = imread("Media/RoadSignRecognitionUnknownSigns/RoadSignsComposite1.JPG", 1);

/// Convert image to gray and blur it
cvtColor(src, src_gray, CV_BGR2GRAY);
blur(src_gray, src_gray, Size(3, 3));

/// Create Window
char* source_window = "Source";
namedWindow(source_window, CV_WINDOW_AUTOSIZE);
imshow(source_window, src);

createTrackbar(" Threshold:", "Source", &thresh, max_thresh, thresh_callback);
thresh_callback(0, 0);

waitKey(0);
return(0);
}

/** @function thresh_callback */
void thresh_callback(int, void*)
{
Mat threshold_output;
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;

/// Detect edges using Threshold
threshold(src_gray, threshold_output, thresh, 255, THRESH_BINARY);
imshow("threshold_output", threshold_output);
/// Find contours
findContours(threshold_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE,     Point(0, 0));

/// Approximate contours to polygons + get bounding rects and circles
vector<vector<Point> > contours_poly(contours.size());
vector<Rect> boundRect(contours.size());
vector<Point2f>center(contours.size());
vector<float>radius(contours.size());

for (int i = 0; i < contours.size(); i++)
{
    approxPolyDP(Mat(contours[i]), contours_poly[i], 3, true);
    boundRect[i] = boundingRect(Mat(contours_poly[i]));
    minEnclosingCircle((Mat)contours_poly[i], center[i], radius[i]);
}


/// Draw polygonal contour + bonding rects + circles
Mat drawing = Mat::zeros(threshold_output.size(), CV_8UC3);
for (int i = 0; i< contours.size(); i++)
{
    Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
    drawContours(drawing, contours_poly, i, color, 1, 8, vector<Vec4i>(), 0, Point());
    rectangle(drawing, boundRect[i].tl(), boundRect[i].br(), color, 2, 8, 0);
    circle( drawing, center[i], (int)radius[i], color, 2, 8, 0 );
}

/// Show in a window
namedWindow("Contours", CV_WINDOW_AUTOSIZE);
imshow("Contours", drawing);
for (int i = 0; i < boundRect.size(); i++)
{
    Mat patch = src(boundRect[i]);
    //boundRect[i]
    //Do whatever you want with the patch (imshow, imwrite,...)
    imshow("Patch", patch);
}

for (int i = 0; i < boundRect.size(); i++){
    //int n = 1;// Here you will need to define n differently (for instance pick the largest     contour instead of the first one)
    cv::Rect rect(boundRect[i]);
    cv::Mat miniMat;
    miniMat = src(rect);
    imshow(""+to_string(i), miniMat);
}
}

How can I make the shape detection better, please?

2
  • Are you trying to detect the sign from this image? or simply finding the image you cropped already? Commented Dec 9, 2014 at 10:00
  • @BalajiR Yes that its what I'm eventually going to do. So I'm taking the pics out separately. Commented Dec 9, 2014 at 11:31

2 Answers 2

1

Here is the Procedure to detect the Sign from the Image:

  1. Convert the Image to HSV format.
  2. Extract the Red component from the image HSV - H Range(0-10) && (170-180).
  3. Dilate , Erode the Binary Red Mask to find the Border.
  4. Find contour With RETR_EXTERNAL flag to extract only outer contours & Find the Bounding Box of that contour.
  5. Filter the Contour based on Known properties of sign board such as Circular, Triangular, Area, Center of Mass, Moments etc...
  6. Create a Sign Mask image of Size equivalent to the Size of Bounding Box & Draw the Filled Contour in the Mask.
  7. Set the ROI of the Input Image to Bounding box Rect.
  8. To Extract Sign Board Perform bit wise And Input with Sign Mask image.
  9. Resize the Image to a constant Size lets say 100x100 & Perform Template Matching/ Any other matching algorithm. Also refer this sample demo for further reference. https://sites.google.com/site/mcvibot2011sep/
Sign up to request clarification or add additional context in comments.

Comments

1

If your images are disjoint as in your example, you can simply compute 2d bounding boxes of every connected components in your binary thresholding. If they are almost disjoint then you can do an erosion first.

2 Comments

Thanks but how do I do that pls?
To compute connected components, you take the graph whose vertices are black pixels and edges are pairs of adjacent pixels. Then every connected comp. in this graph gives you a set of pixels and you get their bounding boxes by finding their min/max x and y.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.