python编程-OpenCV(图像读写-图像处理-图像滤波-角点检测-边缘检测)图像变换

形态变换

图像处理中的形态学操作是处理图像结构的有效方法。以下是一些常见的形态学操作的介绍及其在 OpenCV 中的实现示例。

1. 腐蚀(Erosion)

腐蚀操作通过消除图像边界来减少图像中的白色区域(前景),使物体的边界向内收缩。它的作用是去除小的噪点。根据内核的大小,边界附近的所有像素都将被丢弃。因此,前景对象的厚度或大小在图像中减少或只是白色区域减少。它有助于消除小的白色噪音,分离两个连接的对象等。

import cv2
import numpy as np

# 读取图像
image = cv2.imread('f:/apple.jpg', 0)
# 定义腐蚀的内核
kernel = np.ones((5,5), np.uint8)
# 进行腐蚀操作  
eroded = cv2.erode(image, kernel, iterations=1)

cv2.imshow('Eroded Image', eroded)
cv2.waitKey(0)
cv2.destroyAllWindows()

2. 膨胀(Dilation)

膨胀操作与腐蚀相反,主要是增加图像中的白色区域,使物体的边界向外扩展。

# 进行膨胀操作  
dilated = cv2.dilate(image, kernel, iterations=1)  

cv2.imshow('Dilated Image', dilated)  
cv2.waitKey(0)  
cv2.destroyAllWindows()

3. 开运算(Opening)

开运算是先进行腐蚀再进行膨胀,用于去除小的噪声,并保持图像中物体的形状和大小。

# 进行开运算  
opened = cv2.morphologyEx(image, cv2.MORPH_OPEN, kernel)  

cv2.imshow('Opened Image', opened)  
cv2.waitKey(0)  
cv2.destroyAllWindows()

4. 闭运算(Closing)

闭运算是先进行膨胀再进行腐蚀,主要用于填补图像中的小孔洞或黑色区域。

# 进行闭运算  
closed = cv2.morphologyEx(image, cv2.MORPH_CLOSE, kernel)  

cv2.imshow('Closed Image', closed)  
cv2.waitKey(0)  
cv2.destroyAllWindows()

5. 形态梯度(Morphological Gradient)

形态梯度是图像膨胀与腐蚀之间的差异,用于提取边缘。

# 进行形态梯度  
gradient = cv2.morphologyEx(image, cv2.MORPH_GRADIENT, kernel)  

cv2.imshow('Morphological Gradient', gradient)  
cv2.waitKey(0)  
cv2.destroyAllWindows()

6. 顶帽(Top Hat)

顶帽运算是原图像与开运算结果的差,主要用于突出比周围区域亮的部分。

# 进行顶帽运算  
tophat = cv2.morphologyEx(image, cv2.MORPH_TOPHAT, kernel)  

cv2.imshow('Top Hat', tophat)  
cv2.waitKey(0)  
cv2.destroyAllWindows()

7. 黑帽(Black Hat)

黑帽运算是闭运算结果与原图像的差,主要用于突出比周围区域暗的部分。

# 进行黑帽运算  
blackhat = cv2.morphologyEx(image, cv2.MORPH_BLACKHAT, kernel)  

cv2.imshow('Black Hat', blackhat)  
cv2.waitKey(0)  
cv2.destroyAllWindows()

几何变换

缩放

缩放是调整图片的大小。 OpenCV 使用cv.resize()函数进行调整。可以手动指定图像的大小,也可以指定比例因子。可以使用不同的插值方法。

import numpy as np
import cv2 as cv
img = cv.imread('image.jpg')
res = cv.resize(img,None,fx=2, fy=2, interpolation = cv.INTER_CUBIC)
#OR
height, width = img.shape[:2]
res = cv.resize(img,(2*width, 2*height), interpolation = cv.INTER_CUBIC)

平移变换
平移变换是物体位置的移动。转换矩阵:

t_x,t_y是方向的偏移量,可以将变换矩阵存为 np.float32 类型的 numpy 数组,并将其作为 cv.warpAffine 的第二个参数。cv.warpAffine 函数的第三个参数是输出图像的大小,其形式应为(宽度、高度)。记住宽度=列数,高度=行数。

import numpy as np
import cv2 as cv
img = cv.imread('image.jpg',0)
rows,cols = img.shape
M = np.float32([[1,0,100],[0,1,50]])
dst = cv.warpAffine(img,M,(cols,rows))
cv.imshow('img',dst)
cv.waitKey(0)
cv.destroyAllWindows()

旋转

旋转矩阵:

但 Opencv 提供了可变旋转中心的比例变换,所以你可以在任意位置旋转图片,修改后的转换矩阵为:

例如旋转90度:

img = cv.imread('image.jpg',0)
rows,cols = img.shape
# cols-1 and rows-1 are the coordinate limits.
M = cv.getRotationMatrix2D(((cols-1)/2.0,(rows-1)/2.0),90,1)
dst = cv.warpAffine(img,M,(cols,rows))

仿射变换
在仿射变换中,原始图像中的所有平行线在输出图像中仍然是平行的。仿射变换是图像处理和计算机视觉中的一种重要技术,用于执行图像的几何变换。它保留了点、直线和面之间的相对位置关系,因此常用于图像的旋转、缩放、平移和倾斜等操作。

仿射变换包括:

  1. 平移(Translation):图像中的每个点沿着 x 和 y 轴移动指定的距离。
  2. 缩放(Scaling):根据指定的比例因子缩放图像的大小。
  3. 旋转(Rotation):绕图像中心点旋转一定的角度。
  4. 倾斜(Shearing):沿 x 或 y 方向对图像进行剪切或倾斜。

结合这些操作,可以通过仿射矩阵来实现任意的仿射变换。仿射变换的矩阵形式可以表示为:

在 OpenCV 中,使用 cv2.warpAffine 函数执行仿射变换。下面是一个示例,展示如何进行平移、缩放和旋转:

import cv2
import numpy as np

# 读取图像
image = cv2.imread('f:/apple.jpg')

# 获取图像的尺寸
rows, cols, _ = image.shape

# 定义仿射变换矩阵
# 这里定义一个平移和缩放的组合
# 平移 tx = 50,ty = 30;缩放 sx = 1.5,sy = 1.5(增加 50%)
M = np.float32([[1.5, 0, 50],
                [0, 1.5, 30]])

# 应用仿射变换
dst = cv2.warpAffine(image, M, (int(cols * 1.5), int(rows * 1.5)))

# 显示结果
cv2.imshow('Original Image', image)
cv2.imshow('Transformed Image', dst)
cv2.waitKey(0)
cv2.destroyAllWindows()

综合仿射变换

下面是一个完成平移、缩放和旋转组合的仿射变换示例:

import cv2
import numpy as np

# 读取图像
image = cv2.imread('f:/apple.jpg')
# 获取图像的中心
center = (image.shape[1] // 2, image.shape[0] // 2)

# 定义旋转角度和缩放因子
angle = 45  # 旋转 45 度
scale = 1.0 # 不缩放  

# 获取仿射变换矩阵
M = cv2.getRotationMatrix2D(center, angle, scale)

# 应用仿射变换
transformed = cv2.warpAffine(image, M, (image.shape[1], image.shape[0]))

# 显示结果
cv2.imshow('Original Image', image)
cv2.imshow('Transformed Image', transformed)
cv2.waitKey(0)
cv2.destroyAllWindows()

透视变换
透视变换是一种将图像中某个区域进行变形的技术,使得该区域看起来像从不同的角度观看。透视变换通过将图像中的四个点映射到另一个四边形区域来实现,这样就能够模拟真实世界中由于相机角度变化而引起的视觉变化。

对透视转换,你需要一个 3x3 变换矩阵。即使在转换之后,直线也将保持直线。

要找到这个变换矩阵,需要输入图像上的 4 个点和输出图像上的相应点。在这四点中,任意三点不应该共线。


​在 OpenCV 中,透视变换使用 cv2.getPerspectiveTransform 函数来计算透视变换矩阵,然后用 cv2.warpPerspective 函数应用该变换。
 

import cv2
import numpy as np
from matplotlib import pyplot as plt



img = cv2.imread('f:/apple.jpg')
rows,cols,ch = img.shape
pts1 = np.float32([[56,65],[368,52],[28,387],[389,390]])
pts2 = np.float32([[0,0],[300,0],[0,300],[300,300]])
M = cv2.getPerspectiveTransform(pts1,pts2)
dst = cv2.warpPerspective(img,M,(300,300))
plt.subplot(121),plt.imshow(img),plt.title('Input')
plt.subplot(122),plt.imshow(dst),plt.title('Output')
plt.show()


# 读取图像
image = cv2.imread('f:/apple.jpg')

# 获取图像的尺寸
height, width = image.shape[:2]

# 定义源图像中的四个点(例如,选择四个角点)
pts1 = np.float32([[100, 100], [200, 100], [100, 200], [200, 200]])
# 定义目标图像中的四个点
pts2 = np.float32([[80, 80], [220, 100], [90, 210], [210, 220]])

# 计算透视变换矩阵
M = cv2.getPerspectiveTransform(pts1, pts2)

# 应用透视变换
warped_image = cv2.warpPerspective(image, M, (width, height))

# 显示结果
cv2.imshow('Original Image', image)
cv2.imshow('Warped Image', warped_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

频域变换:傅里叶变换和拉普拉斯变换

Numpy具有FFT软件包进行傅里叶变换。np.fft.fft2() 为我们提供了频率转换。它的第一个参数是输入灰度图像。第二个参数是可选的,它决定输出数组的大小。如果它大于输入图像的大小,则在计算FFT之前用零填充输入图像。如果小于输入图像,将裁切输入图像。如果未传递任何参数,则输出数组的大小将与输入的大小相同。 

使用 NumPy 执行图像的傅里叶变换(FFT)和反傅里叶变换(IFFT):

1. 傅里叶变换(FFT)

np.fft.fft2() 用于计算二维傅里叶变换,适合处理灰度图像。你可以传递一个可选的大小参数来决定输出数组的形状。

2. 逆傅里叶变换(IFFT)

np.fft.ifft2() 用于计算二维逆傅里叶变换,将频域数据转换回时域。

import numpy as np
import cv2
import matplotlib.pyplot as plt

# 读取灰度图像
image = cv2.imread('f:/apple.jpg', cv2.IMREAD_GRAYSCALE)

# 执行傅里叶变换
# 参数为 image 的 shape 可以控制零填充大小
f_transform = np.fft.fft2(image)

# 对傅里叶变换结果进行移位,使得低频部分居中
f_transform_shifted = np.fft.fftshift(f_transform)

# 计算幅度谱,以便可视化
magnitude_spectrum = np.log(np.abs(f_transform_shifted) + 1)  # 避免 log(0)

# 执行逆傅里叶变换
# 首先对移位后的频域图像进行逆变换
inverse_transform_shifted = np.fft.ifftshift(f_transform_shifted)
recovered_image = np.fft.ifft2(inverse_transform_shifted)

# 取实部作为恢复的图像
recovered_image = np.abs(recovered_image)

# 显示原始图像、幅度谱和恢复的图像
plt.figure(figsize=(12, 12))

plt.subplot(1, 3, 1)
plt.title('Original Image')
plt.imshow(image, cmap='gray')
plt.axis('off')

plt.subplot(1, 3, 2)
plt.title('Magnitude Spectrum')
plt.imshow(magnitude_spectrum, cmap='gray')
plt.axis('off')

plt.subplot(1, 3, 3)
plt.title('Recovered Image')
plt.imshow(recovered_image, cmap='gray')
plt.axis('off')

plt.tight_layout()
plt.show()

OpenCV中的傅立叶变换
OpenCV 为此提供了功能 cv.dft() 和 cv.idft() 。它返回与以前相同的结果,但是有两个通道。第一个通道将具有结果的实部,第二个通道将具有结果的虚部。输入的图像应首先转换为np.float32 。

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt

# 读取图像
img = cv.imread('f:/apple.jpg', 0)

# 1. 计算傅里叶变换
dft = cv.dft(np.float32(img), flags=cv.DFT_COMPLEX_OUTPUT)
dft_shift = np.fft.fftshift(dft)

# 2. 计算幅度谱
magnitude_spectrum = 20 * np.log(cv.magnitude(dft_shift[:, :, 0], dft_shift[:, :, 1]))

# 3. 创建掩码,然后将掩码应用于傅里叶变换结果
rows, cols = img.shape
crow, ccol = rows // 2, cols // 2

# 创建一个掩码,中心区域为1,其余区域为0(高通滤波器)
mask = np.zeros((rows, cols, 2), np.uint8)
mask[crow - 30:crow + 30, ccol - 30:ccol + 30] = 1  # 中心区域为1

# 应用掩码
fshift = dft_shift * mask

# 4. 计算逆傅里叶变换
f_ishift = np.fft.ifftshift(fshift)  # 反移位
img_back = cv.idft(f_ishift)  # 逆傅里叶变换
img_back = cv.magnitude(img_back[:, :, 0], img_back[:, :, 1])  # 获取复数的幅度

# 5. 显示原图、傅里叶变换幅度谱和恢复后的图像
plt.figure(figsize=(12, 6))

# 原始图像
plt.subplot(1, 3, 1)
plt.imshow(img, cmap='gray')
plt.title('Input Image')
plt.xticks([]), plt.yticks([])

# 幅度谱
plt.subplot(1, 3, 2)
plt.imshow(magnitude_spectrum, cmap='gray')
plt.title('Magnitude Spectrum')
plt.xticks([]), plt.yticks([])

# 恢复后的图像
plt.subplot(1, 3, 3)
plt.imshow(img_back, cmap='gray')
plt.title('Recovered Image')
plt.xticks([]), plt.yticks([])

plt.tight_layout()  # 自动调整子图参数
plt.show()

拉普拉斯算子是高通滤波器,Sobel是HPF。只需对Laplacian进行傅立叶变换,以获得更大的FFT大小。四种常用算子:

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt

# 简单平均滤波器(不带缩放参数)
mean_filter = np.ones((3, 3))

# 创建高斯滤波器
x = cv.getGaussianKernel(5, 10)
gaussian = x * x.T

# 不同的边缘检测滤波器
# Scharr滤波器(x方向)
scharr = np.array([[-3, 0, 3],
                   [-10, 0, 10],
                   [-3, 0, 3]])

# Sobel滤波器(x方向)
sobel_x = np.array([[-1, 0, 1],
                    [-2, 0, 2],
                    [-1, 0, 1]])

# Sobel滤波器(y方向)
sobel_y = np.array([[-1, -2, -1],
                    [0, 0, 0],
                    [1, 2, 1]])

# 拉普拉斯滤波器
laplacian = np.array([[0, 1, 0],
                      [1, -4, 1],
                      [0, 1, 0]])

# 将所有滤波器放入列表中
filters = [mean_filter, gaussian, laplacian, sobel_x, sobel_y, scharr]
filter_name = ['mean_filter', 'gaussian', 'laplacian', 'sobel_x', 'sobel_y', 'scharr']

# 计算每个滤波器的傅里叶变换
fft_filters = [np.fft.fft2(f) for f in filters]
fft_shift = [np.fft.fftshift(y) for y in fft_filters]

# 计算每个滤波器的幅度谱
mag_spectrum = [np.log(np.abs(z) + 1) for z in fft_shift]

# 绘制幅度谱
plt.figure(figsize=(12, 6))
for i in range(6):  # 使用 range 代替 xrange
    plt.subplot(2, 3, i + 1)
    plt.imshow(mag_spectrum[i], cmap='gray')
    plt.title(filter_name[i])
    plt.xticks([]), plt.yticks([])

plt.tight_layout()  # 调整子图参数
plt.show()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/955910.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux 音视频入门到实战专栏(视频篇)视频编解码 MPP

文章目录 一、MPP 介绍二、获取和编译RKMPP库三、视频解码四、视频编码 沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇将介绍如何调用alsa api来进行音频数据的播放和录制。 一、MPP 介绍 瑞芯微提供的媒体处理软件平台…

阿里云通义实验室自然语言处理方向负责人黄非:通义灵码2.0,迈入 Agentic AI

通义灵码是基于阿里巴巴通义大模型研发的AI 智能编码助手,在通义灵码 1.0 时代,我们针对代码的生成、补全和问答,通过高效果、低时延,研发出了国内最受欢迎的编码助手。 在通义灵码 2.0 发布会上,阿里云通义实验室自然…

Linux网络_套接字_UDP网络_TCP网络

一.UDP网络 1.socket()创建套接字 #include<sys/socket.h> int socket(int domain, int type, int protocol);domain (地址族): AF_INET网络 AF_UNIX本地 AF_INET&#xff1a;IPv4 地址族&#xff0c;适用于 IPv4 协议。用于网络通信AF_INET6&#xff1a;IPv6 地址族&a…

endnote x9 如何将参考文献和文中的应用格式由annotated变为编码,例[1],[2]

在 EndNote X9 中&#xff0c;将参考文献和文中引用格式更改为编码形式&#xff08;如 [1], [2]&#xff09;需要以下步骤&#xff1a; 1. 选择合适的输出样式 打开 EndNote X9。点击菜单栏的 "Edit" > "Output Styles" > "Open Style Manage…

用户中心项目教程(二)---umi3的使用出现的错误

目录 1.情况的说明 2.遇到的问题 1&#xff09;第一个问题-关于npx的使用 2&#xff09;第二个问题--unsupport问题 3&#xff09;第三个收获--nodejs安装问题 4&#xff09;第四个收获---nvm下载问题 5&#xff09;第五个问题--尚未解决的问题 3.个人总结 1.情况的说明…

【面试宝典】Java中创建线程池的几种方式以及区别

强烈推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站:人工智能 创建线程池有多种方式&#xff0c;主要通过 Java 的 java.util.concurrent 包提供的 Executors 工具类来实现。以下是几…

Net Core微服务入门全纪录(三)——Consul-服务注册与发现(下)

系列文章目录 1、.Net Core微服务入门系列&#xff08;一&#xff09;——项目搭建 2、.Net Core微服务入门全纪录&#xff08;二&#xff09;——Consul-服务注册与发现&#xff08;上&#xff09; 3、.Net Core微服务入门全纪录&#xff08;三&#xff09;——Consul-服务注…

通过视觉语言模型蒸馏进行 3D 形状零件分割

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01;对应英文要求比较高&#xff0c;特此说明&#xff01; Abstract This paper proposes a cross-modal distillation framework, PartDistill, which transfers 2D knowledge from vision-language models …

强推未发表!3D图!Transformer-LSTM+NSGAII工艺参数优化、工程设计优化!

目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Transformer-LSTMNSGAII多目标优化算法&#xff0c;工艺参数优化、工程设计优化&#xff01;&#xff08;Matlab完整源码和数据&#xff09; Transformer-LSTM模型的架构&#xff1a;输入层&#xff1a;多个变量作…

如何通过 Apache Airflow 将数据导入 Elasticsearch

作者&#xff1a;来自 Elastic Andre Luiz 了解如何通过 Apache Airflow 将数据导入 Elasticsearch。 Apache Airflow Apache Airflow 是一个旨在创建、安排&#xff08;schedule&#xff09;和监控工作流的平台。它用于编排 ETL&#xff08;Extract-Transform-Load&#xff0…

电脑风扇声音大怎么办? 原因及解决方法

电脑风扇是电脑的重要组件之一&#xff0c;它的作用是为电脑的各个部件提供冷却&#xff0c;防止电脑过热。然而&#xff0c;有时候我们会发现电脑风扇的声音特别大&#xff0c;不仅影响我们的使用体验&#xff0c;也可能是电脑出现了一些问题。那么&#xff0c;电脑风扇声音大…

Oracle报错ORA-01078、LRM-00109

虚拟机异常关机后&#xff0c;rac数据库备机无法启动数据库&#xff0c;报错如下 解决方法&#xff1a; 找到如下路径文件 执行&#xff1a; cp init.ora.016202516818 /u01/app/oracle/product/19.3.0/db/dbs/ mv init.ora.016202516818 initplm2.ora 再次进入命令行sqlpl…

.Net Core微服务入门系列(一)——项目搭建

系列文章目录 1、.Net Core微服务入门系列&#xff08;一&#xff09;——项目搭建 2、.Net Core微服务入门全纪录&#xff08;二&#xff09;——Consul-服务注册与发现&#xff08;上&#xff09; 3、.Net Core微服务入门全纪录&#xff08;三&#xff09;——Consul-服务注…

Ability Kit-程序框架服务(类似Android Activity)

文章目录 Ability Kit&#xff08;程序框架服务&#xff09;简介Stage模型开发概述Stage模型应用组件应用/组件级配置UIAbility组件概述概述声明配置 生命周期概述生命周期状态说明Create状态WindowStageCreate**和**WindowStageDestroy状态WindowStageWillDestroy状态Foregrou…

Harmony OS 5.0.1 模拟器报未开启 Hyper-V解决方法

程序员Feri一名12年的程序员,做过开发带过团队创过业,擅长Java、嵌入式、鸿蒙、人工智能等,专注于程序员成长那点儿事,希望在成长的路上有你相伴&#xff01;君志所向,一往无前&#xff01; 今天在写Harmony NEXT版本的元服务的时候&#xff0c;突然模拟器无法启动了&#xff0…

WPS数据分析000004

目录 一、表格阅读技巧 冻结窗格 拆分窗口 新建窗口 阅读模式 护眼模式 二、表格打印技巧 打印预览 打印缩放 打印区域 打印标题 分页打印 打印位置 页眉页脚 逐份打印 三、表格保护技巧 锁定单元格 隐藏公式 文档权限 文件加密 一、表格阅读技巧 冻结窗…

LabVIEW桥接传感器数据采集与校准程序

该程序设计用于采集来自桥接传感器的数据&#xff0c;执行必要的设置&#xff08;如桥接配置、信号采集参数、时间与触发设置&#xff09;&#xff0c;并进行适当的标定和偏移校正&#xff0c;最终通过图表呈现采集到的数据信息。程序包括多个模块&#xff0c;用于配置通道、触…

2025西湖论剑-babytrace

前言 就做了下题目&#xff0c;pwn1/3 都是签到&#xff0c;pwn2 后面绕 ptrace 有点意思&#xff0c;简单记录一下 漏洞分析 子进程中的读/写功能没有检查负数的情况&#xff0c;存在越界读写&#xff1a; void __fastcall get_value(__int64 *int64_arr) {__int64 ll; //…

【统计的思想】假设检验(一)

假设检验是统计学里的重要方法&#xff0c;同时也是一种“在理想与现实之间观察求索”的测试活动。假设检验从概率的角度去考察理想与现实之间的关系&#xff0c;籍此来缓解测试可信性问题。 我们先来看一个例子。民航旅客服务系统&#xff0c;简称PSS系统&#xff0c;有一种业…

GPT-5 传言:一场正在幕后发生的 AI 变革

新的一年&#xff0c;让我们从一个引人入胜的话题开始&#xff1a;如果我告诉你&#xff0c;GPT-5 并非虚构&#xff0c;而是真实存在呢&#xff1f;它不仅真实存在&#xff0c;而且正在你看不见的地方悄然塑造着世界。我的基本假设是&#xff1a;OpenAI 已经秘密开发出 GPT-5&…