标题

  • 由投影重建图像
    • 投影和雷登变换 Johann Radon
    • 反投影
    • 滤波反投影重建

由投影重建图像

本由投影重建图像,主要是雷登变换与雷登把变换的应用,所以也没有太多的研究,只为了保持完整性,而添加到这里。

# 自制旋转投影图像# 模拟一个图像
img = np.zeros((100, 100))
img[45:46] = 0.25
img[46:47] = 0.5
img[47:48] = 0.75
img[48:51, :] = 1.
img[51:52, :] = 0.75
img[52:53, :] = 0.5
img[53:54, :] = 0.25total_img = img.copy()# 旋转并叠加, it's 32 on the book, but here I want to try 64, but degree / 2, see how is work, seems all the same
for i in range(64):    angle = (5.625) / 2 * (i + 1)C1 = cv2.getRotationMatrix2D((img.shape[1]/2.0, img.shape[0]/2.0), angle, 1)new_img = cv2.warpAffine(img, C1, (img.shape), borderValue=0)total_img = total_img + new_imgtotal_img = normalize(total_img)plt.figure(figsize=(13, 5))
plt.subplot(131), plt.imshow(img, 'gray'), plt.title('Original'), plt.xticks([]), plt.yticks([])
plt.subplot(132), plt.imshow(new_img, 'gray'), plt.title('new_img'), plt.xticks([]), plt.yticks([])
plt.subplot(133), plt.imshow(total_img, 'gray'), plt.title('total_img'), plt.xticks([]), plt.yticks([])
plt.tight_layout()
plt.show()

投影和雷登变换 Johann Radon

g(ρ,θ)=∫−∞∞∫−∞∞f(x,y)δ(xθ+ysinθ−ρ)dxdyg(\rho,\theta) = \int_{-\infty}^{\infty} \int_{-\infty}^{\infty} f(x,y) \; \delta(x\;\theta + y \; sin\theta -\rho) \; dxdyg(ρ,θ)=∫−∞∞​∫−∞∞​f(x,y)δ(xθ+ysinθ−ρ)dxdy

离散情况的雷登变换
g(ρ,θ)=∑x=0M−1∑y=0N−1f(x,y)δ(xθ+ysinθ−ρ)g(\rho,\theta) = \sum_{x=0}^{M-1} \sum_{y=0}^{N-1} f(x,y) \; \delta(x\;\theta + y \; sin\theta -\rho)g(ρ,θ)=x=0∑M−1​y=0∑N−1​f(x,y)δ(xθ+ysinθ−ρ)

由雷登变换得到的图称之为正弦图(Sinogram)

from scipy import ndimagedef radon_transform(img, steps):"""radon tranform for gray imageparam: img: input Imageparam: steps: step for the transform, same of image height"""channels = img.shape[0]dst = np.zeros((channels, channels), dtype=np.float32)for i in range(steps):res = ndimage.rotate(img, -i * 180 / steps, reshape=False).astype(np.float32)dst[:, i] = sum(res)#     dst = ndimage.rotate(dst, 270, reshape=False) # 旋转后就跟书上的结果一致return dst
# 雷登变换
img_ori = cv2.imread("DIP_Figures/DIP3E_Original_Images_CH05/Fig0533(a)(circle).tif", 0)
m, n = img_ori.shape[1], img_ori.shape[0]
img = idea_low_pass_filter(img_ori, (m, n), D0=10)
img_radon = radon_transform(img, img.shape[0])plt.figure(figsize=(24, 12))plt.subplot(131), plt.imshow(img, 'gray'), plt.title('Original'), plt.xticks([]), plt.yticks([])
plt.subplot(132), plt.imshow(img_radon, 'gray'), plt.title('Randon Transform'), plt.xticks([]), plt.yticks([])
# plt.subplot(133), plt.imshow(img_cv2_guass, 'gray'), plt.title('CV2 Guass')
plt.tight_layout()
plt.show()

# 两个物体的雷登变换
img_ori = cv2.imread('DIP_Figures/DIP3E_Original_Images_CH05/Fig0534(a)(ellipse_and_circle).tif', 0) #直接读为灰度图像
img_radon = radon_transform(img_ori, img_ori.shape[0])plt.figure(figsize=(24, 12))
plt.subplot(131), plt.imshow(img_ori, 'gray'), plt.title('Original'), plt.xticks([]), plt.yticks([])
plt.subplot(132), plt.imshow(img_radon, 'gray'), plt.title('Randon Transform'), plt.xticks([]), plt.yticks([])
# plt.subplot(133), plt.imshow(img_cv2_guass, 'gray'), plt.title('CV2 Guass')
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])plt.figure(figsize=(24, 12))plt.subplot(131), plt.imshow(img_ori, 'gray'), plt.title('Original'), plt.xticks([]), plt.yticks([])
plt.subplot(132), plt.imshow(img_radon, 'gray'), plt.title('Randon Transform'), plt.xticks([]), plt.yticks([])
# plt.subplot(133), plt.imshow(img_cv2_guass, 'gray'), plt.title('CV2 Guass')
plt.tight_layout()
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])plt.figure(figsize=(24, 12))plt.subplot(131), plt.imshow(img_ori, 'gray'), plt.title('Original'), plt.xticks([]), plt.yticks([])
plt.subplot(132), plt.imshow(img_radon, 'gray'), plt.title('Randon Transform'), plt.xticks([]), plt.yticks([])
# plt.subplot(133), plt.imshow(img_cv2_guass, 'gray'), plt.title('CV2 Guass')
plt.tight_layout()
plt.show()

反投影

fθ(x,y)=g(xcosθ+ysinθ,θ)f_\theta (x, y) = g(x \; cos\theta \;+\; y \; sin\theta, \theta)fθ​(x,y)=g(xcosθ+ysinθ,θ)
f(x,y)=∫0πfθ(x,y)dθf(x, y) = \int_0^\pi f_\theta(x, y)d\thetaf(x,y)=∫0π​fθ​(x,y)dθ
f(x,y)=∑θ=0πfθ(x,y)f(x, y) = \sum_{\theta=0}^\pi f_\theta(x, y)f(x,y)=θ=0∑π​fθ​(x,y)

反投影的图像有时称为层图,我们可把层图理解为一幅由其生成投影的图像的一个近似。

from scipy import ndimagedef inverse_radon_transform(image, steps):"""inverse radon tranform for radon transform imageparam: image: input Imageparam: steps: step for the transform,  normaly same of image heightreturn: inverse radon transform for image, image is un-normalized"""channels = len(image[0])dst = np.zeros((steps, channels, channels))for i in range(steps):# 传入的图像中的每一列都对应于一个角度的投影值# 这里用的图像是上篇博文里得到的Radon变换后的图像裁剪后得到的temp = image[:, i]# 这里利用维度扩展和重复投影值数组来模拟反向均匀回抹过程temp_expand_dim = np.expand_dims(temp, axis=0)temp_repeat = temp_expand_dim.repeat(channels, axis=0)dst[i] = ndimage.rotate(temp_repeat, i*180 / steps, reshape=False).astype(np.float64)# 各个投影角度的投影值已经都保存在origin数组中,只需要将它们相加即可    iradon = np.sum(dst, axis=0)return iradon
# 雷登反变换
# 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])plt.figure(figsize=(24, 12))plt.subplot(131), plt.imshow(img_ori, 'gray'), plt.title('Original')
plt.subplot(132), plt.imshow(img_radon, 'gray'), plt.title('Randon Transform')
plt.subplot(133), plt.imshow(img_inverse_radon, 'gray'), plt.title('Inverse Randon Transform')
plt.tight_layout()
plt.show()

# 两个物体的雷登反变换
img_ori = cv2.imread('DIP_Figures/DIP3E_Original_Images_CH05/Fig0534(a)(ellipse_and_circle).tif', 0) #直接读为灰度图像img_radon = radon_transform(img_ori, img_ori.shape[0])
img_inverse_radon = inverse_radon_transform(img_radon, img_radon.shape[0])plt.figure(figsize=(24, 12))
plt.subplot(131), plt.imshow(img_ori, 'gray'), plt.title('Original')
plt.subplot(132), plt.imshow(img_radon, 'gray'), plt.title('Randon Transform')
plt.subplot(133), plt.imshow(img_inverse_radon, 'gray'), plt.title('Inverse Randon Transform')
plt.tight_layout()
plt.show()

滤波反投影重建

f(x,y)=∫0π∫−∞∞∣ω∣G(ω,θ)ej2πω(xcosθ+ysinθ)dωdθf(x,y) = \int_0^\pi \int_{-\infty}^{\infty}|\omega| G(\omega,\theta)e^{j2\pi\omega(xcos\theta+ysin\theta)} d\omega d\thetaf(x,y)=∫0π​∫−∞∞​∣ω∣G(ω,θ)ej2πω(xcosθ+ysinθ)dωdθ

f(x,y)=∫0π[∫−∞∞∣ω∣G(ω,θ)ej2πωρdω]ρ=xcosθ+ysinθdθf(x,y) = \int_0^\pi \bigg[\int_{-\infty}^{\infty}|\omega| G(\omega,\theta)e^{j2\pi\omega\rho} d\omega\bigg]_{\rho = xcos\theta+ysin\theta} d\thetaf(x,y)=∫0π​[∫−∞∞​∣ω∣G(ω,θ)ej2πωρdω]ρ=xcosθ+ysinθ​dθ

h(ω)={c+(c−1)cos2πωM,0≤ω≤(M−1)0,othersh(\omega) = \begin{cases}c + (c-1)cos\frac{2\pi \omega}{M}, & {0 \leq\omega \leq (M-1)} \\ 0, & others\end{cases}h(ω)={c+(c−1)cosM2πω​,0,​0≤ω≤(M−1)others​

当c=0.54c=0.54c=0.54时,该函数称为汉明窗(Richard Hamming);当c=0.5c=0.5c=0.5时,该函数称为韩窗(Julius von Hann)。汉明窗和韩窗的主要区别是,韩窗末尾的一些点为零。通常两者的差别在图像处理应用中是觉察不到的。

反投影图像f(x,y)f(x,y)f(x,y)是按如下步骤得到的:

  1. 计算每个投影的一维傅里叶变换。
  2. 将每个全里叶变换乘以滤波器传弟函数∣ω∣|\omega|∣ω∣,这个传递函数已乘以一个合适的窗(如汉明窗)。
  3. 得到的每个滤波后的变换的一维傅里叶反变换。
  4. 对步骤3得到的所有一维反变换进行积分(求和)。

顾名思义,滤波反投影就是先对投影值进行滤波,然后利用的得到的值进行反投影,简单来说滤波的主要目的就是使边缘(对应于图像的高频部分)更加明显。理论上来说,滤波函数应该是:
h(ω)=∣ω∣h(\omega) = |\omega|h(ω)=∣ω∣

但是这个是一个理想滤波器,没办法实现,因此需要考虑其他能够实现并且能够使得到的图像更加接近原始图像的滤波器。这里我仅介绍两种R—L滤波器和S—L滤波器,下面是这两种滤波器的具体形式:
hRL(nδ)={−14δ2,n=00,n为偶数−1(nπδ)2,n为奇数h_{RL}(n\delta)=\begin{cases} -\frac{1}{4\delta^2}, & n =0 \\ 0, & n为偶数 \\ -\frac{1}{(n\pi\delta)^2}, & n 为奇数 \end{cases}hRL​(nδ)=⎩⎪⎨⎪⎧​−4δ21​,0,−(nπδ)21​,​n=0n为偶数n为奇数​

hSL=1π2δ2(4n2−1)h_{SL}= \frac{1}{\pi^2 \delta^2 (4n^2-1)}hSL​=π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] = 0hw = np.fft.fft(hw)hw = np.fft.fftshift(hw)hw = np.real(hw)
#     hw = normalize(np.real(hw))return hw
# 1维汉明窗
x = np.linspace(-5, 5, 200)M = x.shape[0]y = abs(x)c = 0.54hw = 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] = 0np_hamming = np.hamming(M)
np_hann= np.hanning(M)# plt.plot(x, y)
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 windowparam: img, input imageparam: hamming: bool, if True return hamming windows, if False return hann windowreturn normalize 2d hamming or hann windowProblem: 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)#     high_pass = np.sqrt((u - M//2)**2 + (v - N//2)**2)kernel = high_pass # 1 / (1 + ((high_pass * W) / (high_pass ** 2 - D0 **2 + 1e-5))**(2*order))return kernel
# 二维汉明窗
img_hamming = hamming_window(img_radon, hamming=True)# img_radon_hamming = normalize(img_hamming * img_radon)
img_radon_hamming = img_hamming * img_radonplt.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) # 1e-5 加上一个不为零的小数,防止出现除0的问题if np.mod(i - N / 2, 2) == 0:filterRL[i] = 0filterRL[int(N/2)] = 1 / (4 * np.power(d, 2.0))return filterRLdef 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 filterSLdef inverse_filter_radon_transform(image, steps):#定义用于存储重建后的图像的数组channels = len(image[0])origin = np.zeros((steps, channels, channels))
#     filter = box_filtechannelschannels, 0.48)
#     filter = rl_filter(channels, 1)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_radonimg_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()

第5章 Python 数字图像处理(DIP) - 图像复原与重建17 - 由投影重建图像、雷登变换、投影、反投影、反投影重建相关推荐

  1. 第3章 Python 数字图像处理(DIP) - 灰度变换与空间滤波17 - 锐化高通滤波器 - 梯度图像(罗伯特,Sobel算子)

    目录 锐化(高通)空间滤波器 使用一阶导数锐化图像-梯度 锐化(高通)空间滤波器 平滑通过称为低通滤波 类似于积分运算 锐化通常称为高通滤波 微分运算 高过(负责细节的)高频,衰减或抑制低频 使用一阶 ...

  2. 第5章 Python 数字图像处理(DIP) - 图像复原与重建1 - 高斯噪声

    本章主要讲图像复原与重建,首先是了解一下各种噪声的特点与模型,还有形成的方法.一些重点的噪声,如高斯噪声,均匀噪声,伽马噪声,指数噪声,还有椒盐噪声等. 本章主要的噪声研究方法主要是加性噪声. 标题 ...

  3. 第5章 Python 数字图像处理(DIP) - 图像复原与重建12 - 空间滤波 - 使用频率域滤波降低周期噪声 - 陷波滤波、最优陷波滤波

    标题 使用频率域滤波降低周期噪声 陷波滤波深入介绍 最优陷波滤波 本章陷波滤波器有部分得出的结果不佳,如果有更好的解决方案,请赐教,不胜感激. 使用频率域滤波降低周期噪声 陷波滤波深入介绍 零相移滤波 ...

  4. 第5章 Python 数字图像处理(DIP) - 图像复原与重建16 - 约束最小二乘方滤波、几何均值滤波

    标题 约束最小二乘方滤波 几何均值滤波 约束最小二乘方滤波 F^(u,v)=[H∗(u,v)∣H(u,v)∣2+γ∣P(u,v)∣2]G(u,v)(5.89)\hat{F}(u,v) = \bigg[ ...

  5. 第5章 Python 数字图像处理(DIP) - 图像复原与重建15 - 最小均方误差(维纳)滤波

    标题 最小均方误差(维纳)滤波 最小均方误差(维纳)滤波 目标是求未污染图像fff的一个估计f^\hat{f}f^​,使它们之间的均方误差最小. e2=E{(f−f^)2}(5.80)e^2 = E ...

  6. 第5章 Python 数字图像处理(DIP) - 图像复原与重建14 - 逆滤波

    标题 逆滤波 逆滤波 逆滤波 逆滤波 图像的退化函数已知或者由前面的方法获取退化函数,则可以直接逆滤波 F^(u,v)=G(u,v)H(u,v)(5.78)\hat{F}(u,v) = \frac{G ...

  7. 第5章 Python 数字图像处理(DIP) - 图像复原与重建13 - 空间滤波 - 线性位置不变退化 - 退化函数估计、运动模糊函数

    标题 线性位置不变退化 估计退化函数 采用观察法估计退化函数 采用试验法估计退化函数 采用建模法估计退化函数 运动模糊函数 OpenCV Motion Blur 在这一节中,得到的结果,有些不是很好, ...

  8. 第5章 Python 数字图像处理(DIP) - 图像复原与重建11 - 空间滤波 - 自适应滤波器 - 自适应局部降噪、自适应中值滤波器

    标题 自适应滤波器 自适应局部降噪滤波器 自适应中值滤波器 自适应滤波器 自适应局部降噪滤波器 均值是计算平均值的区域上的平均灰度,方差是该区域上的图像对比度 g(x,y)g(x, y)g(x,y)噪 ...

  9. 第5章 Python 数字图像处理(DIP) - 图像复原与重建10 - 空间滤波 - 统计排序滤波器 - 中值、最大值、最小值、中点、修正阿尔法均值滤波器

    标题 统计排序滤波器 中值.最大值.最小值.中点 滤波器 修正阿尔法均值滤波器 统计排序滤波器 中值.最大值.最小值.中点 滤波器 f^(x,y)=median{g(r,c)}(5.27)\hat{f ...

最新文章

  1. 超详细单机版搭建hadoop环境图文解析
  2. 更改多维数组的数据结构形式
  3. Linux远程管理协议相关知识介绍
  4. jQuery.ajaxPrefilter()函数的使用
  5. 西格尔零点猜想_我从埃里克·西格尔学到的东西
  6. java运算符试题,编程语⾔⾯试题之新版javase基础语法篇之运算符
  7. 删除win10开始菜单中程序的目录
  8. [论文阅读][Point-Plane ICP]Object Modeling by Registration of Multiple Range Images
  9. 年底促销海报还没准备好?电商美工看这里
  10. mysql表空间不足_MySQL Innodb表空间不足的处理方法 风好大
  11. xp系统能不能安装mysql_win xp32位系统安装mysql详细步骤
  12. FleaPHP 1.0.70 开发进度汇报专贴
  13. HTML期末大作业~ 仿新浪微博个人主页html网站模板4个页面(HTML+CSS+JavaScript)
  14. 平板电脑黑苹果EFI_首次安装黑苹果系统,原来如此简单,比真正的Mac电脑更快...
  15. 两台计算机怎么ping通,怎么ping网络(2个网段电脑怎么ping通)
  16. 个人整理的免费的Bootstrap模板
  17. 拓展软文写作主题角度
  18. 非常好的产品研发管理文章,后面问题回答的很精彩(转)
  19. 金额转换,阿拉伯数字的金额转换成中国传统的形式如:(¥1011)->(一千零一拾一元整)输出
  20. java-如何用输入流写3000遍“爱你三千次”。

热门文章

  1. 继 承(面向对象特征之一)
  2. 04.openssl编程——哈希表
  3. 学习进度(2016.3.13)
  4. Linux下mysql整库备份
  5. Linux下Web效力器架设攻略-1
  6. 小程序 --- Tab组件的封装
  7. koa --- 扩展hbs方法
  8. SDUT 3347 数据结构实验之数组三:快速转置
  9. AlienVault Ossim各版本镜像下载地址
  10. 《算法之道》精华 经典算法部分