opencv(22)---轮廓特征属性及应用之使用特定形状的轮廓

使用特定形状的轮廓包围

基本概念

在实际应用中, 经常会有将检测到的轮廓用多边形表示出来的需求, 提取包围轮廓的多边形也方便我们做进一步分析, 轮廓包围主要有一下几种:
- 轮廓外接矩形
- 轮廓最小外接矩形(旋转)
- 轮廓最小包围圆形
- 轮廓拟合椭圆
- 轮廓逼近多边形曲线

轮廓外接矩形不能进行旋转,为下图中所示的绿色框。
这里写图片描述

函数原型

轮廓外接矩形—boundingRect()

Rect boundingRect( InputArray points );
  • points: 输入的二维点集, 可以填Mat类型或std::vector
  • 返回值: Rect类矩形对象

代码

   Mat srcImg =imread("33.png");
    imshow("src", srcImg);
    Mat dstImg = srcImg.clone();  //原图备份
    cvtColor(srcImg, srcImg, CV_BGR2GRAY); //转为灰度图
    threshold(srcImg, srcImg, 100, 255, CV_THRESH_BINARY); //二值化

    vector<vector<Point>> contours;
    vector<Vec4i> hierarcy;
    findContours(srcImg, contours, hierarcy, CV_RETR_EXTERNAL, CHAIN_APPROX_NONE); //查找轮廓
    vector<Rect> boundRect(contours.size()); //定义外接矩形集合
    //drawContours(dstImg, contours, -1, Scalar(0, 0, 255), 2, 8);  //绘制轮廓
    int x0=0, y0=0, w0=0, h0=0;
    for(int i=0; i<contours.size(); i++)
    {
        boundRect[i] = boundingRect((Mat)contours[i]); //查找每个轮廓的外接矩形
        drawContours(dstImg, contours, i, Scalar(0, 0, 255), 2, 8);  //绘制轮廓
        x0 = boundRect[i].x;  //获得第i个外接矩形的左上角的x坐标
        y0 = boundRect[i].y; //获得第i个外接矩形的左上角的y坐标
        w0 = boundRect[i].width; //获得第i个外接矩形的宽度
        h0 = boundRect[i].height; //获得第i个外接矩形的高度
        rectangle(dstImg, Point(x0, y0), Point(x0+w0, y0+h0), Scalar(0, 255, 0), 2, 8); //绘制第i个外接矩形
    }
    imshow("boundRect", dstImg);
    waitKey(0);

运行结果

这里写图片描述

这里写图片描述

应用实例一—分割硬币

代码

  Mat srcImg =imread("D:\\1\\33.png");
    imshow("src", srcImg);
    Mat dstImg = srcImg.clone();  //原图备份
    cvtColor(srcImg, srcImg, CV_BGR2GRAY); //转为灰度图
    threshold(srcImg, srcImg, 100, 255, CV_THRESH_BINARY); //二值化
    imshow("threshold", srcImg);
    Mat element = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1)); //获得结构元素
    dilate(srcImg, srcImg, element); //膨胀操作

    vector<vector<Point>> contours;
    vector<Vec4i> hierarcy;
    findContours(srcImg, contours, hierarcy, CV_RETR_EXTERNAL, CHAIN_APPROX_NONE); //查找轮廓
    vector<Rect> boundRect(contours.size()); //定义外接矩形集合
    drawContours(dstImg, contours, -1, Scalar(0, 0, 255), 2, 8);  //绘制轮廓
    int x0=0, y0=0, w0=0, h0=0;
    for(int i=0; i<contours.size(); i++)
    {
        boundRect[i] = boundingRect((Mat)contours[i]); //查找每个轮廓的外接矩形
        drawContours(dstImg, contours, i, Scalar(0, 0, 255), 2, 8);  //绘制轮廓
        x0 = boundRect[i].x;  //获得第i个外接矩形的左上角的x坐标
        y0 = boundRect[i].y; //获得第i个外接矩形的左上角的y坐标
        w0 = boundRect[i].width; //获得第i个外接矩形的宽度
        h0 = boundRect[i].height; //获得第i个外接矩形的高度
        if(w0>30 && h0>30)
            rectangle(dstImg, Point(x0, y0), Point(x0+w0, y0+h0), Scalar(0, 255, 0), 2, 8); //绘制第i个外接矩形
    }
    imshow("boundRect", dstImg);
    waitKey(0);

运行结果

这里写图片描述

这里写图片描述

这里写图片描述

注意知识点

1.膨胀

Mat element = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1)); //获得结构元素
dilate(srcImg, srcImg, element); //膨胀操作

2.绘制条件

    if(w0>30 && h0>30)

应用实例二—简单车牌字符分割

步骤是 :定位车牌区域;字符提取和分割

代码

Mat srcImg =imread("D:\\1\\car.jpg");
   imshow("src", srcImg);
   Mat dstImg = srcImg.clone();  //原图备份
   medianBlur(srcImg, srcImg, 5);  //中值滤波
   cvtColor(srcImg, srcImg, CV_BGR2GRAY); //转为灰度图
   threshold(srcImg, srcImg, 100, 255, CV_THRESH_BINARY); //二值化
   imshow("threshold", srcImg);

   vector<vector<Point>> contours;
   vector<Vec4i> hierarcy;
   findContours(srcImg, contours, hierarcy, CV_RETR_TREE, CHAIN_APPROX_NONE); //查找轮廓
   vector<Rect> boundRect(contours.size()); //定义外接矩形集合
   //drawContours(dstImg, contours, -1, Scalar(0, 0, 255), 2, 8);  //绘制轮廓
   int x0=0, y0=0, w0=0, h0=0;
   for(int i=0; i<contours.size(); i++)
   {
       boundRect[i] = boundingRect((Mat)contours[i]); //查找每个轮廓的外接矩形
       //drawContours(dstImg, contours, i, Scalar(0, 0, 255), 2, 8);  //绘制轮廓
       x0 = boundRect[i].x;  //获得第i个外接矩形的左上角的x坐标
       y0 = boundRect[i].y; //获得第i个外接矩形的左上角的y坐标
       w0 = boundRect[i].width; //获得第i个外接矩形的宽度
       h0 = boundRect[i].height; //获得第i个外接矩形的高度
       if(w0>srcImg.cols/12 && w0<srcImg.cols/7 && h0>srcImg.rows/6 && h0<srcImg.rows*5/6)
       {
           char pic_name[10];
           sprintf(pic_name, "E:\\%d.bmp", i);
           Mat ROI = dstImg(Rect(x0, y0, w0, h0));
           imwrite(pic_name, ROI);
           rectangle(dstImg, Point(x0, y0), Point(x0+w0, y0+h0), Scalar(0, 255, 0), 2, 8); //绘制第i个外接矩形
       }
   }
   imshow("boundRect", dstImg);
   waitKey(0);

运行结果

这里写图片描述

这里写图片描述

这里写图片描述

知识点讲解

1.

  if(w0>srcImg.cols/12 && w0<srcImg.cols/7 && h0>srcImg.rows/6 && h0<srcImg.rows*5/6)

这段代码用于控制分割图像的大小
2.滤波

需要进行滤波来去除边缘的一些杂点

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值