2016/10/07 阅读《Practical OpenCV》 char5

来源:互联网 发布:停课铃软件 编辑:程序博客网 时间:2024/06/13 21:53

下面这段代码是书中的源码。这篇博客主要是想要把程序的目的、思路、实现方法和几个关键点整理一下。

#include<opencv2/opencv.hpp>#include<opencv2/highgui/highgui.hpp>#include<opencv2/imgproc/imgproc.hpp>using namespace std;using namespace cv;Mat img_all_contours;vector<vector<Point> > closed_contours;vector<Vec4i> hierarchy;//function to approximate contours by closed contoursvector<vector<Point> > make_contours_closed(vector<vector<Point>> contours){    vector<vector<Point> > closed_contours;    closed_contours.resize(contours.size());    for(int i=0;i<contours.size();i++)    {        approxPolyDP(contours[i],closed_contours[i],0.1,true);    }    return closed_contours;}//function to return the index of smallest contours in 'closed_contours' surrounding the clicked pointint smallest_contour(Point p,vector<vector<Point>> contours,vector<Vec4i> hierarchy){    int idx = 0;    int prev_idx = -1;    while(idx >= 0)    {        vector<Point> c = contours[idx];        /////point-polgon test        double d = pointPolygonTest(c,p,false);        /////if point is inside the contour,check its children for an even smaller contour        if(d > 0)        {            prev_idx = idx;            idx = hierarchy[idx][2];        }        ///else check the next contour on the same level        else        {            idx = hierarchy[idx][0];        }    }    return prev_idx;}void on_mouse(int event ,int x,int y,int,void*){    if(event != EVENT_LBUTTONDOWN)    {        return;    }    //clicked point    Point p(x,y);    //find index of smallest enclosing contour    int contour_show_idx = smallest_contour(p,closed_contours,hierarchy);    //if no such contours,user clicked outside all contours,hence clear image    if(contour_show_idx < 0)    {        imshow("Contours",img_all_contours);        return;    }    ///draw the smallest contour using a thick red line    vector<vector<Point> > contour_show;    contour_show.push_back(closed_contours[contour_show_idx]);    if(!contour_show.empty())    {        Mat img_show = img_all_contours.clone();        drawContours(img_show,contour_show,-1,Scalar(0,0,255),3);        imshow("Contours",img_show);    }}void main(void){    Mat img = imread("E:\\opencv-logo.png");    img_all_contours = img.clone();    Mat img_b;    cvtColor(img,img_b,CV_RGB2GRAY);    Mat edges;    Canny(img_b,edges,50,100);    ////extract contours and hierarchy    vector<vector<Point> > contours;////主要是要理解这一行是个什么操作机制    findContours(edges,contours,hierarchy,CV_RETR_TREE,CV_CHAIN_APPROX_NONE);    //make contours closed so point-polygon test is valid    closed_contours = make_contours_closed(contours);    ////draw all contours using green line    drawContours(img_all_contours,closed_contours,-1,Scalar(0,255,0));    imshow("Contours",img_all_contours);    //Mouse callback    setMouseCallback("Contours",on_mouse);    while(char(waitKey(1)) != 'q');}
  1. 目的
    程序的目的是为了能够找到图片中的所有的轮廓,并且通过鼠标交互,来显示包含鼠标的最小轮廓。
  2. 思路
    首先通过对图像进行边缘检测,利用边缘信息得到轮廓,再通过函数make_contours_closed寻找近似多边形, 形成封闭的轮廓;随后从等级最高的多边形开始,检验鼠标点在轮廓内部或者外部,在内部的则检验更低等级的多边形,在外面的话则检验同等级的其他多边形,一直到确定是包含鼠标点的最小多边形为止,并且显示。
  3. 实现方法
    下面的图片是程序的大致流程:
    上面程序的大致流程
  4. 关键点
    主要是想弄明白流程,另外一个点就是理解vector
    #include<vector>    #include<iostream>    using namespace std;    void main(void)    {        int x;        cin>>x;        while(x<2)        {            cout<<"input must larger than 1!"<<endl;            cin>>x;        }        vector<vector<char> > tri;        int i,j;        vector<char> tmp;        for(i = 0;i <= x+1; i++)        {            tmp.clear();            for(j = 0;j < i;j++)            {                tmp.push_back('*');///注意这个附近的区别            }            tri.push_back(tmp);        }        for(int i = 0;i < x+1; i++)        {            for(int j = 0;j < i;j++)            {                cout<<tri[i][j];            }            cout<<endl;        }        system("pause");    }

但是不能使用下面的方法,这个还在思考为什么,也解释不了书上的代码的意思。(新增加:其实可以解释了:就是最开始声明了vector

    #include<vector>    #include<iostream>    using namespace std;    void main(void)    {        int x;        cin>>x;        while(x<2)        {            cout<<"input must larger than 1!"<<endl;            cin>>x;        }        vector<vector<char> > tri;        int i,j;        vector<char> tmp;        for(i = 0;i <= x+1; i++)        {            for(j = 0;j < i;j++)            {                tri[i].push_back('*');///注意这一行和上面的代码的区别            }        }        for(int i = 0;i < x+1; i++)        {            for(int j = 0;j < i;j++)            {                cout<<tri[i][j];            }            cout<<endl;        }        system("pause");    }

还有个讲究,就是二维的或者多为的vector声明的时候需要在后面的两个“>”之间加上空格,否则会被认为是重载。

0 0