opencv-python傅里叶变换以及逆变换

opencv-python傅里叶变换

一、图像傅里叶变换

二维傅里叶变换原理

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

opencv-python傅里叶变换以及逆变换_第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] H,W,F(u,v)f(x,y)()u[0,H1],v[0,W1]

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

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

运行结果:

opencv-python傅里叶变换以及逆变换_第2张图片

二、图像傅里叶逆变换

二维傅里叶逆变换原理

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

opencv-python傅里叶变换以及逆变换_第3张图片

其 中 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,H1],y[0,W1]

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

自定义功能函数具体如下:

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

运行结果:
opencv-python傅里叶变换以及逆变换_第4张图片

你可能感兴趣的:(python,opencv,计算机视觉)