用opencv提取几何形式

时间:2013-07-19 11:08:54

标签: c++ opencv image-processing

我正在运行一个视频,其中我要检测3个几何形状的三角形圆和五边形,没有别的,这里是这个视频的框架和我得到的结果:

source

正确的结果

correct result

许多人的一个不好的结果。

Bad result

这是我的代码:

img =src;
cv::Moments mom;
cv::Mat result(img.size(),CV_8U,cv::Scalar(255));
cv::threshold(img,img,127,255,CV_THRESH_BINARY_INV);
cv::findContours(img,contours,/*hiararchy,*/CV_RETR_LIST, CV_CHAIN_APPROX_NONE );
for ( int i=0; i<contours.size();i++){
    cv::approxPolyDP(cv::Mat(contours[i]),approx,(cv::arcLength(cv::Mat(contours[i]),true)*.02),true);
switch(approx.size()){

            case 8: // should be a circle 
                cv::minEnclosingCircle(cv::Mat(contours[i]),center,radius);
                cv::circle(src,cv::Point(center),static_cast<int> (radius),cv::Scalar(255,255,0),3,3);
                mom= cv::moments(cv::Mat(contours[i]));
            // draw mass center
            cv::circle(result,
            // position of mass center converted to integer
                cv::Point(mom.m10/mom.m00,mom.m01/mom.m00),
            2,cv::Scalar(0,0,255),2);// draw black dot 
                break;

case 3: // should be a triangle 
                poly.clear();
                    cv::approxPolyDP(cv::Mat(contours[i]),poly,
                    5, // accuracy of the approximation
                    true); // yes it is a closed shape
                    // Iterate over each segment and draw it
                    itp= poly.begin();
                while (itp!=(poly.end()-1)) {
                    cv::line(src,*itp,*(itp+1),cv::Scalar(0,255,255),2);
                    ++itp;
                    }
                // last point linked to first point
                cv::line(src,*(poly.begin()),*(poly.end()-1),cv::Scalar(100,255,100),2);
                mom= cv::moments(cv::Mat(contours[i]));
                // draw mass center
                cv::circle(result,
                // position of mass center converted to integer
                cv::Point(mom.m10/mom.m00,mom.m01/mom.m00),
                2,cv::Scalar(0,0,255),2);// draw black dot 
                    break;
            case 5 :// should be a pentagon
                poly.clear(); 
                    cv::approxPolyDP(cv::Mat(contours[i]),poly,
                    5, // accuracy of the approximation
                    true); // yes it is a closed shape
                // Iterate over each segment and draw it
                itp= poly.begin();
                while (itp!=(poly.end()-1)) {
                    cv::line(src,*itp,*(itp+1),cv::Scalar(0,0,255),2);
                    ++itp;
                }
                // last point linked to first point
                    cv::line(src,*(poly.begin()),*(poly.end()-1),cv::Scalar(255,0,0),2);
                    mom= cv::moments(cv::Mat(contours[i]));
            // draw mass center
            cv::circle(result,
            // position of mass center converted to integer
                cv::Point(mom.m10/mom.m00,mom.m01/mom.m00),
            2,cv::Scalar(0,0,255),2);// draw black dot 
                    break;

            default : 
                contours[i].clear();
        }
// iterate over all contours
        int j = 0;
        for( int i = 0; i < contours.size();i++) {
            if ( !contours[i].empty()){
            // compute all moments

            j++; // At the end  j should be 3 
    }
            if(j ==3 ){
        cv::drawContours(result,contours,-1, // draw all contours 
            cv::Scalar(0), // in black
            2); // with a thickness of 2
        cv::imshow("result",result);
            }
}   std::cout<<j<<std::endl;


    return j;
}

知道如何解决这个问题吗? 谢谢!

1 个答案:

答案 0 :(得分:0)

如果几何形状总是位于这样的棋盘图案中,并且形状在该图案中始终具有相同的尺寸和方向,我会:

  1. 检测棋盘图案。
  2. 使用单应性删除透视变形
  3. 缩放并旋转,使棋盘图案轴对齐并以给定比例
  4. 使用倒角匹配来检测指定的形状。