Opencv基本操作 (上)

目录

图像基本操作

阈值与平滑处理

图像阈值

图像平滑处理

图像形态学操作

图像梯度计算

Sobel 算子

Canny 边缘检测

图像金字塔与轮廓检测 

 图像轮廓

接口定义

 轮廓绘制

轮廓特征与相似

模板匹配

 傅里叶变换

傅里叶变换的作用

滤波

图像基本操作

  • 读取图像: 使用cv2.imread()函数可以读取图像文件,并将其存储为一个NumPy数组。
import cv2
image = cv2.imread('image.jpg')
#图像的显示,也可以创建多个窗口
cv2.imshow('image',img) 
# 等待时间,毫秒级,0表示任意键终止
cv2.waitKey(0) 
cv2.destroyAllWindows()
  • 读取视频:cv2.VideoCapture可以捕获摄像头,用数字来控制不同的设备,例如0,1。
# 读取视频
vc = cv2.VideoCapture('./img/test.mp4')
# 检查是否打开正确
if vc.isOpened():oepn, frame = vc.read()
else:open = Falsewhile open:ret, frame = vc.read()if frame is None:breakif ret == True:# 彩色图转换为灰度图gray = cv2.cvtColor(frame,  cv2.COLOR_BGR2GRAY)cv2.imshow('result', gray)if cv2.waitKey(100) & 0xFF == 27:break
vc.release()
cv2.destroyAllWindows()
  • 剪裁图像:使用数组切片操作可以裁剪图像的一部分
# 截取部分图像数据
img=cv2.imread('./img/cat.jpg')
# [起始x坐标:宽度,起始y坐标:高度]
cat=img[0:200,0:200]
cv2.imshow('cat', cat)
cv2.waitKey(0)
cv2.destroyAllWindows()
  • 边界填充:cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, borderType=cv2.BORDER_REPLICATE)
top_size,bottom_size,left_size,right_size = (50,50,50,50)replicate = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, borderType=cv2.BORDER_REPLICATE)
reflect = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size,cv2.BORDER_REFLECT)
reflect101 = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, cv2.BORDER_REFLECT_101)
wrap = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, cv2.BORDER_WRAP)
constant = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size,cv2.BORDER_CONSTANT, value=0)

  • 图像融合:cv2.addWeighted(图像1, 0.4(权重), 图像2, 0.6(权重), 0(偏置项))
img_cat=cv2.imread('cat.jpg')
img_dog=cv2.imread('dog.jpg')# 图像变换
img_dog = cv2.resize(img_dog, (500, 414))
img_dog.shape# 图像融合
res = cv2.addWeighted(img_cat, 0.4, img_dog, 0.6, 0)
plt.imshow(res)
  • 调整图像:使用cv2.resize()函数可以调整图像的大小
  • 图像保存:使用cv2.imwrite()函数可以将图像保存到指定的文件路径
# 读取灰度图
img1=cv2.imread('./img/cat.jpg',cv2.IMREAD_GRAYSCALE)
print(img1)
print(img1.shape) # h,w# 图像保存
cv2.imwrite('./img/mycat1.png',img1)
  • 显示图像: 使用cv2.imshow()函数可以在窗口中显示图像

阈值与平滑处理

图像阈值

图像阈值是一种图像处理术,用于将图像中的像素值分为两个或多个不同的类别。阈值可以用来分割图像、提取感兴趣的目标或者进行图像增强等操作。

在图像阈值处理中,首先需要选择一个阈值,然后将图像中的像素值与该阈值进行比较。如果像素值大于阈值,则将其归为一类;如果像素值小于等于阈值,则将其归为另一类。这样就可以将图像中的像素分为不同的区域或者进行二值化处理。

常见的图像阈值处理方法包括全局阈值法、自适应阈值法和多阈值法等。全局阈值法是指在整个图像上使用一个固定的阈值进行处理;自适应阈值法是指根据图像局部的特性来选择不同的阈值;多阈值法是指使用多个阈值将图像分成多个不同的类别。

图像阈值处理可以应用于很多领域,如图像分割、目标检测、字符识别等。通过调整阈值的选择和处理方法,可以实现对图像的不同特征进行提取和分析。

图像平滑处理

图像平滑处理是一种常用的图像处理技术用于减少图像中的噪声和细节,使图像变得更加平滑和模糊。以下是几种常见的图像平滑处理方法:

1. 均值滤波:将图像中每个像素的值替换为其周围像素的平均值。这种方法可以有效地去除高频噪声,但可能会导致图像细节的模糊。

2. 高斯滤波:使用高斯函数对图像进行卷积操作,以减少噪声。高斯滤波器在中心像素周围的像素上施加较大的权重,而在边缘像素周围施加较小的权重。这种方法可以平滑图像并保留边缘信息。

3. 中值滤波:将图像中每个像素的值替换为其周围像素值的中值。中值滤波器对于去除椒盐噪声等椒盐噪声非常有效,但可能会导致图像细节的丢失。

4. 双边滤波:结合了空间域和灰度值域的信息,对图像进行平滑处理。双边滤波器考虑了像素之间的空间距离和像素值之间的差异,以保留边缘信息的同时减少噪声。

5. 维纳滤波:基于信号和噪声的统计特性,通过最小均方误差准则对图像进行滤波。维纳滤波器可以根据图像的噪声特性进行自适应调整,以实现更好的平滑效果。

img = cv2.imread('lenaNoise.png')cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()# 均值滤波
# 简单的平均卷积操作
blur = cv2.blur(img, (3, 3))cv2.imshow('blur', blur)
cv2.waitKey(0)
cv2.destroyAllWindows()# 方框滤波
# 基本和均值一样,可以选择归一化
box = cv2.boxFilter(img,-1,(3,3), normalize=True)  cv2.imshow('box', box)
cv2.waitKey(0)
cv2.destroyAllWindows()# 方框滤波
# 基本和均值一样,可以选择归一化,容易越界
box = cv2.boxFilter(img,-1,(3,3), normalize=False)  cv2.imshow('box', box)
cv2.waitKey(0)
cv2.destroyAllWindows()# 高斯滤波
# 高斯模糊的卷积核里的数值是满足高斯分布,相当于更重视中间的
aussian = cv2.GaussianBlur(img, (5, 5), 1)  cv2.imshow('aussian', aussian)
cv2.waitKey(0)
cv2.destroyAllWindows()# 中值滤波
# 相当于用中值代替
median = cv2.medianBlur(img, 5)  # 中值滤波cv2.imshow('median', median)
cv2.waitKey(0)
cv2.destroyAllWindows()# 展示所有的
res = np.hstack((blur,aussian,median))
#print (res)
cv2.imshow('median vs average', res)
cv2.waitKey(0)
cv2.destroyAllWindows()
图像形态学操作

图像形态学是一种基于数学理论的图像处理方法,主要用于图像的形状分析和特征提取。它通过结构元素与图像进行卷积运算,从而改变图像的形状和结构。

常见的图像形态学操作包括腐蚀、膨胀、开运算、闭运算、击中击不中变换等。

1. 腐蚀(Erosion):腐蚀操作可以使图像中的物体边界向内部收缩。它通过将结构元素与图像进行逐像素的比较,只有当结构元素完全包含在图像中时,该像素才保留,否则被置为背景值。

pie = cv2.imread('pie.png')cv2.imshow('pie', pie)
cv2.waitKey(0)
cv2.destroyAllWindows()kernel = np.ones((30,30),np.uint8) 
erosion_1 = cv2.erode(pie,kernel,iterations = 1)
erosion_2 = cv2.erode(pie,kernel,iterations = 2)
erosion_3 = cv2.erode(pie,kernel,iterations = 3)
res = np.hstack((erosion_1,erosion_2,erosion_3))
cv2.imshow('res', res)
cv2.waitKey(0)
cv2.destroyAllWindows()

2. 膨胀(Dilation):膨胀操作可以使图像中的物体边界向外部扩张。它也是通过将结构元素与图像进行逐像素的比较,只要结构元素与图像中的任意一个像素相交,该像素就被保留。

pie = cv2.imread('pie.png')kernel = np.ones((30,30),np.uint8) 
dilate_1 = cv2.dilate(pie,kernel,iterations = 1)
dilate_2 = cv2.dilate(pie,kernel,iterations = 2)
dilate_3 = cv2.dilate(pie,kernel,iterations = 3)
res = np.hstack((dilate_1,dilate_2,dilate_3))
cv2.imshow('res', res)
cv2.waitKey(0)
cv2.destroyAllWindows()

3. 开运算(Opening):开运算是先进行腐蚀操作,再进行膨胀操作。它可以消除小的噪点,并保持物体的整体形状。

# 开:先腐蚀,再膨胀
img = cv2.imread('dige.png')kernel = np.ones((5,5),np.uint8) 
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)cv2.imshow('opening', opening)
cv2.waitKey(0)
cv2.destroyAllWindows()

4. 闭运算(Closing):闭运算是先进行膨胀操作,再进行腐蚀操作。它可以填充物体内部的小孔,并保持物体的整体形状。

# 闭:先膨胀,再腐蚀
img = cv2.imread('dige.png')kernel = np.ones((5,5),np.uint8) 
closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)cv2.imshow('closing', closing)
cv2.waitKey(0)
cv2.destroyAllWindows()

5. 击中击不中变换(Hit-or-Miss Transform):击中击不中变换是一种用于检测特定形状的图像操作。它通过定义两个结构元素,分别表示要击中的形状和要排除的形状,从而实现对特定形状的检测。

6. 梯度计算:梯度计算基于形态学操作,通过对图像进行膨胀和腐蚀操作,然后计算两幅图像之间的差异来获取边缘信息。

具体而言,图像形态学梯度计算的步骤如下:

  • 首先,选择一个结构元素(也称为核或模板),它定义了形态学操作的形状和大小。
  • 对原始图像进行膨胀操作,膨胀操作将结构元素与图像进行卷积,得到一个膨胀后的图像。
  • 对原始图像进行腐蚀操作,腐蚀操作同样将结构元素与图像进行卷积,得到一个腐蚀后的图像。
  • 将膨胀后的图像减去腐蚀后的图像,得到梯度图像。

梯度图像中的亮点表示边缘或轮廓的位置,亮点的强度表示边缘或轮廓的强度。通过调整结构元素的形状和大小,可以控制梯度计算的敏感度和精度。

# 梯度=膨胀-腐蚀
pie = cv2.imread('pie.png')
kernel = np.ones((7,7),np.uint8) 
dilate = cv2.dilate(pie,kernel,iterations = 5)
erosion = cv2.erode(pie,kernel,iterations = 5)res = np.hstack((dilate,erosion))cv2.imshow('res', res)
cv2.waitKey(0)
cv2.destroyAllWindows()gradient = cv2.morphologyEx(pie, cv2.MORPH_GRADIENT, kernel)cv2.imshow('gradient', gradient)
cv2.waitKey(0)
cv2.destroyAllWindows()

7. 礼帽与黑帽:

图像形态学中的礼帽(top hat)和黑帽(black hat)是两种常用的形态学操作,用于图像的亮区域和暗区域的提取。

礼帽操作是通过对原始图像进行开运算(opening)后再与原始图像相减得到的结果。开运算是先进行腐蚀操作,再进行膨胀操作,用于平滑图像并保留较大的亮区域。因此,礼帽操作可以提取出原始图像中较小的、明亮的细节部分。

黑帽操作则是通过对原始图像进行闭运算(closing)后再与原始图像相减得到的结果。闭运算是先进行膨胀操作,再进行腐蚀操作,用于平滑图像并保留较大的暗区域。因此,黑帽操作可以提取出原始图像中较小的、暗的细节部分。

这两种形态学操作可以用于图像增强、噪声去除、边缘检测等应用。礼帽操作可以突出图像中的细节部分,而黑帽操作可以突出图像中的暗部分。

#礼帽 = 原始输入-开运算结果
#黑帽 = 闭运算-原始输入#礼帽
img = cv2.imread('dige.png')
tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)
cv2.imshow('tophat', tophat)
cv2.waitKey(0)
cv2.destroyAllWindows()#黑帽
img = cv2.imread('dige.png')
blackhat  = cv2.morphologyEx(img,cv2.MORPH_BLACKHAT, kernel)
cv2.imshow('blackhat ', blackhat )
cv2.waitKey(0)
cv2.destroyAllWindows()

这些图像形态学操作在图像处理中有广泛的应用,例如边缘检测、形状分析、图像重建等。

图像梯度计算

Sobel 算子

Sobel算子是一种常用的图像梯度算子,用于检测图像中的边缘。它是一种离散型的差分算子,通过计算图像中每个像素点的梯度来确定边缘的位置和方向。

Sobel算子分为水平和垂直两个方向的算子,分别用于计算图像在水平和垂直方向上的梯度。水平方向的Sobel算子通常表示为:
```
-1  0  1
-2  0  2
-1  0  1
```
垂直方向的Sobel算子通常表示为:
```
-1 -2 -1
 0  0  0
 1  2  1
```
对于图像中的每个像素点,分别将其与周围像素点进行加权求和,得到水平和垂直方向上的梯度值。通过计算这两个方向上的梯度值,可以得到每个像素点的梯度幅值和梯度方向,从而实现边缘检测。

使用Sobel算子进行边缘检测时,通常需要先将图像转换为灰度图像,然后对灰度图像应用Sobel算子。最后,可以根据梯度幅值进行阈值处理,将边缘提取出来。

dst = cv2.Sobel(src, ddepth, dx, dy, ksize)

  • ddepth:图像的深度
  • dx和dy分别表示水平和竖直方向
  • ksize是Sobel算子的大小
def cv_show(img,name):cv2.imshow(name,img)cv2.waitKey()cv2.destroyAllWindows()img = cv2.imread('lena.jpg',cv2.IMREAD_GRAYSCALE)
cv_show(img,'img')# 计算dx
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
# 将负值转换为正值
sobelx = cv2.convertScaleAbs(sobelx)
# 计算dy
sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)
sobely = cv2.convertScaleAbs(sobely)
分别计算x和y,再求和
sobelxy = cv2.addWeighted(sobelx,0.5,sobely,0.5,0)
cv_show(sobelxy,'sobelxy')"""
不建议直接计算
sobelxy=cv2.Sobel(img,cv2.CV_64F,1,1,ksize=3)
sobelxy = cv2.convertScaleAbs(sobelxy) 
cv_show(sobelxy,'sobelxy')
"""

#不同算子的差异
img = cv2.imread('lena.jpg',cv2.IMREAD_GRAYSCALE)
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)
sobelx = cv2.convertScaleAbs(sobelx)   
sobely = cv2.convertScaleAbs(sobely)  
sobelxy =  cv2.addWeighted(sobelx,0.5,sobely,0.5,0)  scharrx = cv2.Scharr(img,cv2.CV_64F,1,0)
scharry = cv2.Scharr(img,cv2.CV_64F,0,1)
scharrx = cv2.convertScaleAbs(scharrx)   
scharry = cv2.convertScaleAbs(scharry)  
scharrxy =  cv2.addWeighted(scharrx,0.5,scharry,0.5,0) laplacian = cv2.Laplacian(img,cv2.CV_64F)
laplacian = cv2.convertScaleAbs(laplacian)   res = np.hstack((sobelxy,scharrxy,laplacian))
cv_show(res,'res')

Canny 边缘检测

 Canny边缘检测是一种经典的图像处理算法,用于检测图像中的边缘。它由John F. Canny在1986年提出,并被广泛应用于计算机视觉和图像处理领域。

Canny边缘检测算法的主要步骤包括:

1.噪声抑制:使用高斯滤波器对图像进行平滑处理,以减少噪声的影响。

2.计算梯度:使用Sobel算子计算图像中每个像素点的梯度幅值和方向。梯度幅值表示像素点的灰度变化程度,而梯度方向表示变化最快的方向。

3.非极大值抑制:在梯度方向上进行非极大值抑制,即对每个像素点,只保留沿着梯度方向上幅值最大的像素点,以细化边缘。

4.双阈值检测:根据设定的高阈值和低阈值,对非极大值抑制后的图像进行阈值分割。高于高阈值的像素点被认为是强边缘,低于低阈值的像素点被认为是弱边缘,介于两者之间的像素点根据其与强边缘的连通性进行判断。

5.边缘连接:通过连接强边缘像素点和与之相连的弱边缘像素点,形成完整的边缘。

Canny边缘检测算法具有以下优点:

  • 对噪声具有较好的抑制能力。
  • 检测到的边缘具有良好的连续性。
  • 可以通过调整阈值来控制检测到的边缘数量。
img=cv2.imread("lena.jpg",cv2.IMREAD_GRAYSCALE)#              minvel maxval
v1=cv2.Canny(img,80,150)
v2=cv2.Canny(img,50,100)res = np.hstack((v1,v2))
cv_show(res,'res')

img=cv2.imread("car.png",cv2.IMREAD_GRAYSCALE)v1=cv2.Canny(img,120,250)
v2=cv2.Canny(img,50,100)res = np.hstack((v1,v2))
cv_show(res,'res')

图像金字塔与轮廓检测 

图像金字塔是一种用于图像处理和计算机视觉的技术,它可以通过对原始图像进行多次缩放和降采样来构建一系列不同分辨率的图像。每个分辨率的图像被称为金字塔的一层,而金字塔的结构类似于由大到小的金字塔形状。

图像金字塔有两种类型:高斯金字塔和拉普拉斯金字塔。高斯金字塔通过对原始图像进行重复的平滑和下采样操作来生成不同分辨率的图像。而拉普拉斯金字塔则是通过从高斯金字塔中恢复原始图像并与下一层高斯图像相减得到的。

轮廓检测是一种用于检测图像中物体边界的技术。它可以通过分析图像中的亮度、颜色或纹理等特征来提取出物体的轮廓信息。常用的轮廓检测算法包括Canny边缘检测、Sobel算子、Laplacian算子等。

 图像轮廓

图像轮廓是指图像中物体的边界线或者轮廓线。它是由物体与背景之间的灰度或颜色差异形成的。图像轮廓可以用于物体检测、形状分析、目标跟踪等计算机视觉任务中。

在图像处理中,常用的方法来提取图像轮廓包括边缘检测和阈值分割。边缘检测算法可以通过检测图像中灰度或颜色的变化来找到物体的边界。常见的边缘检测算法有Sobel算子、Canny算子等。阈值分割则是将图像根据灰度或颜色的阈值进行分割,得到物体的二值图像,然后通过连通区域分析等方法找到物体的轮廓。

图像轮廓可以表示为一系列的点或者线段,也可以通过多边形或曲线来近似表示。常见的表示方法有边界框、最小外接矩形、最小外接圆等。

图像轮廓在计算机视觉和图像处理领域有广泛的应用。例如,可以通过轮廓提取来进行物体识别和分类,可以通过轮廓匹配来进行目标跟踪和姿态估计,还可以通过轮廓分析来进行形状分析和测量等。

接口定义

cv2.findContours(img,mode,method)

mode:轮廓检索模式

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

method:轮廓逼近方法

  • CHAIN_APPROX_NONE:以Freeman链码的方式输出轮廓,所有其他方法输出多边形(顶点的序列)。
  • CHAIN_APPROX_SIMPLE:压缩水平的、垂直的和斜的部分,也就是,函数只保留他们的终点部分。

import cv2
def cv_show(name,img):cv2.imshow(name,img)cv2.waitKey(0)cv2.destroyAllWindows()
# 输入图像
img = cv2.imread('image.jpg')
# 将图像变为灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 为了更高的准确率,使用二值图像
ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)# # 显示图像
# cv_show('thresh',thresh)
# # 图像轮廓
# # binary二值类结果     contours轮廓点      hierarchy层级信息
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
# print(contours.shape)
# #传入绘制图像,轮廓,轮廓索引,颜色模式,线条厚度
# # 注意需要copy,要不原图会变。。。
draw_img = img.copy()
# # 绘制轮廓图           图像       轮廓点  全部点 G   B   R  线条宽度
res = cv2.drawContours(draw_img, contours, -1, (0, 0, 255), 2)
cv_show('res',res)
轮廓特征与相似
# 轮廓特征
# 获取轮廓点
cnt = contours[0]
#面积
cv2.contourArea(cnt)
#周长,True表示闭合的
cv2.arcLength(cnt,True)
# 轮廓近似img = cv2.imread('contours2.png')gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
binary, 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)
cv_show(res,'res')epsilon = 0.15*cv2.arcLength(cnt,True) 
approx = cv2.approxPolyDP(cnt,epsilon,True)draw_img = img.copy()
res = cv2.drawContours(draw_img, [approx], -1, (0, 0, 255), 2)
cv_show(res,'res')
# 边界矩阵
img = cv2.imread('contours.png')gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
binary, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
cnt = contours[0]x,y,w,h = cv2.boundingRect(cnt)
img = cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)
cv_show(img,'img')area = cv2.contourArea(cnt)
x, y, w, h = cv2.boundingRect(cnt)
rect_area = w * h
extent = float(area) / rect_area
print ('轮廓面积与边界矩形比',extent)# 外接圆(x,y),radius = cv2.minEnclosingCircle(cnt) 
center = (int(x),int(y)) 
radius = int(radius) 
img = cv2.circle(img,center,radius,(0,255,0),2)
cv_show(img,'img')
模板匹配

模板匹配是一种在图像处理和计算机视觉中常用的技术,用于在一幅图像中寻找与给定模板最相似的部分。它可以用于目标检测、物体识别、图像对齐等应用。

模板匹配的基本思想是将一个固定大小的模板图像与待匹配图像进行比较,通过计算它们之间的相似度来确定最佳匹配位置。常用的相似度度量方法包括平方差匹配、相关性匹配和归一化互相关匹配。

在平方差匹配中,模板图像与待匹配图像的对应像素值之间的差异被计算,并求和得到一个匹配度量值。最小匹配度量值对应的位置即为最佳匹配位置。

在相关性匹配中,模板图像与待匹配图像的对应像素值之间的相关性被计算,并求和得到一个匹配度量值。最大匹配度量值对应的位置即为最佳匹配位置。

在归一化互相关匹配中,模板图像与待匹配图像的对应像素值之间的归一化互相关性被计算,并求和得到一个匹配度量值。最大匹配度量值对应的位置即为最佳匹配位置。

模板匹配的实现可以使用各种图像处理库或者计算机视觉库,如OpenCV。在实际应用中,还可以通过使用多尺度模板匹配、旋转不变模板匹配等技术来提高匹配的准确性和鲁棒性。

# 模板匹配
img = cv2.imread('lena.jpg', 0)
template = cv2.imread('face.jpg', 0)
h, w = template.shape[:2] img.shape
template.shapemethods = ['cv2.TM_CCOEFF', 'cv2.TM_CCOEFF_NORMED', 'cv2.TM_CCORR','cv2.TM_CCORR_NORMED', 'cv2.TM_SQDIFF', 'cv2.TM_SQDIFF_NORMED']res = cv2.matchTemplate(img, template, cv2.TM_SQDIFF)
res.shape#最小差异 最大差异 最小距离坐标 最大距离坐标
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)for meth in methods:img2 = img.copy()# 匹配方法的真值method = eval(meth)print (method)res = cv2.matchTemplate(img, template, method)min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)# 如果是平方差匹配TM_SQDIFF或归一化平方差匹配TM_SQDIFF_NORMED,取最小值if method in [cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]:top_left = min_locelse:top_left = max_locbottom_right = (top_left[0] + w, top_left[1] + h)# 画矩形cv2.rectangle(img2, top_left, bottom_right, 255, 2)plt.subplot(121), plt.imshow(res, cmap='gray')plt.xticks([]), plt.yticks([])  # 隐藏坐标轴plt.subplot(122), plt.imshow(img2, cmap='gray')plt.xticks([]), plt.yticks([])plt.suptitle(meth)plt.show()

 傅里叶变换

傅里叶变换是一种数学变换,它将一个函数从时域(时间域)转换到频域(频率域)。通过傅里叶变换,我们可以将一个信号分解成一系列不同频率的正弦和余弦函数的叠加。这种变换在信号处理、图像处理、通信等领域中广泛应用。

傅里叶变换的数学表达式为:
F(ω) = ∫[−∞,+∞] f(t) * e^(-jωt) dt

其中,F(ω)表示频域中的复数函数,f(t)表示时域中的函数,e^(-jωt)是一个复指数函数,ω是角频率。

傅里叶变换有两种形式:连续傅里叶变换(CTFT)和离散傅里叶变换(DFT)。连续傅里叶变换适用于连续信号,而离散傅里叶变换适用于离散信号。

在实际应用中,傅里叶变换可以用来分析信号的频谱特性,提取信号中的频率信息,滤波、压缩、编码等。同时,傅里叶变换也有逆变换,可以将频域信号转换回时域信号。

傅里叶变换的作用
  • 高频:变化剧烈的灰度分量,例如边界

  • 低频:变化缓慢的灰度分量,例如一片大海

滤波
  • 低通滤波器:只保留低频,会使得图像模糊

  • 高通滤波器:只保留高频,会使得图像细节增强

  • opencv中主要就是cv2.dft()和cv2.idft(),输入图像需要先转换成np.float32 格式。
  • 得到的结果中频率为0的部分会在左上角,通常要转换到中心位置,可以通过shift变换来实现。
  • cv2.dft()返回的结果是双通道的(实部,虚部),通常还需要转换成图像格式才能展示(0,255)
import numpy as np
import cv2
from matplotlib import pyplot as plt
# 灰度图转换
img = cv2.imread('lena.jpg',0)
# 输入图像需要先转换成np.float32 格式
img_float32 = np.float32(img)
# 先dft
dft = cv2.dft(img_float32, flags = cv2.DFT_COMPLEX_OUTPUT)
# 转换到中心位置
dft_shift = np.fft.fftshift(dft)rows, cols = img.shape
crow, ccol = int(rows/2) , int(cols/2)     # 中心位置# 低通滤波
mask = np.zeros((rows, cols, 2), np.uint8)
mask[crow-30:crow+30, ccol-30:ccol+30] = 1# IDFT
fshift = dft_shift*mask
# 从中心位置还原
f_ishift = np.fft.ifftshift(fshift)
# 后idft
img_back = cv2.idft(f_ishift)
# 得到灰度图能表示的形式
img_back = cv2.magnitude(img_back[:,:,0],img_back[:,:,1])plt.subplot(121),plt.imshow(img, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(img_back, cmap = 'gray')
plt.title('Result'), plt.xticks([]), plt.yticks([])plt.show()                

img = cv2.imread('lena.jpg',0)img_float32 = np.float32(img)dft = cv2.dft(img_float32, flags = cv2.DFT_COMPLEX_OUTPUT)
dft_shift = np.fft.fftshift(dft)rows, cols = img.shape
crow, ccol = int(rows/2) , int(cols/2)     # 中心位置# 高通滤波
mask = np.ones((rows, cols, 2), np.uint8)
mask[crow-30:crow+30, ccol-30:ccol+30] = 0# IDFT
fshift = dft_shift*mask
f_ishift = np.fft.ifftshift(fshift)
img_back = cv2.idft(f_ishift)
img_back = cv2.magnitude(img_back[:,:,0],img_back[:,:,1])plt.subplot(121),plt.imshow(img, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(img_back, cmap = 'gray')
plt.title('Result'), plt.xticks([]), plt.yticks([])plt.show()    

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

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

相关文章

GDPU 算法分析与设计 天码行空 1

实验1 排序算法的效率分析 一、【实验目的】 (1)复习排序算法的实现过程; (2)设计平均与最坏情况下时间复杂度的数据环境并理解相关含义; (3)初步了解算法时间复杂度的分析方法。…

【Maven】Maven 基础教程(二):Maven 的使用

《Maven 基础教程》系列,包含以下 2 篇文章: Maven 基础教程(一):基础介绍、开发环境配置Maven 基础教程(二):Maven 的使用 😊 如果您觉得这篇文章有用 ✔️ 的话&#…

Qt中关于信号与槽函数的思考

信号与槽函数的思考 以pushbutton控件为例,在主界面上放置一个pushbutton控件,点击右键选择关联槽函数,关联一个click函数,如下图所示: 在该函数中,实现了一个点击pushbutton按钮后,弹出一个窗…

nginx使用详解--反向代理

什么是反向代理? 正向代理: 一般的访问流程是客户端直接向目标服务器发送请求并获取内容,使用正向代理后,客户端改为向代理服务器发送请求,并指定目标服务器(原始服务器),然后由代理…

在极狐GitLab 配置 SSL/https

本文作者 徐晓伟 说明 极狐GitLab https 使用的是 nginx 实现的本文使用的域名是IP 192.168.80.14(原因:如果使用域名,必须拥有这个域名的所有权,并增加解析才可以,要不然在 Docker 容器中,无法使用域名检…

go并发模式之----使用时顺序模式

常见模式之二:使用时顺序模式 定义 顾名思义,起初goroutine不管是怎么个先后顺序,等到要使用的时候,需要按照一定的顺序来,也被称为未来使用模式 使用场景 每个goroutine函数都比较独立,不可通过参数循环…

DOM 获取父子节点

DOM 是以树状结构排列的,所以父子关系是相对的,当li为我们的目标节点的时候,ul为其父节点,其他li为它的兄弟节点,li里面包含的标签为子节点,以此类推。 那我们如何找父节点? 元素.parentNode&am…

libigl 网格质量矩阵

文章目录 一、简介二、应用三、实现效果参考资料一、简介 在 libigl 中,igl::massmatrix 是一个用于计算给定三角网格的质量矩阵的函数。质量矩阵在有限元分析和其他模拟技术中非常有用,它通常用于描述网格中各个节点的质量或者用于计算模拟过程中的惯性效应。 igl::massmatr…

分布式系统如何做数据对账?

前言 在分布式系统中,虽然我们会使用各种分布式事务的方案,来保证各个系统之间的一致性。但是,很多时候往往事与愿违。 尤其是现在很多公司都采用最终一致性的方案,而所谓最终一致性,无论是本地消息表、事务消息、还…

蓝桥杯:数组分割(Java)

目录 问题描述输入格式输出格式代码实现 问题描述 小蓝有一个长度为N的数组A[A0,A1,… AN-1]。现在小蓝想要从A对应的数组下标所构成的集合Ⅰ0,1,2,…,N -1中找出一个子集R1,那么R1在Ⅰ中的补集为R2。记S1∈∑Ar,S2∈∑Ar,我们要求S1和S2均为…

node 之 npm

1.什么是包 node.js中的第三方模块又叫做包 就像电脑和计算机指的是相同的东西,第三方模块和包指的是同一个概念,只不过叫法不同 2.包的来源 不同于 Node.js 中的内置模块与自定义模块,包是由第三方个人或团队开发出来的,免费供所…

【计算机网络——应用层】http协议

文章目录 1. http协议1.1 http协议简介1.2 url组成1.3 urlencode与urldecode 2. http协议的格式2.1 http协议的格式2.2 一些细节问题 3. http的方法、状态码和常见响应报头3.1 http请求方法3.2 http状态码3.3 http常见的响应报头属性 4. 一个非常简单的http协议服务端5. http长…

【X806开发板试用】文章一 ubuntu开发环境搭建

一、环境配置 官方链接: 环境配置 1.安装必要的库和软件 sudo apt-get install build-essential gcc g make zlib* libffi-dev e2fsprogs pkg-config flex bison perl bc openssl libssl-dev libelf-dev libc6-dev-amd64 binutils binutils-dev libdwarf-dev u-b…

pix2pix-zero

pix2pix-zero:零样本图像到图像转换 论文介绍 Zero-shot Image-to-Image Translation 关注微信公众号: DeepGoAI 项目地址:https://github.com/pix2pixzero/pix2pix-zero 论文地址:https://arxiv.org/abs/2302.03027 本文介绍了一种名为…

Golang 函数中 defer 和 return 的调用顺序

先来看一段代码: package mainimport "fmt"func f() (ret int) {defer func() {ret}()return 1 } func main() {fmt.Println(f()) }上面这段代码的输出是2,不是1 原因在于: 1)ret 是在执行 return 1 语句后发生的 2&…

基于SpringBoot多模块项目引入其他模块时@Autowired无法注入

基于SpringBoot多模块项目引入其他模块时Autowired无法注入 一、问题描述1、解决方案 一、问题描述 启动Spring Boot项目时报 Could not autowire. No beans of ‘xxxxxxxx’ type found. 没有找到bean的实例,即spring没有实例化对象,也就无法根据配置文…

【LeetCode-中等】209.长度最小的子数组-双指针/滑动窗口

力扣题目链接 1. 暴力解法 这道题的暴力解法是两层嵌套for循环,第一层循环从 i 0 开始遍历至数组末尾,第二层循环从 j i 开始遍历至找到总和大于等于 target 的连续子数组,并将该连续子数组的长度与之前找到的子数组长度相比较&#xff0…

传输层两大战将TCP、UDP的定位

传输层 定义一些传输数据的协议和端口,传输协议同时进行流量控制,根据接收方的数据吞入熟读,规定适当的发送速率,解决传输效率及能力问题 什么是TCP TCP/IP即传输控制/网络协议,是面向连接的协议,发送数…

什么是IP公网?

IP公网是指互联网上可以公开访问的IP地址。它是经过互联网服务提供商(ISP)向用户提供的公共网络IP地址。与之相对的是内网IP地址,内网IP地址一般是由路由器或交换机分配给连接在局域网中的设备使用。 IP公网的作用非常广泛,可以应…

C#解析JSON

https://blog.csdn.net/weixin_43046974/article/details/131449900 C#解析JSON 1. JSON定义2. JSON一般构成及解析方法3. 解析举例子 1. JSON对象解析,只包含一层对象{}2. 嵌套JSON对象解析,包含多层对象{}3. JSON数组解析1(数组循环遍历&…