π2δ2(4n2−1)1
利用以上两个滤波器和投影值进行卷积,然后再进行反投影,就可以得到得到原始的图像,大致上来说,就是在上面的代码中增加滤波器的构建和投影与滤波器的卷积过程,具体的代码如下:
def box_filter(M, c):
hw = np.zeros((M, ))
for w in range(M):
if 0 <= w <= M - 1:
hw[w] = c + (c - 1) * np.cos(2 * np.pi * w / M)
else:
hw[w] = 0
hw = np.fft.fft(hw)
hw = np.fft.fftshift(hw)
hw = np.real(hw)
return hw
x = np.linspace(-5, 5, 200)
M = x.shape[0]
y = abs(x)
c = 0.54
hw = np.zeros_like(x)
for w in range(M):
if 0 <= w <= M - 1:
hw[w] = c + (c - 1) * np.cos(2 * np.pi * w / M)
else:
hw[w] = 0
np_hamming = np.hamming(M)
np_hann= np.hanning(M)
plt.plot(x, hw)
plt.plot(x, np_hamming)
plt.plot(x, np_hann)
plt.show()
def hamming_window(img, hamming=True):
2d hamming and hann window
param: img, input image
param: hamming: bool, if True return hamming windows, if False return hann window
return normalize 2d hamming or hann window
Problem: I still not very sure if this right, since result is not very good.
M, N = img.shape[1], img.shape[0]
if hamming:
u = np.hamming(M)
v = np.hamming(N)
else:
u = np.hanning(M)
v = np.hanning(N)
u, v = np.meshgrid(u, v)
high_pass = np.sqrt(u**2 + v**2)
kernel = high_pass
return kernel
img_hamming = hamming_window(img_radon, hamming=True)
img_radon_hamming = img_hamming * img_radon
plt.figure(figsize=(24, 12))
plt.subplot(131), plt.imshow(img_radon, 'gray'), plt.title('img radon'), plt.xticks([]), plt.yticks([])
plt.subplot(132), plt.imshow(img_hamming, 'gray'), plt.title('img_hamming'), plt.xticks([]), plt.yticks([])
plt.subplot(133), plt.imshow(img_radon_hamming, 'gray'), plt.title('img_radon_hamming'), plt.xticks([]), plt.yticks([])
plt.tight_layout()
plt.show()
def rl_filter(N, d):
filterRL = np.zeros((N,))
for i in range(N):
filterRL[i] = - 1.0 / (np.power((i - N / 2) * np.pi * d, 2.0) + 1e-5)
if np.mod(i - N / 2, 2) == 0:
filterRL[i] = 0
filterRL[int(N/2)] = 1 / (4 * np.power(d, 2.0))
return filterRL
def sl_filter(N, d):
filterSL = np.zeros((N,))
for i in range(N):
filterSL[i] = - 2 / (np.pi**2.0 * d**2.0 * (4 * (i - N / 2)**2.0 - 1))
return filterSL
def inverse_filter_radon_transform(image, steps):
channels = len(image[0])
origin = np.zeros((steps, channels, channels))
filter = sl_filter(channels, 1)
for i in range(steps):
projectionValue = image[:, i]
projectionValueFiltered = np.convolve(filter, projectionValue, "same")
projectionValueExpandDim = np.expand_dims(projectionValueFiltered, axis=0)
projectionValueRepeat = projectionValueExpandDim.repeat(channels, axis=0)
origin[i] = ndimage.rotate(projectionValueRepeat, i*180/steps, reshape=False).astype(np.float64)
iradon = np.sum(origin, axis=0)
return iradon
hx = box_filter(200, 0.5)
sl = sl_filter(200, 1)
plt.figure(figsize=(10, 4))
plt.subplot(1, 2, 1), plt.plot(x, hx)
plt.subplot(1, 2, 2), plt.plot(x, sl)
plt.show()
img_ori = cv2.imread('DIP_Figures/DIP3E_Original_Images_CH05/Fig0539(c)(shepp-logan_phantom).tif', 0)
img_radon = radon_transform(img_ori, img_ori.shape[0])
img_inverse_radon = inverse_radon_transform(img_radon, img_radon.shape[0])
img_filter_inverse_radon = inverse_filter_radon_transform(img_radon, img_radon.shape[0])
plt.figure(figsize=(18, 6))
plt.subplot(131), plt.imshow(img_ori, 'gray'), plt.title('Original'), plt.xticks([]), plt.yticks([])
plt.subplot(132), plt.imshow(img_inverse_radon, 'gray'), plt.title('Inverse Randon Transform'), plt.xticks([]), plt.yticks([])
plt.subplot(133), plt.imshow(img_filter_inverse_radon, 'gray'), plt.title('Inverse Filter Randon Transform')
plt.xticks([]), plt.yticks([])
plt.tight_layout()
plt.show()
img_ori = cv2.imread('DIP_Figures/DIP3E_Original_Images_CH05/Fig0539(a)(vertical_rectangle).tif', 0)
img_radon = radon_transform(img_ori, img_ori.shape[0])
img_inverse_radon = inverse_radon_transform(img_radon, img_radon.shape[0])
img_hamming = hamming_window(img_radon, hamming=True)
img_radon_hamming = img_hamming * img_radon
img_filter_inverse_radon = inverse_filter_radon_transform(img_radon_hamming, img_radon_hamming.shape[0])
plt.figure(figsize=(18, 6))
plt.subplot(131), plt.imshow(img_ori, 'gray'), plt.title('Original'), plt.xticks([]), plt.yticks([])
plt.subplot(132), plt.imshow(img_inverse_radon, 'gray'), plt.title('Inverse Randon Transform'), plt.xticks([]), plt.yticks([])
plt.subplot(133), plt.imshow(img_filter_inverse_radon, 'gray'), plt.title('Inverse Filter Randon Transform')
plt.xticks([]), plt.yticks([])
plt.tight_layout()
plt.show()
标题瑞利噪声爱尔兰(伽马)噪声指数噪声均匀噪声椒盐噪声周期噪声估计噪声参数只存在噪声的复原 - 空间滤波均值滤波器算术平均滤波器几何均值滤波器谐波平均滤波器反(逆)谐波平均滤波器统计排序滤波器中值、最大值、最小值、中点 滤波器修正阿尔法均值滤波器自适应滤波器自适应局部降噪滤波器自适中值滤波器使用频率域滤波降低周期噪声陷波滤波深入介绍最优陷波滤波线性位置不变退化估计退化函数采用观察法估计退化函数采用试验法估计退化函数采用建模法估计退化函数运动模糊函数OpenCV Motion Blur逆滤波逆滤波最小均方误差
本博客将实现Python版本的双目三维重建系统,项目代码实现包含:`双目标定`,`立体校正(含消除畸变)`,`立体匹配`,`视差计算`和`深度距离计算/3D坐标计算` 的知识点。限于篇幅,本博客不会过多赘述算法原理,而是手把手教你,如果搭建一套属于自己的双目三维重建的系统。该系统包含:
支持双USB连接线的双目摄像头
支持单USB连接线的双目摄像头(左右摄像头被拼接在同一个视频中显示)
支持单目相机标定:mono_camera_calibration.py
支持双目相机标定:stereo_camera
关于投影的基础知识:
假设我们要用一束细细的,平行的X射线从左到右穿过(通过一个图像平面),这里我们假设物体吸收的射线束能量 比背景吸收的射线束能量多。我们利用放在放在另一端的X射线吸收检测器来检测射线通过这个物体的能量
所以当左侧有一排X射线(光束带),右侧有一排X射线检测器(检测器带/吸收剖面)的时候,就会形成一副函数图像(通过接收器的位置和应该接收点接收能量的离散值形成),我们的目的是为了复原X射线穿过物体的图像,但是只是知道这个函数有什么用呢?
反投影法:
我们需要基于上述函数的信息来重建一
参考博文进行了平行束滤波反投影的修改,将时域滤波修改为频域滤波,重建后消除原博文中图像的竖条状伪影。
https://blog.csdn.net/hsyxxyg/article/details/106433940
频域平行束滤波反投影(反radon变换)
产生频域滤波信号:
nextpow2函数的实现可参见github:
https://github.com/freenowill/Denoise-/blob/ba99babb685f6c80f07a23275c8c2127de601815/Denois
图像重建之由投影重建图像简述部分引言
最初接触由投影重建图像这块内容的时候是在车牌识别中。上图是在90°的投影下的结果。
下面我们开一个简单图像的特定角度下的投影 当我们收集到各个角度的投影后,并希望通过这些投影的图像重建原图像。上图的最后一张图片就是直接重建的图像。可见,其有非常明显的“晕环”现象。
雷登变换
雷登变换阐述了一幅图像与其在各个角度下投影的具体表示。 下面我们在matlab上展示一副
import numpy as np
import matplotlib.pyplot as plt
from skimage.transform import radon, iradon
# 生成一个圆形模板
N = 128
R = 40
x, y = np.indices((N, N))
mask = ((x-N//2)**2 + (y-N//2)**2) < R**2
# 生成雷登变换图
theta = np.linspace(0, 180, 180, endpoint=False)
sinogram = radon(mask.astype(float), theta=theta, circle=True)
# 显示正弦图
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(8, 4.5))
ax1.imshow(mask, cmap='gray')
ax1.set_title('Original')
ax2.imshow(sinogram, cmap='gray', extent=(-90, 90, 0, sinogram.shape[0]), aspect='auto')
ax2.set_title('Sinogram')
plt.show()
# 重建图像
reconstruction = iradon(sinogram, theta=theta, circle=True)
reconstruction *= np.pi / (2. * len(theta)) # 标准化
error = np.sqrt(np.mean((mask - reconstruction) ** 2))
# 显示重建图像和误差
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(8, 4.5))
ax1.imshow(mask, cmap='gray')
ax1.set_title('Original')
ax2.imshow(reconstruction, cmap='gray')
ax2.set_title('Reconstruction\nRMSE: %.3g' % error)
plt.show()
这个示例代码生成一个直径为80的圆形模板,并使用Radon函数生成180个角度下的正弦图像,然后使用iradon函数进行重建。你可以根据自己的需求修改代码中的参数。