当前位置: 首页 > news >正文

【python】OpenCV—findContours(4.3)

在这里插入图片描述

文章目录

  • 1、功能描述
  • 2、代码实现
  • 3、完整代码
  • 4、结果展示
  • 5、涉及到的库函数
    • 5.1、cv2.Canny
    • 5.2 cv2.boxPoints
  • 6、参考

1、功能描述

找出图片中的轮廓,拟合轮廓外接椭圆和外接矩阵

2、代码实现

导入必要的库,固定好随机种子

import cv2 as cv
import numpy as np
import argparse
import random as rngrng.seed(12345)

读取输入图片,判定图片是否读入成功

parser = argparse.ArgumentParser(description='Code for Creating Bounding rotated boxes and ellipses for contours tutorial.')
parser.add_argument('--input', help='Path to input image.', default='1.png')
args = parser.parse_args()
src = cv.imread(cv.samples.findFile(args.input))if src is None:print('Could not open or find the image:', args.input)exit(0)

灰度化图片,并平滑

# Convert image to gray and blur it
src_gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
src_gray = cv.blur(src_gray, (3, 3))
source_window = 'Source'
cv.namedWindow(source_window)
cv.imshow(source_window, src)

创建滚动条,动态配置参数,随着滑动条的滑动实现不同的算法效果

max_thresh = 255
thresh = 100  # initial threshold
cv.createTrackbar('Canny Thresh:', source_window, thresh, max_thresh, thresh_callback)
thresh_callback(thresh)
cv.waitKey()

算法核心函数 thresh_callback,下面具体看看细节

def thresh_callback(val):global src_graythreshold = valsrc_gray = cv.GaussianBlur(src_gray, (3, 3), 0.1)canny_output = cv.Canny(src_gray, threshold, threshold * 2)

高斯模糊,canny 算子

    contours, _ = cv.findContours(canny_output, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)# Find the rotated rectangles and ellipses for each contourminRect = [None] * len(contours)minEllipse = [None] * len(contours)for i, c in enumerate(contours):minRect[i] = cv.minAreaRect(c)if c.shape[0] > 5:minEllipse[i] = cv.fitEllipse(c)# Draw contours + rotated rects + ellipses

找出轮廓,遍历轮廓,最小外接矩形框直接调用 cv2.minAreaRect 即可

如果轮廓多于 5 个点,cv2.fiEllipse 找椭圆

    # Draw contours + rotated rects + ellipsesdrawing = np.zeros((canny_output.shape[0], canny_output.shape[1], 3), dtype=np.uint8)for i, c in enumerate(contours):color = (rng.randint(0, 256), rng.randint(0, 256), rng.randint(0, 256))# contourcv.drawContours(drawing, contours, i, color)# ellipseif c.shape[0] > 5:cv.ellipse(drawing, minEllipse[i], color, 2)# rotated rectanglebox = cv.boxPoints(minEllipse[i])# box = cv.boxPoints(minRect[i])box = np.intp(box)  # np.intp: Integer used for indexing (same as C ssize_t; normally either int32 or int64)# box = np.int0(box)  # normally either int32 or int64)cv.drawContours(drawing, [box], 0, color)cv.imshow('Contours', drawing)cv.imshow("Canny", canny_output)

绘制轮廓,轮廓外接矩阵,轮廓拟合出来的椭圆,随机颜色

注意 box = cv.boxPoints(minEllipse[i]) 绘制的是椭圆的外接矩阵,而 box = cv.boxPoints(minRect[i]) 绘制轮廓的外接矩阵被注释掉了

3、完整代码

import cv2 as cv
import numpy as np
import argparse
import random as rngrng.seed(12345)def thresh_callback(val):global src_graythreshold = valsrc_gray = cv.GaussianBlur(src_gray, (3, 3), 0.1)canny_output = cv.Canny(src_gray, threshold, threshold * 2)contours, _ = cv.findContours(canny_output, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)# Find the rotated rectangles and ellipses for each contourminRect = [None] * len(contours)minEllipse = [None] * len(contours)for i, c in enumerate(contours):minRect[i] = cv.minAreaRect(c)if c.shape[0] > 5:minEllipse[i] = cv.fitEllipse(c)# Draw contours + rotated rects + ellipsesdrawing = np.zeros((canny_output.shape[0], canny_output.shape[1], 3), dtype=np.uint8)for i, c in enumerate(contours):color = (rng.randint(0, 256), rng.randint(0, 256), rng.randint(0, 256))# contourcv.drawContours(drawing, contours, i, color)# ellipseif c.shape[0] > 5:cv.ellipse(drawing, minEllipse[i], color, 2)# rotated rectanglebox = cv.boxPoints(minEllipse[i])# box = cv.boxPoints(minRect[i])box = np.intp(box)  # np.intp: Integer used for indexing (same as C ssize_t; normally either int32 or int64)# box = np.int0(box)  # normally either int32 or int64)cv.drawContours(drawing, [box], 0, color)cv.imshow('Contours', drawing)cv.imshow("Canny", canny_output)parser = argparse.ArgumentParser(description='Code for Creating Bounding rotated boxes and ellipses for contours tutorial.')
parser.add_argument('--input', help='Path to input image.', default='1.png')
args = parser.parse_args()
src = cv.imread(cv.samples.findFile(args.input))if src is None:print('Could not open or find the image:', args.input)exit(0)# Convert image to gray and blur it
src_gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
src_gray = cv.blur(src_gray, (3, 3))
source_window = 'Source'
cv.namedWindow(source_window)
cv.imshow(source_window, src)
max_thresh = 255
thresh = 100  # initial threshold
cv.createTrackbar('Canny Thresh:', source_window, thresh, max_thresh, thresh_callback)
thresh_callback(thresh)
cv.waitKey()

4、结果展示

Canny Thresh:0

在这里插入图片描述

Canny Thresh:5
在这里插入图片描述

Canny Thresh:15
在这里插入图片描述

Canny Thresh:25
在这里插入图片描述

Canny Thresh:35

在这里插入图片描述
Canny Thresh:45
在这里插入图片描述

Canny Thresh:100

在这里插入图片描述

Canny Thresh:150

在这里插入图片描述

Canny Thresh:200

在这里插入图片描述

Canny Thresh:255
在这里插入图片描述

5、涉及到的库函数

5.1、cv2.Canny

cv2.Canny 是 OpenCV 库中用于边缘检测的一个函数,它实现了 Canny 边缘检测算法。Canny 边缘检测是一种非常流行的边缘检测算法,由 John F. Canny 在 1986 年提出。这个算法旨在寻找图像中的最优边缘,它通过应用多尺度高斯滤波来减少噪声,然后计算图像梯度,接着通过非极大值抑制和滞后阈值化来检测边缘。

edges = cv2.Canny(image, threshold1, threshold2[, edges[, apertureSize[, L2gradient]]])
  • image:输入的灰度图像。在进行 Canny 边缘检测之前,通常需要先将图像转换为灰度图像。
  • threshold1:第一个阈值,用于滞后阈值化中的低阈值。
  • threshold2:第二个阈值,用于滞后阈值化中的高阈值。只有那些梯度值高于 threshold2 的像素才会被当作边缘,而梯度值位于 threshold1 和 threshold2 之间的像素只有在它们连接到高阈值边缘时才会被接受。
  • edges:输出参数,用于存储检测到的边缘。如果不指定,则会自动创建一个同大小的输出图像。
  • apertureSize:Sobel 算子的大小,默认为 3。这个参数影响梯度计算的精度,但增加大小也会增加计算时间。
  • L2gradient:一个布尔值,指示是否使用更精确的 L2 范数来计算图像梯度幅值。默认值为 False,即使用 L1 范数(即简单地将梯度在 x 和 y 方向的分量相加)。

返回值:

  • edges:一个二值图像,其中检测到的边缘像素被设置为白色(255),其他像素被设置为黑色(0)。

Canny 边缘检测的优点在于它能够有效地抑制噪声,并且检测到的边缘通常是连续的。然而,它的效果也依赖于所选的阈值,因此在实际应用中,可能需要根据具体情况调整 threshold1 和 threshold2 的值。

5.2 cv2.boxPoints

cv2.boxPoints 用于计算给定矩形旋转后的顶点坐标。这个函数在需要处理旋转矩形时非常有用,比如在图像中绘制旋转的边界框时

points = cv2.boxPoints(box[, rotMat])

参数解释:

  • box:表示矩形的参数。这可以是一个包含四个元素的元组或列表 (center_x, center_y, width, height),其中 (center_x, center_y) 是矩形中心的坐标,width 和 height 分别是矩形的宽度和高度(注意:这里的宽度和高度是按照矩形的原始大小,不考虑旋转)。在某些版本的 OpenCV 中,box 也可能是一个 cv2.RotatedRect 对象。
  • rotMat:可选参数,表示旋转矩阵。这是一个 2x3 的浮点数数组,用于指定对矩形进行额外旋转的角度。如果未提供此参数,则矩形不会被额外旋转,只返回根据 box 参数计算出的四个顶点坐标。

返回值:

  • points:一个包含四个点的 NumPy 数组,每个点都是一个包含两个元素的元组或列表 (x, y),表示旋转后矩形的顶点坐标。

需要注意的是,如果 box 是一个 cv2.RotatedRect 对象,那么它本身就包含了旋转信息(即旋转角度和中心点),此时 rotMat 参数将被忽略,因为 cv2.RotatedRect 已经定义了矩形的旋转状态。

示例代码:

import cv2  
import numpy as np  # 定义一个中心点、宽度、高度的矩形  
center = (100, 100)  
width = 200  
height = 100  
angle = 45  # 旋转角度(以度为单位)  # 创建一个旋转矩形对象  
rect = cv2.RotatedRect(center, (width, height), angle)  # 获取旋转矩形的顶点  
points = cv2.boxPoints(rect)  
points = np.intp(points)  # 将坐标转换为整数类型,以便在图像上绘制  # 创建一个黑色图像  
image = np.zeros((256, 256, 3), dtype=np.uint8)  # 在图像上绘制旋转矩形的边  
for i in range(4):  cv2.line(image, tuple(points[i]), tuple(points[(i+1)%4]), (255, 0, 0), 2)  
# 显示图像  
cv2.imshow('Rotated Rectangle', image)  
cv2.waitKey(0)  
cv2.destroyAllWindows()

在这里插入图片描述

在这个示例中,我们首先定义了一个矩形的中心点、宽度、高度和旋转角度,然后创建了一个 cv2.RotatedRect 对象来表示这个旋转矩形。接着,我们使用 cv2.boxPoints 函数来获取旋转矩形的顶点坐标,并在一个黑色图像上绘制了这个矩形的边。最后,我们显示了包含旋转矩形的图像。

6、参考

  • 根据轮廓创建旋转框和椭圆
  • 【python】OpenCV—findContours(4.2)
http://www.lryc.cn/news/477255.html

相关文章:

  • 前端通过nginx部署一个本地服务的方法
  • Linux:防火墙和selinux对服务的影响
  • 从 vue 源码看问题 — vue 如何进行异步更新?
  • 【go从零单排】go中的基本数据类型和变量
  • 标签之文字排版,图片,链接,音视频(HTML) 基础版
  • 基于SpringBoot+Gpt个人健康管家管理系统【提供源码+答辩PPT+参考文档+项目部署】
  • 十四届蓝桥杯STEMA考试Python真题试卷第二套第一题
  • 【Windows修改Docker Desktop(WSL2)内存分配大小】
  • 阿里云-部署CNI flannel集群网络
  • favicon是什么文件?如何制作网站ico图标?
  • Linux云计算个人学习总结(一)
  • DCRNN解读(论文+代码)
  • 雷池社区版新版本功能防绕过人机验证解析
  • 一文详解开源ETL工具Kettle!
  • 《IMM交互式多模型滤波MATLAB实践》专栏目录,持续更新……
  • 解决数据集中xml文件类别标签的首字母大小写不一致问题
  • 手边酒店多商户版V2源码独立部署_博纳软云
  • 32位汇编——通用寄存器
  • vue3项目中实现el-table分批渲染表格
  • 开源办公软件 ONLYOFFICE 深入探索
  • 原生鸿蒙应用市场:开发者的新机遇与深度探索
  • MATLAB实现蝙蝠算法(BA)
  • WPF使用Prism框架首页界面
  • Linux中的软硬链接文件详解
  • 「Mac畅玩鸿蒙与硬件18」鸿蒙UI组件篇8 - 高级动画效果与缓动控制
  • pgsql数据量大之后可能遇到的问题
  • Android 解决MTK相机前摄镜像问题
  • 在 Oracle 数据库中,SERVICE_NAME 和 SERVICE_NAMES 有什么区别?
  • 【Maven】——基础入门,插件安装、配置和简单使用,Maven如何设置国内源
  • AIGC时代LaTeX排版的应用、技巧与未来展望