【问题标题】:Detecting the region between two straight lines检测两条直线之间的区域
【发布时间】:2016-08-13 06:45:01
【问题描述】:

我有 1000 多张下面附上的图片。

我只需要从这些图像中提取手写部分。输入区域的大小变化很大,手写部分的大小也变化很大,所以我不能像 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');

但得到的结果非常嘈杂。

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

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

但即便如此,也没有按预期检测到线条。

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

如果是这样,那么如何确保检测到线条并获得这些线条的坐标。

谢谢

【问题讨论】:

    标签: image matlab image-processing image-segmentation


    【解决方案1】:

    大部分信息都在代码 cmets 中,但这里是一个简短的大纲:

    我使用形态过滤器做了一些初步的图像清理(我确信高斯过滤器或类似的过滤器会证明同样有效)

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

    最后的假设是这个轮廓中两个最大的峰(从图像底部开始)应该是线条。

    不幸的是,我对两个参数进行了一些实证分析(猜测和检查),它们可能需要修改

    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');
    

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

    [

    【讨论】:

      【解决方案2】:

      也许在检测边缘之前尝试进一步处理。您可以尝试沿 x 轴进行投影。这可以通过遍历行并沿各个行求和来完成。 然后你会得到文本和线条所在的峰值。然后,您只需选择线条中较细的峰即可检测线条。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-09-23
        • 1970-01-01
        • 1970-01-01
        • 2020-07-12
        • 2023-03-22
        • 2021-08-14
        • 2017-11-09
        • 2020-06-16
        相关资源
        最近更新 更多