OpenCV—轮廓发现与对象测量

函数原型:

1、查找轮廓---findContours()

def findContours(image, mode, method, contours=None, hierarchy=None, offset=None)

image:输入图像,image必须为一个2值单通道图像

mode:表示轮廓的检索模式

  • CV_RETR_EXTERNAL表示只检测外轮廓
  • CV_RETR_LIST检测的轮廓不建立等级关系
  • CV_RETR_CCOMP建立两个等级的轮廓,上面的一层为外边界,里面的一层为内孔的边界信息。如果内孔内还有一个连通物体,这个物体的边界也在顶层。
  • CV_RETR_TREE建立一个等级树结构的轮廓。具体参考contours.c这个demo

method:轮廓的近似办法

  • CV_CHAIN_APPROX_NONE存储所有的轮廓点,相邻的两个点的像素位置差不超过1,即max(abs(x1-x2),abs(y2-y1))==1
  • CV_CHAIN_APPROX_SIMPLE压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息
  • CV_CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似算法

contours:检测的轮廓数组,每一个轮廓用一个point类型的vector表示

hiararchy:参数和轮廓个数相同,每个轮廓contours[ i ]对应4个hierarchy元素hierarchy[ i ][ 0 ] ~hierarchy[ i ][ 3 ],分别表示后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号,如果没有对应项,该值设置为负数。 

offset:表示代表轮廓点的偏移量,可以设置为任意值。对ROI图像中找出的轮廓,并要在整个图像中进行分析时,这个参数还是很有用的。 

2、绘制轮廓---drawContours()

def drawContours(image, contours, contourIdx, color, thickness=None, lineType=None, hierarchy=None, maxLevel=None, offset=None)

image: 目标图像, Mat类型对象即可
contours: 所有的输入轮廓, 每个轮廓存储为一个点向量
contourIdx: 轮廓绘制指示变量(索引), 若为负值, 则表示绘制所有轮廓
color: 绘制轮廓的颜色
thickness: 轮廓线条的粗细, 默认值1, 如果为负值, 则绘制轮廓内部, 可选宏 CV_FILLED
lineType: 线条类型, 默认值8
hierarcy: 可选的层次结构信息, 默认值noArray()
maxLevel: 表示用于绘制轮廓的最大等级, 默认值INT_MAX
offset: 可选的轮廓偏移参数, 默认值Point()

3、寻找凸包---convexHull() 

def convexHull(points, hull=None, clockwise=None, returnPoints=None)

points: 输入的二维点集, 可以填Mat类型或std::vector
hull: 函数调用后找到的凸包
clockwise: 操作方向标志符, 当为true时, 输出的凸包为顺时针方向, false为逆时针方向(假定坐标系x轴指向右,y轴指向上方)
returnPoints: 操作标志符, 默认值true. 当标志符为true时, 函数返回凸包各个点, 否则返回凸包各点的指数, 当输出数组是std::vector时, 此标志被忽略

4、凸包缺陷分析---convexityDefects()

def convexityDefects(contour, convexhull, convexityDefects=None)

contour: 表示输入参数检测到的轮廓, 可以用findContours函数获得
convexhull: 输入参数表示检测到的凸包, 可以用convexHull函数获得
convexityDefects: 检测到的最终结果, 应为vector<vector<Vec4i>>类型, Vec4i存储了起始点、结束点、距离及最远点到凸包的距离

5、轮廓外接矩形---boundingRect() 

def boundingRect(array)

6、轮廓最小外接矩形---minAreaRect()

def minAreaRect(points)

points: 输入的二维点集, 可以填Mat类型或std::vector

返回值: RotatedRect类矩形对象, 外接旋转矩形主要成员有center、size、 angle、points

7、轮廓最小外接圆---minEnclosingCircle()

def minEnclosingCircle(points)

8、轮廓椭圆拟合---fitEllipse()

def fitEllipse(points)

points: 输入的二维点集, 可以填Mat类型或std::vector

返回值: RotatedRect类旋转矩形对象

 9、逼近多边形曲线---approxPolyDP()

def approxPolyDP(curve, epsilon, closed, approxCurve=None)

curve: 输入的二维点集, 可以填Mat类型或std::vector
epsilon: 逼近的精度, 为原始曲线和近似曲线间的最大值
closed: 如果其为真, 则近似的曲线为封闭曲线, 否则近似的曲线不封闭
approxCurve: 多边形逼近的结果, 其类型和输入二维点集类型一致

 10、计算轮廓面积---contourArea()

def contourArea(contour, oriented=None)

contour: 输入的二维点集或轮廓, 可以填Mat类型或std::vector

oriented: 默认值false, 表示返回面积为绝对值, 负责带符号

返回值: double类型返回轮廓面积

11、计算轮廓长度---arcLength()

def arcLength(curve, closed)

curve: 输入的二维点集, 可以填Mat类型或std::vector

colsed: 用于指示曲线是否封闭的标识符, 默认值true, 表示曲线封闭

返回值: double类型返回轮廓长度

12、计算点与轮廓的距离及位置关系---pointPolygonTest()

def pointPolygonTest(contour, pt, measureDist)

 contour: 所需检测的轮廓对象
pt: Point2f 类型的pt, 待判定位置的点
measureDist: 是否计算距离的标志, 当其为true时, 计算点到轮廓的最短距离, 当其为false时, 只判定轮廓与点的位置关系, 具体关系如下:
    ①返回值为-1, 表示点在轮廓外部

    ②返回值为0, 表示点在轮廓上

    ③返回值为1, 表示点在轮廓内部

13、矩的计算---moments() 

def moments(array, binaryImage=None)

array: 输入参数, 可以是光栅图像或二维数组

binaryImage:默认值false, 非零像素取其本身值, 若为true, 则非零像素取1

返回值: Moments类的对象, 返回对应的轮廓的空间矩/中心矩和归一化中心矩(最高3阶)

14、形状匹配---matchShapes()

def matchShapes(contour1, contour2, method, parameter)

 contour1: 所需比较的轮廓1

contour2: 所需比较的轮廓2

method: 轮廓比较的方法

parameter: 比较方法的特殊参数(目前不支持)

15、颜色空间转换---cvtColor()

def cvtColor(src, code, dst=None, dstCn=None)
cv.cvtColor(gaus,cv.COLOR_BGR2GRAY)

16、颜色区间范围删选---inRange()

def inRange(src, lowerb, upperb, dst=None)

src: 输入原图或数组

lowerb: 低边界或者颜色阈值

upperb: 高边界或者颜色阈值

dst: 输出目标图像, 需要和原图一样的size并且类型需为CV_8U

测试:

1、轮廓发现

import cv2 as cv


def canny_demo(img):
    gaus = cv.GaussianBlur(img, (3, 3), 0)
    gray = cv.cvtColor(gaus,cv.COLOR_BGR2GRAY)
    grad_x = cv.Sobel(gray, cv.CV_16SC1, 1, 0)
    grad_y = cv.Sobel(gray, cv.CV_16SC1, 0, 1)
    edge_out = cv.Canny(grad_x, grad_y, 50, 150)  # 黑白的边缘 高低阈值比值为2:1或3:1最佳(50:150 = 1:3)
    return edge_out


def contour_demo(img):


    # dst = cv.GaussianBlur(img, (3, 3), 0)
    # gray = cv.cvtColor(dst, cv.COLOR_BGR2GRAY)
    # ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_OTSU)
    # cv.imshow("binary", binary)

    binary = canny_demo(img)

    contours, heriachy = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
    cv.imshow("binary", binary)
    for i, contour in enumerate(contours):
        cv.drawContours(img, contours, i, (0, 0, 0), 3)
    cv.imshow("contour", img)


src = cv.imread("./../img/b.png")  # 读取图像
cv.namedWindow("input img", cv.WINDOW_AUTOSIZE)
cv.imshow("input img", src)  # 显示图像
contour_demo(src)
cv.waitKey(0)
cv.destroyAllWindows()

2、对象测量 

import cv2 as cv
import numpy as np


def measure_object(img):
    gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
    ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV | cv.THRESH_OTSU)
    contours, hierarchy = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE, contours=None, hierarchy=None)
    for i, contour in enumerate(contours):
        area = cv.contourArea(contour)
        x, y, w, h = cv.boundingRect(contour)
        men = cv.moments(contour)
        type(men)
        cx = men['m10'] / men['m00']
        cy = men['m01'] / men['m00']
        cv.circle(img, (np.int(cx), np.int(cy)), 3, (0, 0, 255), -1)
        cv.rectangle(img, (x, y), (x + w, y + h), (0, 255 ,255), 2)
    cv.imshow("measure", img)


src = cv.imread("./../img/num.png") # 读取图像
cv.namedWindow("input img", cv.WINDOW_AUTOSIZE)
cv.imshow("input img", src) # 显示图像
measure_object(src)
cv.waitKey(0)
cv.destroyAllWindows()

import cv2 as cv
import numpy as np


def measure_object(img):
    gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
    ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV | cv.THRESH_OTSU)
    contours, hierarchy = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE, contours=None, hierarchy=None)
    bgr = cv.cvtColor(binary, cv.COLOR_GRAY2BGR)
    for i, contour in enumerate(contours):
        area = cv.contourArea(contour)
        x, y, w, h = cv.boundingRect(contour)
        men = cv.moments(contour)
        type(men)
        cx = men['m10'] / men['m00']
        cy = men['m01'] / men['m00']
        cv.circle(bgr, (np.int(cx), np.int(cy)), 3, (0, 0, 255), -1)
        cv.rectangle(bgr, (x, y), (x + w, y + h), (0, 255 ,255), 2)
        approx = cv.approxPolyDP(contour, 4, True)
        if approx.shape[0] > 5:
            cv.drawContours(bgr, contours, i, (0, 255, 0), 2)
        if approx.shape[0] == 4:
            cv.drawContours(bgr,contours, i, (0 , 0, 255), 2)
    cv.imshow("measure", bgr)


src = cv.imread("./../img/b.png") # 读取图像
cv.namedWindow("input img", cv.WINDOW_AUTOSIZE)
cv.imshow("input img", src) # 显示图像
measure_object(src)
cv.waitKey(0)
cv.destroyAllWindows()

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python中的OpenCV库是一个广泛使用的计算机视觉库,提供了许多图像处理和分析的功能。其中包括轮廓提取和抠图的功能。 在OpenCV中,可以使用函数`findContours()`来提取图像中的轮廓。该函数接受一个二值化图像作为输入,并返回一个包含所有轮廓点的列表。具体步骤如下: 1. 将图像进行二值化处理,使得背景为黑色(像素值为0),感兴趣的对象为白色(像素值为255)。 2. 使用`findContours()`函数提取轮廓。该函数会修改输入图像,所以需要首先对输入图像进行备份。 3. `findContours()`函数返回两个值:轮廓点的列表和层级信息。我们只需要轮廓点的列表,可以使用索引0来获取。 4. 可以通过绘制轮廓来查看或显示轮廓,使用`drawContours()`函数可以实现该功能。 抠图是将感兴趣的对象从图像中分离出来形成一个新的图像。可以使用OpenCV中的函数`bitwise_and()`来实现抠图。具体步骤如下: 1. 选择一个感兴趣的对象,并使用函数`findContours()`提取其轮廓。 2. 创建一个与原图像尺寸相同的空白图像(全黑)作为抠图结果。 3. 使用函数`drawContours()`将感兴趣的对象轮廓绘制到空白图像上。 4. 使用`bitwise_and()`函数将原图像和抠图结果进行按位与操作,将背景部分变为黑色。可以使用反色操作将背景变为白色。 5. 得到的结果即为抠图后的图像。 总而言之,Python中的OpenCV库提供了丰富的图像处理功能,使用其提供的函数可以轻松实现图像的轮廓提取和抠图操作。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值