OpenCV C ++ / Obj-C:检测一张纸/正方形检测

我在测试应用程序中成功实现了OpenCV平方检测示例,但是现在需要过滤输出,因为它很乱-还是我的代码错误?

我对减少偏斜(如那样)和进一步处理的四个角落很感兴趣……

码:

double angle( cv::Point pt1, cv::Point pt2, cv::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);

}

- (std::vector<std::vector<cv::Point> >)findSquaresInImage:(cv::Mat)_image

{

std::vector<std::vector<cv::Point> > squares;

cv::Mat pyr, timg, gray0(_image.size(), CV_8U), gray;

int thresh = 50, N = 11;

cv::pyrDown(_image, pyr, cv::Size(_image.cols/2, _image.rows/2));

cv::pyrUp(pyr, timg, _image.size());

std::vector<std::vector<cv::Point> > contours;

for( int c = 0; c < 3; c++ ) {

int ch[] = {c, 0};

mixChannels(&timg, 1, &gray0, 1, ch, 1);

for( int l = 0; l < N; l++ ) {

if( l == 0 ) {

cv::Canny(gray0, gray, 0, thresh, 5);

cv::dilate(gray, gray, cv::Mat(), cv::Point(-1,-1));

}

else {

gray = gray0 >= (l+1)*255/N;

}

cv::findContours(gray, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);

std::vector<cv::Point> approx;

for( size_t i = 0; i < contours.size(); i++ )

{

cv::approxPolyDP(cv::Mat(contours[i]), approx, arcLength(cv::Mat(contours[i]), true)*0.02, true);

if( approx.size() == 4 && fabs(contourArea(cv::Mat(approx))) > 1000 && cv::isContourConvex(cv::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);

}

}

}

}

}

return squares;

}

编辑17/08/2012:

要在图像上绘制检测到的正方形,请使用以下代码:

cv::Mat debugSquares( std::vector<std::vector<cv::Point> > squares, cv::Mat image )

{

for ( int i = 0; i< squares.size(); i++ ) {

// draw contour

cv::drawContours(image, squares, i, cv::Scalar(255,0,0), 1, 8, std::vector<cv::Vec4i>(), 0, cv::Point());

// draw bounding rect

cv::Rect rect = boundingRect(cv::Mat(squares[i]));

cv::rectangle(image, rect.tl(), rect.br(), cv::Scalar(0,255,0), 2, 8, 0);

// draw rotated rect

cv::RotatedRect minRect = minAreaRect(cv::Mat(squares[i]));

cv::Point2f rect_points[4];

minRect.points( rect_points );

for ( int j = 0; j < 4; j++ ) {

cv::line( image, rect_points[j], rect_points[(j+1)%4], cv::Scalar(0,0,255), 1, 8 ); // blue

}

}

return image;

}

回答:

这是反复出现的主题,由于我找不到相关的实现,因此决定接受挑战。

我对OpenCV中存在的squares演示进行了一些修改,下面生成的C ++代码能够检测图像中的纸:

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);

}

}

}

}

}

执行此过程后,纸页将成为以下位置中最大的正方形vector >

以上是 OpenCV C ++ / Obj-C:检测一张纸/正方形检测 的全部内容, 来源链接: utcz.com/qa/419001.html

回到顶部