Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
357 views
in Technique[技术] by (71.8m points)

c++ - OpenCV convexity defects drawing

I have stored the defects using convexity defects in an 4 element vector integer array using vec4i.

My convex hull array is in hull element and contours in Contours; What i want to do is draw a line from start point of a convexity defect to the end point of one. For this i need to access the element start index which is present in the vec4i of a defects vector!

How do i do this??

   #include <opencvcv.h>
#include <opencv2highguihighgui.hpp>
#include<opencvcvaux.h>
#include<opencvcxcore.h>
#include <opencv2imgprocimgproc.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;



    }

}

Also my output window shows error when i add the convexityDefects(..) line i think it is in wrong format! Thanks in advance.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

convexityDefects needs a

Convex hull obtained using convexHull() that should contain indices of the contour points that make the hull.

that contains more than 3 indices. So you need this:

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]);
    }
}

Then your drawing part is (adapted from 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);
        }
    }
}   

Complete code

#include <opencv2opencv.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;

    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...