当前位置: 首页 > news >正文

OpenCV-Python Tutorial : A Candy from Official Main Page(二)

三、image processing

3.8图像金字塔-cv.pyrDown、cv.pyrUp

图像金字塔有两种,一种是高斯金字塔,一种是拉普拉斯金字塔。

3.8.1高斯金字塔

高斯金字塔是一种多分辨率图像表示方法,通过对图像逐层降采样(缩小)生成一系列分辨率递减的图像集合。其核心思想是模拟人眼观察物体时从粗到细的感知过程,广泛应用于图像缩放、特征提取、图像融合等任务。

3.8.2拉普拉斯金字塔

拉普拉斯金字塔是一种基于高斯金字塔的多尺度图像表示方法,通过差分操作提取不同分辨率下的高频细节信息,常用于图像融合、压缩和增强等任务。其核心思想是存储高斯金字塔相邻层之间的丢失信息,从而实现图像的无损重建。

cv.pyrDown()对图像进行高斯平滑(模糊)并降采样(缩小到 1/4 大小,宽高各减半)

dst = cv.pyrDown(src[, dst[, dstsize[, borderType]]])
src:输入图像(单通道或多通道)。
dst(可选):输出图像。
dstsize(可选):目标尺寸,默认自动计算为 (src.cols/2, src.rows/2)。
borderType(可选):边界填充方式(默认 cv.BORDER_DEFAULT)。

cv.pyrUp()对图像进行上采样(放大到 2 倍宽高)并高斯平滑,但不会恢复降采样时丢失的信息

dst = cv.pyrUp(src[, dst[, dstsize[, borderType]]])
参数:
(同 cv.pyrDown,但 dstsize 默认为 (src.cols*2, src.rows*2))

cv.subtract()计算两幅图像的差值(逐像素相减),用于提取拉普拉斯金字塔层。

dst = cv.subtract(src1, src2[, dst[, mask[, dtype]]])
src1, src2:输入图像(需同尺寸、同通道数)。
mask(可选):掩膜,仅处理指定区域。
dtype(可选):输出数据类型。

demo1:对比原图与cv.pyrdown下采样与cv.pyrup上采样的结果

import cv2 as cv
import numpy as np
from matplotlib import pyplot as pltimg = cv.imread('image1.png')
img = cv.cvtColor(img, cv.COLOR_BGR2RGB)
assert img is not None, "file could not be read, check with os.path.exists()"
lower_reso = cv.pyrDown(img)
higher_reso = cv.pyrUp(lower_reso)titles = ['img', 'lower_reso', 'higher_reso']
images = [img, lower_reso, higher_reso]for i in range(3):plt.subplot(1, 3, i+1)plt.imshow(images[i])plt.title(titles[i])plt.xticks([])plt.yticks([])
plt.show()

demo2:可视化图像金字塔

import cv2
import numpy as np
from matplotlib import pyplot as pltdef build_gaussian_pyramid(img, levels):g = img.copy()# 确保初始尺寸是偶数if g.shape[0] % 2 != 0 or g.shape[1] % 2 != 0:g = cv2.resize(g, (g.shape[1] // 2 * 2, g.shape[0] // 2 * 2))pyramid = [g]for _ in range(levels):g = cv2.pyrDown(g)pyramid.append(g)return pyramiddef build_laplacian_pyramid(gaussian_pyramid):pyramid = [gaussian_pyramid[-1]]for i in range(len(gaussian_pyramid)-1, 0, -1):up_img = cv2.pyrUp(gaussian_pyramid[i])# 确保尺寸匹配h, w = gaussian_pyramid[i-1].shape[:2]up_img = cv2.resize(up_img, (w, h))err = cv2.subtract(gaussian_pyramid[i-1], up_img)pyramid.append(err)return pyramid[::-1]# 读取图像并翻转
img1 = cv2.imread('image3.png')
img1 = img1[:,:1200]
cv2.imshow("",img1)
cv2.waitKey(0)
cv2.destroyAllWindows()
img2 = cv2.flip(img1, 1)# 构建金字塔
gp1 = build_gaussian_pyramid(img1, 5)  # 注意:6层高斯金字塔实际生成7个图像(含原图)
gp2 = build_gaussian_pyramid(img2, 5)
lp1 = build_laplacian_pyramid(gp1)
lp2 = build_laplacian_pyramid(gp2)# 绘制子图
plt.figure(figsize=(15, 10))
for i in range(6):plt.subplot(4, 6, i+1)plt.imshow(cv2.cvtColor(gp1[i], cv2.COLOR_BGR2RGB))plt.title(f'GP1 L{i}')plt.axis('off')
for i in range(6):plt.subplot(4, 6, i+7)plt.imshow(cv2.cvtColor(gp2[i], cv2.COLOR_BGR2RGB))plt.title(f'GP2 L{i}')plt.axis('off')
for i in range(6):plt.subplot(4, 6, i+13)plt.imshow(cv2.cvtColor(lp1[i], cv2.COLOR_BGR2RGB))plt.title(f'LP1 L{i}')plt.axis('off')
for i in range(6):plt.subplot(4, 6, i+19)plt.imshow(cv2.cvtColor(lp2[i], cv2.COLOR_BGR2RGB))plt.title(f'LP2 L{i}')plt.axis('off')
plt.tight_layout()
plt.show()

如图,img1和img2的高斯金字塔和拉普拉斯金字塔,以img1为例:

img1的高斯金字塔是第一行,拉普拉斯金字塔是第三行,然后高斯金字塔和拉普拉斯金字塔的最顶层L5是一样的,拉普拉斯的L4 = 高斯的L4 - cv.pyrup(高斯的L5)

3.9 轮廓(contours in opencv)

3.9.1基础介绍-cv.findContours()、cv.drawContours() 

轮廓可以简单地解释为连接所有具有相同颜色或强度的连续点(沿边界)的曲线。轮廓是用于形状分析、物体检测与识别的有用工具。

为提高准确性,请使用二值图像。因此在查找轮廓前,应先应用阈值处理或Canny边缘检测
从OpenCV 3.2版本开始,findContours()函数不再修改源图像。
在OpenCV中,查找轮廓就像从黑色背景中寻找白色物体。所以请记住:待检测物体应为白色,背景应为黑色。

cv.findContours() 是 OpenCV 中用于检测图像轮廓的函数

contours, hierarchy = cv.findContours(image, mode, method[, contours[, hierarchy[, offset]]])
参数说明
image – 输入图像(必须为 二值图像,通常需要先进行阈值处理或边缘检测)。
注意:OpenCV 3.2 之后,该函数不会修改原始图像。
目标物体应为 白色(前景),背景应为 黑色。
mode – 轮廓检索模式,决定如何提取轮廓:
cv.RETR_EXTERNAL – 只检测最外层轮廓
cv.RETR_LIST – 检测所有轮廓,不建立层级关系
cv.RETR_TREE – 检测所有轮廓,并建立完整的层级结构(嵌套轮廓)
method – 轮廓近似方法:
cv.CHAIN_APPROX_NONE – 存储所有轮廓点(不压缩)
cv.CHAIN_APPROX_SIMPLE – 压缩冗余点(如直线只保留端点)返回值
contours – 检测到的轮廓列表,每个轮廓是一个点集(np.array)。
hierarchy – 轮廓的层级信息(用于嵌套轮廓分析)。

绘制轮廓

cv.drawContours() 函数用于绘制轮廓,也可以用来绘制任何已知边界点的形状

cv.drawContours(image,          # 要绘制轮廓的目标图像(通常先复制原图)contours,       # 轮廓列表(Python list格式)contourIdx,     # 要绘制的轮廓索引(-1表示绘制所有轮廓)color,          # 轮廓颜色(BGR格式,如 (0, 255, 0) 代表绿色)thickness,      # 轮廓线粗细(像素值,-1表示填充轮廓内部)[lineType],     # (可选)线型(如 cv.LINE_AA抗锯齿)[hierarchy],    # (可选)层级关系(配合复杂轮廓结构使用)[maxLevel],     # (可选)最大绘制层级(默认全部绘制)[offset]        # (可选)轮廓点坐标偏移量
)
关键参数
image
目标图像:必须是 彩色图像(如果是灰度图需先转BGR,否则无法显示颜色)。
contours
轮廓列表:直接传入 cv.findContours() 返回的 contours 列表。
注意:即使只画一个轮廓,也要以列表形式传入,如 [contour]。
contourIdx
轮廓索引:
-1:绘制所有轮廓。
0:只绘制第一个轮廓。
1:只绘制第二个轮廓,依此类推。
color 和 thickness
颜色:BGR格式,例如 (255, 0, 0) 表示蓝色。
线粗:
2:2像素宽的线条。
-1:填充轮廓内部(如绘制实心形状)。

demo画出图片轮廓

from pickle import NONE
import cv2 as cv
import numpy as np
from matplotlib import pyplot as pltimg = cv.imread("image1.png")
assert img is not None, "img is not exists"
# img = cv.cvtColor(img, cv.COLOR_BGR2RGB)
img_gray = cv.cvtColor(img, cv.COLOR_RGB2GRAY)
img_edge = cv.Canny(img_gray,100,200)contours, hierarchy = cv.findContours(img_edge, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
cv.drawContours(img, contours, -1, (0,125,0), 2)
cv.imshow('All Contours', img)
cv.waitKey(0)

轮廓实际上是一层包含一层的numpy数组

3.9.2Contour Features基础特征提取(轮廓分析基础

  • 常用特征(面积、周长、质心、边界框等)
  • 轮廓近似(多边形拟合)
  • 凸包(Convex Hull)
  • 几何形状检查(矩形度、圆形度等)
1.矩(Moments)-cv.moments(contour)
moments = cv.moments(contour)
cx = int(moments["m10"] / moments["m00"])  # 质心x坐标
cy = int(moments["m01"] / moments["m00"])  # 质心y坐标
area = moments["m00"]                      # 轮廓面积
2.面积与周长-cv.contourArea(contour)、cv.arcLength(contour, closed=True)
area = cv.contourArea(contour)              # 轮廓面积
perimeter = cv.arcLength(contour, closed=True)  # 周长(closed表示轮廓是否闭合)
3.边框cv.boundingRect(contour)、cv.rectangle、cv.minAreaRect(contour)、cv.boxPoints

矩形

x, y, w, h = cv.boundingRect(contour)      # 矩形框坐标和宽高
cv.rectangle(img, (x,y), (x+w,y+h), (0,255,0), 2)

旋转矩形

rect = cv.minAreaRect(contour)             # 返回旋转矩形(中心点、宽高、旋转角度)
box = cv.boxPoints(rect)                   # 获取四个顶点坐标
box = np.int0(box)                         # 转为整数
cv.drawContours(img, [box], 0, (0,0,255), 2)
4.轮廓近似-cv.arcLength、cv.approxPolyDP

用更少的点简化轮廓(减少噪声或压缩数据)

epsilon = 0.01 * cv.arcLength(contour, True)  # 近似精度(1%周长)
approx = cv.approxPolyDP(contour, epsilon, True)  # 多边形近似
应用:检测图像中的多边形(如识别四边形、三角形)。
5.凸包(Convex Hull)-cv.convexHull

计算轮廓的凸包(包裹轮廓的最小凸多边形)

hull = cv.convexHull(contour)              # 计算凸包
cv.drawContours(img, [hull], 0, (255,0,0), 2)
应用:检测凸性缺陷或物体形状分析。
6.几何形状检查-cv.isContourConvex、cv.minEnclosingCircle

(1) 凸性检测

is_convex = cv.isContourConvex(contour)      # 返回True/False

(2) 矩形度与圆形度

矩形度:轮廓面积与最小外接矩形面积的比值。

rect_area = w * h
extent = area / rect_area                   # 接近1则为矩形

圆形度:衡量轮廓接近圆形的程度。

(x,y), radius = cv.minEnclosingCircle(contour)
circle_area = np.pi * radius**2
circularity = area / circle_area            # 接近1则为圆形
7 .关键应用场景
  • 目标检测:通过边界框定位物体。
  • 形状分类:利用面积、周长、Hu矩区分不同形状。
  • 工业检测:检查零件是否符合几何规格(如凸性缺陷)。
  • OCR预处理:用多边形近似提取文字区域。

3.9.3提取高级几何属性

包括:

  • 纵横比(Aspect Ratio)
  • 轮廓面积与凸包面积比(Solidity)
  • 等效直径(Equivalent Diameter)
  • 方向(Orientation)
  • 掩膜与像素点(Mask & Pixel Points)
  • 最大值/最小值及其位置
  • 平均颜色/强度
  • 极点(Extreme Points)
1.纵横比

边界矩形宽高比(width/height

x, y, w, h = cv.boundingRect(contour)
aspect_ratio = float(w) / h
应用:区分细长物体(如笔)与方形物体(如硬币)。
2.轮廓面积与凸包面积比(Solidity)

轮廓面积(contourArea)与凸包面积(convexHull)的比值。

hull = cv.convexHull(contour)
hull_area = cv.contourArea(hull)
solidity = float(area) / hull_area  # area为轮廓面积
应用:检测凹性缺陷(如零件损伤)。
3.等效直径(Equivalent Diameter)

与轮廓面积相同的圆的直径。

equi_diameter = np.sqrt(4 * area / np.pi)
4.方向(Orientation)

轮廓的主轴角度(通过拟合椭圆获取)。

(x, y), (MA, ma), angle = cv.fitEllipse(contour)  # MA:长轴, ma:短轴, angle:角度
5.生成轮廓掩膜(Mask)
mask = np.zeros(gray.shape, np.uint8)
cv.drawContours(mask, [contour], 0, 255, -1)  # -1表示填充内部
pixel_points = np.transpose(np.nonzero(mask))  # 获取轮廓内所有像素坐标
6.最大值/最小值及位置

在ROI内找到最亮/最暗点。

min_val, max_val, min_loc, max_loc = cv.minMaxLoc(gray, mask=mask)
7.平均颜色/强度
mean_val = cv.mean(img, mask=mask)  # 返回BGR通道均值
8.极点(Extreme Points)

轮廓的最上、最下、最左、最右点。

leftmost = tuple(contour[contour[:, :, 0].argmin()][0])
rightmost = tuple(contour[contour[:, :, 0].argmax()][0])
topmost = tuple(contour[contour[:, :, 1].argmin()][0])
bottommost = tuple(contour[contour[:, :, 1].argmax()][0])
应用:物体姿态估计或裁剪感兴趣区域。
9.属性速查表
属性	函数/公式	应用场景
纵横比	w / h	形状分类
Solidity	area / hull_area	凹性检测
等效直径	sqrt(4*area/π)	尺寸筛选
方向	cv.fitEllipse()	物体朝向分析
极值点	argmin() / argmax()	边界定位
平均颜色	cv.mean()	区域色彩分析

3.9.4 凸性缺陷(Convexity Defects)-cv.convexHull、cv.convexityDefects

OpenCV: Contours : More Functions

  • 凸包(Convex Hull):包裹轮廓的最小凸多边形(无凹陷)。

  • 凸性缺陷:轮廓与凸包之间的偏离区域(即轮廓的凹陷部分)。

hull = cv.convexHull(contour, returnPoints=False)  # 返回凸包的索引而非坐标点
defects = cv.convexityDefects(contour, hull)       # 计算凸性缺陷returnPoints=False:要求 convexHull 返回凸包点在原始轮廓中的索引(而非坐标),这是计算缺陷的必要条件。
defects 返回值:一个形状为 (N,1,4) 的 NumPy 数组,每行包含 4 个值:
[start_index, end_index, farthest_index, distance]
start_point:缺陷起始点(轮廓索引)。
end_point:缺陷结束点(轮廓索引)。
farthest_point:凹陷最深处点(轮廓索引)。
distance:最远点到凸包的近似距离。

示例

import cv2 as cv
import numpy as npimg = cv.imread('star.jpg')
assert img is not None, "file could not be read, check with os.path.exists()"
img_gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
ret,thresh = cv.threshold(img_gray, 127, 255,0)
contours,hierarchy = cv.findContours(thresh,2,1)
cnt = contours[0]hull = cv.convexHull(cnt,returnPoints = False)
defects = cv.convexityDefects(cnt,hull)for i in range(defects.shape[0]):s,e,f,d = defects[i,0]start = tuple(cnt[s][0])end = tuple(cnt[e][0])far = tuple(cnt[f][0])cv.line(img,start,end,[0,255,0],2)cv.circle(img,far,5,[0,0,255],-1)cv.imshow('img',img)
cv.waitKey(0)
cv.destroyAllWindows()

应用

手势识别

通过手指间的凸性缺陷数量判断伸出的手指数。

工业检测

检测零件表面的凹痕或缺陷(如齿轮齿槽的完整性)。

医学图像分析

识别器官轮廓的异常凹陷(如心脏瓣膜形态)。

3.9.5匹配形状-cv.matchShapes()

OpenCV附带一个函数cv.matchShapes(),它使我们能够比较两个形状或两个轮廓,并返回一个显示相似性的指标。结果越低,匹配度越好。它是根据hu-moment值计算的。

import cv2 as cv
import numpy as npimg1 = cv.imread('star.jpg', cv.IMREAD_GRAYSCALE)
img2 = cv.imread('star2.jpg', cv.IMREAD_GRAYSCALE)
assert img1 is not None, "file could not be read, check with os.path.exists()"
assert img2 is not None, "file could not be read, check with os.path.exists()"ret, thresh = cv.threshold(img1, 127, 255,0)
ret, thresh2 = cv.threshold(img2, 127, 255,0)
contours,hierarchy = cv.findContours(thresh,2,1)
cnt1 = contours[0]
contours,hierarchy = cv.findContours(thresh2,2,1)
cnt2 = contours[0]ret = cv.matchShapes(cnt1,cnt2,1,0.0)
print( ret )

3.9.6轮廓层级(Hierarchy)

主要内容包括:

1.轮廓层级(Hierarchy) 的本质与数据结构

2. 4 种轮廓检索模式(RETR_LISTRETR_EXTERNALRETR_CCOMPRETR_TREE)的区别

3.举例如何利用层级关系分析嵌套轮廓(如孔洞检测)

3.10Histograms

http://www.lqws.cn/news/592093.html

相关文章:

  • 使用FFmpeg+SDL2读取本地摄像头并渲染
  • 07 Springboot+netty+mqtt服务端实现【重构】
  • php-mqtt/client 发布、订阅
  • 学习threejs,使用自定义GLSL 着色器,生成艺术作品
  • Redis-渐进式遍历
  • Android实现仿iOS风格滚动时间选择器
  • 【机器学习深度学习】理解欠拟合、拟合、过拟合
  • React安装使用教程
  • Linux->进程控制(精讲)
  • 文心一言开源版测评:能力、易用性与价值的全面解析
  • 通过http调用来访问neo4j时报错,curl -X POST 执行指令报错
  • 博途多重背景、参数实例
  • swing音频输入
  • 跨境证券交易系统合规升级白皮书:全链路微秒风控+开源替代,护航7月程序化交易新规落地
  • 7.可视化的docker界面——portainer
  • CloudBase AI ToolKit实战:从0到1开发一个智能医疗网站
  • LLM中的思维链,仅仅在提示词中加上思维链,让模型输出,和加上思维链限制模型输出答案,这两方式模型是不是进行了思考的
  • 鸿蒙Next开发中三方库使用指南之-nutpi-privacy_dialog集成示例
  • 用“做饭”理解数据分析流程(Excel三件套实战)​
  • 网站崩溃的幕后黑手:GPTBot爬虫的流量冲击
  • 论文阅读:Align and Prompt (ALPRO 2021.12)
  • 零开始git使用教程-传html文件
  • 浅谈Docker Kicks in的应用
  • 51单片机制作万年历
  • 观察者模式
  • 新版本 Spring Data Jpa + QueryDSL 使用教程
  • TensorFlow源码深度阅读指南
  • 【科研绘图系列】基于R语言的复杂热图绘制教程:环境因素与染色体效应的可视化
  • C#程序设计简介
  • 9-2 MySQL 分析查询语句:EXPLAIN(详细说明)