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

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

3.11傅立叶变换

3.11.1Fourier Transform in OpenCV-cv.dft、cv.magnitude、cv.idft

这两个函数是图像频域处理(如去噪、边缘增强、纹理分析)的基础工具。

1.cv.dft() —— 离散傅里叶变换

功能
将图像从空间域(像素强度)转换到频域(频率成分),用于分析图像中的高频(边缘、噪声)和低频(平滑区域)信息。

dft_output = cv.dft(src, flags=cv.DFT_COMPLEX_OUTPUT)
src: 输入图像(需为单通道灰度图,格式 np.float32)。
flags:
cv.DFT_COMPLEX_OUTPUT(默认):输出复数形式(实部+虚部)。
cv.DFT_SCALE:归一化结果(便于可视化)。
cv.DFT_ROWS:对多行单独执行DFT。
返回值:
复数形式的频域矩阵(尺寸与输入相同,类型为 np.complex64 或双通道 np.float32),是一个双通道数组(dft[:,:,0]为实部,dft[:,:,1]为虚部)。

cv.magnitude() 是 OpenCV 中用于计算二维向量幅值的函数,在频域处理中常用于从傅里叶变换的复数结果(实部 + 虚部)中提取幅度谱(即频率分量的强度)

magnitude = cv.magnitude(x, y)
参数:
x:输入矩阵的实部(如 dft[:,:,0])。
y:输入矩阵的虚部(如 dft[:,:,1])。

返回值:与输入同尺寸的单通道矩阵,每个元素值为:

作用:

2. cv.idft() —— 逆离散傅里叶变换

功能
将频域数据还原回空间域图像,常用于滤波后的重建。

idft_output = cv.idft(src, flags=cv.DFT_SCALE | cv.DFT_REAL_OUTPUT)
src: 频域数据(复数或双通道浮点矩阵)。
flags:
cv.DFT_SCALE:对结果归一化(抵消DFT的系数)。
cv.DFT_REAL_OUTPUT:输出实数图像(单通道)。
返回值:
重建的空间域图像(双通道 np.float32)。

关键注意事项

  1. 输入格式cv.dft() 的输入必须是单通道 np.float32

  2. 频谱可视化:需对DFT结果取对数并归一化(cv.magnitude() + cv.normalize())。

  3. 频移操作:使用 np.fft.fftshift() 将低频分量移到频谱中心。

  4. 滤波应用:通过掩码(mask)修改频域数据(如高通/低通滤波)。

3.demo

通过DFT和IDFT)实现把图片从颜色空间变换到频域空间,再通过低通滤波,模糊图像以去除高频成分(如边缘和噪声)

from operator import eq
from turtle import title
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
from numpy.fft import fftshiftimg = cv.imread("image4.png")
assert img is not None, "file could not be read, check with os.path.exists()"
img = cv.cvtColor(img,cv.COLOR_BGR2GRAY)# 转到频域可视化
dft = cv.dft(np.float32(img),flags = cv.DFT_COMPLEX_OUTPUT)
dft_shift = np.fft.fftshift(dft)magnitude = 20*np.log(cv.magnitude(dft_shift[:,:,0],dft_shift[:,:,1]))# 从频域转到颜色空间,带有低通滤波mask
row,col = img.shape
crow,ccol = row//2,col//2
mask = np.zeros((row,col,2),np.uint8)
mask[crow-30:crow+30,ccol-30:ccol+30] = 1fshift = dft_shift * mask
fshift = np.fft.ifftshift(fshift)
img_back = cv.idft(fshift)
img_back = cv.magnitude(img_back[:,:,0],img_back[:,:,1])titles = ['img','dft','img_back']
images = [img,magnitude,img_back]
for i in range(3):plt.subplot(1,3,i+1)plt.imshow(images[i],cmap='gray')plt.title(titles[i])
plt.show()

4.解读-幅度谱的关键特征
  • 中心亮点:代表低频成分(图像中的平滑区域,如背景或缓慢变化的颜色)。

  • 外围亮点:代表高频成分(图像中的边缘、纹理或噪声)。

  • 对称性:幅度谱是中心对称的(因为DFT的结果是共轭对称的)。

示例分析

  • 如果原始图像中有明显的边缘(如物体的轮廓),幅度谱的外围会显示对应的亮点。

  • 如果图像整体较模糊(低频主导),幅度谱的中心区域会更亮。

如何验证结果是否正确?

5.最常用的2种滤波操作

必须避开的坑

  • 错误1:未转float32直接DFT → 报错

  • 错误2:逆变换后未取实部(.real)→ 结果异常

  • 错误3:未中心化频谱 → 低频分布在四角

3.11.2DFT的性能优化

3.11.3Why Laplacian is a High Pass Filter?

不做重点介绍

3.12模板匹配Template Matching-cv2.matchTemplate()、cv2.minMaxLoc()

模板匹配(Template Matching)

  • 作用:在输入图像(大图)中查找与模板图像(小图)最相似的部分。
  • 原理:滑动模板窗口,用数学方法计算每个位置的相似度,返回最佳匹配位置。
  • 特点平移有效但对旋转、缩放、光照变化敏感适合固定图案的快速定位(如按钮检测、LOGO识别)

匹配函数:cv2.matchTemplate()

result = cv2.matchTemplate(image, templ, method, mask=None)
参数:
image:输入图像(大图),必须为单通道灰度图(若彩色需先转灰度)。
templ:模板图像(小图),尺寸≤大图且数据类型相同。
method:匹配方法(见下方6种选项)。
mask:可选掩模,与模板同尺寸,仅匹配掩模非零区域。
返回值:
result:浮点型矩阵,尺寸为 (W-w+1, H-h+1)(W/H=大图宽高,w/h=模板宽高)。
每个像素值表示该位置的匹配程度(具体含义取决于method)。
method介绍如下:
方法名	公式/原理	最佳匹配位置	返回值范围
cv2.TM_SQDIFF	平方差最小化	最小值点	[0, ∞)
cv2.TM_SQDIFF_NORMED	归一化平方差	最小值点	[0, 1]
cv2.TM_CCORR	互相关(亮度敏感)	最大值点	[0, ∞)
cv2.TM_CCORR_NORMED	归一化互相关	最大值点	[0, 1]
cv2.TM_CCOEFF	相关系数(去均值)	最大值点	[-1, 1]
cv2.TM_CCOEFF_NORMED	归一化相关系数(推荐)	最大值点	[-1, 1]
推荐:TM_CCOEFF_NORMED(抗亮度变化)或 TM_SQDIFF_NORMED(精确差异)。

结果解析函数:cv2.minMaxLoc()

min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
作用:找到匹配结果矩阵中的极值位置。
返回值:
min_val, max_val:最小/最大值(根据method决定取哪个)。
min_loc, max_loc:对应极值的坐标(左上角点,格式 (x, y))。

demo:完成单模板的匹配,多模板其实就是加个循环结构画结果出来

from unittest import result
import cv2 as cv
import numpy as npimg1 = cv.imread('image4.png')
img = cv.cvtColor(img1,cv.COLOR_BGR2GRAY)
template = cv.imread('template.png',cv.IMREAD_GRAYSCALE)
h,w = template.shaperesult = cv.matchTemplate(img,template,cv.TM_CCOEFF_NORMED)# 获取最佳匹配位置
min_val, max_val, min_loc, max_loc = cv.minMaxLoc(result)
# print(min_val, max_val, min_loc, max_loc)
top_left = max_loc  # TM_CCOEFF_NORMED取最大值位置
bottom_right = (top_left[0] + w, top_left[1] + h)# 绘制矩形框
cv.rectangle(img1,top_left,bottom_right,[0,255,0],2)cv.imshow('match',img1)
cv.waitKey(0)
cv.destroyAllWindows()

3.13hough transformation-cv2.HoughLines()、cv2.HoughLinesP()、cv2.HoughCircles()

3.13.1直线霍夫变换

标准霍夫线变换:cv2.HoughLines()

lines = cv2.HoughLines(image, rho, theta, threshold, lines=None, srn=None, stn=None, min_theta=None, max_theta=None)
参数:
image:输入图像(必须为二值图,常用Canny边缘检测结果)。
rho:距离分辨率(像素),推荐1。
theta:角度分辨率(弧度),推荐np.pi/180(即1度)。
threshold:投票阈值(低于此值的直线被忽略),值越小检测越多。
srn, stn:多尺度霍夫变换参数,通常设为0。
min_theta, max_theta:角度范围限制(默认0~π)。
返回值:
lines:(N, 1, 2)的NumPy数组,每行为[ρ, θ]。

概率霍夫线变换(推荐):cv2.HoughLinesP()

lines = cv2.HoughLinesP(image, rho, theta, threshold, lines=None, minLineLength=None, maxLineGap=None)
参数:
minLineLength:线段最小长度(小于此值被过滤)。
maxLineGap:允许的同一直线上点的最大间隔。
返回值:
lines:(N, 1, 4)数组,每行为[x1, y1, x2, y2](线段端点坐标)。

对比

  • HoughLines:返回无限长的直线参数,需自行计算端点。
  • HoughLinesP:直接返回线段端点,更易使用。

demo1:使用标准霍夫变换

import cv2 as cv
import numpy as npimg = cv.imread(cv.samples.findFile('sudoku.png'))
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
edges = cv.Canny(gray,50,150,apertureSize = 3)lines = cv.HoughLines(edges,1,np.pi/180,200)
for line in lines:rho,theta = line[0]a = np.cos(theta)b = np.sin(theta)x0 = a*rhoy0 = b*rhox1 = int(x0 + 1000*(-b))y1 = int(y0 + 1000*(a))x2 = int(x0 - 1000*(-b))y2 = int(y0 - 1000*(a))cv.line(img,(x1,y1),(x2,y2),(0,0,255),2)cv.imwrite('houghlines3.jpg',img)

demo2:使用概率霍夫变换

import cv2 as cv
import numpy as npimg = cv.imread(cv.samples.findFile('sudoku.png'))
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
edges = cv.Canny(gray,50,150,apertureSize = 3)
lines = cv.HoughLinesP(edges,1,np.pi/180,100,minLineLength=100,maxLineGap=10)
for line in lines:x1,y1,x2,y2 = line[0]cv.line(img,(x1,y1),(x2,y2),(0,255,0),2)cv.imwrite('houghlines5.jpg',img)

3.13.2霍夫圆变换

demo:检测圆形

import numpy as np
import cv2 as cvimg = cv.imread('opencv-logo-white.png', cv.IMREAD_GRAYSCALE)
assert img is not None, "file could not be read, check with os.path.exists()"
img = cv.medianBlur(img,5)
cimg = cv.cvtColor(img,cv.COLOR_GRAY2BGR)circles = cv.HoughCircles(img,cv.HOUGH_GRADIENT,1,20,param1=50,param2=30,minRadius=0,maxRadius=0)circles = np.uint16(np.around(circles))
for i in circles[0,:]:# draw the outer circlecv.circle(cimg,(i[0],i[1]),i[2],(0,255,0),2)# draw the center of the circlecv.circle(cimg,(i[0],i[1]),2,(0,0,255),3)cv.imshow('detected circles',cimg)
cv.waitKey(0)
cv.destroyAllWindows()

3.14基于分水岭算法的图像分割-cv2.watershed()

这一节简单介绍原理,目前分割基本都是基于深度学习的。如果需要处理重叠/粘连物体,那么需要这个方法。

markers = cv2.watershed(image, markers)
参数:
image:输入3通道彩色图像(BGR格式)。
markers:标记矩阵(与图像同尺寸,数据类型为int32):
markers[i,j]=0:未确定区域(待分割)
markers[i,j]>0:前景对象的唯一标签
markers[i,j]=-1:算法输出的边界像素
返回值:
修改后的markers矩阵,边界像素被标记为-1。

3.15GrabCut算法-cv2.grabCut()

mask, bgdModel, fgdModel = cv2.grabCut(image, mask, rect, bgdModel, fgdModel, iterCount, mode
)
参数说明:
参数	类型	说明
image	np.uint8 (RGB)	输入图像(必须为3通道彩色图)
mask	np.uint8	掩模矩阵,取值:
• 0(GC_BGD): 明确背景
• 1(GC_FGD): 明确前景
• 2(GC_PR_BGD): 可能背景
• 3(GC_PR_FGD): 可能前景
rect	tuple	前景的矩形框 (x,y,w,h),仅在 mode=GC_INIT_WITH_RECT 时使用
bgdModel/fgdModel	np.float64	算法内部使用的临时数组,初始化为 np.zeros((1,65), np.float64)
iterCount	int	迭代次数(通常5~10次)
mode	int	GC_INIT_WITH_RECT(矩形初始化)或 GC_INIT_WITH_MASK(掩模初始化)
返回值:
mask:更新后的掩模(需后处理提取最终结果)
bgdModel/fgdModel:可复用的模型参数

关键注意事项

  1. 输入图像:必须是RGB格式(BGR顺序),且为np.uint8类型。

  2. 掩模初始化

    • 矩形模式:mask会被自动覆盖,无需手动设置。

    • 掩模模式:需提前用GC_FGD/GC_BGD标记明确区域。

  3. 结果优化

    • 对边缘粗糙部分,可用cv2.erode()cv2.GaussianBlur()平滑。

  4. 性能权衡

    • iterCount=5:快速但可能欠分割

    • iterCount=10:速度慢但精度高

demo:使用该方法进行分割

import numpy as np
import cv2# 1. 加载图像
img = cv2.imread('test.jpg')
mask = np.zeros(img.shape[:2], np.uint8)  # 初始化掩模# 2. 定义前景矩形框 (x,y,width,height)
rect = (50, 50, 300, 400)  # 需完全包围目标物体# 3. 执行GrabCut
bgdModel = np.zeros((1,65), np.float64)
fgdModel = np.zeros((1,65), np.float64)
cv2.grabCut(img, mask, rect, bgdModel, fgdModel, 5, cv2.GC_INIT_WITH_RECT)# 4. 提取前景(类型转换)
mask = np.where((mask==1)|(mask==3), 255, 0).astype('uint8')# 5. 应用掩模并显示
result = cv2.bitwise_and(img, img, mask=mask)
cv2.imshow('Result', result)
cv2.waitKey(0)

此方法速度很慢,并不是特别适合处理一般图像。


文章转载自:
http://bateleur.jopebe.cn
http://brigantine.jopebe.cn
http://chested.jopebe.cn
http://acrobatic.jopebe.cn
http://allosteric.jopebe.cn
http://chartula.jopebe.cn
http://aclu.jopebe.cn
http://affectation.jopebe.cn
http://acerb.jopebe.cn
http://applicability.jopebe.cn
http://bla.jopebe.cn
http://adorer.jopebe.cn
http://acgb.jopebe.cn
http://brawny.jopebe.cn
http://chambermaid.jopebe.cn
http://belitoeng.jopebe.cn
http://amish.jopebe.cn
http://bromal.jopebe.cn
http://cambist.jopebe.cn
http://chokecherry.jopebe.cn
http://bridle.jopebe.cn
http://biomedicine.jopebe.cn
http://bell.jopebe.cn
http://calibration.jopebe.cn
http://calorifacient.jopebe.cn
http://billfish.jopebe.cn
http://affined.jopebe.cn
http://acidophile.jopebe.cn
http://atapi.jopebe.cn
http://avg.jopebe.cn
http://www.dtcms.com/a/281795.html

相关文章:

  • Redis原理之持久化
  • 【构建 SHAP 解释器】X:每个样本的特征表(不能含 label,否则解释不纯粹)。
  • 隐私计算四大主流开源框架:从学术研究到工业落地,附PySyft实战Demo
  • 梁的振动特征函数分析2
  • 智驾芯片软件分层测试
  • kdump生成转储文件调试内核崩溃、死机
  • 电涡流位移测量技术深度解密
  • View2 UI聊天框架源码分享 - 支持[图文视频]混排 加入AI 分享一套功能强大的View2 UI聊天框架源码
  • Python初学者笔记第十四期 -- (自定义模块与包)
  • NFS磁盘共享
  • 基础专有术语
  • Model Control Protocol 一种开放的应用层协议,让大模型与工具能够协调配合起来,了解他的定义、定位、组成及实现机制...
  • 手提式干粉灭火器检查工作,如何做到可执行、可追溯、可管理?
  • 移动碰撞法 ——套料排版算法——CAD c#
  • java基础(day08)-面向对象
  • Redis 高频面试题
  • 【删库跑路】一次删除pip的所有第三方库
  • vllm本地部署qwen3-4b
  • 场景设计题+智力题
  • windows下安装difi(无docker desktop版)
  • 7.15 腾讯云智面经整理
  • Wiz笔记二次开发
  • AI大模型开发架构设计(22)——LangChain的大模型架构案例实战
  • 记忆力训练day41
  • 1-Nodejs介绍与安装
  • 基于STM32的智能火灾报警系统设计
  • 【人工智能99问】激活函数有哪些,如何选择使用哪个激活函数?(5/99)
  • ADAU系列DSP用MCU来做控制,怎么去理解这个逻辑
  • Vue3 + MapLibre 地图管理工具 useMap 使用指南
  • 牛客:HJ22 汽水瓶[华为机考][数字处理]