• opencv图像轮廓


    最小外接圆

    函数cv2.minEnclosingCircle() 可以帮我们找到一个对象的外切圆。它是所有能够包括对象的圆中面积最小的一个。

    案例:现有下面这样一张图片,要求将图片中心的花朵标记出来。

    代码:

    import numpy as np
    import cv2 as cv
    
    img=cv.imread("image.jpg",0)
    
    #为了显示方便,这里将图片进行缩放
    x,y=img.shape
    img=cv.resize(img,(y//2,x//2))
    #将图片二值化,由于前景物体是黑色的,因此在二值化时采用cv.THRESH_TOZERO_INV这种方式
    ret,thresh=cv.threshold(img,127,255,cv.THRESH_TOZERO_INV)
    #寻找图片中的轮廓,mode=cv.RETR_EXTERNAL,这是为了寻找最外层的轮廓
    im,contour,hierarchy=cv.findContours(thresh,cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE)
    
    #cv.minEnclosingCircle函数的参数要求是ndarray类型,因此这里将找到的
    # 轮廓中的所有的点存放在一个列表中,然后使用这个列表创建数组
    point_list=[]
    for i in contour:
        for j in i:
            point_list.append(j[0])
    point_array=np.array(point_list)
    
    #使用最小外接圆函数,返回值为这个圆的圆心坐标和圆半径长度
    (x,y),radius=cv.minEnclosingCircle(point_array)
    
    #图片上的坐标均为整数,圆的半径也要求是整数,因此将它们强制转换为int类型
    center=(int(x),int(y))
    color=cv.cvtColor(img,cv.COLOR_GRAY2BGR)
    color=cv.circle(color,center,radius=int(radius),color=(0,0,255),thickness=2)
    #显示图片
    cv.imshow("color",color)
    cv.waitKey(0)
    cv.destroyAllWindows()

    程序结果:

     凸包

    凸包与轮廓近似相似,但不同,虽然有些情况下它们给出的结果是一样的。函数cv2.convexHull() 可以用来检测一个曲线是否具有凸性缺陷,并能纠正缺陷。一般来说,凸性曲线总是凸出来的,至少是平的。在opencv中使用函数cv.convexhull来寻找轮廓的凸包,该函数的定义为:

    hull=cv.convexHull( points[, hull[, clockwise[, returnPoints]]])

    这个函数的参数如下:

    Points:我们需要传入的轮廓

    Hull:输出,通常不需要

    clockwise : 取向标志,如果为True,凸包的方向是顺时针方向,否则为逆时针方向;

    returnPoints : 默认为True. 它会返回凸包上点的坐标。如果设置为False,就会返回与凸包点对应的轮廓上的点。

    还是上面的这副图片,我们对上面的代码稍加修改,可以得到凸包的形状,代码如下:

    import numpy as np
    import cv2 as cv
    
    img=cv.imread("image.jpg",0)
    
    #为了显示方便,这里将图片进行缩放
    x,y=img.shape
    img=cv.resize(img,(y//2,x//2))
    #将图片二值化,由于前景物体是黑色的,因此在二值化时采用cv.THRESH_TOZERO_INV这种方式
    ret,thresh=cv.threshold(img,127,255,cv.THRESH_TOZERO_INV)
    #寻找图片中的轮廓,mode=cv.RETR_EXTERNAL,这是为了寻找最外层的轮廓
    im,contour,hierarchy=cv.findContours(thresh,cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE)
    
    #cv.minEnclosingCircle函数的参数要求是ndarray类型,因此这里将找到的
    # 轮廓中的所有的点存放在一个列表中,然后使用这个列表创建数组
    point_list=[]
    for i in contour:
        for j in i:
            point_list.append(j[0])
    point_array=np.array(point_list)
    
    #寻找凸包,返回值是凸包上的点
    hull=cv.convexHull(point_array,returnPoints=True)
    color=cv.cvtColor(img,cv.COLOR_GRAY2BGR)
    
    #将凸包绘制出来,需要注意的是:这里需要将凸包上点的坐标写成一个
    #列表传入函数cv.ploylines,否则绘制出来的只是凸包上的一系列点
    color=cv.polylines(color,[hull],True,(0,0,255),2)
    #显示图片
    cv.imshow("color",color)
    cv.waitKey(0)
    cv.destroyAllWindows()

    程序运行结果为:

     

     图像掩模和像素点

    有时我们需要构成对象的所有像素点,我们可以将图像的所有轮廓提取出来,然后使用函数cv.drawContours()将轮廓内的区域填充为指定的颜色。然后使用cv.findNonZeros()函数将非零像素点的坐标提取出来,这样就得到了构成对象的像素点。我们还是在上面的图片上进行操作,代码如下:

    import numpy as np
    import cv2 as cv
    
    img=cv.imread("image.jpg",0)
    
    #为了显示方便,这里将图片进行缩放
    x,y=img.shape
    img=cv.resize(img,(y//2,x//2))
    #将图片二值化,由于前景物体是黑色的,因此在二值化时采用cv.THRESH_TOZERO_INV这种方式
    ret,thresh=cv.threshold(img,127,255,cv.THRESH_TOZERO_INV)
    #寻找图片中的轮廓,mode=cv.RETR_EXTERNAL,这是为了寻找最外层的轮廓
    im,contour,hierarchy=cv.findContours(thresh,cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE)
    #创建一个填充轮廓内像素点的画板,背景颜色为黑色,这里我们使用numpy创建一个全零的二维数组
    mask=np.zeros(img.shape,dtype=np.uint8)
    #将参数thickness设置为-1,这样cv.drawContours函数就会将轮廓内的像素点填充为指定的颜色
    mask=cv.drawContours(mask,contour,contourIdx=-1,color=(255,255,255),thickness=-1)
    
    #寻找mask内非零像素点,将其存放为一个numpy数组
    NonZeroPoints=np.array(cv.findNonZero(mask))
    #形状变换,将其改变为一个二维数组,数组的每一行存放一个非零像素点的坐标
    NonZeroPoints=NonZeroPoints.reshape((-1,2))
    #验证我们提取出来的像素点坐标是否正确,我们使用变量
    #column和row分别存放非零像素点在图像中坐标的列数和行数
    column=NonZeroPoints[:,0]
    row=NonZeroPoints[:,1]
    #在新的画板上将这些点绘制出来,将这些坐标对应的像素点的值设为255
    mask1=np.zeros(img.shape)
    mask1[row,column]=255
    #显示结果
    cv.imshow("mask",mask)
    cv.imshow("mask1",mask1)
    cv.waitKey(0)
    cv.destroyAllWindows()

    程序运行结果:

    通过上面两幅图的对比结果,我们可以看到:对象的组成像素点被正确地提取出来了。

     

     

     

  • 相关阅读:
    概率论与数理统计(3)
    平衡二叉树(AVL)实现(3)删除
    平衡二叉树(AVL)实现(1)
    利用C#2005实现数据表的基本操作
    用js计算时间差,得到比较人性化的结果
    WinForm 窗口最小化到托盘 notifyIcon
    wget 使用技巧
    使用javascript从url获取参数值
    OWC做电子表格和图表的试验
    C#中combobox 和TreeView控件属性、事件、方法收集
  • 原文地址:https://www.cnblogs.com/puheng/p/9351177.html
Copyright © 2020-2023  润新知