• Opencv学习(三)轮廓检测


    什么是轮廓检测

    轮廓检测就是在一张只有0和1的图片上绘制一系列的点,这些点就是图像中的曲线。函数findContours()就是从二值图像中寻找轮廓,在这个函数中,输入图像可以是从Canny()函数得到的有边缘像素的图像,或者是通过threshold()、adaptiveThreshold()处理后得到的图像。

    比如下面这张0-9的原始图片
    image

    经过轮廓检测后得到的图片
    image

    如何进行轮廓检测

    findcontours函数

    在opencv中使用函数findContours()来进行轮廓检测
    下面是函数原型
    python:cv.FindContours(image, storage, mode=CV_RETR_LIST, method=CV_CHAIN_APPROX_SIMPLE, offset=(0, 0))
    C++: void findContours(InputOutputArray image, OutputArrayOfArrays contours, int mode, int method, Point offset=Point())

    findcontours参数介绍

    1.image:原始图像,必须是8bit单通道图像,并且应该是二值图像,(如果不是--非0值被当做1,0值仍然是0)。该参数传入后会在原始图像上直接修改,因此,一般使用时传入原图像的副本

    2.contours:被检测到的轮廓,是一个存储坐标点的向量。(在py中,作为第一个返回值。在c++中是一个传入传出参数。)

    3.mode:轮廓检测方法。

    | CV_RETR_EXTERNAL | 只检测外轮廓 |
    | CV_RETR_LIST | 检测所有轮廓(内和外)但不建立任何层次关系 |
    | CV_RETR_CCOMP | 检索所有轮廓并将它们组织成一个两级层次结构(顶层--外轮廓,底层--内轮廓) |
    | CV_RETR_TREE | 检索所有轮廓并重建嵌套轮廓的完整层次结构 |

    4.method:轮廓近似方法。

    | CV_CHAIN_APPROX_NONE | 用绝对值存储所有轮廓点 |
    | CV_CHAIN_APPROX_SIMPLE | 压缩水平、垂直和对角线段,只留下它们的端点。 |

    5.offset:每个轮廓点移位的可选偏移量

    drawContours函数

    该函数用来绘制经过检测的轮廓
    函数原型
    Python: cv2.drawContours(image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset]]]]])
    C++: void drawContours(InputOutputArray image, InputArrayOfArrays contours, int contourIdx, const Scalar& color, int thickness=1, int lineType=8, InputArray hierarchy=noArray(), int maxLevel=INT_MAX, Point offset=Point() )

    drawContours参数介绍

    1.image:输入图像,(在C++中为输入输出参数)
    2.contours:所有检测到的轮廓,每个元素作为一个Point存储在vector中
    3.contourIdx:表示要绘制的轮廓参数,如果为-1就绘制所有轮廓
    4.color:绘制的颜色,是一个Scalar
    5.thickness:绘制线条的粗细
    6.lineType:线条类型,常用LINE_AA
    7~9 可选参数,没用过,不知道效果如何

    注意事项:
    1.一般是在读入的原始图像上进行绘制,如果在灰度图或者二值图上绘制,好像没有效果(上次很久绘制不出来,一直找不到原因,踩坑+1)
    2.drawContours的第二个参数可以直接用-1。但是如果是在循环中,可以用循环因子来绘制每个轮廓,效果都是一样的

    使用实例

    #读取图像
    template=cv2.imread("D:image	emplate.png")
    imshow("image",template)
    #化为灰度图
    ref_template=cv2.cvtColor(template,cv2.COLOR_BGR2GRAY)
    imshow("ref_gray",ref_template)
    #化为二值图
    ref_template=cv2.threshold(ref_template,10,255,cv2.THRESH_BINARY_INV)[1]
    imshow("ref_threshold",ref_template)
    
    #轮廓检测
    ##findContours 只接受二值图   RETR_EXTERNAL 只检测外轮廓   CHAIN_APPROX_SIMPLE 只保留终点坐标
    #在opencv4中要用hierarchy接收,而不能直接取[1]
    refCnts,hierarchy=cv2.findContours(ref_template.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
    #绘制轮廓
    cv2.drawContours(template,refCnts,-1,(0,0,255),3)
    imshow("draw_contours",template)
    

    结果展示

    1.读取的原始图像
    image

    2.灰度图
    image

    3.二值图
    image

    4.绘制检测的轮廓
    image


    如果我想把每个数字用一个矩形框而不是绘制它的边框,该怎么解决?-----轮廓近似

    什么是轮廓近似

    将轮廓形状近似到另外一种由更少点组成的轮廓形状,新轮廓的点的数目由我们设定的准确度来决定
    比如在上面的几个数字中,我想把边界用矩形框住,此时就需要使用到轮廓近似

    如何进行轮廓近似

    假设我们要在一幅图像中查找一个矩形,但是由于图像的种种原因我们不能得到一个完美的矩形,而是一个“坏形状”,现在就可以使用这个函数来近似这个形状,第二个参数是epsilon,它是从原始轮廓到近似轮廓的最大距离,它是一个准确度参数。

    float peri = arcLength(threshCnts[i], true);//周长
    //轮廓近似
    approxPolyDP(threshCnts[i], contoursPoly[i], 0.02 * peri, true);
    rectangle(cur_img, boundRect[i].tl(), boundRect[i].br(), Scalar(0, 0, 255), 2);
    

    结果展示

    1.直接绘制轮廓效果
    image

    2.轮廓近似后效果
    image

  • 相关阅读:
    面试
    vue axios 应用
    3D全景之ThreeJs
    css垂直居中
    事件处理过程中遇到的问题
    文字溢出
    jquery: 偏移量计算
    jquery: sand picture
    jquery: update carousel logic & animate
    jquery: carousel arrow click
  • 原文地址:https://www.cnblogs.com/hongweijiang/p/14897132.html
Copyright © 2020-2023  润新知