【问题标题】:How to remove horizontal and vertical lines如何去除水平线和垂直线
【发布时间】:2015-07-21 17:14:41
【问题描述】:

我需要删除二值图像中的水平线和垂直线。有什么方法可以过滤这些行吗? bwareaopen() 不是删除这些线条的好方法,而且 Dilation 和 Erosion 也不适合这些情况。 有谁知道解决办法吗?

示例图片:

编辑:(添加更多示例图片:

http://s1.upload7.ir/downloads/pPqTDnmsmjHUGTEpbwnksf3uUkzncDwr/example%202.png

图片源文件:

https://www.dropbox.com/sh/tamcdqk244ktoyp/AAAuxkmYgBkB8erNS9SajkGVa?dl=0

www.directexe.com/9cg/pics.rar

【问题讨论】:

  • 这可能会给你一些想法Hough transform to detect and delete lines。请注意,霍夫变换不是使这个想法奏效的必要条件。这个想法很笼统。
  • 感谢亲爱的@kkuilla 的建议,但是霍夫变换对我的工作来说太慢了。
  • 是的,但你不需要霍夫变换来实现这个想法。这个想法是您将一条线拟合到所有段并删除不是一条线的段。

标签: matlab image-processing


【解决方案1】:

使用regionprops 并删除具有高偏心率的区域(意味着该区域又长又细)和接近 0 度或接近 90 度的方向(垂直或水平的区域)。

代码:

img = im2double(rgb2gray(imread('removelines.jpg')));

mask = ~im2bw(img);

rp = regionprops(mask, 'PixelIdxList', 'Eccentricity', 'Orientation');

% Get high eccentricity and orientations at 90 and 0 degrees
rp = rp([rp.Eccentricity] > 0.95 & (abs([rp.Orientation]) < 2 | abs([rp.Orientation]) > 88));

mask(vertcat(rp.PixelIdxList)) = false;

imshow(mask);

输出:

【讨论】:

  • 我采用了同样的方法。比形态学方法效果更好。
  • 亲爱的@jucestain,我真的很感谢你为我所做的一切。如何更改您的代码以消除我添加到问题中的这些示例的噪音? PLZ 看看例子并帮助我更多......非常感谢。
  • @KaroAmini 对于该数据集,您能否始终将边框完全围绕字母并未裁剪?如果是这样,您应该能够通过删除具有非常大的BoundingBoxConvexArea 数量的区域来检测边界。此外,仅供参考,但有一个很酷的link 描述了一种直接检测字母的方法。这可能也有帮助。
  • @KaroAmini 基本上,您需要确定是否要检测并删除非字母是否要直接检测字母并删除其他所有内容。
  • 亲爱的@jucestain,因为各种图片我无法裁剪字母或边框。在这一步中,我想去除噪音,下一步通过 OCR 提取和读取字母,实际上主要目标是检测和提取字母。
【解决方案2】:

如果您的所有图像在水平线和垂直线接触边框的位置都相同,则只需调用imclearborder 即可解决问题。 imclearborder 删除任何接触图像边界的对象像素。您需要反转图像,使字符为白色,背景为深色,然后重新反转,但我认为这不是问题。但是,为了确保没有任何实际字符被删除,因为它们也可能接触到边框,谨慎的做法是人为地用单个像素厚度填充图像的顶部边框,清除边框,然后重新裁剪。

im = imread('http://i.stack.imgur.com/L1hUa.jpg'); %// Read image directly from StackOverflow

im = ~im2bw(im); %// Convert to black and white and invert
im_pad = zeros(size(im,1)+1, size(im,2)) == 1; %// Pad the image too with a single pixel border
im_pad(2:end,:) = im;

out = ~imclearborder(im_pad); %// Clear border pixels then reinvert
out = out(2:end,:); %// Crop out padded pixels

imshow(out); %// Show image

我们得到这个:

【讨论】:

  • 谢谢@rayryeng 先生,您总是帮助我解决问题。我添加了更多示例图像,如何更改您的代码以消除这些图像的二进制噪声?我很感激你为我所做的一切。
  • @KaroAmini - 这些图像与您的原始问题完全不同。一方面,有大量的噪音。我将不得不完全重新表述我的问题以适应您上传的那些图像。
  • 我在这个链接中单独上传了图片:dropbox.com/sh/tamcdqk244ktoyp/AAAuxkmYgBkB8erNS9SajkGVa?dl=0,非常感谢你。
  • @KaroAmini - 不幸的是,目前这不是优先事项。当我解决这个问题时,我会尝试重新表述这个问题,使其更适应您的数据。
  • 你真好。确实谢谢你亲爱的@rayryeng先生
【解决方案3】:

你可以先找到水平线和垂直线。因为,边缘图也将是二进制的,因此您可以在图像之间执行逻辑减法运算。要查找垂直线,您可以使用(在 MATLAB 中)

BW = edge(I,'sobel','vertical');

对于水平线,可以使用

% Generate horizontal edge emphasis kernel
h = fspecial('sobel');

% invert kernel to detect vertical edges
h = h';

J = imfilter(I,h);

【讨论】:

  • 你试过了吗?我怀疑这是否适用于粗线,因为边缘检测器不是线检测器。他们发现了不同灰度之间的过渡。所以你不会删除整条线,因为里面的线不会改变它的颜色。此外,您还将检测到字母沿线的任何垂直或水平渐变,这些是不想触摸的。
  • 这只会找到,而不是线。但是,如果线条只有一个像素粗,这可能会起作用,但对于可变粗细的线条,这只会检测线条的周长。在那种情况下,我看不出这将如何解决这个问题。