如何使用水平投影清洁二进制图像? [英] How to clean binary image using horizontal projection?

查看:29
本文介绍了如何使用水平投影清洁二进制图像?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想用二进制过滤器从车牌上删除文本以外的任何内容.

我在每个轴上都有投影,但是我不知道如何应用它.我的想法是消除白色轮廓.

这是我现在正在使用的图像:

这是在X轴上的投影:

从matplotlib中的

 导入pyplot作为plt导入pylab(行,列)= img.shapeh_projection = np.array([img.sum(axis = 0)中x的x/255/行)plt.plot(范围(cols),h_projection.T) 

这是结果:

您可以在图中看到,最后,该线是由白色轮廓线拍摄的.

如何删除照片中某个特定阈值的所有内容?感谢您的帮助

解决方案

因此,您要提取白色字符中的黑色区域.例如,您可以在直方图中选择值小于特定阈值的列(或行).

从matplotlib中的

 导入pyplot作为plt导入pylab将numpy导入为npimg = plt.imread('binary_image/iXWgw.png')(行,列)= img.shapeh_projection = np.array([img.sum(axis = 0)中x的x/行)阈值=(np.max(h_projection)-np.min(h_projection))/4print(我们将水平使用阈值{}".format(阈值))#选择黑色区域black_areas = np.where(h_projection <阈值)无花果= plt.figure(figsize =(16,8))fig.add_subplot(121)对于black_areas中的j:img [:, j] = 0plt.plot((j,j),(0,1),'g-')plt.plot(范围(cols),h_projection.T)v_projection = np.array([[img.sum(axis = 1)中x的x/cols])阈值=(np.max(v_projection)-np.min(v_projection))/4print(我们将对垂直使用阈值{}".format(threshold))black_areas = np.where(v_projection<阈值)fig.add_subplot(122)对于black_areas中的j:img [j,:] = 0plt.plot((0,1),(j,j),'g-')plt.plot(v_projection,range(rows))plt.show()#遮盖图像上的区域plt.figure(figsize =(16,12))plt.subplot(211)plt.title(带有投影蒙版的图像")plt.imshow(img)#侵蚀功能导入密码plt.subplot(212)plt.title(侵蚀后的图像(建议)")eroded_img = scipy.ndimage.morphology.binary_erosion(img,structure = np.ones((5,5))).astype(img.dtype)plt.imshow(eroded_img)plt.show() 

所以现在您有了水平和垂直投影,看起来像这样

然后您可以应用该掩码:有几种方法可以执行此操作,因为代码已在for循环中应用,我们将 img [:,j] = 0 设置为列, img [j ,:] = 0 代表行.这很简单,我认为很直观,但是您可以寻找其他方法.作为建议,我可以说您可以研究

不幸的是,上部和下部仍显示白色区域.您可以将行手动设置为白色 img [:10 ,:] = 0,img [100:,:] = 0 ,但这可能不适用于您拥有的所有图像(如果您在尝试训练神经网络时,我假设您有很多神经网络,因此您需要有一个适用于所有神经网络的代码.

因此,由于现在您也要求细分,因此打开了另一个主题.分段是一项复杂的任务,它不像二进制掩码那样简单.我强烈建议您在不理解的情况下应用某些内容之前,先阅读一些相关材料.例如,

作为示例,我显示了 S 字母.如果您更改 label_im == 6 ,您将获得下一个字母.如您所见,它并不总是正确的,图像的其他小部分也被视为对象.因此,您将需要做更多的工作.

I want to remove anything other than text from a license plate with a binary filter.

I have the projections on each axis but I don't know how to apply it. My idea is to erase the white outlines.

This is the image I'm working for now:

This is the projection in Axis X:

from matplotlib import pyplot as plt
import pylab

(rows,cols)=img.shape
h_projection = np.array([ x/255/rows for x in img.sum(axis=0)])
plt.plot(range(cols), h_projection.T)

And this is the result:

As you can see in the graph, at the end the line is shot by the white contour.

How can I erase everything that is at a certain threshold of the photo? Every help is appreciated

解决方案

So, you want to extract the black areas within the white characters. For example, you can select the columns (or rows) in your histograms where the value is less than a certain threshold.

from matplotlib import pyplot as plt
import pylab
import numpy as np


img = plt.imread('binary_image/iXWgw.png')
(rows,cols)=img.shape
h_projection = np.array([ x/rows for x in img.sum(axis=0)])
threshold = (np.max(h_projection) - np.min(h_projection)) / 4
print("we will use threshold {} for horizontal".format(threshold))
# select the black areas
black_areas = np.where(h_projection < threshold)
fig = plt.figure(figsize=(16,8))
fig.add_subplot(121)
for j in black_areas:
    img[:, j] = 0
    plt.plot((j, j), (0, 1), 'g-')
plt.plot(range(cols), h_projection.T)

v_projection = np.array([ x/cols for x in img.sum(axis=1)])
threshold = (np.max(v_projection) - np.min(v_projection)) / 4
print("we will use threshold {} for vertical".format(threshold))
black_areas = np.where(v_projection < threshold)
fig.add_subplot(122)
for j in black_areas:
    img[j, :] = 0
    plt.plot((0,1), (j,j), 'g-')
plt.plot(v_projection, range(rows))
plt.show()

# obscurate areas on the image
plt.figure(figsize=(16,12))
plt.subplot(211)
plt.title("Image with the projection mask")
plt.imshow(img)

# erode the features
import scipy
plt.subplot(212)
plt.title("Image after erosion (suggestion)")
eroded_img = scipy.ndimage.morphology.binary_erosion(img,  structure=np.ones((5,5))).astype(img.dtype)
plt.imshow(eroded_img)
plt.show()

So now you have the horizontal and vertical projections, that look like this

And after that you can apply the mask: there are several ways of doing this, in the code is already applied within the for loop, where we set img[:,j] = 0 for the columns, and img[j,:] = 0 for the rows. It was easy and I think intuitive, but you can look for other methods. As a suggestion, I would say you can look into the morphological operator of erosion that can help to separate the white parts. So the output would look like this.

Unfortunately, the upper and lower part still show white regions. You can manually set the rows to white img[:10,:] = 0, img[100:,:] = 0, but that probably would not work on all the images you have (if you are trying to train a neural network I assume you have lots of them, so you need to have a code that works on all of them.

So, since now you ask for segmentation also, this opens another topic. Segmentation is a complex task, and it is not as straightforward as a binary mask. I would strongly suggest you read some material on that before you just apply something without understanding. For example here a guide on image processing with scipy, but you may look for more. As a suggestion and a small snippet to make it work, you can use the labeling from scipy.ndimage. Here a small part of code (from the guide)

label_im, nb_labels = scipy.ndimage.label(eroded_img)
plt.figure(figsize=(16,12))
plt.subplot(211)
plt.title("Segmentation")
plt.imshow(label_im)   
plt.subplot(212)
plt.title("One Object as an example")
plt.imshow(label_im == 6)   # change number for the others!

Which will output:

As an example I showed the S letter. if you change label_im == 6 you will get the next letter. As you will see yourself, it is not always correct and other little pieces of the image are also considered as objects. So you will have to work a little bit more on that.

这篇关于如何使用水平投影清洁二进制图像?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆