Python OpenCV 图像区域轮廓标记(框选各种小纸条)
作者:梦想橡皮擦 发布时间:2023-12-18 05:42:08
学在前面
上篇 OpenCV 博客原计划完成一个 识别银行卡号 的项目,但是写的过程中发现,技术储备不足,我无法在下述图片中,提取出卡号区域,也就无法进行后续的识别了,再次意识到了自己技术还不达标,继续学习。完不成,就实现其它学习项目。
轮廓识别实战
先看一下最终实现的效果,针对一张图片(该图片前景色和背景色差异较大),进行轮廓标记。
图片基本处理
import cv2 as cv
src = cv.imread("./demo.jpg")
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
# cv.imshow("src", src)
gray = cv.GaussianBlur(gray, (5, 5), 0)
edges = cv.Canny(gray, 70, 210)
cv.imshow("edged", edges)
转换成灰度图,高斯模糊去噪,Canny 边缘检测,这些都是图像处理的基本函数,使用方法已经在前文进行过相关学习。
运行上述代码之后,获取基本边缘数据。
轮廓检测
下面就是检测图像轮廓具体位置的代码了:
contours, hierarchy = cv.findContours(edges.copy(), cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)
print(f"轮廓数量:{len(contours)}")
在 cv.findContours(edges, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)
中,第二个参数使用的是 cv.RETR_LIST
,该参数值表示检测所有轮廓,不建立等级关系,彼此独立。如果只想获取轮廓边缘信息,不关心是否嵌套在另一个轮廓之内,使用该参数值即可。
第三个参数使用的是 cv.CHAIN_APPROX_SIMPLE
,表示压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需 4 个点来保存轮廓信息,这也是为了后面便于计算。
观察上图,可以发现最外侧的边缘面积是最大的,所以依据面积进行排序,依据其他值也可以,获取面积最大的轮廓。
contours = sorted(contours, key = cv.contourArea, reverse = True)[:3]
对轮廓进行简单绘制,获得下图效果。
cv.drawContours(src,contours,-1,(0,0,255),2)
遍历轮廓,计算轮廓近似
先看代码:
# 遍历轮廓
for c in contours:
# 计算轮廓近似
peri = cv.arcLength(c, True)
approx = cv.approxPolyDP(c, 0.02 * peri, True)
一个新的函数 cv.arcLength
,该函数的原型如下:
retval = cv2.arcLength(curve, closed)
该函数用于计算轮廓的周长。
下面的 cv.approxPolyDP
函数原型如下:
approxCurve = cv2.approxPolyDP(curve, epsilon, closed[, approxCurve])
函数参数如下:
curve
:源图像的某个轮廓;epsilon
:距离值,表示多边形的轮廓接近实际轮廓的程度,值越小,越精确;closed
:轮廓是否闭合。
最重要的参数就是 epsilon
简单记忆为:该值越小,得到的多边形角点越多,轮廓越接近实际轮廓,该参数是一个准确度参数。
该函数返回值为轮廓近似多边形的角点。
绘制轮廓
最后判断,当上文返回的角点为 4 的时候,提取轮廓,代码如下:
# 遍历轮廓
for c in contours:
# 计算轮廓近似
peri = cv.arcLength(c, True)
approx = cv.approxPolyDP(c, 0.02 * peri, True)
# 当恰好是 4 个角点的时候,获取轮廓。
if len(approx) == 4:
screen_cnt = approx
break
# 结果显示
cv.drawContours(src, [screen_cnt], -1, (0, 0, 255), 2)
更换图片,进行再次轮廓检测,注意修改轮廓近似部分代码即可。
# 遍历轮廓
for c in contours:
# 计算轮廓近似
approx = cv.approxPolyDP(c, 30, True)
if len(approx) == 4:
screen_cnt = approx
break
来源:https://blog.csdn.net/hihell/article/details/114532181


猜你喜欢
- http://swik.net/Ajax/Ajax+Mistakes在某网站瞎逛时,发现这个链接,进去逛了逛,觉得很有意思,大家也可以去看看
- Google以其简洁的搜索框引领着互联网,搜索系统似乎成了每个网站必备品,甚至于是那些本身几乎是由静态页面组成的企业网站都要来个搜索功能,这
- python flask搭建web应用教程1.flask介绍2.所需工具和环境3.搭建flaskApp4.具体程序编写5.综上1.flask
- Python读写文件模式 1、r 打开只读文件,该文件必须存在。 2、r+ 打开可读写的文件,该文件必须存在。 3、w 打开只写文件,若文件
- 导读:分析时间序列数据的一种简单而有效的方法就是将时间序列数据可视化在一个图表上,这样我们就可以从中推断出某些假设。本文将以股价数据集为例,
- <% Rem Rem ## 在线升级类声明 Class Cls_oUpdate
- 什么是探索性数据分析(EDA)?EDA 是数据分析下的一种现象,用于更好地理解数据方面,例如: – 数据的主要
- 大家一定使用过 phpmyadmin 里面的数据库导入,导出功能,非常方便。但是在实际应用中,我发现如下几个问题:1、数据库超过一定尺寸,比
- 前端使用ajax进行数据交互时:$.ajax({ cache: false, type: "POST", url: {%
- 方法一、使用在父模板中使用{include file="child.tpl"}直接将子模板包含进来优点:1、有利于模块的
- 首先上一段程序:import numpy as nplist_a = list(range(10))print("list_a:
- 本文实例讲述了Yii2框架实现登陆添加验证码功能。分享给大家供大家参考,具体如下:models中LoginForm.phppublic $v
- 今天尝试了一下据说最好用的编译器Jupyter Lab,安装期间遇到了很多问题,以此为记录。1.安装jupyter labjupyter l
- 本文实例为大家分享了js动态时间显示 的具体代码,供大家参考,具体内容如下<!doctype html><html>
- 如下所示:1、计算总帧数import osimport cv2video_cap = cv2.VideoCapture('ffmpe
- SQL Server数据库如何获取TEXT字段的内容长度的方法,是通过DATALENGTH函数来实现的,接下来我们就通过DATALENGTH
- 这个是作者自己封装的一个钉钉机器人的包,目前只支持发文本格式、链接格式、markdown格式的消息,我们可以在很多场景用到这个,比如告警通知
- jupyter notebook的安装在这里都不赘述可以参考jupyter官网的步骤http://jupyter-notebook.read
- 首先创建如下的数组和矩阵,其中a,b为数组,A,B为矩阵import numpy as npa = np.arange(1,5).resha
- SQLServer中开启CDC之后,在某些情况下会导致事务日志空间被占满的现象为:在执行增删改语句(产生事务日志)的过程中提示,The tr