对于我的项目,我正在尝试在 python 中使用 openCV 对图像进行二值化。我使用来自 openCV 的自适应高斯阈值来转换具有以下结果的图像:
我想将二进制图像用于 OCR,但它太吵了。有什么方法可以从 python 中的二进制图像中去除噪声?我已经尝试过 openCV 中的 fastNlMeansDenoising,但没有任何区别。
PS也欢迎更好的二值化选项
也可以将 GraphCuts 用于此类任务。您需要安装maxflow库才能运行代码。我很快从他们的教程中复制了代码并对其进行了修改,因此您可以更轻松地运行它。只需使用平滑参数来增加或减少图像的去噪。
import cv2
import numpy as np
import matplotlib.pyplot as plt
import maxflow
# Important parameter
# Higher values means making the image smoother
smoothing = 110
# Load the image and convert it to grayscale image
image_path = 'your_image.png'
img = cv2.imread('image_path')
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img = 255 * (img > 128).astype(np.uint8)
# Create the graph.
g = maxflow.Graph[int]()
# Add the nodes. nodeids has the identifiers of the nodes in the grid.
nodeids = g.add_grid_nodes(img.shape)
# Add non-terminal edges with the same capacity.
g.add_grid_edges(nodeids, smoothing)
# Add the terminal edges. The image pixels are the capacities
# of the edges from the source node. The inverted image pixels
# are the capacities of the edges to the sink node.
g.add_grid_tedges(nodeids, img, 255-img)
# Find the maximum flow.
g.maxflow()
# Get the segments of the nodes in the grid.
sgm = g.get_grid_segments(nodeids)
# The labels should be 1 where sgm is False and 0 otherwise.
img_denoised = np.logical_not(sgm).astype(np.uint8) * 255
# Show the result.
plt.subplot(121)
plt.imshow(img, cmap='gray')
plt.title('Binary image')
plt.subplot(122)
plt.title('Denoised binary image')
plt.imshow(img_denoised, cmap='gray')
plt.show()
# Save denoised image
cv2.imwrite('img_denoised.png', img_denoised)
您应该首先将参数调整为自适应阈值,以便它使用更大的区域。这样它就不会分割出噪音。每当您的输出图像比输入图像具有更多噪声时,您就知道自己做错了。
我建议作为一个自适应阈值,使用一个结构元素(在输入灰度值图像上)的关闭,其结构元素刚好足够删除所有文本。此结果与输入图像之间的差异正是所有文本。然后,您可以对该差异应用常规阈值。
您可以尝试关闭形态变换以去除小“洞”。首先使用 numpy 定义一个内核,您可能需要调整大小。选择与噪声一样大的内核大小。
kernel = np.ones((5,5),np.uint8)
然后使用内核运行morphologyEx。
denoised = cv2.morphologyEx(image, cv2.MORPH_CLOSE, kernel)
如果文本被删除,您可以尝试侵蚀图像,这将“增长”黑色像素。如果噪声与数据一样大,这种方法将无济于事。
erosion = cv2.erode(img,kernel,iterations = 1)