cvFindContours/findContours提取轮廓

opencv在提取轮廓时,C/C++有两种方式,有些许不同,结合查找的资料和补充,做个小笔记;

功能,提取满足一定面积阈值和宽高比例的轮廓;

主函数

static int getContoursByC(char* Imgname, double minarea = 100, double whRatio = 1);  
static int getContoursByCplus(char* Imgname, double minarea=0, double whRatio=1);  
int main()  
{  
    char* filename = new char[50];  
    strcpy(filename, "../image/rl_4.jpg");  
    getContoursByCplus(filename);  
    delete[] filename;  
    return 0;  
}  

API实现

cvFindContours形式

/*采用cvFindContours提取轮廓,并过滤掉小面积轮廓,最后将轮廓保存*/  
/*采用cvFindContours提取轮廓,并过滤掉小面积轮廓,最后将轮廓保存*/
static int getContoursByC(char* Imgname, double minarea, double whRatio)
{
    IplImage* src = cvLoadImage(Imgname, CV_LOAD_IMAGE_GRAYSCALE);
    if (!src)
    {
        printf("read data error!\n");
        return -1;
    }
    IplImage* dst = cvCreateImage(cvGetSize(src), 8, 3);

    //the parm. for cvFindContours
    CvMemStorage* storage = cvCreateMemStorage(0);
    CvSeq* contour = 0;
    double maxarea = 0;

    //for display
    cvNamedWindow("Source", CV_WINDOW_NORMAL);
    cvShowImage("Source", src);

    //二值化
    cvThreshold(src, src, 120, 255, CV_THRESH_BINARY);

    //提取轮廓
    cvFindContours(src, storage, &contour, sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);
    cvZero(dst);//清空数组

    /*CvSeq* _contour为了保存轮廓的首指针位置,因为随后contour将用来迭代*/
    CvSeq* _contour = contour;


    int maxAreaIdx = -1, iteratorIdx = 0;//n为面积最大轮廓索引,m为迭代索引
    for (int iteratorIdx = 0; contour != 0; contour = contour->h_next, iteratorIdx++/*更新迭代索引*/)
    {

        double tmparea = fabs(cvContourArea(contour));
        if (tmparea > maxarea)
        {
            maxarea = tmparea;
            maxAreaIdx = iteratorIdx;
            continue;
        }
        if (tmparea < minarea)
        {
            //删除面积小于设定值的轮廓
            cvSeqRemove(contour, 0); 
            continue;
        }
        CvRect aRect = cvBoundingRect(contour, 0);
        if ((aRect.width / aRect.height)<whRatio)
        {
            //删除宽高比例小于设定值的轮廓
            cvSeqRemove(contour, 0); 
            continue;
        }
        //CvScalar color = CV_RGB( rand()&255, rand()&255, rand()&255 );//创建一个色彩值
        //CvScalar color = CV_RGB(0, 255, 255);

        //max_level 绘制轮廓的最大等级。如果等级为0,绘制单独的轮廓。如果为1,绘制轮廓及在其后的相同的级别下轮廓。
        //如果值为2,所有的轮廓。如果等级为2,绘制所有同级轮廓及所有低一级轮廓,诸此种种。
        //如果值为负数,函数不绘制同级轮廓,但会升序绘制直到级别为abs(max_level)-1的子轮廓。 
        //cvDrawContours(dst, contour, color, color, -1, 1, 8);//绘制外部和内部的轮廓
    }
    contour = _contour; /*int k=0;*/
    //统计剩余轮廓,并画出最大面积的轮廓
    int count = 0;
    for (; contour != 0; contour = contour->h_next)
    {
        count++;
        double tmparea = fabs(cvContourArea(contour));
        if (tmparea == maxarea /*k==n*/)
        {
            CvScalar color = CV_RGB(255, 0, 0);
            cvDrawContours(dst, contour, color, color, -1, 1, 8);
        }
        /*k++;*/
    }
    printf("The total number of contours is:%d", count);
    cvNamedWindow("Components", CV_WINDOW_NORMAL);
    cvShowImage("Components", dst);
    cvSaveImage("dst.jpg", dst);
    //roateProcess(dst);
    cvWaitKey(0);
    //销毁窗口和图像存储
    cvDestroyWindow("Source");
    cvReleaseImage(&src);
    cvDestroyWindow("Components");
    cvReleaseImage(&dst);
    return 0;
}

findContours形式


static int getContoursByCplus(char* Imgname, double minarea, double whRatio)
{
    cv::Mat src, dst, canny_output;
    /// Load source image and convert it to gray
    src = imread(Imgname, 0);

    if (!src.data)
    {
        std::cout << "read data error!" << std::endl;
        return -1;
    }
    blur(src, src, Size(3, 3));


    //the pram. for findContours,
    vector<vector<Point> > contours;
    vector<Vec4i> hierarchy;

    /// Detect edges using canny
    Canny(src, canny_output, 80, 255, 3);
    /// Find contours
    findContours(canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
    //CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE

    double maxarea = 0;
    int maxAreaIdx = 0;

    for (int i = 0; i<contours.size(); i++)
    {

        double tmparea = fabs(contourArea(contours[i]));
        if (tmparea>maxarea)
        {
            maxarea = tmparea;
            maxAreaIdx = i;
            continue;
        }

        if (tmparea < minarea)
        {
            //删除面积小于设定值的轮廓
            contours.erase(contours.begin() + i); 
            std::wcout << "delete a small area" << std::endl;
            continue;
        }
        //计算轮廓的直径宽高
        Rect aRect =boundingRect(contours[i]);
        if ((aRect.width / aRect.height)<whRatio)
        {
            //删除宽高比例小于设定值的轮廓
            contours.erase(contours.begin() + i); 
            std::wcout << "delete a unnomalRatio area" << std::endl;
            continue;
        }
    }
    /// Draw contours,彩色轮廓
    dst= Mat::zeros(canny_output.size(), CV_8UC3);
    for (int i = 0; i< contours.size(); i++)
    {
        //随机颜色
        Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
        drawContours(dst, contours, i, color, 2, 8, hierarchy, 0, Point());
    }
    // Create Window
    char* source_window = "countors";
    namedWindow(source_window, CV_WINDOW_NORMAL);
    imshow(source_window, dst);
    cv:: waitKey(0);

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值