Opencv基本操作 (上)

news2024/11/18 9:26:42

目录

图像基本操作

阈值与平滑处理

图像阈值

图像平滑处理

图像形态学操作

图像梯度计算

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 = False

while open:
    ret, frame = vc.read()
    if frame is None:
        break
    if 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.shape

methods = ['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_loc
    else:
        top_left = max_loc
    bottom_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.coloradmin.cn/o/1479116.html

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

相关文章

electron 项目环境变量使用注意 public

问题 最近项目中,electron需要调用唤醒本地的另一个客户端程序,但是这个客户端程序报错了。sqlite3 报out of memory. apiSHGetFolderPathW 获取CSIDL_COMMON_DOCUMENTS报 1008,试图引用不存在的令牌。 排查 一看到这个,首先想…

javaWeb学习04

AOP核心概念: 连接点: JoinPoint, 可以被AOP控制的方法 通知: Advice 指哪些重复的逻辑,也就是共性功能(最终体现为一个方法) 切入点: PointCut, 匹配连接点的条件,通知仅会在切入点方法执行时被应用 目标对象: Target, 通知所应用的对象 通知类…

Django Web架构:全面掌握Django模型字段(上)

Django Web架构 全面掌握Django模型字段(上) - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite:http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article…

数电学习笔记——逻辑函数及其描述方法

目录 一、逻辑函数 二、逻辑函数的描述方法 1、逻辑真值表 2、逻辑函数式 3、逻辑图 4、波形图 三、逻辑函数的两种标准形式 1、最小项与最大项 最小项 最小项的性质 最大项 最大项的性质 2、最大项与最小项的关系 3、逻辑函数的最小项之和形式 4、逻辑函数的最…

Unity(第二十四部)UI

在游戏开发中,用户界面(UI)是至关重要的一部分。它负责与玩家进行交互,提供信息,并增强游戏的整体体验。Unity 提供了强大的工具和功能来创建和管理 UI。 ui的底层就是画布,创建画布的时候会同时创建一个事…

k8s部署mysql

(作者:陈玓玏) 一、前置条件 已部署k8s,服务端版本为1.21.14 二、部署mysql 拉取镜像; docker pull mysql将账号密码等信息写到configmap,创建configmap; apiVersion: v1 kind: ConfigMap m…

C++笔记(五)--- 虚函数(virtual)

目录 虚函数介绍 虚函数、覆盖和重载区别 虚函数介绍 C的虚函数是多态性的表现 1.构造函数不能为虚函数2.子类继承时虚函数仍为虚函数3.虚函数类外实现时,不需要加virtual4.有虚函数的类,析构函数一定要写成虚函数(否则可能会造成内存泄漏&…

Docker实战——容器

目录 Docker 容器的基本概念与操作1.使用“docker create”创建容器。这里基于Nginx的镜像创建了一个容器,名字为mycontainer。2.使用“docker ps -a”命令查看所有的容器,这时的容器不一定是运行状态。3.使用 “docker start” 命令可以启动容器。4.使用…

SpringBoot整合rabbitmq-主题交换机队列(四)

说明:Topic主题交换机它的大致流程是交换机和一个或者多个队列绑定,这个绑定的Routingkey是包含通配符的,满足通配符的队列会接收到消息。 通配符规则: #:匹配一个或多个词 *:匹配一个词 例如&#xff…

android TextView 实现富文本显示

android TextView 实现富文本显示,实现抖音直播间公屏消息案例 使用: val tvContent: TextView helper.getView(R.id.tvContent)//自己根据UI业务要求,可以控制 图标显示 大小val levelLabel MyImgLabel( bitmap 自己业务上的bitmap )va…

Prometheus 安装指南

目录 介绍 安装 介绍 Prometheus是一款开源监控系统,适用于容器化和微服务。它使用多维数据模型,支持PromQL查询语言,可以通过多种方式采集数据。具备灵活的告警和通知机制,可集成图形工具创建仪表盘。通过本地存储高效保存时间…

ywtool check命令及ywtool clean命令

一.ywtool check命令 1.1 ywtool check -I 1.2 ywtool check all 1.3 ywtool check io 1.4 ywtool check elk 1.5 ywtool check php 1.6 ywtool check mysql 1.7 ywtool check nginx 1.8 ywtool check system 1.9 ywtool check docker_nbip [容器名称] 1.10 ywtool check 1.10…

buuctf_crypto_丢失的MD5+Quoted-printable+RSA

丢失的MD5 题目:(就一python文件,MD5.py) for i in range(32,127):for j in range(32,127):for k in range(32,127):mhashlib.md5()m.update(TASCchr(i)O3RJMVchr(j)WDJKXchr(k)ZM)desm.hexdigest()if e9032 in des and da in d…

吴恩达《机器学习》学习笔记

本笔记资料来源于 http://www.ai-start.com/ml2014/,该笔记来自于https://blog.csdn.net/dadapongi6/article/details/105668394,看了忘,忘了看,再看一遍。 时间统计:2024.2.29 5个番茄钟,从week1开始&…

游戏陪玩精品系统源码优化版3.0

下载地址:游戏陪玩精品系统源码优化版.zip 截图:

[Vulnhub]靶场 Web Machine(N7)

kali:192.168.56.104 主机探测: arp-scan -l 靶机ip:192.168.56.104 端口扫描 nmap -p- 192.168.56.106 看一下web 目录扫描 gobuster dir -u http://192.168.56.106 -x html,txt,php,bak,zip --wordlist/usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt exp…

基于springboot实现街球社区网站系统项目【项目源码+论文说明】

基于springboot实现街球社区网站系统演示 摘要 本文主要讲述了基于SpringBootVue模式的街球社区网站的设计与实现。这里所谓的街球社区网站是通过类似于百度贴吧之类的网上论坛使得所有的街球爱好者有一个可以互相交流的平台,并使所有用户可以在社区进行教学视频的观看以及相关…

使用Fabric创建的canvas画布背景图片,自适应画布宽高

之前的文章写过vue2使用fabric实现简单画图demo,完成批阅功能;但是功能不完善,对于很大的图片就只能显示一部分出来,不符合我们的需求。这就需要改进,对我们设置的背景图进行自适应。 有问题的canvas画布背景 修改后的…

Python:练习:编写一个程序,写入一个美金数量,然后显示出如何用最少的20美元、10美元、5美元和1美元来付款

案例: python编写一个程序,写入一个美金数量,然后显示出如何用最少的20美元、10美元、5美元和1美元来付款: Enter a dollar amout:93 $20 bills: 4 $10 bills: 1 $5 bills:0 $1 bills:3 思考: 写入一个美金数量&…

leetcode 热题 100_字母异位词分组

题解一: 排序:对两个字母异位词,二者排序后的字符串完全一样,因此可以对所给字符串进行排序,以排序后的字符串作为HashMap哈希表的键值,将排序前的字符串作为值进行存储分组,最后返回。 import…