使用opencv从图像中检测三角形的矩形

时间:2012-11-29 14:49:37

标签: c++ opencv geometry

我有image

我想从图像中取出三角形和矩形。我有2个算法,一个用于三角形,另一个用于下面代码中的矩形。但它们非常相似。但通过这种方式我只能把三角形更加明亮。任何人都可以帮助我。

IplImage* DetectAndDrawTriang(IplImage* img){
    CvSeq* contours;
    CvSeq* result;
    CvMemStorage *storage = cvCreateMemStorage(0);
    int d=30;

    IplImage* ret = cvCreateImage(cvGetSize(img), 8, 3);
    IplImage* temp = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);
    cvSet(ret,cvScalar(0,0,0));
    cvCvtColor(img, temp, CV_BGR2GRAY);
    cvThreshold( temp, temp, 180, 255, CV_THRESH_BINARY );
    //cvSmooth(temp, temp, CV_GAUSSIAN, 9, 9, 0,0);
    cvNamedWindow("thre");
    cvShowImage("thre", temp);

    cvFindContours(temp, storage, &contours, sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0));

    while(contours)
    {
        result = cvApproxPoly(contours, sizeof(CvContour), storage, CV_POLY_APPROX_DP, cvContourPerimeter(contours)*0.1, 0);
        if(result->total==3)
        {
            CvPoint *pt[3];
            for(int i=0;i<3;i++)
                pt[i] = (CvPoint*)cvGetSeqElem(result, i);


            if((int)sqrt((pt[0]->x-pt[2]->x)*(pt[0]->x-pt[2]->x)+(pt[0]->y-pt[2]->y)*(pt[0]->y-pt[2]->y))>=d && (int)sqrt((pt[0]->x-pt[1]->x)*(pt[0]->x-pt[1]->x)+(pt[0]->y-pt[1]->y)*(pt[0]->y-pt[1]->y))>=d && (int)sqrt((pt[1]->x-pt[2]->x)*(pt[1]->x-pt[2]->x)+(pt[1]->y-pt[2]->y)*(pt[1]->y-pt[2]->y))>=d)
            {
                cvLine(ret, *pt[0], *pt[1], cvScalar(255,255,255));

                cvLine(ret, *pt[1], *pt[2], cvScalar(255,255,255));

                cvLine(ret, *pt[2], *pt[0], cvScalar(255,255,255));
            }
        }
        contours = contours->h_next;
    }

    cvReleaseImage(&temp);
    cvReleaseMemStorage(&storage);

    return ret;

}

2 个答案:

答案 0 :(得分:2)

我能想到的一个想法是使用cv :: matchShapes函数(我建议使用带有Mat而不是Ipl图像的cv2库)。 matchShapes使用要检测的对象的Mat和要与其进行比较的对象的Mat。因此,在您的情况下,您可以制作三角形和正方形轮廓的Mat,并将这些图像与您正在搜索的图像中的每个轮廓进行比较。

您也可以考虑简单地进行模板匹配,因为您的对象是静态的。查看cv :: matchTemplate及其与上一段几乎相同的想法。

答案 1 :(得分:0)

近似是一个很好的解决方案如果你可以确定你的轮廓是完整的。 如果轮廓是正方形但没有关闭,则它将是近似后具有四个段和三个角的线。

另一个解决方案是在轮廓点周围安装一个方框(有一个功能可以做到这一点)并检查宽度/高度比。然后,您可以测试轮廓列表中的各个线段,看它们是否与箱边匹配。