去噪和过滤图像

Denoise and filter an image

我正在进行车牌识别。我裁剪了盘子,但它非常 模糊 。因此我无法拆分出 digits/characters 并识别它。

这是我的图片:

我尝试使用 scikit 图像 函数去噪

首先,导入库:

import cv2
from skimage import restoration
from skimage.filters import threshold_otsu, rank
from skimage.morphology import closing, square, disk

然后,我读取图像并将其转换为灰度

image = cv2.imread("plate.jpg")
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

我尝试消除噪音:

denoise = restoration.denoise_tv_chambolle(image , weight=0.1)
thresh = threshold_otsu(denoise)
bw = closing(denoise  > thresh, square(2))

我得到的是:

如您所见,所有数字都混合在一起。因此,我无法将它们分开,无法一一识别。

我期望的是这样的(我画的):

我正在寻求帮助如何更好地过滤图像?谢谢。

============================================= ======================== 更新

使用skimage.morphology.erosion后,我得到:

首先,这张图片似乎被模糊处理得比噪点更严重,所以没有充分的理由对其进行降噪,尝试去模糊处理。

最简单的是逆滤波甚至维纳滤波。然后你需要通过亮度级别将图像的背景与字母分开,例如使用分水岭算法。然后你会得到单独的字母,你需要通过一个分类器,例如,基于神经网络(即使是简单的前馈网络也可以)。

然后您将最终获得文本表示。这就是通常进行此类识别的方式。 那里很好book by Gonzalez&Woods,试试看那里有详细的解释。

我同意您应该尝试优化输入图像质量的观点。

车牌模糊是运动模糊的典型例子。 去模糊的效果取决于模糊半径的大小。 一般车速越大,模糊半径越大,越难还原。

一个在一定程度上起作用的简单解决方案是图像去隔行扫描。

请注意,它仅比您的输入图像更具可读性。 在这里,我删除了每一行,并使用 PIL/Pillow 将图像大小调整为一半,这就是我得到的:

from PIL import Image
img=Image.open("license.jpeg")
size=list(img.size)
size[0] /= 2
size[1] /= 2
smaller_image=img.resize(size, Image.NEAREST)
smaller_image.save("smaller_image.png")

下一个更正式的方法是反卷积

由于模糊是使用图像的卷积实现的,因此去模糊需要对图像进行逆卷积或反卷积。有各种反卷积算法,如维纳反卷积, Richardson-Lucy 方法、Radon 变换和几种贝叶斯过滤。

您可以使用此 code 应用维纳反卷积算法。调整角度、直径和信噪比,看看它是否提供了一些改进。

skimage.restoration 模块还提供了 unsupervised_wienerrichardson_lucy 反卷积的实现。

在下面的代码中,我展示了这两种实现方式,但您必须修改 psf 以查看哪一种更适合。

import numpy as np
import matplotlib.pyplot as plt
import cv2
from skimage import color, data, restoration
from scipy.signal import convolve2d as conv2

img = cv2.imread('license.jpg')
licence_grey_scale = color.rgb2gray(img)

psf = np.ones((5, 5)) / 25

# comment/uncomment next two lines one by one to see unsupervised_wiener and richardson_lucy deconvolution
deconvolved, _ = restoration.unsupervised_wiener(licence_grey_scale, psf)
deconvolved = restoration.richardson_lucy(licence_grey_scale, psf)

fig, ax = plt.subplots()
plt.gray()
ax.imshow(deconvolved)
ax.axis('off')
plt.show()

不幸的是,这些解卷积算法中的大多数都要求您提前知道 模糊内核(又名点扩散函数又名 PSF)。

这里因为你不知道PSF,所以你将不得不使用盲反卷积。 盲反卷积试图在不知道模糊核的情况下估计原始图像。

我没有用你的图像试过这个,但这里有一个 Python 盲解卷积算法的实现: https://github.com/alexis-mignon/pydeconv

请注意,有效的通用盲反卷积算法尚未被发现,并且是一个活跃的研究领域。

使用图像增强二值化内核的 ChanVeseBinarize 给了我这个结果。这有助于突出显示 4、8、1 和 2。我猜你需要对每个字符进行单独的卷积,如果卷积的峰值高于阈值,我们可以假设该字母出现在峰值位置.要处理失真问题,您需要使用给定字符的几种不同类型的字体进行卷积。

另一个潜在的改进是使用导数滤波器和一点点高斯平滑。 K 和 X 不像以前的解决方案那样扭曲。