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://www.pswp.cn/news/914608.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/914608.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

移动端字体适配

一、移动端图片适配1、使用 <img> 的 srcset<img src"logo.png"srcset"logo2x.png 2x,logo3x.png 3x"alt"Logo">优点&#xff1a;原生支持&#xff0c;浏览器自动选择最合适的图片。2、使用媒体查询切换背景图.logo {background-ima…

git起步

git官网&#xff1a;https://git-scm.com git使用手册&#xff1a;https://git-scm.com/book/zh/v2 一、Git 是什么&#xff1f; 1、版本控制 版本控制是一种记录一个或若干文件内容变化&#xff0c;以便将来查阅特定版本修订情况的系统。我们经常是用的是保存软件源代码的…

SSL与HTTP概述

一、概念1.SSL概念SSL&#xff08;Secure Sockets Layer&#xff09;是一种网络安全协议&#xff0c;用于在互联网通信中建立加密链接&#xff0c;保护在网络中传输的敏感数据免遭窃取或篡改。2.TLS概念虽然现在更先进的 TLS&#xff08;Transport Layer Security&#xff09; …

前端报错:“Uncaught SyntaxError: missing ) after argument list

问题描述&#xff1a;前端报错&#xff1a;“Uncaught SyntaxError: missing ) after argument list在 JavaScript 中遇到“SyntaxError: missing ) after argument list”这个错误通常意味着在函数调用或者声明中&#xff0c;参数列表的括号没有正确闭合。错误代码&#xff1a…

广州邮科光纤交换机的应用:网络世界中的幕后核心

你知道吗&#xff1f;在我们每天畅游互联网&#xff0c;发送邮件、看视频、打游戏时&#xff0c;背后支撑这一切流畅体验的关键设备之一就是光纤交换机。它像一个幕后英雄&#xff0c;默默地确保信息传输高效、稳定。那么&#xff0c;究竟邮科光纤交换机有哪些不可或缺的应用领…

C++内存布局、构造函数规则和优化策略解析

一、类对象内存布局深度解析 1.1 核心内存占用规则 ​非静态成员变量​&#xff1a;每个对象独立存储&#xff0c;按声明顺序排列&#xff08;含内存对齐填充&#xff09; 示例&#xff1a;class A{int x; char y;}; → 实际占用8字节&#xff08;413填充&#xff09;4​静态…

Fastapi框架总览与核心架构

Fastapi框架总览与核心架构 FastAPI 是一个基于 Python 的现代 Web 框架&#xff0c;专注于 高性能、高并发 和 开发效率&#xff0c;特别适合构建 异步 API 服务、微服务接口&#xff0c;同时在大模型接口封装中也广泛应用。它基于 Starlette&#xff08;异步 Web 框架&#x…

高并发四种IO模型的底层原理

高并发四种IO模型的底层原理 1 IO读写的基本原理 为了避免用户进程直接操作内核&#xff0c;保证内核安全&#xff0c;操作系统将内存&#xff08;虚拟内存&#xff09;划分为两部分&#xff1a;一部分是内核空间(Kernel-Space)&#xff0c;另一部分是用户空间(User-Space)。在…

腾讯云短信实战:Spring Boot接入YML配置与签名/模板/发送/统计/状态/号码包工具类详解

下面是一个Spring Boot集成腾讯云短信服务的详细示例&#xff0c;包含配置和6个工具类&#xff08;签名、模板、发送、统计、状态&#xff09;&#xff0c;采用YML配置&#xff1a; 1. 添加Maven依赖 <dependency><groupId>com.tencentcloudapi</groupId>&…

【Java篇】IntelliJ IDEA 安装与基础配置指南

序 本篇文章将介绍IDEA 2023 版本。 提高开发人员的生产力。无论您是刚开始接触编程的新手&#xff0c;还是经验丰富的开发专家。 一&#xff1a;官网下载安装包&#xff1a; IDEA下载链接 这个版本可以根据自己的需要选择。 二、安装方法 双击进这个.exe文件 这里要选择合…

2-Nodejs运行JS代码

2-Nodejs运行JS代码 创建一个 js 文件编写 JS 代码 要注意的是&#xff0c;在nodejs环境中不能操作浏览器 DOM 对象相关的api&#xff0c;在Nodejs 中运行 JS 代码 按住 shift 键&#xff0c;在 js 文件所在文件夹空白处右键&#xff0c;选择 Powershell 窗口执行如下命令&…

vue中使用西瓜播放器xgplayer (封装)+xgplayer-hls 播放.m3u8格式视频

1.西瓜播放器官网 http://h5player.bytedance.com/guide/2.安装 # 最新稳定版 $ npm install xgplayer对于已有项目也可以通过 CDN 引入&#xff0c;代码如下&#xff1a; <script src"//unpkg.byted-static.com/xgplayer/2.31.2/browser/index.js" type"tex…

2025-07-15通过边缘线检测图像里的主体有没有出血

本节观点&#xff1a;一个好的提问就已经解决了问题的90%。 对于问题的描述正确与否决定了解决问题的方法和路径&#xff0c;所以我们在AI时代必须要学会正确的描述问题和表达问题&#xff0c;否则即使有AI辅助也是很难精准的解决问题。 我的问题&#xff1a; 如何利用代码从图…

【Docker基础】Dockerfile指令速览:文件与目录操作指令详解

目录 引言 1 ADD&#xff1a;高级文件复制与解压 1.1 指令简介 1.2 语法 1.3 功能详解 1.4 使用场景 1.5 执行流程 1.6 示例 1.7 注意事项 2 WORKDIR&#xff1a;设置工作目录 2.1 指令简介 2.2 语法 2.3 使用场景 2.4 创建流程 2.5 示例 2.6 注意事项 3 VOLU…

Python 程序设计讲义(2):Python 概述

Python 程序设计讲义&#xff08;2&#xff09;&#xff1a;Python 概述 一、Python 语言的发展史 Python 语言诞生于 1990 年。 2002 年 10 月&#xff0c;Python2.0 正式发布。 2008 年 12 月&#xff0c;Python3.0 正式发布。 Python3.0 在语法层面和解释器内部做了很多重大…

多租户SaaS系统中设计安全便捷的跨租户流程共享

四维协同架构​​,结合动态授权、加密传输、行为审计和智能策略 一、​​权限控制体系​​ 1. ​​动态权限模型​ ​ 2. ​​授权策略实现​​ ​​RBAC+ABAC混合模型​​ 在流程表增加shared_tenants字段存储授权信息,结合属性动态校验: CREATE TABLE workflow_process…

Spring Ioc Bean 到底是什么

Bean 到底是什么&#xff1f; 简单来说&#xff0c;Spring Bean 就是一个由 Spring IoC 容器负责创建、管理和装配的 Java 对象。 它不是一种新的技术&#xff0c;它本质上还是一个普普通通的 Java 对象&#xff08;POJO - Plain Old Java Object&#xff09;&#xff0c;但它的…

【PCIe 总线及设备入门学习专栏 5.1.1 -- PCIe PERST# 信号的作用】

文章目录 PCIe PERSTN#PERST# 信号作用概述简要定义PERST# 的关键功能PERST# 的时序图示意Synopsys PCIe EP IP 中 PERST# 的作用关键信号接口典型复位流程示例代码(Verilog for Synopsys PCIe)PERST# 使用场景举例(Synopsys PCIe EP)1. 系统上电初始化2. 热复位特定设备3.…

使用python的pillow模块将图片转化为灰度图,获取值和修改值

使用python的pillow模块可以将图片转化为灰度图&#xff0c; 可以获取灰度图的特定点值&#xff0c;区域值&#xff0c; 修改值并保存到图片 图片转换为灰度图 from PIL import Image# 打开图片 image Image.open("d://python//2//1.jpg")gray_image image.convert…

记忆力训练day41

通常是一个地点记2组词 数字和人体记忆宫殿更注重 即时性&#xff1b;地点记忆宫殿是长久性