[OpenCV 提取矩形轮廓]

冒泡泡的绿色颜料 2014-05-06 10:38:27
[OpenCV 提取矩形轮廓]
在VS2008平台下,用OpenCV图像处理。
问题:怎样提取图像中的特定的某一个矩形轮廓?进而求得矩形芯片中心点(如图中芯片中间的黑点)。

它不是最外层轮廓,除它外还有一个矩形轮廓和三四个圆形轮廓。
实物拍摄,不是标准的形状。

...全文
1813 2 打赏 收藏 转发到动态 举报
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2014-05-06
  • 打赏
  • 举报
回复
仅供参考:
double angle( Point pt1, Point pt2, Point pt0 ) {// finds a cosine of angle between vectors from pt0->pt1 and from pt0->pt2
    double dx1 = pt1.x - pt0.x;
    double dy1 = pt1.y - pt0.y;
    double dx2 = pt2.x - pt0.x;
    double dy2 = pt2.y - pt0.y;
    double ratio;//边长平方的比
    ratio=(dx1*dx1+dy1*dy1)/(dx2*dx2+dy2*dy2);
    if (ratio<0.8 || 1.2<ratio) {//根据边长平方的比过小或过大提前淘汰这个四边形,如果淘汰过多,调整此比例数字
//      Log("ratio\n");
        return 1.0;//根据边长平方的比过小或过大提前淘汰这个四边形
    }
    return (dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10);
}
void findSquares( const Mat& gray0, vector<vector<Point> >& squares ) {// returns sequence of squares detected on the gray0. the sequence is stored in the specified memory storage
    squares.clear();

    Mat pyr,gray1,timg;

    // down-scale and upscale the gray0 to filter out the noise
    pyrDown(gray0, pyr, Size(gray0.cols/2, gray0.rows/2));
    pyrUp(pyr, timg, gray0.size());
    vector<vector<Point> > contours;

    // 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 ) {//可试试不对l==0做特殊处理是否能在不影响判断正方形的前提下加速判断过程
//          // apply Canny. Take the upper threshold from slider
//          // and set the lower to 0 (which forces edges merging)
//          Canny(timg, gray1, 0, thresh, 5);
//          // dilate canny output to remove potential
//          // holes between edge segments
//          dilate(gray1, gray1, Mat(), Point(-1,-1));
//      } else {
            // apply threshold if l!=0:
            //     tgray(x,y) = gray1(x,y) < (l+1)*255/N ? 255 : 0
            gray1 = timg >= (l+1)*255/N;
//      }

        // find contours and store them all as a list
        findContours(gray1, 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);//0.02为将毛边拉直的系数,如果对毛边正方形漏检,可试试调大

            // 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 && isContourConvex(Mat(approx))) {
                double area;
                area=fabs(contourArea(Mat(approx)));
                if (4000.0<area && area<30000.0) {//当正方形面积在此范围内……,如果有因面积过大或过小漏检正方形问题,调整此范围。
//                  printf("area=%lg\n",area);
                    double maxCosine = 0.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 (maxCosine==1.0) break;// //边长比超过设定范围
                    }

                    // if cosines of all angles are small
                    // (all angles are ~90 degree) then write quandrange
                    // vertices to resultant sequence
                    if (maxCosine < 0.1 ) {//四个角和直角相比的最大误差,可根据实际情况略作调整,越小越严格
                        squares.push_back(approx);
                        return;//检测到一个合格的正方形就返回
//                  } else {
//                      Log("Cosine>=0.1\n");
                    }
                }
            }
        }
    }
}
  • 打赏
  • 举报
回复
腐蚀和膨胀、 平滑滤波、 灰度化、 cvThreshold 二值化、 canny 边缘检测、 cvFindContours查找物体轮廓 已经有相关代码实现,但是结果不理想。 请问各位,怎样查找特定轮廓?或者全部轮廓? 看过关于cvFindContours函数的解释,但是具体实现不是很懂,知道的请解答。 以下为查找最外层轮廓的代码,有输出轮廓数目,但是没有轮廓重绘,出错。各位仔细看看,帮忙分析一下。 //查找轮廓,重绘 IplImage *Countours(IplImage *img) { int i=0; int mode; //提取轮廓的模式 int contours_num=0;//图像中提取轮廓的数目 CvMemStorage *storage=cvCreateMemStorage(0); //设置轮廓时需要的存储容器 CvSeq *contour =0; //设置存储提取的序列指针 IplImage *img=cvLoadImage("F:\\image\\lena_color.png" ,0); cvThreshold(img,img,128,255,CV_THRESH_BINARY); //二值化 IplImage *pContourImg = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U,3); //cvNamedWindow("windows",1); cvShowImage("windows",img);//显示二值图 //cvFindContours查找物体轮廓 mode = CV_RETR_EXTERNAL;//提取物体最外层轮廓 contours_num=cvFindContours(img,storage,&contour, sizeof(CvContour),mode,CV_CHAIN_APPROX_NONE); cout<<"检测出的轮廓数目为:"<<contours_num<<" "<<endl; //逐点将轮廓画出 CvSeqReader reader;//读序列 int count=0; if (contour!=0) { count=contour->total; cout<<count<<endl; } cvStartReadSeq(contour,&reader,0); CvPoint pt1; CvScalar color=CV_RGB(255,255,255); cvNamedWindow("contour",1); cvShowImage("contour",pContourImg); //轮廓重绘 for (i=0;i<count;i++) { CV_READ_SEQ_ELEM(pt1,reader);//读出一个点 cvCircle(pContourImg,pt1,1,color);//画出一个点(就是一个以一个像素大小为半径的圆) cvShowImage("contour",pContourImg); cvWaitKey(5); } cvWaitKey(0); cvReleaseImage(&img); cvReleaseImage(&pContourImg); cvReleaseMemStorage(&storage); return 0; }

64,646

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧