将直线拟合到傅里叶变换

问题描述 投票:0回答:1

编辑:添加了最少的代码和进一步的说明:

我正在研究图像空间中的周期性模式。当我们在傅里叶空间中看到它们时,我看到一个十字形光谱,其旋转角度与图像空间中的光谱相同。

我尝试过的:

import cv2
import numpy as np

# Read Image:
frame=  cv2.imread("ImageSpace.png")[:,:,0]
size= frame.shape[0]
#compute DFT and shift it:
dft=    cv2.dft(np.float32(frame),flags=cv2.DFT_COMPLEX_OUTPUT)
mag=    cv2.magnitude(dft[:,:,0],dft[:,:,1])
mag=    np.fft.fftshift(mag)
# Filter lower frequencies:
mag[size//2-3:size//2+3,size//2-3:size//2+3]= np.zeros((6,6))
# We focus on the right bottom quadrant for simplification
quarterMag= mag[size//2:,size//2:]
#Search for a local maxima:
XYmax=  np.unravel_index(quarterMag.argmax(), quarterMag.shape)

if XYmax[0]!=0 and XYmax[1]!=0:
    theta_hat= np.arctan(XYmax[1]/XYmax[0])*180/np.pi
else:
    theta_hat= 90


srcTri= np.array([
    [size//2,size//2],
    [size,size//2],
    [size//2,size]
]).astype(np.float32)

dstTri= np.array([
        [size//2,size//2], 
        [size//2-size//2*np.cos(theta_hat*np.pi/180),
        size//2-size//2*np.sin(theta_hat*np.pi/180)],
        [size//2+size//2*np.sin(theta_hat*np.pi/180),
        size//2-size//2*np.cos(theta_hat*np.pi/180)] 
]).astype(np.float32)

warp_Mat=   cv2.getAffineTransform(srcTri, dstTri)
correctedFrame= cv2.warpAffine(frame,warp_Mat,(frame.shape[0],frame.shape[0]))


#Normalize function in order to display it
mag=    cv2.normalize((mag),None,255, 0, cv2.NORM_MINMAX, cv2.CV_8UC1)

cv2.imwrite("CorrectedFrame.png", correctedFrame)

while True:
    cv2.imshow("Frame",frame)
    cv2.imshow("Magnitude Spectrum",mag)
    cv2.imshow("Corrected Frame", correctedFrame)
    cv2.waitKey(1)

此代码产生以下结果:

我的问题是,由于我仅使用第一个局部最大值来查找角度,因此我的分辨率很差,这取决于输入图像的分辨率。

对于一组模拟图像,我得到这样的结果,其中蓝色实线是我旋转的角度,十字是使用这种方法测量的角度:

您会看到存在约 4-5° 的“非线性阶梯”效果。

我想做(或知道)的是,是否有一种方法可以仅“过滤”傅立叶中“主线”中的值,将它们放入 fitLine 函数中,以便我获得最大分辨率的角度,而无需增加输入图像的大小。

感谢您的帮助!

python opencv image-processing signal-processing
1个回答
0
投票

您的输入图像分辨率是计算角度量化背后的主要问题。您必须增加 dft 输出的大小,使其对较小的频率更加敏感。

由于 dft 是像素大小不变的(意味着频率是根据宽度而不是像素数量),因此您不能简单地调整输入大小,而是必须对其进行填充。

pad=250
frame = cv2.copyMakeBorder(frame, pad, pad, pad, pad, cv2.BORDER_CONSTANT, value=0)

为什么会有4-5度的误差?
局部最大值仅落在距中心 27 像素处,在 90 度范围内留下 21 (= 2 π r/4) 像素,产生 4.3 度 (90/21) 间隙。

© www.soinside.com 2019 - 2024. All rights reserved.