3
votes

Hi I am working on computer vision project and trying to detect square by using openCV/C++ from camera. I had download the source code from openCV library but it seems like losing fps so hard. Does anybody have idea how to fix this problem? There is a video link about my testing below, check it out: http://magicbookproject.blogspot.co.uk/2012/12/detect-paper-demo.html

Here is the code and just found on another post:

void find_squares(Mat& image, vector<vector<Point> >& squares)
{
// blur will enhance edge detection
Mat blurred(image);
medianBlur(image, blurred, 9);

Mat gray0(blurred.size(), CV_8U), gray;
vector<vector<Point> > contours;

// find squares in every color plane of the image
for (int c = 0; c < 3; c++)
{
    int ch[] = {c, 0};
    mixChannels(&blurred, 1, &gray0, 1, ch, 1);

    // try several threshold levels
    const int threshold_level = 2;
    for (int l = 0; l < threshold_level; l++)
    {
        // Use Canny instead of zero threshold level!
        // Canny helps to catch squares with gradient shading
        if (l == 0)
        {
            Canny(gray0, gray, 10, 20, 3); // 

            // Dilate helps to remove potential holes between edge segments
            dilate(gray, gray, Mat(), Point(-1,-1));
        }
        else
        {
                gray = gray0 >= (l+1) * 255 / threshold_level;
        }

        // Find contours and store them in a list
        findContours(gray, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);

        // Test contours
        vector<Point> approx;
        for (size_t i = 0; i < contours.size(); i++)
        {
                // approximate contour with accuracy proportional
                // to the contour perimeter
                approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*0.02, true);

                // Note: absolute value of an area is used because
                // area may be positive or negative - in accordance with the
                // contour orientation
                if (approx.size() == 4 &&
                        fabs(contourArea(Mat(approx))) > 1000 &&
                        isContourConvex(Mat(approx)))
                {
                        double maxCosine = 0;

                        for (int j = 2; j < 5; j++)
                        {
                                double cosine = fabs(angle(approx[j%4], approx[j-2], approx[j-1]));
                                maxCosine = MAX(maxCosine, cosine);
                        }

                        if (maxCosine < 0.3)
                                squares.push_back(approx);
                }
        }
    }
}

}

2
Can you show us some code... are you working from the squares sample supplied with the source?foundry
Here is, any advice please? I know its for image and how could change it a little bit and then its would work for camera.user1959079

2 Answers

3
votes

You can speed it up if you don't mind losing accuracy. For example

// find squares in every color plane of the image
for (int c = 0; c < 3; c++)

You are looping through three color planes. Just examine one color (as if the image is grayscale), that should triple the speed.

Also try without Canny, which is quite slow. Set a use_canny parameter,

 if (l == 0 && use_canny)
     {
        Canny(gray0, gray, 10, 20, 3); // 

Compare with and without. I am getting acceptable results, considerably faster.

1
votes

A good rule of thumb for computer vision is to convert your image to grayscale before doing any intensive processing. Only loop through color channels if you find it absolutely necessary. I recommend the following pattern for object recognition:

  1. Convert image to grayscale
  2. Filter grayscale image to a simpler format (canny, threshold, edge-detect)
  3. Do heavy processing (detect square shapes)
  4. Reconstruct original image with the processed values (draw/store your squares)

Remember that you are doing all these steps for each and every frame, so be sure to remove whatever you find is unnecessary. Since this code will run so often, you will see huge performance benefits from even a minor optimization, so it's worth spending some time optimizing.