如何从图像中删除水平和垂直线条 [英] How to remove horizontal and vertical lines from an image

查看:240
本文介绍了如何从图像中删除水平和垂直线条的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的图像是用螺旋笔记本纸上写的文字。纸张有水平线。我想从图像中删除水平线。

I have an image that is of a text written on a spiral notebook paper. the paper has horizontal lines. I would like to remove the horizontal lines from the image.

谷歌搜索时我发现了一个我认为可行的解决方案:使用形态学操作提取水平和垂直线解决方案是在C ++中,所以我将其转换为Python。它适用于该解决方案中提供的示例图像,但它似乎不适用于我的图像。

While googling I found a solution that I thought would work: Extract horizontal and vertical lines by using morphological operations The solution was in C++ so I converted it to Python. It works well on the sample image provided in that solution however, it does not seem to work for my images.

在我的图片上运行时,我得到以下结果:

While running it on my image I get these results:

原始图片

< a href =https://www.dropbox.com/s/n3ooq9tyo3rv7as/final.jpg?dl=0 =noreferrer>结果图片

以下是我从C ++翻译的Python代码

Below is the Python code that I translated from C++

 #cpp code converted from     http://docs.opencv.org/3.2.0/d1/dee/tutorial_moprh_lines_detection.html

import cv2
import numpy as np

img = cv2.imread("original.jpg")
img=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

img = cv2.bitwise_not(img)
th2 = cv2.adaptiveThreshold(img,255, cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,15,-2)
cv2.imshow("th2", th2)
cv2.imwrite("th2.jpg", th2)
cv2.waitKey(0)
cv2.destroyAllWindows()

horizontal = th2
vertical = th2
rows,cols = horizontal.shape
horizontalsize = cols / 30
horizontalStructure = cv2.getStructuringElement(cv2.MORPH_RECT, (horizontalsize,1))
horizontal = cv2.erode(horizontal, horizontalStructure, (-1, -1))
horizontal = cv2.dilate(horizontal, horizontalStructure, (-1, -1))
cv2.imshow("horizontal", horizontal)
cv2.imwrite("horizontal.jpg", horizontal)
cv2.waitKey(0)
cv2.destroyAllWindows()

verticalsize = rows / 30
verticalStructure = cv2.getStructuringElement(cv2.MORPH_RECT, (1, verticalsize))
vertical = cv2.erode(vertical, verticalStructure, (-1, -1))
vertical = cv2.dilate(vertical, verticalStructure, (-1, -1))
cv2.imshow("vertical", vertical)
cv2.imwrite("vertical.jpg", vertical)
cv2.waitKey(0)
cv2.destroyAllWindows()

vertical = cv2.bitwise_not(vertical)
cv2.imshow("vertical_bitwise_not", vertical)
cv2.imwrite("vertical_bitwise_not.jpg", vertical)
cv2.waitKey(0)
cv2.destroyAllWindows()

#step1
edges = cv2.adaptiveThreshold(vertical,255, cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,3,-2)
cv2.imshow("edges", edges)
cv2.imwrite("edges.jpg", edges)
cv2.waitKey(0)
cv2.destroyAllWindows()

#step2
kernel = np.ones((2, 2), dtype = "uint8")
dilated = cv2.dilate(edges, kernel)
cv2.imshow("dilated", dilated)
cv2.imwrite("dilated.jpg", dilated)
cv2.waitKey(0)
cv2.destroyAllWindows()

# step3
smooth = vertical.copy()

#step 4
smooth = cv2.blur(smooth, (4,4))
cv2.imshow("smooth", smooth)
cv2.imwrite("smooth.jpg", smooth)
cv2.waitKey(0)
cv2.destroyAllWindows()

#step 5
(rows, cols) = np.where(img == 0)
vertical[rows, cols] = smooth[rows, cols]

cv2.imshow("vertical_final", vertical)
cv2.imwrite("vertical_final.jpg", vertical)
cv2.waitKey(0)
cv2.destroyAllWindows()

我在我身上尝试了ImageMagik我们的原始形象ll努力删除线条。

I've tried ImageMagik on my original image as well in an effort to remove lines.

我使用 ImageMagik 获得更好的结果,但仍然不完全准确。

I get better results with ImageMagik but still not completely accurate.

convert original -morphology close:3 "1x5: 0,1,1,1,0" original_im.jpg


推荐答案

您的案例不如您在教程中提供的案例那么简单基于你的解决方案。使用这种方法,您将无法100%过滤线条,因为角色的水平部分有时会被视为线条。

Your case is less trivial than the one provided in the tutorial that you have based your solution on. With this approach you will not be able to filter the lines in 100%, because of the fact that horizontal parts of the characters will sometimes be treated as lines.

取决于你的期望(你没有真正指定),特别是你期望的准确性,你可能想要找到字符而不是找到线。这应该会为你提供更强大的功能。

Depends on your expectations (which you haven't really specified) and specifically the accuracy that you expect, you might want to try to find the characters instead of finding the line. That should provide you with more robustness.

关于你的代码,通过在图像上找到水平线后添加几行代码(在 verticalsize之前) = rows / 30 代码行),你可以得到一些结果。我已经制作了一张半尺寸的图片。

Regarding your code, by adding few lines of code right after finding horizontal lines on the image (before verticalsize = rows / 30 line of code), you can get some results. I've worked on a half size image.

结果horizo​​ntalsize = int(cols / 30)

结果horizo​​ntalsize = int(cols / 15)

再次,我强调那些永远不会是在你的情况下,准确的方法。这是片段:

Again, I'm stressing that those will never be accurate with that approach in your case. Here's the snippet:

#inverse the image, so that lines are black for masking
horizontal_inv = cv2.bitwise_not(horizontal)
#perform bitwise_and to mask the lines with provided mask
masked_img = cv2.bitwise_and(img, img, mask=horizontal_inv)
#reverse the image back to normal
masked_img_inv = cv2.bitwise_not(masked_img)
cv2.imshow("masked img", masked_img_inv)
cv2.imwrite("result2.jpg", masked_img_inv)
cv2.waitKey(0)
cv2.destroyAllWindows()

尝试使用 horizo​​ntalsize 如果我提供的图像有点令人满意。我也使用了int转换,因为 getStructuringElement 函数需要: horizo​​ntalsize = int(cols / 30)

Try playing with horizontalsize if the images I provided are somewhat satisfactory. I've also used int conversion, since that's what the getStructuringElement function expects: horizontalsize = int(cols / 30).

你也可以在结果上尝试一些平滑和形态。这应该使角色更具可读性。

You can also try some smoothing and morphology on the result. That should make the characters a little bit more readable.

这篇关于如何从图像中删除水平和垂直线条的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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