广场检测不find正方形
我正在使用OpenCV库样本中的square.c程序。 它适用于每个图像,但我真的不知道为什么它不能识别在该图像中绘制的正方形
http://desmond.imageshack.us/Himg12/scaled.php?server=12&filename=26725680.jpg&res=medium
CANNY之后: http : //img847.imageshack.us/img847/6787/canny.jpg
DILATE之后: http : //img593.imageshack.us/img593/3010/dilate.jpg
结果图片(红色) http://img267.imageshack.us/img267/8016/resultuq.jpg
正如你所看到的,广场是不被检测到的。
检测后,我需要提取广场中包含的区域…如果没有投资回报率,怎么可能?
下面的源代码提供了Square Detector程序的一个小的变化。 这不是完美的,但它说明了解决您的问题的一种方法。
您可以将此代码与原始代码区分开来,并检查所做的所有更改,但主要的代码是:
-
减less阈值级别的数量为2 。
-
在
findSquares()
的开始处, 扩大图像以检测薄的白色正方形,然后模糊整个图像,以便algorithm不会将海和天空检测为单独的正方形。
编译完成后,使用以下语法运行应用程序: ./app <image>
// The "Square Detector" program. // It loads several images sequentially and tries to find squares in // each image #include "highgui.h" #include "cv.h" #include <iostream> #include <math.h> #include <string.h> using namespace cv; using namespace std; void help() { cout << "\nA program using pyramid scaling, Canny, contours, contour simpification and\n" "memory storage (it's got it all folks) to find\n" "squares in a list of images pic1-6.png\n" "Returns sequence of squares detected on the image.\n" "the sequence is stored in the specified memory storage\n" "Call:\n" "./squares\n" "Using OpenCV version %s\n" << CV_VERSION << "\n" << endl; } int thresh = 50, N = 2; // karlphillip: decreased N to 2, was 11. const char* wndname = "Square Detection Demo"; // helper function: // finds a cosine of angle between vectors // from pt0->pt1 and from pt0->pt2 double angle( Point pt1, Point pt2, Point pt0 ) { double dx1 = pt1.x - pt0.x; double dy1 = pt1.y - pt0.y; double dx2 = pt2.x - pt0.x; double dy2 = pt2.y - pt0.y; return (dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10); } // returns sequence of squares detected on the image. // the sequence is stored in the specified memory storage void findSquares( const Mat& image, vector<vector<Point> >& squares ) { squares.clear(); Mat pyr, timg, gray0(image.size(), CV_8U), gray; // karlphillip: dilate the image so this technique can detect the white square, Mat out(image); dilate(out, out, Mat(), Point(-1,-1)); // then blur it so that the ocean/sea become one big segment to avoid detecting them as 2 big squares. medianBlur(out, out, 7); // down-scale and upscale the image to filter out the noise pyrDown(out, pyr, Size(out.cols/2, out.rows/2)); pyrUp(pyr, timg, out.size()); 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(&timg, 1, &gray0, 1, ch, 1); // try several threshold levels for( int l = 0; l < N; l++ ) { // hack: use Canny instead of zero threshold level. // Canny helps to catch squares with gradient shading if( l == 0 ) { // apply Canny. Take the upper threshold from slider // and set the lower to 0 (which forces edges merging) Canny(gray0, gray, 0, thresh, 5); // dilate canny output to remove potential // holes between edge segments dilate(gray, gray, Mat(), Point(-1,-1)); } else { // apply threshold if l!=0: // tgray(x,y) = gray(x,y) < (l+1)*255/N ? 255 : 0 gray = gray0 >= (l+1)*255/N; } // find contours and store them all as a list findContours(gray, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE); vector<Point> approx; // test each contour 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); // square contours should have 4 vertices after approximation // relatively large area (to filter out noisy contours) // and be convex. // 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++ ) { // find the maximum cosine of the angle between joint edges double cosine = fabs(angle(approx[j%4], approx[j-2], approx[j-1])); maxCosine = MAX(maxCosine, cosine); } // if cosines of all angles are small // (all angles are ~90 degree) then write quandrange // vertices to resultant sequence if( maxCosine < 0.3 ) squares.push_back(approx); } } } } } // the function draws all the squares in the image void drawSquares( Mat& image, const vector<vector<Point> >& squares ) { for( size_t i = 0; i < squares.size(); i++ ) { const Point* p = &squares[i][0]; int n = (int)squares[i].size(); polylines(image, &p, &n, 1, true, Scalar(0,255,0), 3, CV_AA); } imshow(wndname, image); } int main(int argc, char** argv) { if (argc < 2) { cout << "Usage: ./program <file>" << endl; return -1; } // static const char* names[] = { "pic1.png", "pic2.png", "pic3.png", // "pic4.png", "pic5.png", "pic6.png", 0 }; static const char* names[] = { argv[1], 0 }; help(); namedWindow( wndname, 1 ); vector<vector<Point> > squares; for( int i = 0; names[i] != 0; i++ ) { Mat image = imread(names[i], 1); if( image.empty() ) { cout << "Couldn't load " << names[i] << endl; continue; } findSquares(image, squares); drawSquares(image, squares); imwrite("out.jpg", image); int c = waitKey(); if( (char)c == 27 ) break; } return 0; }
产出 :
我会build议你在这个图像中的广场太薄。 square.c中的第一步是在传递到Canny边缘检测器之前将图像缩小并返回以减less噪声。
缩放与5×5的内核卷积,所以在你的情况下,这可能会导致在这么薄的边缘上失去任何渐变。
如果要将它们覆盖在连续的背景上,请尝试使方块的边缘至less有5个像素。