【问题标题】:How to create synthetic blurred image from sharp image using PSF kernel (in image format)如何使用 PSF 内核从清晰图像创建合成模糊图像(图像格式)
【发布时间】:2019-09-13 02:12:43
【问题描述】:

根据@Fix 的建议进行更新,我应该将 BGR 转换为 RGB,但输出仍然与论文的输出不同。

(小记:这篇文章已经发布在https://dsp.stackexchange.com/posts/60670,但由于我需要快速帮助,所以我想我在这里重新发布,希望这不会违反任何政策)

我尝试使用 PSF 内核(png 格式)从真实图像创建合成模糊图像,一些论文只提到我需要对其进行卷积操作,但似乎我需要的不止这些。 我做了什么

import matplotlib.pyplot as plt
import cv2 as cv
import scipy
from scipy import ndimage
import matplotlib.image as mpimg
import numpy as np

img = cv.imread('../dataset/text_01.png')
norm_image = cv.normalize(img, None, alpha=-0.1, beta=1.8, norm_type=cv.NORM_MINMAX, dtype=cv.CV_32F)

f = cv.imread('../matlab/uniform_kernel/kernel_01.png')
norm_f = cv.normalize(f, None, alpha=0, beta=1, norm_type=cv.NORM_MINMAX, dtype=cv.CV_32F)

result = ndimage.convolve(norm_image, norm_f, mode='nearest')

result = np.clip(result, 0, 1)

imgplot = plt.imshow(result)
plt.show()

这只会给我一个全白的图像。 我尝试将 beta 降低到像这样norm_f = cv.normalize(f, None, alpha=0, beta=0.03, norm_type=cv.NORM_MINMAX, dtype=cv.CV_32F) 这样的较低数字,并且图像出现了,但它的颜色非常不同。

我知道如何做到这一点的论文和数据集(具有地面实况和 PNG 格式的 PSF 内核的图像)是 here

他们是这么说的:

我们以类似于 [3, 10] 的方式创建合成饱和图像。 具体来说,我们首先拉伸潜像的强度范围 从 [0,1] 到 [−0.1,1.8],并将模糊核与 图片。然后我们将模糊图像剪辑到 [0,1] 的范围内。这 生成非均匀模糊图像采用相同的过程。

这是我从来源获得的一些图像。

这是真实图像:

这是PNG格式文件的PSF内核:

这是他们的输出(合成图像):

请帮帮我,解决方案并不重要,即使它是一个软件、另一种语言、另一种工具。我只关心最终我从具有良好性能的 PSF 内核的原始(清晰)图像合成模糊图像(我在 Matlab 上尝试过,但遇到了类似的问题,我使用了 imfilter,Matlab 的另一个问题是它们很慢)。

(请不要判断只关心过程的输出,我没有使用反卷积方法将模糊模糊回原始图像,因此我希望有足够的数据集(原始和模糊)对来测试我的假设/方法)

谢谢。

【问题讨论】:

    标签: python motion-blur


    【解决方案1】:

    OpenCV 以 BGR 格式读取/写入图像,而 Matplotlib 以 RGB 格式读取/写入图像。所以如果你想显示正确的颜色,你应该先把它转换成RGB:

    result_rgb = cv.cvtColor(result, cv.COLOR_BGR2RGB)
    imgplot = plt.imshow(result)
    plt.show()
    

    编辑:您可以分别对每个通道进行卷积并像这样标准化您的卷积图像:

    f = cv.cvtColor(f, cv.COLOR_BGR2GRAY)  
    norm_image = img / 255.0
    norm_f = f / 255.0  
    result0 = ndimage.convolve(norm_image[:,:,0], norm_f)/(np.sum(norm_f))
    result1 = ndimage.convolve(norm_image[:,:,1], norm_f)/(np.sum(norm_f))
    result2 = ndimage.convolve(norm_image[:,:,2], norm_f)/(np.sum(norm_f))
    result = np.stack((result0, result1, result2), axis=2).astype(np.float32)
    

    那么你应该得到正确的颜色。虽然这对图像和内核都使用了 0.0 到 1.0 之间的归一化(不像论文建议的图像在 -0.1 和 1.8 之间)。

    【讨论】:

    • 这只是一个有用的信息,但它不会改变我的输出仍然与纸张输出不同的事实。
    • 对不起,我误解了你的问题。我编辑了我的答案:为了获得正确的颜色,我必须分别对每个通道进行卷积。
    • 非常感谢。但是,如果您能向我解释为什么每个频道都使用ndimage.convolve(norm_image[:,:,0], norm_f)/(np.sum(norm_f)),那将不胜感激?我认为 ndimage.convolve 已经为以后的每个图像进行卷积,为什么/(np.sum(norm_f))