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

020 OpenCV 轮廓、外接圆、外接矩形

一、环境

本文使用环境为:

  • Windows10
  • Python 3.9.17
  • opencv-python 4.8.0.74

二、原理

2.1 函数接口

OpenCV中的findContours函数用于检测图像中的轮廓。轮廓是图像中连续的点集,它们通常表示物体的边缘或形状。在计算机视觉和图像处理中,轮廓分析是一种常见的任务,例如目标检测、形状识别等。

findContours函数的基本语法如下:

contours, hierarchy = cv.findContours(image, mode, method[, contours[, hierarchy[, offset ]]])

参数说明:

  • image:输入图像,通常是一个二值图像。
  • mode:轮廓检索模式。这个参数决定了函数如何返回轮廓。常见的模式有:
    • cv2.RETR_EXTERNAL:只检索最外层的轮廓。
    • cv2.RETR_LIST:检索所有轮廓并将其保存到列表中。
    • cv2.RETR_CCOMP:检索所有轮廓,并将它们组织到两个不同的层次结构中(例如,外部和内部)。
    • cv2.RETR_TREE:检索所有轮廓,并将它们组织到一个层次结构中。
  • method:轮廓的近似方法。常见的有:
    • cv2.CHAIN_APPROX_SIMPLE:压缩水平、垂直和对角分段。
    • cv2.CHAIN_APPROX_NONE:存储所有的段(4点)。
    • cv2.CHAIN_APPROX_SIMPLE 和 cv2.CHAIN_APPROX_DP:使用动态规划压缩轮廓。
  • contours(可选):输出参数,返回找到的轮廓。
  • hierarchy(可选):输出参数,返回有关轮廓之间关系的信息。
  • offset(可选):偏移量,用于调整轮廓的位置。

返回值:

  • 如果指定了 contours 参数,则返回找到的轮廓。
  • 如果指定了 hierarchy 参数,则返回有关轮廓之间关系的信息。

2.2 原理理解

在OpenCV库中,函数cv2.findContours()是一个用于查找图像中物体轮廓的重要工具。该函数的主要参数包括:输入图像、轮廓检索模式和近似方法等。

首先,输入的图像通常是二值化的单通道图像,其中黑色代表背景,白色代表目标物体。这样的图像通常通过Canny或拉普拉斯等边缘检测算子进行处理得到。

其次,轮廓检索模式决定了如何处理图像中的轮廓。例如,cv2.RETR_EXTERNAL只检测外轮廓;cv2.RETR_LIST检测的轮廓不建立等级关系;cv2.RETR_CCOMP建立两个等级的轮廓,上一层为外边界,内层为内孔的边界;而cv2.RETR_TREE则建立一个等级树结构的轮廓。

最后,近似方法决定了如何简化轮廓。例如,cv2.CHAIN_APPROX_SIMPLE就表示用尽可能少的像素点表示轮廓。

函数的返回值包括两个部分:contours和hierarchy。其中,contours是一个包含所有检测到的轮廓信息的数组,每个轮廓又是由若干个点所构成的;而hierarchy则是一个包含了各轮廓之间的层次关系的数组。

三、完整代码

from __future__ import print_function
import cv2 as cv
import numpy as np
import argparse
import random as rngrng.seed(12345)def thresh_callback(val):threshold = val# 使用canny检测边缘canny_output = cv.Canny(src_gray, threshold, threshold * 2)# 查找轮廓contours, _ = cv.findContours(canny_output, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)# 这里在分配空间contours_poly = [None]*len(contours)boundRect = [None]*len(contours)centers = [None]*len(contours)radius = [None]*len(contours) # 依据canny检测出来的边缘,下面查找边缘的轮廓、边缘的外接圆、外接矩形for i, c in enumerate(contours):contours_poly[i] = cv.approxPolyDP(c, 3, True) # 轮廓boundRect[i] = cv.boundingRect(contours_poly[i]) # 外接矩形centers[i], radius[i] = cv.minEnclosingCircle(contours_poly[i]) # 外接圆# 搞一张黑色的图,用于绘制drawing = np.zeros((canny_output.shape[0], canny_output.shape[1], 3), dtype=np.uint8)# 绘制轮廓、矩形、圆for i in range(len(contours)):color = (rng.randint(0,256), rng.randint(0,256), rng.randint(0,256))cv.drawContours(drawing, contours_poly, i, color)cv.rectangle(drawing, (int(boundRect[i][0]), int(boundRect[i][1])), \(int(boundRect[i][0]+boundRect[i][2]), int(boundRect[i][1]+boundRect[i][3])), color, 2)cv.circle(drawing, (int(centers[i][0]), int(centers[i][1])), int(radius[i]), color, 2) cv.imshow('Contours', drawing)parser = argparse.ArgumentParser(description='Code for Creating Bounding boxes and circles for contours tutorial.')
parser.add_argument('--input', help='Path to input image.', default='data/stuff.jpg')
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)# 彩色图转灰度图
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)# 创建滑条,控制canny查找边缘的阈值
max_thresh = 255
thresh = 100 # canny初始化阈值
cv.createTrackbar('Canny thresh:', source_window, thresh, max_thresh, thresh_callback)
thresh_callback(thresh)cv.waitKey()

相关文章:

  • Postman-脚本自动化及定时执行脚本(7)
  • Mac 中文版 Navicat Premium 16 下载安装详细教程
  • LeetCode力扣每日一题(Java):58、最后一个单词的长度
  • 内网服务器部署maven私服简记
  • 微信小程序map视野发生改变时切换定位点
  • 案例055:基于微信小程序的四六级词汇
  • 服务器被DDOS攻击如何用高防ip去防护?
  • 小程序开发实战案例四 | 小程序标题栏如何设置
  • 微信小程序:布局样式
  • Python实现多种图像锐化方法:拉普拉斯算子和Sobel算子
  • WPF-一个简单登录界面
  • 跨境电商如何利用跨境客服软件提升销售额
  • 使用FiscoBcos的Go-SDK【1:配置go环境】
  • hive数据仓库工具
  • 华为数通---配置基本QinQ示例
  • 网络传输文件的问题
  • .pyc 想到的一些问题
  • Java教程_软件开发基础
  • Java-详解HashMap
  • Python 使用 Tornado 框架实现 WebHook 自动部署 Git 项目
  • react 代码优化(一) ——事件处理
  • Sass 快速入门教程
  • WinRAR存在严重的安全漏洞影响5亿用户
  • Xmanager 远程桌面 CentOS 7
  • 彻底搞懂浏览器Event-loop
  • 基于 Ueditor 的现代化编辑器 Neditor 1.5.4 发布
  • 简单数学运算程序(不定期更新)
  • 将 Measurements 和 Units 应用到物理学
  • 开源SQL-on-Hadoop系统一览
  • 入职第二天:使用koa搭建node server是种怎样的体验
  • 少走弯路,给Java 1~5 年程序员的建议
  • #NOIP 2014# day.1 生活大爆炸版 石头剪刀布
  • #大学#套接字
  • #我与Java虚拟机的故事#连载05:Java虚拟机的修炼之道
  • $.each()与$(selector).each()
  • (4)事件处理——(6)给.ready()回调函数传递一个参数(Passing an argument to the .ready() callback)...
  • (Arcgis)Python编程批量将HDF5文件转换为TIFF格式并应用地理转换和投影信息
  • (二)学习JVM —— 垃圾回收机制
  • ./include/caffe/util/cudnn.hpp: In function ‘const char* cudnnGetErrorString(cudnnStatus_t)’: ./incl
  • .htaccess 强制https 单独排除某个目录
  • .MyFile@waifu.club.wis.mkp勒索病毒数据怎么处理|数据解密恢复
  • .net core开源商城系统源码,支持可视化布局小程序
  • .Net 代码性能 - (1)
  • .net程序集学习心得
  • .NET教程 - 字符串 编码 正则表达式(String Encoding Regular Express)
  • .NET开发人员必知的八个网站
  • .NET框架设计—常被忽视的C#设计技巧
  • .NET学习全景图
  • .Net转Java自学之路—基础巩固篇十三(集合)
  • .net最好用的JSON类Newtonsoft.Json获取多级数据SelectToken
  • @cacheable 是否缓存成功_让我们来学习学习SpringCache分布式缓存,为什么用?
  • @EnableConfigurationProperties注解使用
  • @transaction 提交事务_【读源码】剖析TCCTransaction事务提交实现细节
  • [ JavaScript ] JSON方法
  • [ 渗透工具篇 ] 一篇文章让你掌握神奇的shuize -- 信息收集自动化工具