opencv进阶学习笔记12:轮廓发现和对象测量

2023-11-08

基础版笔记目录:
python3+opencv学习笔记汇总目录(适合基础入门学习)
进阶版笔记目录链接:
python+opencv进阶版学习笔记目录(适合有一定基础)

轮廓发现

1轮廓发现介绍
基础版讲解:
opencv学习笔记20:图像轮廓

2轮廓发现API
cv2.findContours()
cv2.drawContours()
通过cv2.findContours() 查找轮廓在哪里,再通过 cv2.drawContours()将查找的轮廓绘制出来。

contours,hierarchy=cv2.findContours(image,mode,method)
contours:轮廓
hierarchy:图像的拓扑信息(轮廓层次)(存储上一个轮廓,父轮廓…)
image:二值图像
mode:轮廓检索方式
method:轮廓的近似方法

r=cv2.drawContours(image, contours, contourIdx, color[, thickness])
r:目标图像
image:原始图像
contours: 所有的输入轮廓边缘数组
contourIdx :需要绘制的边缘索引,如果全部绘制为-1。如果有多个目标,可以绘制第一个目标0,第二个目标1,第三个目标2.。。
color:绘制的颜色,为BGR格式的SCalar
thickness:可选,绘制的密度,即轮廓的画笔粗细

import cv2 as cv
import numpy as np


#边缘提取
def edge_demo(image):
    blurred = cv.GaussianBlur(image, (3, 3), 0)#去噪
    gray = cv.cvtColor(blurred, cv.COLOR_BGR2GRAY)
    # X Gradient
    xgrad = cv.Sobel(gray, cv.CV_16SC1, 1, 0)
    # Y Gradient
    ygrad = cv.Sobel(gray, cv.CV_16SC1, 0, 1)
    #edge
    #edge_output = cv.Canny(xgrad, ygrad, 50, 150)
    edge_output = cv.Canny(gray, 30, 100)
    cv.imshow("Canny Edge", edge_output)
    return edge_output


def contours_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_BINARY | cv.THRESH_OTSU)#cv.THRESH_OTSU自动寻找阈值
    cv.imshow("binary image", binary)"""
    binary = edge_demo(image)#边缘提取后的二值图像

    contours, heriachy = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
    for i, contour in enumerate(contours):
        cv.drawContours(image, contours, i, (0, 0, 255), 2)
    cv.imshow("detect contours", image)
print("--------- Python OpenCV Tutorial ---------")
src = cv.imread("daqiu.jpg")
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
contours_demo(src)
cv.waitKey(0)
cv.destroyAllWindows()

前面是通过边缘提取,然后再来寻找轮廓的。

改用
基于图像二值化方法 来提取

def contours_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_BINARY | cv.THRESH_OTSU)#cv.THRESH_OTSU自动寻找阈值
    cv.imshow("binary image", binary)
    #binary = edge_demo(image)#边缘提取后的二值图像

    contours, heriachy = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
    for i, contour in enumerate(contours):
        cv.drawContours(image, contours, i, (0, 0, 255), 2)
    cv.imshow("detect contours", image)

差点意思,还是基于边缘提取更好。

对象测量

对象测量:对找到的图像轮廓,计算它弧长与面积,多边形拟合,几何矩计算

多边形拟合API
获取轮廓的多边形拟合结果
cv2.approxPolyDP(contour,epsilon,close)
参数:
contour 轮廓
epsilon越小越折线越逼近真实形状
close – 是否为闭合区域

输出的是多边形点集

import cv2 as cv
import numpy as np


def measure_object(image):
    gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
    ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV | cv.THRESH_OTSU)
    print("threshold value : %s"%ret)#打印阈值
    cv.imshow("binary image", binary)#显示二值图像
    dst = cv.cvtColor(binary, cv.COLOR_GRAY2BGR)
    contours, hireachy = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
    for i, contour in enumerate(contours):
        area = cv.contourArea(contour)# 求轮廓面积
        x, y, w, h = cv.boundingRect(contour)# 求轮廓外接矩形
        rate = min(w, h)/max(w, h)
        print("rectangle rate : %s"%rate)#宽高比
        mm = cv.moments(contour)# 求几何矩,返回字典类型
        print(type(mm))
        # 求得图形的重心坐标
        cx = mm['m10']/mm['m00']
        cy = mm['m01']/mm['m00']
        cv.circle(dst, (np.int(cx), np.int(cy)), 3, (0, 255, 255), -1)#绘制轮廓中心

        cv.rectangle(dst, (x, y), (x+w, y+h), (0, 0, 255), 2)#在原图上,给轮廓绘制矩形
        print("contour area %s"%area)
    cv.imshow("measure-contours", dst)


print("--------- Python OpenCV Tutorial ---------")
src = cv.imread("shuzi.jpg")
src=cv.resize(src,None,fx=0.5,fy=0.5)
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
measure_object(src)
cv.waitKey(0)
cv.destroyAllWindows()

计算出啦每个数字的面积,宽高比,可以用于简单数字识别
注意 原图中数字为黑色, 需要反二值化 ,使数字为轮廓,因为轮廓为白色

注意事项:有些图太小时,cx = mm['m10']/mm['m00'] cy = mm['m01']/mm['m00'] 出现分母为0,报错。所以得首先把图放大
src=cv.resize(src,None,fx=1.5,fy=1.5)

算例2

import cv2 as cv
import numpy as np


def measure_object(image):
    gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
    ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
    print("threshold value : %s"%ret)#打印阈值
    cv.imshow("binary image", binary)#显示二值图像
    dst = cv.cvtColor(binary, cv.COLOR_GRAY2BGR)
    contours, hireachy = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
    for i, contour in enumerate(contours):
        area = cv.contourArea(contour)# 求轮廓面积
        x, y, w, h = cv.boundingRect(contour)# 求轮廓外接矩形
        rate = min(w, h)/max(w, h)
        #print("rectangle rate : %s"%rate)
        mm = cv.moments(contour)# 求几何矩,返回字典类型
        print(type(mm))
        # 求得图形的重心坐标
        cx = mm['m10']/mm['m00']
        cy = mm['m01']/mm['m00']
        cv.circle(dst, (np.int(cx), np.int(cy)), 3, (0, 255, 255), -1)#绘制轮廓中心

        #cv.rectangle(dst, (x, y), (x+w, y+h), (0, 0, 255), 2)
        #print("contour area %s"%area)
        #轮廓多边形拟合
        approxCurve = cv.approxPolyDP(contour,2, True)
        #print(approxCurve.shape)
        print(approxCurve.shape)

        #轮廓拟合
        if approxCurve.shape[0] > 6:
            cv.drawContours(dst, contours, i, (0, 255, 0), 2)#i表示第几个轮廓
        if approxCurve.shape[0] == 4:
            cv.drawContours(dst, contours, i, (0, 0, 255), 2)
        if approxCurve.shape[0] == 3:
            cv.drawContours(dst, contours, i, (255, 0, 0), 2)

    cv.imshow("measure-contours", dst)
print("--------- Python OpenCV Tutorial ---------")
src = cv.imread("duobianxin.jpg")
src=cv.resize(src,None,fx=1.5,fy=1.5)
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
measure_object(src)
cv.waitKey(0)

cv.destroyAllWindows()

部分print(approxCurve.shape)数据如下
approxCurve.shape 有三维数据,第一维表示轮廓可以由几条线绘制出来,如三角形由三条直线就可绘制。如if approxCurve.shape[0] == 3: cv.drawContours(dst, contours, i, (255, 0, 0), 2)
图中蓝色均有3条绘制

同样要注意图的大小

电气专业的计算机萌新,写博文不容易。如果你觉得本文对你有用,请点个赞支持下,谢谢。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

opencv进阶学习笔记12:轮廓发现和对象测量 的相关文章

随机推荐

  • 音频-基于Core Audio技术采集音频(版本1)

    这个是第一次版本优化 优化是简单易懂 代码 WindowsAudioSession cpp 基本的利用WAS采集音频的demo include
  • extern关键字作用

    语法 extern放在变量和函数声明之前 表示该变量或者函数在别的文件中已经定义 提示编译器在编译时要从别的文件中寻找 除此之外 extern还可以用来进行链接指定 作用 声明外部变量 在声明全局变量时 不同的文件在编译器编译时是不透明的
  • 字节流与字符流

    流是个抽象的概念 是对输入输出设备的抽象 输入流可以看作一个输入通道 输出流可以看作一个输出通道 输入流是相对程序而言的 外部传入数据给程序需要借助输入流 输出流是相对程序而言的 程序把数据传输到外部需要借助输出流 字节流 传输过程中 传输
  • java基础系列 -- 类的三大特性:封装、继承、多态

    java类的特性 类有三大特性 封装 继承 多态 封装 封装就是将类的某些属性隐藏起来 限制在类的外部对类内部成员进行访问 通过接口对外开放 但是在外部不能直接进行查找属性 只通过公共接口来访问类的成员数据 为什么要设置隐藏 隐藏数据是为了
  • jpa.hibernate.ddl-auto属性说明

    jpa hibernate ddl auto 的几个常用属性值 none 默认值 什么都不做 每次启动项目 不会对数据库进行任何验证和操作 create 每次运行项目 没有表会新建表 如果表内有数据会被清空 create drop 每次程序
  • nginx_http_proxy,upstream,stream模块简析

    一 ngx http proxy module模块 模块功能 为后端httpd服务做反向代理 并且与Httpd 之间使用http进行通信 1 proxy pass URL Context location if in location li
  • 如何求C语言字符串长度(strlen函数和sizeof关键字)

    如何求C语言字符串长度 strlen函数和sizeof关键字 在程序里 一般会用 strlen 函数或 sizeof 来获取一个字符串的长度 但这2种方法获取的字符串的长度其实是不一样 我们用如下函数进行测试 void test6 char
  • Java8新特性-Lambda表达式

    Lambda表达式 也可称为闭包 它是推动Java8发布的最重要的特性 Lambda允许把函数作为一个方法的参数 函数作为参数传递进入方法中去 使用lambda表达式可以把代码变得更加简洁紧凑 语法 lambda表达式的语法格式如下 par
  • Ciclop开源3D扫描仪软件---Horus源码分析之point_cloud_roi.py

    联系方式 QQ 2468851091 call 18163325140 Email 2468851091 qq com coding utf 8
  • C语言小游戏——井字棋(数组实现)

    学c也学了有一些时间了 今天用c语言做了一个小游戏 井字棋 相信大家也玩过 我们这个游戏的思路呢 是玩家和电脑对弈 谁先把三颗棋子连成一条线 谁就赢了 如下图所示 要想实现我们这个井字棋需要用到数组的知识 所以 老规矩我们先简单的把数组讲一
  • SCI审稿流程(转)

    1 收到邮件 编辑约审稿 同意就接受 会约定审稿期限 一般三个月 Dear Mr Cat Please be informed you have been registered by our editorial team as a user
  • scheduler学习率设置

    在炼丹的过程中 学习率的调整是必不可少的 下面给出scheduler模块的调学习率的方法 后面会慢慢补充 调整学习率 PyTorch官方文档 一 CyclicLR torch optim lr scheduler CyclicLR opti
  • php把二维数组变为一维,如何将PHP二维数组转换为一维数组

    如何将PHP二维数组转换为一维数组 发布时间 2020 07 22 11 12 05 来源 亿速云 阅读 137 作者 Leah 如何将PHP二维数组转换为一维数组 相信很多没有经验的人对此束手无策 为此本文总结了问题出现的原因和解决方法
  • 网络协议详解:TCP Part1

    目录 TCP的可靠性 TCP的机制 ack 编号机制 1 发送的数据编号 SN 2 确认的数据编号 ASN 3 编号规则 4 SN在发送TCP Segment 的 Header 中如何体现 5 ASN的填写规则 6 ISN TCP segm
  • 2.4.3 分区状态

    最后更新2021 07 17 No Active 分区处于非活动状态 在此状态 分区仅存在Profile的定义 可以有多个Profile定义 但都没有激活 而不占据任何系统资源 SMS服务模式状态 分区启动经过自检后将会根据Profile的
  • 香港爱情电影二十四经

    香港爱情电影二十四经之第一经 寻找 飞一般爱情小说 叶锦鸿1997 我们不是在寻找 我们只是在给邂逅一个机会 叶锦鸿的这部电影清新温暖 恬淡动人 一幅如流水般的爱情图画 三个青年相约一块寻找一个女孩 然后确定爱情的归属 谁都知道 这不是爱情
  • Vue路由基础部分,Vue路由基础知识

    Vue路由基础部分 Vue路由基础知识 1 介绍 2 基础 1 起步 2 动态路由匹配 3 嵌套路由 4 编程式的导航 5 命名路由 6 命名视图 7 重定向和别名 1 介绍 Vue Router 是 Vue js 官方的路由管理器 它由V
  • Chrome浏览器不能同步书签的解决方法

    问题现象 在Chrome浏览器登陆同步书签的时候 提示报错 解决方法 需要 使用Chrome访问助手 操作步骤 下载Chrome访问助手 https www ggfwzs com 下载后进行解压 然后依次点击如下操作 把刚才解压的 crx直
  • Microsoft Office 2007的安装

    哈喽 大家好 今天一起学习的是office2007的安装 有兴趣的小伙伴也可以来一起试试手 一 测试演示参数 演示操作系统 Windows 7 不建议win10及以上操作系统使用 系统类型 64位 演示版本 cn office ultima
  • opencv进阶学习笔记12:轮廓发现和对象测量

    基础版笔记目录 python3 opencv学习笔记汇总目录 适合基础入门学习 进阶版笔记目录链接 python opencv进阶版学习笔记目录 适合有一定基础 轮廓发现 1轮廓发现介绍 基础版讲解 opencv学习笔记20 图像轮廓 2轮