2

我有这张图片

我想从图像中取出三角形和矩形。在下面的代码中,我有 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;

}
4

2 回答 2

2

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

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

于 2012-11-30T17:47:00.737 回答
0

如果您可以确定您的轮廓是完整的,ApproxPoly 是一个很好的解决方案。如果轮廓是正方形但不闭合,则在近似后它将是一条具有四段和 3 个角的线。

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

于 2012-11-30T20:16:08.750 回答