首页 > 其他分享 >opencv学习笔记(八)

opencv学习笔记(八)

时间:2023-06-22 11:22:04浏览次数:30  
标签:img RETR res cv2 笔记 学习 opencv 图像 轮廓

图像轮廓:
用于识别和提取图像中物体的边界或轮廓信息。轮廓是由连续的边缘像素点组成的曲线,表示了物体在图像中的外形。

常用方法:
  1、预处理:首先,对图像进行预处理,例如:灰度化、滤波、二值化,以便更好地分离物体和背景;

  2、边缘检测:使用边缘检测算法(例如canny边缘检测)在预处理后的图像中找到物体的边缘。边缘检测算法可以根据 像素之间的灰度或者梯度差异来确定边缘;

  3、轮廓提取:通过对边缘图像应用轮廓提取算法(如OpenCV中的findContours函数),从边缘图像中提取物体的轮廓。该算法会将边缘像素连接成连续的轮廓曲线。

  4、轮廓处理:根据需要,可以对提取到的轮廓进行一些后续处理,如去除小的噪声轮廓、合并相邻的轮廓等。

  5、轮廓绘制:最后,将提取到的轮廓绘制在原始图像上,以便可视化或进一步的分析。

cv2.findContours(img,mode, method)

mode:轮廓检索模式

  • RETR_EXTERNAL:只检索最外面的轮廓;
  • RETR_LIST:检索所有的轮廓,并将其保存到一条链表中;
  • RETR_CCOMP:检索所有的轮廓,并将他们组织为两层,顶层是各部分的外部边界,第二层是空洞的边界;
  • RETR_TREE:检索所有的轮廓,并重构给嵌套轮廓的整个层次;

method:轮廓逼近方法

  • CHAIN_APPROX_NONE:以Freeman链码的方式输出轮廓,所有其他方法输出多边形(顶点的序列)
  • CHAIN_APPROX_SIMPLE:仅存储水平、垂直和对角线方向的终点,将中间点进行压缩
  • CHAIN_APPROX_TC89_L1 和 CHAIN_APPROX_TC89_KCOS:  应用 Teh-Chin 链逼近算法进行轮廓压缩

函数返回值:

  • contours: 检测到的轮廓列表。每个轮廓表示为一个点集的列表,其中每个点是 (x, y) 的坐标。
#图像轮廓检测
import cv2
import numpy as np

"""cv2.findContours(img,mode,method)
mode:轮廓检测模式
>RETR_EXTEREANL:只检索最外面的轮廓;
>RETR_LIST:检索所有的轮廓,并将其保存到一条链表中;
>RETR_CCOMP:检索所有的轮廓,并将他们组织为两层:顶层是各个部分的外部边界,第二层是空洞的边界;
>RETR_TREE:检索所有的轮廓,并重构嵌套轮廓的整个层次(常用)
method:轮廓逼近方法
>CHAIN_APPROX_NONE:以freeman链码的方式输出所有轮廓,所有其他方法输出多边形(顶点的序列);
>CHAIN_APPROX_SIMPLE:压缩水平的、垂直的和斜的部分,也就是,函数只保留他们的终点部分。"""

img = cv2.imread('C:/Users/hellou/Desktop/beautiful.jpg')
img = cv2.resize(img,(600,600))
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#转灰度图
#为了更高的准确率,使用二值图像
ret, thersh = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
cv2.imshow('thersh',thersh)
cv2.waitKey(0)
cv2.destroyAllWindows()

contours, hierachy = cv2.findContours(thersh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
#contours保存的轮廓信息,hiercahy保存的层级
"""cv2.findContours()有三个参数:thresh、cv2.RETR_TREE、cv2.CHAIN_APPROX_SIMPLE。

    参数说明:

        thresh:图像数据(二值图像或经过Canny算法处理之后的图像)
        cv2.RETR_TREE:轮廓检索方式,还有cv2.RETR_LIST、cv2.RETR_EXTERNAL、cv2.RETR_CCOMP
        cv2.CHAIN_APPROX_SIMPLE:轮廓的估计方法,除此之外还有 cv2.CHAIN_APPROX_NONE"""
"""绘制轮廓
传入绘制图像,轮廓,轮廓索引,颜色模式,线条厚度
注意需要copy,不然原图会变"""
draw_img = img.copy()
res = cv2.drawContours(draw_img, contours, -1, (0, 0, 255), 2)
cv2.imshow('res',res)
cv2.waitKey(0)
cv2.destroyAllWindows()

draw_img = img.copy()
res_2 = cv2.drawContours(draw_img, contours, 0, (0, 0, 255), 2)
"""cv2.drawContours(image, contours, contourIdx, color, thickness=None, lineType=None, hierarchy=None, maxLevel=None, offset=None)
第一个参数是指明在哪幅图像上绘制轮廓;image为三通道才能显示轮廓
第二个参数是轮廓本身,在Python中是一个list;
第三个参数指定绘制轮廓list中的哪条轮廓,如果是-1,则绘制其中的所有轮廓。后面的参数很简单。其中thickness表明轮廓线的宽度,如果是-1(cv2.FILLED),则为填充模式。
-1指默认全部轮廓,指定为char值就是按照顺序依次选择(分内外)
2代表线条宽度
"""
cv2.imshow("res_2",res_2)
cv2.waitKey(0)
cv2.destroyAllWindows()

#轮廓特征
cnt = contours[0]#方括号里面的数字表示第几个轮廓
cv2.contourArea(cnt)#表示面积
cv2.arcLength(cnt,True)#周长,True表示闭合的

ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)

是使用 OpenCV 中的阈值化函数对灰度图像进行二值化处理。

参数说明:

  • gray: 输入的灰度图像。
  • 127: 阈值,用于将图像中的像素分成两类:小于等于阈值的像素设为0,大于阈值的像素设为255。
  • 255: 阈值化后的像素的最大值。
  • cv2.THRESH_BINARY: 阈值化方法,表示使用二进制阈值化方法,将像素分为两类。

函数返回值:

  • ret: 所选择的阈值。
  • thresh: 阈值化后的二值图像。

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

  • image: 要在其上绘制轮廓的图像。
  • contours: 要绘制的轮廓列表。
  • contourIdx: 指定要绘制的轮廓在轮廓列表中的索引。如果为负值(如 -1),则绘制所有的轮廓。
  • color: 绘制轮廓的颜色,可以是单个整数值(灰度图像)或包含三个整数值的元组/列表(彩色图像)。
  • thickness: 绘制轮廓线的宽度。如果为负值,则绘制轮廓的内部区域。
  • lineType: 线条类型,指定绘制线条的样式。默认为 8 连接线条。
  • hierarchy: 轮廓的层级关系数组,与 cv2.findContours() 函数返回的层级关系数组一致。
  • maxLevel: 绘制轮廓的最大层级。如果为 0,则绘制最外层的轮廓,如果为 1,则绘制最外层和内层轮廓,以此类推。
  • offset: 可选的偏移量参数,用于指定轮廓点坐标的偏移。

函数无返回值,它会直接在输入的图像上绘制轮廓。

轮廓特征:
几个常用的轮廓特征:

  1. 轮廓面积(Contour Area): 表示轮廓所包围的区域的面积,可以通过 cv2.contourArea() 函数计算得到。

  2. 轮廓周长(Contour Perimeter): 表示轮廓的周长或长度,可以通过 cv2.arcLength() 函数计算得到。

  3. 轮廓近似多边形: 使用多边形逼近方法将轮廓曲线拟合为近似的多边形。通过调整逼近的精度参数,可以获得不同级别的近似多边形。

  4. 轮廓凸包(Convex Hull): 表示能够包围整个轮廓的最小凸多边形,可以使用 cv2.convexHull() 函数计算得到。

  5. 轮廓重心(Contour Centroid): 表示轮廓的重心位置,可以通过计算轮廓中所有点的坐标的平均值得到。

  6. 轮廓方向(Contour Orientation): 表示轮廓的主要方向或朝向,通常使用轮廓的拟合椭圆的角度或最小外接矩形的角度来表示。

  7. 轮廓边界框(Bounding Box): 表示能够完全包围轮廓的最小矩形框,可以使用 cv2.boundingRect() 函数计算得到。

  8. 轮廓形状特征: 包括圆度、长宽比、矩形度等特征,用于描述轮廓的形状特点。

轮廓近似:
approx = cv2.approxPolyDP(curve, epsilon, closed)

  • curve: 输入的轮廓曲线,通常为一个点集的列表。
  • epsilon: 近似精度,表示最大允许的拟合误差。较小的 epsilon 值会产生更接近原始轮廓的近似结果。
  • closed: 是否将近似结果作为封闭的曲线返回。如果为 True,则返回封闭的曲线;如果为 False,则返回非封闭的多边形。

函数返回近似的轮廓曲线或多边形,类型与输入的曲线类型相同(如点集列表或 Numpy 数组)。

#图像轮廓近似
import cv2
import numpy as np

#轮廓近似
img = cv2.imread('C:/Users/hellou/Desktop/zhong.jpg')
img = cv2.resize(img,(600,600))

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_OTSU)
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
cnt = contours[0]

draw_img = img.copy()
res = cv2.drawContours(draw_img, [cnt], -1, (0, 0, 255), 2)
cv2.imshow('res',res)
cv2.waitKey(0)
cv2.destroyAllWindows()

epsilon =0.1*cv2.arcLength(cnt,True)
approx = cv2.approxPolyDP(cnt,epsilon,True)

draw_img = img.copy()
res_2 = cv2.drawContours(draw_img, [approx], -1, (0, 0, 255), 2)
cv2.imshow('res_2',res_2)
cv2.waitKey(0)
cv2.destroyAllWindows()

res_3 = np.hstack((img,res,res_2))
cv2.imshow('res_3',res_3)
cv2.waitKey(0)
cv2.destroyAllWindows()

 

标签:img,RETR,res,cv2,笔记,学习,opencv,图像,轮廓
From: https://www.cnblogs.com/hellou/p/17497606.html

相关文章

  • 好家伙66万字,又一份牛逼的Android笔记面世了
    前言很久以前,凭借四大组件、Java基础等知识,便可开开心心的开发,轻松地上岗。而随着Android的不断发展完善,各种组件库越来越成熟,学习资料越来越多,我们却慢慢地看不到方向。信息爆炸的时代,到底该如何提升自己?如何才能找到真正利己的信息?如何才能看清前路的方向?为此我专门找了一份《And......
  • Flutter 学习 之 权限管理 permission_handler 9.2.0
    官方文档地址permission_handler控制台打印提示信息的时候可能会有两种(我遇到的)Noandroidspecificpermissionsneededfor:9可能表示你当前申请的权限你的系统不支持就是备注里nothing的Noandroidspecificpermissionsneededfor:[]9可能表示你没在AndroidM......
  • 基础算法:二分,贪心等 学习笔记
    普及组基础算法这些都是零零散散接触过的基础算法,写个笔记把这些整理到一起来。线性降维技巧之前在学校洛谷团队里看到一个题单,觉得这些技巧可能有用,就转存了。前缀和差分前缀和是一种对区间求和问题进行降维的方法。具体地,对于给定数组\(A[n]\),求出\(A[l,r]\)区间和这个......
  • 掌控习惯-学习总结
    一直以来,我都有一个困扰自己许久的问题,如何让自己的良好行为形成习惯,比如练字,比如健身,比如读书。这些行为一般会在我制定计划的前几天或者前几周可以顺利实行,但不幸的是,一但因为某天的突发状况将这个过程打断之后,这些行为就像从来没有出现过一样,从我的工作生活中消失得干干净净。......
  • celery笔记五之消息队列的介绍
    本文首发于公众号:Hunter后端原文链接:celery笔记五之消息队列的介绍前面我们介绍过task的处理方式,将task发送到队列queue,然后worker从queue中一个个的获取task进行处理。task的队列queue可以是多个,处理task的worker也可以是多个,worker可以处理任意queue......
  • 近期高性能计算报班培训学习总结
    工作以来,我鲜有时间停下来做一些总结,偶有所得也是记录在公司内部的文档里。我细细想来,发现原因主要是这份工作实在是有些螺丝钉了,脱离了公司的环境就很难成立。去年10月底以来,我开始报班培训C++,为什么要这样做呢?因为我发现大厂的算法工程师很容易变成“螺丝钉”,数据、训练和部署......
  • opencv学习笔记(七)
    图像金字塔:用于图像的分辨率降低。它通过连续的图像平滑和下采样操作来生成一系列分辨率逐渐降低的图像。构建过程:1、将原始图像作为底层2、应用高斯滤波器对当前的图像进行平滑处理,以减少图像中的高频细节。高斯滤波器通过卷积运算在图像上进行平滑操作,使得图像变得更......
  • 外设驱动库开发笔记54:外设库驱动设计改进的思考
      不知不觉中我们已经发布了五十多篇外设驱动的文章。前段时间有一位网友提出了一些非常中肯的建议,这也让我们开始考虑怎么优化驱动程序设计的问题。在这一篇中我们将来讨论这一问题。1、问题分析  首先我们来分析一下网友提出的几点问题。第一点是说在驱动设计时,使用了type......
  • 最近公共祖先-算法学习
    问题提出如何计算树上任意两点x和y的最近公共祖先呢?通俗地理解-假设在一棵二叉树中,有两个节点和那么该如何求这两个节点的最近公共祖先节点如下图,节点和节点的最近公共祖先节点是思路解析假设一个节点的深度为,这可以通过一次DFS预处理出来。那么这里如何进行预处理呢?单......
  • 现代C++学习指南-具体类
    类作为C++中重要的概念之一,有着众多的特性,也是最迷人的部分!类是一个加工厂,开发者使用C++提供的各种材料组装这个工厂,使得它可以生产出符合自己要求的数据,通过对工厂的改造,可以精细控制对象从出生到死亡的各种行为,真正达到我的代码我做主的境界。类我们经常说的面向对象三大特......