<>opencv-python傅里叶变换

<>一、图像傅里叶变换

<>二维傅里叶变换原理

​ 灰度图像是由二维的离散的点构成的。二维离散傅里叶变换(Two-Dimensional Discrete Fourier
Transform)常用于图像处理中,对图像进行傅里叶变换后得到其频谱图。频谱图中频率高低表征图像中灰度变化的剧烈程度。图像中边缘和噪声往往是高频信号,而图像背景往往是低频信号。我们在频率域内可以很方便地对图像的高频或低频信息进行操作,完成图像去噪,图像增强,图像边缘提取等操作。

其 中 H , W 分 别 为 图 像 的 高 、 宽 , F ( u , v ) 表 示 频 域 图 像 , f ( x , y ) 表 示 时 域 图
像 ( 某 点 的 像 素 ) , u 范 围 为 [ 0 , H − 1 ] , v 范 围 为 [ 0 , W − 1 ]
其中H,W分别为图像的高、宽,F(u,v)表示频域图像,f(x,y)表示时域图像(某点的像素),u范围为[0,H-1],v范围为[0,W-1]其中H,W分别为图
像的高、宽,F(u,v)表示频域图像,f(x,y)表示时域图像(某点的像素),u范围为[0,H−1],v范围为[0,W−1]

<>自定义图像傅里叶变换功能函数

<>1、自定义傅里叶变换函数
#自定义傅里叶变换功能函数 def dft(img): #获取图像属性 H,W,channel=img.shape
#定义频域图,从公式可以看出为求出结果为复数,因此,需要定义为复数矩阵 F = np.zeros((H, W,channel), dtype=np.
complex) # 准备与原始图像位置相对应的处理索引 x = np.tile(np.arange(W), (H, 1)) y = np.arange(H).
repeat(W).reshape(H, -1) #通过公式遍历 for c in range(channel):#对彩色的3通道数进行遍历 for u in
range(H): for v in range(W): F[u, v, c] = np.sum(img[..., c] * np.exp(-2j * np.
pi* (x * u / W + y * v / H))) / np.sqrt(H * W) return F
<>2、读取图像,进行傅里叶变化并显示变换后的结果
gray=cv2_imread("C://Users//小白二号//Desktop//dd.png",1) gray=cv2.resize(gray,(400
,400)) img_dft = dft(gray) dft_shift = np.fft.fftshift(img_dft) fimg = np.log(np
.abs(dft_shift)) cv2.imshow("fimg", fimg) cv2.imshow("gray", gray) cv2.waitKey(0
) cv2.destroyAllWindows()
<>opencv库函数实现傅里叶变换
<>(1)傅里叶变换函数cv2.dft()
函数原型如下:
img=cv2.dft(src, flags=None, nonzeroRows=None)
src表示输入图像,需要通过np.float32转换格式

flag表示转换标记,其中cv2.DFT _INVERSE执行反向一维或二维转换,而不是默认的正向转换;cv2.DFT
_SCALE表示缩放结果,由阵列元素的数量除以它;cv2.DFT
_ROWS执行正向或反向变换输入矩阵的每个单独的行,该标志可以同时转换多个矢量,并可用于减少开销以执行3D和更高维度的转换等;cv2.DFT
_COMPLEX_OUTPUT执行1D或2D实数组的正向转换,这是最快的选择,默认功能;cv2.DFT
_REAL_OUTPUT执行一维或二维复数阵列的逆变换,结果通常是相同大小的复数数组,但如果输入数组具有共轭复数对称性,则输出为真实数组。

nonzeroRows表示当参数不为零时,函数假定只有nonzeroRows输入数组的第一行(未设置)或者只有输出数组的第一个(设置)包含非零,因此函数可以处理其余的行更有效率,并节省一些时间;这种技术对计算阵列互相关或使用DFT卷积非常有用。
<>(2)复数求模函数cv2.magnitude()
由于输出的频谱结果是一个复数,需要调用cv2.magnitude()函数将傅里叶变换的双通道结果转换为0到255的范围,函数原型如下:
result=cv2.magnitude(x, y)
x表示浮点型X坐标值,即实部

y表示浮点型Y坐标值,即虚部

最终结果为复数的模
<>(3)应用实例 def cv2_imread(file_path, flag=1): #读取图片数据 return cv2.imdecode(np.
fromfile(file_path, dtype=np.uint8), flag) gray=cv2_imread(
"C://Users//小白二号//Desktop//壁纸2.png",1) gray=cv2.cvtColor(gray,cv2.COLOR_BGR2GRAY
) gray=cv2.resize(gray,(640,420)) np.float32(gray) img_dft = cv2.dft(np.float32(
gray),flags=cv2.DFT_COMPLEX_OUTPUT) dft_shift = np.fft.fftshift(img_dft) fimg =
20 * np.log(cv2.magnitude(dft_shift[:, :, 1], dft_shift[:, :, 0])) plt.subplot(
121), plt.imshow(gray,'gray'), plt.title('原图像') plt.axis('off') plt.subplot(122)
, plt.imshow(np.int8(fimg),'gray'), plt.title('傅里叶变换') plt.axis('off') plt.show(
) cv2.waitKey(0) cv2.destroyAllWindows()
运行结果:

<>二、图像傅里叶逆变换

<>二维傅里叶逆变换原理

傅里叶反变换原理就是将图像频域还原为图像时域,具体原理公式如下所示:

其 中 H , W 分 别 为 图 像 的 高 、 宽 , F ( u , v ) 表 示 频 域 图 像 , f ( x , y ) 表 示 时 域 图
像 ( 某 点 的 像 素 ) , x 范 围 为 [ 0 , H − 1 ] , y 范 围 为 [ 0 , W − 1 ]
其中H,W分别为图像的高、宽,F(u,v)表示频域图像,f(x,y)表示时域图像(某点的像素),x范围为[0,H-1],y范围为[0,W-1]其中H,W分别为图
像的高、宽,F(u,v)表示频域图像,f(x,y)表示时域图像(某点的像素),x范围为[0,H−1],y范围为[0,W−1]

<>自定义傅里叶逆变换功能函数

自定义功能函数具体如下:
def idft(G): H, W, channel = G.shape #定义空白时域图像 out = np.zeros((H, W, channel),
dtype=np.float32) # 准备与原始图像位置相对应的处理索引 x = np.tile(np.arange(W), (H, 1)) y = np.
arange(H).repeat(W).reshape(H, -1) #通过公式遍历 for c in range(channel): for u in
range(H): for v in range(W): out[u, v, c] = np.abs(np.sum(G[..., c] * np.exp(2j
* np.pi * (x * u / W + y * v / H)))) / np.sqrt(W * H) # 剪裁 out = np.clip(out, 0,
255) out = out.astype(np.uint8) return out
<>OpenCV库函数实现傅里叶逆变换
<>(1)傅里叶逆变换函数
opencv能实现傅里叶逆变换的函数是cv2.idft(),函数原型如下:
img=cv2.idft(src,flags,nonzeroRows)
src表示输入图像,包括实数或复数
flags表示转换标记
nonzeroRows表示要处理的图片行数,其余行的内容未定义
<>(2)应用实例 def cv2_imread(file_path, flag=1): # 读取图片数据 return cv2.imdecode(np.
fromfile(file_path, dtype=np.uint8), flag) gray = cv2_imread(
"C://Users//小白二号//Desktop//壁纸2.png", 1) gray = cv2.cvtColor(gray, cv2.
COLOR_BGR2GRAY) gray = cv2.resize(gray, (640, 420)) # 傅里叶变换 img_dft = cv2.dft(np
.float32(gray), flags=cv2.DFT_COMPLEX_OUTPUT) dft_shift = np.fft.fftshift(
img_dft)# 将频域从左上角移动到中间 fimg = 20 * np.log(cv2.magnitude(dft_shift[:, :, 0],
dft_shift[:, :, 1])) # 傅里叶逆变换 idft_shift = np.fft.ifftshift(dft_shift) #
将频域从中间移动到左上角 ifimg = cv2.idft(idft_shift)#傅里叶库函数调用 ifimg = 20*np.log(cv2.
magnitude(ifimg[:, :, 0], ifimg[:, :, 1]))#转化为0-255 ifimg=np.abs(ifimg) # 绘制图片
plt.subplot(131), plt.imshow(gray, 'gray'), plt.title('原图像') plt.axis('off') plt
.subplot(132), plt.imshow(np.int8(fimg), 'gray'), plt.title('傅里叶变换') plt.axis(
'off') plt.subplot(133), plt.imshow(np.int8(ifimg), 'gray'), plt.title('傅里叶逆变换')
plt.show() cv2.waitKey(0) cv2.destroyAllWindows()
运行结果:

技术
©2019-2020 Toolsou All rights reserved,
TypeScript:函数类型接口8道大厂指针笔试题让你秒杀指针!!!MySQL 日期时间加减mysql 查询条件之外的数据_mysql 查询符合条件的数据查linux的操作系统版本,如何查看Linux操作系统版本?将String类型转换成Map数据类型使用uuid做MySQL主键,被老板,爆怼一顿C语言中的字符串函数和字符函数linux服务器中毒排查--基础篇C# ASCII码字符转换