【问题标题】:OpenCV convexity defects drawingOpenCV凸面缺陷绘图
【发布时间】:2015-09-29 23:49:33
【问题描述】:

我已使用 vec4i 将使用凸性缺陷的缺陷存储在 4 元素向量整数数组中。

我的凸包数组在轮廓中的包元素和轮廓中; 我想要做的是从凸度缺陷的起点到终点画一条线。 为此,我需要访问缺陷向量的 vec4i 中存在的元素起始索引!

我该怎么做??

   #include <opencv\cv.h>
#include <opencv2\highgui\highgui.hpp>
#include<opencv\cvaux.h>
#include<opencv\cxcore.h>
#include <opencv2\imgproc\imgproc.hpp>
#include <iostream>
#include<conio.h>
#include <stdlib.h>



using namespace cv;
using namespace std;

int main(){


    Mat img, frame, img2, img3;


    VideoCapture cam(0);
    while (true){
        cam.read(frame);
        cvtColor(frame, img, CV_BGR2HSV);
        //thresholding 
        inRange(img, Scalar(0, 143, 86), Scalar(39, 255, 241), img2);

        imshow("hi", img2);

        //finding contours
        vector<vector<Point>> Contours;
        vector<Vec4i> hier;
        //morphological transformations
        erode(img2, img2, getStructuringElement(MORPH_RECT, Size(3, 3)));
        erode(img2, img2, getStructuringElement(MORPH_RECT, Size(3, 3)));

        dilate(img2, img2, getStructuringElement(MORPH_RECT, Size(8, 8)));
        dilate(img2, img2, getStructuringElement(MORPH_RECT, Size(8, 8)));


        //finding the contours required
        findContours(img2, Contours, hier, CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE, Point(0, 0));



        //finding the contour of largest area and storing its index
        int lrgctridx = 0;
        int maxarea = 0;
        for (int i = 0; i < Contours.size(); i++)
        {
            double a = contourArea(Contours[i]);
            if (a> maxarea)
            {
                maxarea = a;
                lrgctridx = i;
            }

        }
        //convex hulls
        vector<vector<Point> >hull(Contours.size());
        vector<vector<Vec4i>> defects(Contours.size());
        for (int i = 0; i < Contours.size(); i++)
        {
            convexHull(Contours[i], hull[i], false);
            convexityDefects(Contours[i], hull[i], defects[i]);
        }
        //REQUIRED contour is detected,then convex hell is found and also convexity defects are found and stored in defects




        if (maxarea>100){
            drawContours(frame, hull, lrgctridx, Scalar(255, 255, 255), 1, 8, vector<Vec4i>(), 0, Point());
        \\ drawing the required lines joining defects!im facing problem on how to acheive this since i dont know how to access the elements stored in defects
           line(frame, \\startindex, \\endindex, \\color, 1);

        }


        imshow("output", frame);
        char key = waitKey(33);
        if (key == 27) break;



    }

}

当我添加 convexityDefects(..) 行时,我的输出窗口也显示错误,我认为它的格式错误! 提前致谢。

【问题讨论】:

  • Vec4i 中存储了什么?
  • 我已经添加了我的代码。我已经尝试并在 4 元素向量数组中存储了有关凸面缺陷的信息。此外,我的输出窗口在代码中添加线 convexityDefects(...) 时崩溃。我认为它的格式错误。
  • 那段代码似乎很熟悉.. :D
  • 那是因为我昨天发了一部分……我在一步步学习……正在做手势识别!
  • 看我的回答。下次多花点时间在 google 和 SO

标签: c++ opencv


【解决方案1】:

convexityDefects 需要一个

使用convexHull() 获得的凸包应该包含构成该包的轮廓点的索引。

包含超过 3 个索引。所以你需要这个:

vector<vector<Point> >hull(Contours.size());
vector<vector<int> > hullsI(Contours.size()); // Indices to contour points
vector<vector<Vec4i>> defects(Contours.size());
for (int i = 0; i < Contours.size(); i++)
{
    convexHull(Contours[i], hull[i], false);
    convexHull(Contours[i], hullsI[i], false); 
    if(hullsI[i].size() > 3 ) // You need more than 3 indices          
    {
        convexityDefects(Contours[i], hullsI[i], defects[i]);
    }
}

那么你的绘图部分是(改编自here):

/// Draw convexityDefects
for (int i = 0; i < Contours.size(); ++i)
{
    for(const Vec4i& v : defects[i])
    {
        float depth = v[3] / 256;
        if (depth > 10) //  filter defects by depth, e.g more than 10
        {
            int startidx = v[0]; Point ptStart(Contours[i][startidx]);
            int endidx = v[1]; Point ptEnd(Contours[i][endidx]);
            int faridx = v[2]; Point ptFar(Contours[i][faridx]);

            line(frame, ptStart, ptEnd, Scalar(0, 255, 0), 1);
            line(frame, ptStart, ptFar, Scalar(0, 255, 0), 1);
            line(frame, ptEnd, ptFar, Scalar(0, 255, 0), 1);
            circle(frame, ptFar, 4, Scalar(0, 255, 0), 2);
        }
    }
}   

完整代码

#include <opencv2\opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main()
{
    Mat img, frame, img2, img3;
    VideoCapture cam(0);
    while (true){
        cam.read(frame);

        cvtColor(frame, img, CV_BGR2HSV);

        //thresholding 
        inRange(img, Scalar(0, 143, 86), Scalar(39, 255, 241), img2);

        imshow("hi", img2);

        //finding contours
        vector<vector<Point>> Contours;
        vector<Vec4i> hier;
        //morphological transformations
        erode(img2, img2, getStructuringElement(MORPH_RECT, Size(3, 3)));
        erode(img2, img2, getStructuringElement(MORPH_RECT, Size(3, 3)));

        dilate(img2, img2, getStructuringElement(MORPH_RECT, Size(8, 8)));
        dilate(img2, img2, getStructuringElement(MORPH_RECT, Size(8, 8)));

        //finding the contours required
        findContours(img2, Contours, hier, CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE, Point(0, 0));

        //finding the contour of largest area and storing its index
        int lrgctridx = 0;
        int maxarea = 0;
        for (int i = 0; i < Contours.size(); i++)
        {
            double a = contourArea(Contours[i]);
            if (a> maxarea)
            {
                maxarea = a;
                lrgctridx = i;
            }
        }
        //convex hulls
        vector<vector<Point> >hull(Contours.size());
        vector<vector<int> > hullsI(Contours.size()); 
        vector<vector<Vec4i>> defects(Contours.size());
        for (int i = 0; i < Contours.size(); i++)
        {
            convexHull(Contours[i], hull[i], false);
            convexHull(Contours[i], hullsI[i], false); 
            if(hullsI[i].size() > 3 )            
            {
                convexityDefects(Contours[i], hullsI[i], defects[i]);
            }
        }
        //REQUIRED contour is detected,then convex hell is found and also convexity defects are found and stored in defects

        if (maxarea>100){
            drawContours(frame, hull, lrgctridx, Scalar(2555, 0, 255), 3, 8, vector<Vec4i>(), 0, Point());

            /// Draw convexityDefects
            for(int j=0; j<defects[lrgctridx].size(); ++j)
            {
                const Vec4i& v = defects[lrgctridx][j];
                float depth = v[3] / 256;
                if (depth > 10) //  filter defects by depth
                {
                    int startidx = v[0]; Point ptStart(Contours[lrgctridx][startidx]);
                    int endidx = v[1]; Point ptEnd(Contours[lrgctridx][endidx]);
                    int faridx = v[2]; Point ptFar(Contours[lrgctridx][faridx]);

                    line(frame, ptStart, ptEnd, Scalar(0, 255, 0), 1);
                    line(frame, ptStart, ptFar, Scalar(0, 255, 0), 1);
                    line(frame, ptEnd, ptFar, Scalar(0, 255, 0), 1);
                    circle(frame, ptFar, 4, Scalar(0, 255, 0), 2);
                }
            }
        }

        imshow("output", frame);
        char key = waitKey(33);
        if (key == 27) break;

    }
}

【讨论】:

  • 感谢您的示例。它大部分工作正常,唯一的例外是 contours[i], hullsI[i], false);需要“真”顺时针参数。也许这是opencv 3+的事情。使用 false 会导致无法找到所有缺陷。
  • @Umka false 将返回convexityDefects 函数所需的索引(而不是点)。不太清楚你在说什么,实际上
  • 在我的opencv 3.3中有这样一个convexityHull(): CV_EXPORTS_W void convehull( InputArray points, OutputArray hull, bool 顺时针= false, bool returnPoints = true );这就是我的意思。
  • @Umka 是的,你是对的。 false 是为clockwise 使用的,但我打算将它用于returnPoints。幸运的是我通过了vector,所以returnPoints 标志无论如何都被忽略了。那么如果你做CW或CCW,它可能会改变......我实际上不知道。感谢您的反馈;)
  • 您不知道我花了多长时间才找到绘制轮廓缺陷的示例。谢谢先生:-)
猜你喜欢
  • 1970-01-01
  • 2012-10-10
  • 2013-02-20
  • 2011-10-12
  • 1970-01-01
  • 2012-06-13
  • 2013-09-03
  • 2012-01-05
  • 1970-01-01
相关资源
最近更新 更多