首页 文章

为什么opencv会发现轮廓的边界点,无序和未完成?

提问于
浏览
0

我想编写一个程序,可以通过C语言中的opencv更正答案表 .

但是当我使用 cvFindContours() 时,完全找到了轮廓_2914723 .

我的意思是,我没有封闭的物体 . (我使用 cvDilatecvErode ,不知道它们的真正功能,但是扩张省略了一些轮廓并且侵蚀了一些额外的,不需要的轮廓)

更大的问题是我想在每个轮廓中找到一个中心点(比较答案的位置与预定义的左侧和下侧边栏),但是一些轮廓不对称,所以中心点的位置不完全在中间 .

查看左侧黑色图片,在第二个轮廓中,检测到一些底部点,但未检测到顶部点 .

This is the Answer sheet:

First 8 answers

cvCvtColor(pic, blackpic, CV_BGR2GRAY);
cvResize(blackpic, src0);
cvSmooth(src0, src0, CV_GAUSSIAN, 3, 3);
cvThreshold(src0, src, 140, 255, CV_THRESH_BINARY);


//Find Contour
CvMemStorage* st = cvCreateMemStorage();
CvSeq* first_contour = NULL;
cvFindContours(src, st, &first_contour, sizeof(CvContour), CV_RETR_LIST);

vector <vector <CvPoint> > cont;
vector <CvPoint> dot;

for (CvSeq* s = first_contour; s != NULL; s = s->h_next)
    if (s -> total > C_MIN_SIZE && cvContourArea(s) > C_MIN_AREA)
    {
        cont.push_back(vector <CvPoint>()); //convert seq to vector
        CvPoint c = cvPoint(0,0);
        for (int i = 0; i < s -> total; i++)
        {
            CvPoint* p = CV_GET_SEQ_ELEM(CvPoint, s, i);
            cont.back().push_back(*p);
            CV_IMAGE_ELEM(test, uchar, p -> y, p -> x) = 255; //drawing each contour's point
            c.x += p -> x; //find the center point by average
            c.y += p -> y;
        }
        c.x = floor(c.x / s -> total);
        c.y = floor(c.y / s -> total);
        dot.push_back(c);
    }
  • 虽然我使用C,但是我使用IplImage *和CvPoint(c structres for opencv)insted of cv :: Mat和cv :: Point(C stractures),如果有可能,请不要使用Mat和C模式 .

  • 我不明白当我通过 cvDrawContours() 绘制轮廓时,轮廓是完全绘制的,但是当我亲自遍历轮廓点并逐点绘制它们时,似乎大多数都没有被检测到!

1 回答

  • 2

    对于您的第一个问题,您可以在互联网上找到数以千计的链接来解释Erode, Dilate以及所有其他基本的图像处理支柱,在阅读文档时花点时间不要跳过步骤 .

    第二个问题:

    我不确定你对轮廓中心有什么期望?你认为你会准确地指出那些椭圆的中心吗?不,这将永远不会发生,如果是这样的话,祝贺图像处理历史中的这一大堆!

    我建议做的是一个简单的操作来解决你的问题:

    • 找到轮廓(就像你现在正在做的那样)

    • 计算每个轮廓的中心

    • 当您将答案与中心位置进行比较时,请不要使用 a == b 进行比较,因为这绝不会发生!!相反,使用距离(阈值)的比较来确保软件的运行

    示例:

    bool correct;
    CvPoint answer, center;
    double distance = sqrt((answer.X - center.X)^2 + (answer.Y - center.Y)^2); // Euclidean distance
    
    // judge using this distance 
    
    if (distance <= 5)    // here you select the number as you (want) i gave example 5
    {
        correct = true; // correct answer :)
    }
    

    祝好运

相关问题