轮廓(python->opencv)

img = cv2.imread('contours.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
#传入绘制图像,轮廓,轮廓索引,颜色模式,线条厚度
# 注意需要copy,要不原图会变。。。
draw_img = img.copy()
res = cv2.drawContours(draw_img, contours, -1, (0, 0, 255), 2)#-1表示显示所有轮廓,123表示第123个轮廓
cv_show(res,'res')

代码解析

这段代码用于在图像上检测并绘制轮廓。以下是每一步的解析:
  1. 读取图像
img = cv2.imread('contours.png')
  • 使用OpenCV读取名为contours.png的图像。
  1. 转换为灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  • 将彩色图像转换为灰度图,以便进行阈值处理。
  1. 二值化处理
ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
  • 使用固定阈值对灰度图进行二值化处理,生成二值图像thresh。
  1. 查找轮廓
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
  • cv2.findContours函数用于查找二值图像中的轮廓。
  • cv2.RETR_TREE:检索所有层级的轮廓。
  • cv2.CHAIN_APPROX_NONE:存储所有的轮廓点。
  1. 绘制轮廓
draw_img = img.copy() res = cv2.drawContours(draw_img, contours, -1, (0, 0, 255), 2)
  • img.copy():创建图像的副本,避免修改原图像。
  • cv2.drawContours用于绘制轮廓:
    • contours:要绘制的轮廓集合。
    • -1:绘制所有轮廓。
    • (0, 0, 255):轮廓线条颜色(红色)。
    • 2:线条厚度。
  1. 显示结果
cv_show(res, 'res')
  • 使用自定义函数cv_show显示结果图像res。
  • 确保定义了cv_show,或者使用cv2.imshow替代。
def cv_show(image, title): cv2.imshow(title, image) cv2.waitKey(0) cv2.destroyAllWindows()

代码应用

  • 边缘检测与分析
  • 该代码可以用于图像中物体的边缘检测和分析。
  • 形状识别
  • 通过分析轮廓的形状,可以进行简单的形状识别和分类。

注意事项

  • 确保输入图像路径正确。
  • 调整阈值参数以适应不同的图像类型和对比度。
cnt = contours[0]
#面积
cv2.contourArea(cnt)
#周长,True表示闭合的
cv2.arcLength(cnt,True)
这段代码用于计算指定轮廓的面积和周长。以下是每一步的解析:

1. 选择轮廓

cnt = contours[0]
  • contours 是之前用 cv2.findContours 函数检测到的所有轮廓。
  • cnt = contours[0] 表示选择第一个轮廓。

2. 计算轮廓面积

cv2.contourArea(cnt)
  • cv2.contourArea(cnt) 用于计算给定轮廓 cnt 的面积。
  • 返回值是一个浮点数,表示轮廓内的像素总数。

3. 计算轮廓周长

cv2.arcLength(cnt, True)
  • cv2.arcLength(cnt, True) 用于计算给定轮廓 cnt 的周长。
  • cnt 是指定的轮廓。
  • 第二个参数 True 表示轮廓是闭合的。如果轮廓不是闭合的,应传 False。

完整代码示例

结合之前的代码:
import cv2 # 读取图像 img = cv2.imread('contours.png') # 转换为灰度图 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 二值化处理 ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY) # 查找轮廓 contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE) # 选择第一个轮廓 cnt = contours[0] # 计算面积 area = cv2.contourArea(cnt) print("Contour Area: ", area) # 计算周长 perimeter = cv2.arcLength(cnt, True) print("Contour Perimeter: ", perimeter) # 绘制轮廓 draw_img = img.copy() res = cv2.drawContours(draw_img, contours, -1, (0, 0, 255), 2) # 显示结果 def cv_show(image, title): cv2.imshow(title, image) cv2.waitKey(0) cv2.destroyAllWindows() cv_show(res, 'res')

应用场景

  1. 轮廓分析
  • 面积和周长是基本的几何特征,可以用于分析和分类不同的形状和物体。
  1. 形状识别
  • 通过计算面积和周长,可以进一步计算形状特征,比如圆度、长宽比等,以识别和分类不同形状的物体。
  1. 图像处理
  • 在图像增强、物体检测等任务中,这些几何特征可以提供有价值的信息。

注意事项

  • 确保轮廓 cnt 是有效的。如果 contours 为空,尝试其他预处理方法提高轮廓检测的效果。
  • 调整阈值参数 127,以适应不同的图像对比度和亮度。

轮廓近似

轮廓近似,用最少的线来代替,在几个点之间的直线,如果能用更少的点来表示,就采用更少的点。
轮廓近似是图像处理中常用的技术,用于简化轮廓,减少轮廓点的数量,从而用更少的直线段来表示轮廓。这种技术在形状识别和分析中非常有用。OpenCV 提供了一个函数 cv2.approxPolyDP 来执行轮廓近似。

轮廓近似算法

cv2.approxPolyDP 基于道格拉斯-普克曲线简化算法(Douglas-Peucker algorithm)。其基本思想是用少量的点来近似一个给定的轮廓曲线,使得近似后的曲线在视觉上和原始曲线非常接近。

代码示例

以下是如何使用 OpenCV 进行轮廓近似的示例代码:
import cv2 import numpy as np # 读取图像 img = cv2.imread('contours.png') # 转换为灰度图 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 二值化处理 ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY) # 查找轮廓 contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE) # 选择第一个轮廓 cnt = contours[0] # 计算轮廓的周长 epsilon = 0.01 * cv2.arcLength(cnt, True) # 进行轮廓近似 approx = cv2.approxPolyDP(cnt, epsilon, True) # 绘制原始轮廓和近似轮廓 draw_img = img.copy() cv2.drawContours(draw_img, [cnt], -1, (0, 0, 255), 2) # 红色表示原始轮廓 cv2.drawContours(draw_img, [approx], -1, (0, 255, 0), 2) # 绿色表示近似轮廓 # 显示结果 def cv_show(image, title): cv2.imshow(title, image) cv2.waitKey(0) cv2.destroyAllWindows() cv_show(draw_img, 'Approximated Contours')

参数说明

  1. cnt:要进行近似的轮廓。
  2. epsilon:近似精度,表示原始轮廓到近似轮廓的最大距离。该值越小,近似结果越精细。通常,epsilon 的值可以设置为轮廓周长的百分比,如 0.01 * cv2.arcLength(cnt, True)。
  3. True:表示轮廓是闭合的。

结果

  • 红色轮廓:表示原始轮廓。
  • 绿色轮廓:表示近似后的轮廓。

应用场景

  1. 形状简化
  • 通过轮廓近似,可以将复杂的形状简化为简单的多边形,这对于形状分析和识别非常有用。
  1. 形状匹配
  • 近似后的轮廓可以用于形状匹配和比较,减少计算复杂度。
  1. 图像压缩
  • 将复杂的轮廓简化为少量的直线段,可以用于图像数据的压缩和传输。

注意事项

  • 选择合适的 epsilon 值非常重要。epsilon 过大可能导致轮廓过度简化,失去原有形状的特征。epsilon 过小则可能无法起到简化作用。
  • 在实际应用中,可以通过实验调整 epsilon 值,以获得最优结果。
epsilon = 0.15*cv2.arcLength(cnt,True) #主要进行调参的函数
approx = cv2.approxPolyDP(cnt,epsilon,True)
draw_img = img.copy()
res = cv2.drawContours(draw_img, [approx], -1, (0, 0, 255), 2)
cv_show(res,'res')
这段代码旨在对轮廓进行近似,然后绘制近似后的轮廓。通过调整 epsilon 参数,可以控制轮廓近似的精度。以下是每一步的解析:

1. 计算近似参数 epsilon

epsilon = 0.15 * cv2.arcLength(cnt, True)
  • epsilon 是近似精度参数。
  • cv2.arcLength(cnt, True) 返回轮廓 cnt 的周长。
  • 0.15 是一个比例系数,表示原始轮廓到近似轮廓的最大距离。这个值可以根据需要进行调整。

2. 进行轮廓近似

approx = cv2.approxPolyDP(cnt, epsilon, True)
  • cv2.approxPolyDP 执行轮廓近似。
  • cnt 是要进行近似的轮廓。
  • epsilon 是近似精度。
  • True 表示轮廓是闭合的。

3. 绘制近似轮廓

draw_img = img.copy() res = cv2.drawContours(draw_img, [approx], -1, (0, 0, 255), 2)
  • draw_img = img.copy() 创建图像的副本,避免修改原图像。
  • cv2.drawContours(draw_img, [approx], -1, (0, 0, 255), 2) 绘制近似后的轮廓:
    • draw_img 是要绘制轮廓的图像。
    • [approx] 是近似后的轮廓。
    • -1 表示绘制所有层级的轮廓。
    • (0, 0, 255) 是轮廓线条的颜色(红色)。
    • 2 是线条厚度。

4. 显示结果

cv_show(res, 'res')
  • 使用自定义函数 cv_show 显示结果图像 res。

完整代码示例

为了让代码更完整,这里包括了前面的所有步骤:
import cv2 import numpy as np # 自定义显示函数 def cv_show(image, title): cv2.imshow(title, image) cv2.waitKey(0) cv2.destroyAllWindows() # 读取图像 img = cv2.imread('contours.png') # 转换为灰度图 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 二值化处理 ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY) # 查找轮廓 contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE) # 选择第一个轮廓 cnt = contours[0] # 计算近似参数 epsilon epsilon = 0.15 * cv2.arcLength(cnt, True) # 进行轮廓近似 approx = cv2.approxPolyDP(cnt, epsilon, True) # 绘制近似轮廓 draw_img = img.copy() res = cv2.drawContours(draw_img, [approx], -1, (0, 0, 255), 2) # 显示结果 cv_show(res, 'res')

调参建议

  • 0.15 的调整: 这个值是一个经验值,可以根据实际情况进行调整。值越大,轮廓近似的程度越高,轮廓会变得更加简化;值越小,轮廓近似的程度越低,轮廓会更加接近原始形状。
  • 实验性调整: 在实际应用中,你可以通过实验调整这个值,查看不同 epsilon 值下的效果,找到最佳的近似参数。

应用场景

  • 形状识别和分析: 通过近似后的轮廓,可以更容易地进行形状识别和分析,因为简化的轮廓减少了计算复杂度。
  • 图像压缩: 简化后的轮廓可以用于图像数据的压缩和传输。
  • 对象检测: 在对象检测中,简化后的轮廓可以提高检测的速度和准确性。
图中白色的是原图像,红色的是轮廓近似。
边界矩形
img = cv2.imread('contours.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
binary, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
cnt = contours[0]
x,y,w,h = cv2.boundingRect(cnt)
img = cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)
cv_show(img,'img')
你的代码旨在读取图像、进行预处理、查找轮廓,然后在图像上绘制一个包围轮廓的矩形。以下是每一步的详细解析及改进的代码示例。

代码解析

  1. 读取图像
img = cv2.imread('contours.png')
  1. 转换为灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  1. 二值化处理
ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
  1. 查找轮廓
binary, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
注意: 从 OpenCV 4.0 开始,cv2.findContours 只返回两个值:contours 和 hierarchy。在旧版本中返回三个值。
  1. 选择第一个轮廓
cnt = contours[0]
  1. 计算包围轮廓的矩形
x, y, w, h = cv2.boundingRect(cnt)
  1. 绘制矩形
img = cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
  1. 显示结果
cv_show(img, 'img')
下面是改进后的完整代码:

完整代码示例

import cv2 import numpy as np # 自定义显示函数 def cv_show(image, title): cv2.imshow(title, image) cv2.waitKey(0) cv2.destroyAllWindows() # 读取图像 img = cv2.imread('contours.png') # 转换为灰度图 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 二值化处理 ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY) # 查找轮廓 (适用于 OpenCV 4.0 及以上版本) contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE) # 选择第一个轮廓 cnt = contours[0] # 计算包围轮廓的矩形 x, y, w, h = cv2.boundingRect(cnt) # 绘制矩形 img = cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2) # 显示结果 cv_show(img, 'img')

关键点说明

  1. cv2.findContours
返回值
  • 在 OpenCV 4.0 及以上版本中,cv2.findContours 只返回 contours 和 hierarchy,而不是 binary。
  • 因此,你的代码中的 binary, contours, hierarchy 会引发错误,需要改为 contours, hierarchy = cv2.findContours(...)。
  1. cv2.boundingRect
  • cv2.boundingRect(cnt) 返回的 (x, y, w, h) 分别是矩形的左上角坐标 (x, y) 和矩形的宽度 w 及高度 h。
  1. 绘制矩形
  • cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2) 绘制的矩形颜色为绿色 (0, 255, 0),线条宽度为 2。

应用场景

  • 目标检测:绘制包围目标的矩形框,用于目标检测和识别。
  • 形状分析:通过计算包围矩形的宽和高,可以进行形状分析和统计。
  • 图像标注:将感兴趣的区域用矩形框标注出来,便于后续处理和分析。

注意事项

  • 选择适当的阈值 127 以适应不同的图像对比度和亮度。
  • 如果图像中有多个轮廓,可以选择其他轮廓进行绘制。你可以通过遍历 contours 列表来处理所有轮廓。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

张槊哲

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值