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 = 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()    

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

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

相关文章

关键字:private关键字作用,解析及用法

private关键字在 Java 中用于定义类的成员(如变量、方法)的访问权限。它表示该成员只能在类的内部被访问和修改,而在类的外部是不可见的。 以下是private关键字的主要作用和解析: 作用: 封装性:通过将类的…

低代码中的可视化表单:效率与灵活兼备的设计工具

近年来,随着数字化转型的加速推进,企业对于高效率、灵活性和可定制性的软件开发需求不断增长。传统的软件开发过程通常需要耗费大量的时间和资源,而低代码开发平台的出现为企业提供了一种更加快速和灵活的解决方案。在低代码开发平台中&#…

【QT+QGIS跨平台编译】之五十九:【QGIS_CORE跨平台编译】—【错误处理:字符串错误】

文章目录 一、字符串错误二、处理方法三、涉及到的文件四、宽字节与多字节问题五、字符转换处理一、字符串错误 常量中有换行符错误: 也有const char * 到 LPCWSTR 转换的错误 二、处理方法 需要把对应的文档用记事本打开,另存为 “带有BOM的UTF-8” 三、涉及到的文件 src…

Vue3+springboot实现简单登录demo

Vue3从0搭建脚手架步骤【默认已安装node.js】 前置条件:默认已安装node.js、yarn 第一步:创建项目 选择任意一个空白文件夹如下: cmd进入该文件夹下的命令窗口模式,然后输入指令创建vue项目:vue create my-project …

vue3中实现elementPlus表格选中行的上移下移

先看效果&#xff1a; 实现步骤&#xff1a; 1、给el-table添加current-change事件、高亮属性及ref属性 2、给上移下移按钮添加事件 // 定义当前选中的行参数 const currentRow ref<any>(null); // 定义表格的ref const singleTableRef ref(); // 行选中事件 const ha…

【机器学习:Recommendation System】推荐系统

推荐系统&#xff08;或推荐系统&#xff09;是一类机器学习&#xff0c;它使用数据来帮助预测、缩小范围并在呈指数级增长的选项中找到人们正在寻找的内容。 【机器学习&#xff1a;Recommendation System】推荐系统 什么是推荐系统&#xff1f;用例和应用电子商务与零售&…

阿里云轻量服务器,ubuntu20.04安装Redis

第一步&#xff1a;下载xshell7,连接阿里云服务器 就是下图这个ip 第二步&#xff1a;输入用户名和密码 上面那一步完成之后&#xff0c;就会弹出来下面这个图片 用户名是root 密码是你的阿里云服务器密码 如果你要是忘了&#xff0c;如下图&#xff0c;重置密码&#xff0…

AI Agent

目录 一、什么是Agent 二、什么是MetaGPT【多智能体框架介绍】 三、MetaGPT的背景 一、什么是Agent 智能体 LLM观察思考行动记忆 Agent&#xff08;智能体&#xff09; 一个设置了一些目标或任务&#xff0c;可以迭代运行的大型语言模型。这与大型语言模型&#xff08;LLM&am…

ywtool network命令

一.network功能介绍 network功能就是通过脚本的方式配置IP信息&#xff0c;分为4项: (1) 配置单网卡(2)配置br网桥(单网卡)(3)配置bond(两张网卡)(4)配置ovs网桥(单网卡) 日志文件:/var/log/ywtools/ywtools-network.log/usr/local/ywtools/config/config.ini中network参数:…

电子科技大学课程《计算机网络系统》(持续更新)

前言 本校的课程课时有所缩减&#xff0c;因此可能出现与你学习的课程有所减少的情况&#xff0c;因此对其他学校的同学更多的作为参考作用。本文章适合学生的期中期末考试&#xff0c;以及想要考研电子科技大学的同学&#xff0c;电子科技大学同学请先看附言。 第一章 计算…

Mac OS 制作可引导安装器并重新安装系统

Mac 使用 U盘或移动固态硬盘制作可引导的安装器&#xff08;以 Monterey 为例&#xff09; 本教程参考 Apple 官网相关教程 创建可引导 Mac OS 安装器 重新安装 Mac OS 相关名词解释 磁盘分区会将其划分为多个单独的部分&#xff0c;称为分区。分区也称为容器&#xff0c;不同…

AOP(黑马学习笔记)

AOP基础 学习完spring的事务管理之后&#xff0c;接下来我们进入到AOP的学习。 AOP也是spring框架的第二大核心&#xff0c;我们先来学习AOP的基础。 在AOP基础这个阶段&#xff0c;我们首先介绍一下什么是AOP&#xff0c;再通过一个快速入门程序&#xff0c;让大家快速体验A…

易货模式微信小程序的可行性分析

随着移动互联网技术的快速发展&#xff0c;微信小程序作为一种轻量级的应用形态&#xff0c;已经成为众多创业者和服务提供者关注的焦点。微信小程序以其便捷的使用体验、较低的开发成本和广泛的用户基础&#xff0c;成为了各类业务模式的创新平台。在这样的背景下&#xff0c;…

图解知识蒸馏

soft labels与soft predictions越接近越好&#xff0c;通过Loss Fn来实现&#xff0c;产生的数值叫做distillation loss&#xff0c;也叫soft loss。 hard label y与hard prediction越接近越好&#xff0c;通过Loss Fn来实现&#xff0c;产生的数值叫做student loss&#xff0c…

[OpenCv]图像增强

目录 前言 一、灰度变化 二、直方图修整 1.直方图概念 2.直方图变化 3.直方图均衡化 二、图像平滑 1.卷积模板 2.均值滤波 3.高斯滤波 4.中值滤波 三、图像锐化 1.梯度算子 2.使用Laplacian算子进行锐化 3.使用Sobel算子进行锐化 四、代码总结 1.图片 2.代码 …

深度强化学习入门(待修改)

目录 前言 一、强化学习 1.马可洛夫链 2.蒙地卡罗 3.时序差分TD 4.gym学习​编辑 FrozenLake 二、RL基本算法 1.Q-learning和SARSA 2.DQN Deep network Qlearning DQN 三、PG策略算法 总结 前言 这段时间学习深度强化学习的总结。 一、强化学习 强化学习是做出最佳决策的科学…

vue-electron 项目创建记录及注意事项

vue-electron 项目创建记录及注意事项 1、使用vue ui或者命令行创建vue项目 2、添加electron插件 3、安装element-plus: npm install --save element-plus 4、修改配置文件如下图: vue.config.js增加配置&#xff1a; pluginOptions:{ electronOutput: { contextIsolation…

centos物理电脑安装过程(2024年1月)

开机时&#xff1a;CtrlAltDelete键重启电脑 重启开始时&#xff1a;按F11&#xff0c;桌面弹出蓝色框&#xff0c;选择第二个SSK SFD142 1.00&#xff0c;回车 选择install centos7安装 选择后弹出选择安装选项&#xff0c;选择语言 连接无线网络 安装设置&#xff0c;选择磁…

gpt批量原创文章生成器,不限制内容的生成器

在当今的数字化时代&#xff0c;内容创作是网站持续发展的重要组成部分。然而&#xff0c;对于拥有大量内容需求的网站来说&#xff0c;手动创作文章可能会耗费大量时间和精力。为了解决这一问题&#xff0c;许多GPT&#xff08;生成式预训练模型&#xff09;文章生成软件应运而…

lv20 QT事件

1 事件模型 2 事件处理 virtual void keyPressEvent(QKeyEvent *event) virtual void keyReleaseEvent(QKeyEvent *event) virtual void mouseDoubleClickEvent(QMouseEvent *event) virtual void mouseMoveEvent(QMouseEvent *event) virtual void mousePressEvent(QMou…