2016-08-12 87 views
0

我有超过1000张以下附件的图像。检测两条直线之间的区域

enter image description here

我只需要从这些图像中提取手写部分。打字区域的大小变化很大,手写部分的大小也不一样,所以我不能根据行和列的固定像素值进行提取,如img = img(300:1800,200:1600)

但是手写部分总是在两条直线之间,所以我正在研究的一种解决方案是以某种方式检测图像中的线条,然后提取线条之间的区域。

我试着按照这里的教程:http://www.mathworks.com/examples/image/mw/images-ex64995063-detect-lines-in-images-using-hough它使用霍夫变换来检测线条,但我没有得到预期的结果。

我第一次尝试它的原始图像

edg1 = edge(img,'canny'); 

上,但有一个非常嘈杂的结果。

enter image description here

所以,我试图将其转换为逻辑,然后再次尝试。

img_bw = im2bw(img,graythresh(img)); 
edg2 = edge(img_bw,'canny'); 

但即使如此,行并未按预期检测到。

enter image description here

我该怎么在正确的道路上?这是我从文件中提取手写部分的最佳方式吗?

如果是这样,那么我怎样才能确保线被检测到,并得到这些线的坐标。

谢谢

回答

1

大部分的信息代码中的注释,但这里是一个简要介绍:

我没有使用形态滤波器的一些初步图像清洁(我敢肯定,高斯滤波器或类似的将被证明同样有效)

我的方法是如何使用行信息来查找行。考虑采取单列并绘制像素值。这些格式(或任何黑色文本)应该很容易看到。所以我取了整行的平均值,并使用该配置文件来帮助查找线条。由于一条线越过一行,所有的值都会很低,并产生一个强烈的峰值。这些字符有很大的空白,所以行平均值应该包含更多的白色像素,因此峰值将不会很好定义

最后的假设是该配置文件中的两个最大峰值(从图像底部开始)应该是线条。

不幸的是,我做了一些经验分析(猜测并检查),用于两个参数,它们可能需要修改

  1. st_size用于图像清洁结构元素的大小。如果所有图像尺寸几乎相同,则不需要修改。尽管它不是自动确定的,但这与使用设定尺寸的平滑滤波器没有什么不同,所以这不应引起太多问题

  2. mask_thresh用于查找峰值的值。这可能会导致其他图像出现问题。标准是它低于bot_lin_loc但高于手写文本部分的高峰。我只是做了它最大峰值这是在算法中最薄弱的环节,并可能需要您投入更多调整的1/3

im = imread('http://i.stack.imgur.com/1mO1S.jpg'); 
gim = rgb2gray(im); 
[im_h,im_w] = size(gim); 

%this is a quick attempt to remove background noise, the goal is to remove 
%all the letters, and what you are left with is background 
st_size = 10; 
st = strel('disk',10); 
im_background = imdilate(gim,st); 

%now we take the difference between our background and original image 
im_foreground = abs(im_background-gim); 

%reduce the image to a row average to find lines 
rowavg = mean(im_foreground,2); 

%peak threshold (unfortunately this was determined empircally,I'm not sure 
%if it could easily be automated) 
mask_thresh = max(rowavg)/3; 
masked = rowavg > mask_thresh; 

%finds the peaks using the values over the threshold (this is sort of like 
%non-maxima suppression) 
potential_peak_idx = find(masked); 
[~,peak_loc] = findpeaks(double(masked)); 

%at this point we assume the two "lines" closest to the bottom of the image 
%are the lines that outline the text 
bot_lin_loc = peak_loc(end); 
top_lin_loc = peak_loc(end-1); 

    %% plots results 
figure(1) 
subplot(2,2,1); imshow(gim); title('bw input image'); 
subplot(2,2,2); imshow(im_background); title('background image'); 
subplot(2,2,3); imshow(im_foreground); title('foreground image'); 
subplot(2,2,4); 
    imshow(im); 
    hold on 
    line([0,im_w],[top_lin_loc, top_lin_loc],'color','g') 
    line([0,im_w],[bot_lin_loc, bot_lin_loc],'color','r') 
    plot(rowavg,(1:1:numel(rowavg)),'color','b') 
    hold off 
    title('annotated image'); 

figure(2) 
plot(rowavg); title('row average') 
hold on 
grid on 
scatter(peak_loc,rowavg(peak_loc)) 
line([0,im_h],[mask_thresh, mask_thresh],'color','g') 
hold off 
legend('rowavg profile','peaks','peak threshold') 

%this is just a large version of subplot 4 
figure(3) 
imshow(im); 
hold on 
line([0,im_w],[top_lin_loc, top_lin_loc],'color','g') 
line([0,im_w],[bot_lin_loc, bot_lin_loc],'color','r') 
plot(rowavg,(1:1:numel(rowavg)),'color','b') 
hold off 
legend('top loc','bot loc','row avg') 
title('annotated image'); 

和图像处理的代码是没有图片一文不值,所以在这里是结果

[subprocesses[1]
rowavg plot annotated results

0

也许尝试在检测边缘之前进一步处理。您可以尝试沿x轴进行投影。这可以通过遍历行并对各行进行求和来完成。 然后,您会在文本和线条所在的位置获得高峰。然后,您可以通过简单地选择线条较薄的峰值来检测线条。