IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> python的opencv操作记录(二) -> 正文阅读

[人工智能]python的opencv操作记录(二)

前言

? 接前一篇,最近几天关注的问题是图像的轮廓问题,所以这一篇主要写的是findContoursdrawContours两个函数,另外还有和文件操作相关的一个os.walk函数。

文件操作

os.walk

  • 基本逻辑

    walk会以深度优先的方式来遍历整个文件夹,也就是先把某一个文件夹及其子文件夹全部遍历一遍。每次遍历返回一个三元组(parent, dirs, files),分别代表这次遍历过程的父目录、当前目录下的子目录列表、当前目录下的文件列表。

    我的代码啊逻辑是将所有最底层的目录(最底层的目录中包含一个特定文件)收集成一个列表,代码如下:

    def loadAllFileInfos(src):
        fileDirs = []
        for parent, dirs, fileNames in os.walk(src):
            for name in fileNames:
                if name == "img.xml":
                    print(parent)
                    fileDirs.append(parent)
    
  • 文件夹中的"/“和”\“的处理,不区分,但是可以考虑使用”\\"的方式

  • 文件夹中包含中文

    判断:

    def is_contains_chinese(strs):
        for _char in strs:
            if '\u4e00' <= _char <= '\u9fa5':
                return True
        return False
    

    修改,注意的两点:

    • parent是绝对路径而不是相对路径,本来想根据parent的特征来修改,后来逻辑上行不通
    • os.rename是需要绝对路径,所以需要使用os.path.join进行一下拼装
    def change(src):
        for parent, dirs, fileNames in os.walk(src):
            i = 0
            for dir in dirs:
                if is_contains_chinese(dir):
                    i = i + 1
                    src = os.path.join(parent, dir)
                    dst = os.path.join(parent, "case_"+str(i))
                    os.rename(src, dst)
    

图像轮廓问题

轮廓的基本逻辑

? 为了更好的理解opencv里处理轮廓的两个函数,我自己构造了一张比较简单的图:

在这里插入图片描述

? 构造代码:

img = np.zeros((500, 500, 3), dtype="uint8")
cv2.rectangle(img, (100, 100), (200, 200), (255, 255, 255), 5)
cv2.rectangle(img, (120, 120), (140, 160), (255, 255, 255), 5)
cv2.rectangle(img, (160, 120), (180, 160), (255, 255, 255), 5)

cv2.rectangle(img, (300, 300), (400, 400), (255, 255, 255), 5)
cv2.rectangle(img, (320, 320), (350, 350), (255, 255, 255), 5)

? 在图中我画了5个矩形,每个矩形的线宽是5个像素,这里面有两个重要的概念:

  • 5个矩形,总共形成了10个轮廓,每个矩形的外框都是两个轮廓,里面一个外面一个,我们可以把这个称作外轮廓内轮廓,这个在后面的介绍中还要用到。

在这里插入图片描述

  • 轮廓与轮廓之间是有拓扑结构关系的,我理解是轮廓之间的一个包含关系,比如刚才的外轮廓就是包含内轮廓的,里面小矩形的轮廓就是包含在外轮廓之内的。可以在图形处理中做一些空洞或者其他方面的应用

findContours函数

? 在python中的基本调用方法:

contours, hierarchy = cv2.findContours(bi_img, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)

? 对应的函数原型就是:

? contours, hierarchy = cv2.findContours(bi_img, RetrievalModes, ContourApproximationModes),这个里面最重要的就是理解两个入参和hierarchy这个出参。

  • 首先看一下这个函数在上面那个图上的情况(使用的就是上面的代码调用,因为改变参数的话,输出不太一样):

在这里插入图片描述

可以看到,函数总共输出了10条轮廓数据,从shape上来看,第一条轮廓是92个Point,每个Point是一个<x, y>的坐标点。

  • ContourApproximationModes,官网上的介绍如下:

在这里插入图片描述

这个参数主要是影响输出参数contours,后面两种用得少,主要是前面两种。这两个参数的主要区别就在用于描述轮廓的点是否进行压缩,如果使用SIMPLE这个参数,那么理论上一个矩形轮廓只需要四个点就可以了,而不压缩的话就会把这个矩形轮廓线上的所有点全部输出。

我们把上面的代码改成

contours, hierarchy = cv2.findContours(bi_img, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

重新看一下输出:

在这里插入图片描述

可以看到,这个轮廓从92个点压缩成了8个点,应该是每条线用两个点来表示。这里我的一个疑问是:这个轮廓应该是一个矩形框才对,为什么不是4个点来描述。想了半天想到一种可能,就是我这个里面的轮廓是通过rectangle函数画出来的,可能是矩形框的四个顶点并没有包含在轮廓之内,也就是说这个轮廓是有4条没有连接起来的线段组成,而不是一个完整的矩形框

  • 轮廓的拓扑结构:hierarchy出参和入参RetrievalModes

    这两个参数可以一起来看,RetrievalModes这个参数就控制了hierarchy的输出。先看看官网的描述

在这里插入图片描述

在这里插入图片描述

  • hierarchy是对应contours中的每个元素,每个元素都有四个属性分量:
    • 0分量:拓扑中同一级别的下一个
    • 1分量:拓扑中同一级别的前一个
    • 2分量:拓扑中第一个child
    • 3分量:拓扑中的上一级别(parent)

这样看基本上是蒙的,还是针对上面的图,针对每个参数进行输出分析。

  • 先看RETR_LIST:

    contours, hierarchy = cv2.findContours(bi_img, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
    

    输出的结构为:

在这里插入图片描述

参考官网上的描述,RETR_LIST不会构建上下级关系,所有的轮廓都是平铺,从数据中可以看到,基本上就是按照数组的顺序,填充了hierarchy的第0分量和第1分量,其他的都是-1。
  • RETR_EXTERNAL,从官网上看就是只输出外轮廓。

    输出结果,只有两个轮廓了:

在这里插入图片描述

利用drawContours(参考后面一个小节)来查看一下:

在这里插入图片描述

相当于只找出了最外成的轮廓,从拓扑上来说,这是最外层的。
  • RETR_CCOMP,官网上的描述是:形成一个两层的结构,第一层是最外层的轮廓,然后是这层轮廓里面的轮廓。如果有第三层,那么都放到最外层去。

    在我构造的图中,idx=2和idx=8的轮廓是最外层的图,就是RETR_EXTERNAL中的这两个轮廓,再打开hierarchy的输出结果看一下:

在这里插入图片描述

根据每个的3号分量,等于2或者8的就是idx=3和idx=9的轮廓,用drawContours画出来就是:

在这里插入图片描述

可以看出来,就是刚才最外面轮廓的里面一层。再来看看其他几个,除了idx=2,3,8,9的轮廓除外,还有parent=-1的是idx=0,4,6,画出来之后就是:

在这里插入图片描述

相当于也是外层轮廓,这些也是放在了顶层,因为这个参数控制它只能有两层结构,另外的三个内层轮廓的parent就是分别等于0,4,6了。
  • RETR_TREE,这个参数就是形成一个从里到外的树形结构:

在这里插入图片描述

顺序和上面的顺序是不一样的,这里能看出来:

- 最外层的idx = 0, 4
- 第二层(parent = 0, 4)的是1, 5
- 第三层是2, 6, 8
- 第四层是3, 7,  9

用不同的颜色画一下就是:

在这里插入图片描述

展现了明显的层次结构关系。

drawContours函数

? 上面提到的绘制轮廓的方法,这个函数比较简单。

? 调用方法:

	cv2.drawContours(img, contours, 3, (255, 255, 0), 1)
  • img必须是三通道图
  • 第三个参数是绘制contours数组中的第几个轮廓
  • 第四个是BGR颜色,第五个是轮廓的粗细。
  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2022-05-11 16:27:02  更:2022-05-11 16:27:52 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 6:21:48-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码