python使用opencv查找轮廓_Python+opencv学习记录20:轮廓发现,Pythonopencv

1.轮廓发现

轮廓发现是基于图像边缘提取的基础寻找对象轮廓的方法,所以边缘提取的阈值选定会影响最终轮廓发现结果。

1.1发现轮廓

在此步骤中我们会使用到findContours这个API,其原型为:

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

注:opencv3会返回三个值,分别是img, countours, hierarchy;

而opencv4中只有 countours, hierarchy两个返回值

第一个参数是寻找轮廓的图像;

第二个参数表示轮廓的检索模式,有四种:

(1)RETR_EXTERNAL表示只检测外轮廓

(2)RETR_LIST检测的轮廓不建立等级关系

(3)RETR_CCOMP建立两个等级的轮廓,上面的一层为外边界,里面的一层为内孔的边界信息

(4)RETR_TREE建立一个等级树结构的轮廓

其中最常用的是第一种和第四种。

第三个参数method为轮廓的近似办法:

(1)CHAIN_APPROX_NONE存储所有的轮廓点,相邻的两个点的像素位置差不超过1,即max(abs(x1-x2),abs(y2-y1))==1

(2)CHAIN_APPROX_SIMPLE压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息

(3)CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似算法

1.2绘制轮廓

在绘制轮廓时我们会用到drawContours该API,其原型为:

cv2.drawContours(image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset ]]]]])

第一个参数是指明在哪幅图像上绘制轮廓;

第二个参数是是轮廓本身,在Python中是一个list;

第三个参数指定绘制轮廓list中的哪条轮廓,如果是-1,则绘制其中的所有轮廓;

之后的参数分别为线的颜色和线宽。

2.操作步骤

1.转换图像为二值化图像:threshold方法或者Canny边缘提取获取的都是二值化图像;

2.通过二值化图像寻找轮廓:findContours;

3.描绘轮廓:drawContours。

2.1阈值法获取轮廓

其代码为:

def conters_demo(image):

dst = cv.GaussianBlur(image, (3, 3), 0) # 图像降噪模糊

gray = cv.cvtColor(dst, cv.COLOR_BGR2GRAY)

ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_OTSU | cv.THRESH_BINARY)# 用大律法、全局自适应阈值方法进行图像二值化

cv.imshow("binary_image", binary)

contours, heriachy = cv.findContours(binary, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE) # RETR_TREE检测内部

# contours, heriachy = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE) # RETR_EXTERNAL检测外部轮廓

for i, contour in enumerate(contours):

cv.drawContours(image, contours, i, (0, 0, 255), 2) # 绘制轮廓

# cv.drawContours(image, contours, i, (0, 0, 255), -1) # 填充轮廓

print(i)

cv.imshow("detect_contours", image)

原图为:

经过二值化后:

绘制其轮廓后:

2.2使用Canny边缘检测获取轮廓

代码为:

def edge_demo(image):

blur = cv.GaussianBlur(image, (3, 3), 0) # 降低噪声

gray = cv.cvtColor(blur, cv.COLOR_BGR2GRAY)

# x方向的梯度

xgrad = cv.Sobel(gray, cv.CV_16SC1, 1, 0)

# y方向的梯度

ygrad = cv.Sobel(gray, cv.CV_16SC1, 0, 1)

# 求出图像的边缘

edge_output = cv.Canny(xgrad, ygrad, 50, 150)

cv.imshow("Canny_Edge", edge_output)

return edge_output

def conters_demo(image):

binary = edge_demo(image)

contours, heriachy = cv.findContours(binary, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE) # RETR_TREE检测内部

# contours, heriachy = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE) # RETR_EXTERNAL检测外部轮廓

for i, contour in enumerate(contours):

cv.drawContours(image, contours, i, (0, 0, 255), 2) # 绘制轮廓

# cv.drawContours(image, contours, i, (0, 0, 255), -1) # 填充轮廓

print(i)

cv.imshow("detect_contours", image)

Canny边缘检测后的结果为:

绘制其轮廓为:

完整代码

import cv2 as cv # 导入opencv模块

import numpy as np # 导入数学函数库

def edge_demo(image):

blur = cv.GaussianBlur(image, (3, 3), 0) # 降低噪声

gray = cv.cvtColor(blur, cv.COLOR_BGR2GRAY)

# x方向的梯度

xgrad = cv.Sobel(gray, cv.CV_16SC1, 1, 0)

# y方向的梯度

ygrad = cv.Sobel(gray, cv.CV_16SC1, 0, 1)

# 求出图像的边缘

edge_output = cv.Canny(xgrad, ygrad, 50, 150)

cv.imshow("Canny_Edge", edge_output)

return edge_output

def conters_demo(image):

""""""

dst = cv.GaussianBlur(image, (3, 3), 0) # 图像降噪模糊

gray = cv.cvtColor(dst, cv.COLOR_BGR2GRAY)

ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_OTSU | cv.THRESH_BINARY)# 用大律法、全局自适应阈值方法进行图像二值化

cv.imshow("binary_image", binary)

# binary = edge_demo(image)

contours, heriachy = cv.findContours(binary, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE) # RETR_TREE检测内部

# contours, heriachy = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE) # RETR_EXTERNAL检测外部轮廓

for i, contour in enumerate(contours):

cv.drawContours(image, contours, i, (0, 0, 255), 2) # 绘制轮廓

# cv.drawContours(image, contours, i, (0, 0, 255), -1) # 填充轮廓

print(i)

cv.imshow("detect_contours", image)

print("------------hello python!------------")

src = cv.imread("D:/opencv3/image/huafen.jpg")

cv.namedWindow("input_image", cv.WINDOW_AUTOSIZE)

cv.imshow("input_image", src)

conters_demo(src)

cv.waitKey(0)

cv.destroyAllWindows() # 释放所有窗口

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/304701.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

今天,送你一份交通行业最全数据集(共享单车、自动驾驶、网约出租车、交通信号识别)

近几年来共享单车、自动驾驶等交通行业发展得如荼如火,小编也一直有意识地收集相关数据集,经过长时间的积累和沉淀,已经拥有将近300G的交通数据,内容涵盖国内外“自动驾驶”、“共享单车”、“网约出租车”、“交通信号识别”等方…

空谈Saas都扯淡,让你看看真正的云计算

最近“虚拟化”的话题似乎热度有所降低,而“云计算”的概念却不断升温,就连Vmware的新的服务器虚拟化产品,都要加上一个第一款“云计算”操作系统,而正如hubisheng兄弟在《名头不小!!VMware vSphere实为VI升…

重要的是改变命运,而非升职加薪

阅读本文大概需要4分钟。写公众号以来,被问的最多的问题就是工作选择。在这件事上,很多读者明显会更重视薪资、福利、Title,而不是:未来会怎么样。就在昨天,又有一个读者问我Offer选择的问题,给出建议后&am…

python中的成员运算符是干嘛的_在Python中使用成员运算符的示例

下表列出了所有Python语言支持的成员运算符。例如:试试下面的例子就明白了所有的Python编程语言提供会员运算符:#!/usr/bin/pythona 10b 20list [1, 2, 3, 4, 5 ];if ( a in list ):print "Line 1 - a is available in the given list"else…

前方高能 | 你写过什么有趣的程序?最后一个笑出猪叫

苍冥 说:我们从高一到高三都强制采用图形计算器,可以画函数图像的那种。我们用的是德州仪器系列,Ti-Nspire,贵的要死要死的。然而我却买错了计算器的制式,便宜货,相比其他同学的系统少了很多重要的功能。作…

鼠标 . 软驱 . 打印机 . 硬盘. 风扇 . 常见事故处理 -

鼠标 . 软驱 . 打印机 . 硬盘. 风扇 . 常见事故处理 -鼠标鼠标的故障分析与维修比较简单,大部分故障为接口或按键接触不良、断线、机械定位系统污垢等原因造成的。少数故障为鼠标内部元器件或电路虚焊造成的,这主要存在于某些劣质产品中,其中…

php mysql 云虚拟机_虚拟机+apache+php+mysql 环境安装配置

虚拟机的安装:直接下一步即可,注意修改路径。安装完成后新建虚拟机,直接下一步。如果选择镜像文件后出现错误,可以试着去修改电脑bios中的虚拟化设置,改为enable,如下图:apache安装:…

python逐行读取数据时出现错误_python如何逐行读取数据

在实际开发的过程中,文件读写也很重要,下面说一下python如何逐行读取文件。如果程序要读取行,通常只能用文本方式来读取,道理很简单,只有文本文件才有行的概念,二进制文件没有所谓行的概念。文件对象提供了…

日志框架NLog之将日志发送到邮件

背景NLog可以将日志输出到不同的媒介上&#xff0c;邮件是其中一个&#xff0c;通过邮件可以让我们第一时间收到信息。使用SMTP协议通过电子邮件发送日志消息。与FallbackGroup Target很好地结合在一起&#xff0c;以创建具有多个SMTP主机的后备。配置语法<targets><t…

简单六步,用数据说服你的听众

“相比表格&#xff0c;利用数据图展现数据的方法有可观的优势。庞大的数据令人厌烦&#xff0c;普通人在其中根本获取不到有用的信息&#xff0c;就像从黄瓜里面汲取不到阳光一样。”——摘取自《Economic and Industrial Delusions》一书&#xff0c;作者Arthur Briggs Farqu…

CCNA第五章WAN连接

转载于:https://blog.51cto.com/centrevy/176434

探索 .NET Core 依赖注入的 IServiceCollection

如果您使用了.NET Core&#xff0c;则很可能已使用Microsoft.Extensions.DependencyInjection中的内置依赖项注入容器&#xff0c;在本文中&#xff0c;我想更深入地了解Microsoft Dependency Injection&#xff08;DI&#xff09;容器中的 IServiceCollection。什么是依赖注入…

dev可以运行mysql文件夹_Linux查看mysql 安装路径和运行路径

一、查看文件安装路径由于软件安装的地方不止一个地方&#xff0c;所有先说查看文件安装的所有路径(地址)。这里以mysql为例。比如说我安装了mysql,但是不知道文件都安装在哪些地方、放在哪些文件夹里&#xff0c;可以用下面的命令查看所有的文件路径在终端输入&#xff1a;whe…

看完这13张图,不得不佩服还是外国人会玩人工智能

对于程序员来说&#xff0c;机器学习领域无疑充满着巨大的诱惑和挑战&#xff0c;很多人对里面复杂的概念和算法头疼不已&#xff0c;那么&#xff0c;有没有一套对新手既友好又明了&#xff0c;对老手能加深印象&#xff0c;不断复习的学习办法呢&#xff1f;有&#xff0c;今…

python通过封装可以实现代码复用_Python学习笔记(五)函数和代码复用

函数能提高应用的模块性&#xff0c;和代码的重复利用率。在很多高级语言中&#xff0c;都可以使用函数实现多种功能。在之前的学习中&#xff0c;相信你已经知道Python提供了许多内建函数&#xff0c;比如print()。同样&#xff0c;你也可以自己创建函数&#xff0c;这被叫做用…

实用的网络命令汇总

通过ping检测网络故障的典型次序 正常情况下&#xff0c;当你使用ping命令来查找问题所在或检验网络运行情况时&#xff0c;你需要使用许多ping命令&#xff0c;如果所有都运行正确&#xff0c;你就可以相信基本的连通性和配置参数没有问题&#xff1b;如果某些ping命令出现运行…

EFCore查缺补漏(二):查询

相关文章&#xff1a; EFCore查缺补漏第 20 轮 TechEmpower 评测结果出炉了&#xff0c;ASP.NET Core 的 Plaintext 成绩名列前茅&#xff0c;带着 EFCore 的测试却在 Single query / Multiple queries / Fortunes 中落了下风&#xff0c;成绩远不如 dapper&#xff0c;更不如直…

如何在mysql中打开mongodb_图解:如何从MySQL移植到MongoDB

【IT168 技术】下图是使用 SQL 和 MongoDB 的对应信息图表&#xff0c;点击图片查看大图&#xff1a;MongoDB是一个介于关系数据库和非关系数据库之间的产品&#xff0c;是非关系数据库当中功能最丰富&#xff0c;最像关系数据库的。他支持的数据结构非常松散&#xff0c;是类似…

仿真模拟,需要注意这几点!

周日晚上的直播甚是精彩先是潘同学分享了获奖论文和解题技巧接着是董同学分享了论文的写作小技巧po几张截图让大家感受下此时此刻可能会有不少童鞋正在为错过直播而懊悔不用担心超模君还准备了一份豪华大礼本周超模君特意邀请到今年美赛D题特等奖获奖者谢挺同学&#xff08;获奖…

mfc从mysql中读取数据类型_在MFC中使用SQlite数据库读取数据

本人在数据库里面用回调函数来处理读取函数的返回值&#xff0c;回调函数必须使用static类型才可以,这样处理起返回的数据变得非常的麻烦&#xff0c;很难处理结果集。后来从网上找了一个预编译的例子&#xff0c;放在网上和网友分享。例子成功的调试通过了sqlite3 *db 0;sqli…