检测两条直线之间的区域
Detecting the region between two straight lines
我有 1000 多张图片附在下面。
我只需要从这些图像中提取手写部分。打字区域的大小变化很大,手写部分的大小也变化很大,所以我不能像 img = img(300:1800,200:1600)
那样根据行和列的固定像素值提取
但是手写部分总是在两条直线之间,所以我正在研究的一种解决方案是以某种方式检测图像中的线条,然后提取线条之间的区域。
我尝试按照此处的教程进行操作:http://www.mathworks.com/examples/image/mw/images-ex64995063-detect-lines-in-images-using-hough 使用 hough 变换来检测线条,但我没有得到预期的结果。
我先在原图上试了一下
edg1 = edge(img,'canny');
但是得到了一个非常嘈杂的结果。
所以我尝试将其转换为逻辑,然后再试一次。
img_bw = im2bw(img,graythresh(img));
edg2 = edge(img_bw,'canny');
但即便如此,也没有按预期检测到线条。
我走的路对吗?这是我从文件中提取手写部分的最佳方式吗?
如果是这样,那么我如何确保检测到这些线并获得这些线的坐标。
谢谢
也许在检测边缘之前尝试进一步处理。您可以尝试沿 x 轴进行投影。这可以通过遍历行并对各个行求和来完成。
然后你会在文本和线条所在的位置出现峰值。然后,您可以通过简单地选择线条的较细峰来检测线条。
大部分信息都在代码注释中,但这里有一个简要概述:
我使用形态过滤器做了一些初步的图像清理(我确信高斯过滤器或类似过滤器会证明同样有效)
我的方法是了解如何使用行信息来查找行。考虑采用单列并绘制像素值。这种格式的线条(或任何黑色文本)应该很容易看到。所以我取了整行的平均值并使用该配置文件来帮助找到这些行。由于一条线穿过一行,因此所有值都将很低并产生一个强峰。字符有很多白色 space 所以行平均值应该包含更多的白色像素因此峰值不会那么明确
最后的假设是此配置文件中的两个最大峰(从图像底部开始)应该是线条。
不幸的是,我对两个参数做了一些经验分析(猜测和检查),它们可能需要修改
st_size
用于图像清洗的结构元素的大小。如果所有图像的大小几乎相同,则不需要修改。尽管它不是自动确定的,但这与使用设置大小的平滑滤波器没有什么不同,所以这应该不会导致太多问题
mask_thresh
用于查找峰值的值。这可能会导致其他图像出现问题。标准是低于bot_lin_loc
但高于手写文本部分的峰值。我只是把它设为最大峰值的 1/3 这是算法中最弱的 link,您可能需要更多调整
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');
如果没有图片,图像处理代码就毫无价值,所以这里是结果
[
我有 1000 多张图片附在下面。
我只需要从这些图像中提取手写部分。打字区域的大小变化很大,手写部分的大小也变化很大,所以我不能像 img = img(300:1800,200:1600)
但是手写部分总是在两条直线之间,所以我正在研究的一种解决方案是以某种方式检测图像中的线条,然后提取线条之间的区域。
我尝试按照此处的教程进行操作:http://www.mathworks.com/examples/image/mw/images-ex64995063-detect-lines-in-images-using-hough 使用 hough 变换来检测线条,但我没有得到预期的结果。
我先在原图上试了一下
edg1 = edge(img,'canny');
但是得到了一个非常嘈杂的结果。
所以我尝试将其转换为逻辑,然后再试一次。
img_bw = im2bw(img,graythresh(img));
edg2 = edge(img_bw,'canny');
但即便如此,也没有按预期检测到线条。
我走的路对吗?这是我从文件中提取手写部分的最佳方式吗?
如果是这样,那么我如何确保检测到这些线并获得这些线的坐标。
谢谢
也许在检测边缘之前尝试进一步处理。您可以尝试沿 x 轴进行投影。这可以通过遍历行并对各个行求和来完成。 然后你会在文本和线条所在的位置出现峰值。然后,您可以通过简单地选择线条的较细峰来检测线条。
大部分信息都在代码注释中,但这里有一个简要概述:
我使用形态过滤器做了一些初步的图像清理(我确信高斯过滤器或类似过滤器会证明同样有效)
我的方法是了解如何使用行信息来查找行。考虑采用单列并绘制像素值。这种格式的线条(或任何黑色文本)应该很容易看到。所以我取了整行的平均值并使用该配置文件来帮助找到这些行。由于一条线穿过一行,因此所有值都将很低并产生一个强峰。字符有很多白色 space 所以行平均值应该包含更多的白色像素因此峰值不会那么明确
最后的假设是此配置文件中的两个最大峰(从图像底部开始)应该是线条。
不幸的是,我对两个参数做了一些经验分析(猜测和检查),它们可能需要修改
st_size
用于图像清洗的结构元素的大小。如果所有图像的大小几乎相同,则不需要修改。尽管它不是自动确定的,但这与使用设置大小的平滑滤波器没有什么不同,所以这应该不会导致太多问题mask_thresh
用于查找峰值的值。这可能会导致其他图像出现问题。标准是低于bot_lin_loc
但高于手写文本部分的峰值。我只是把它设为最大峰值的 1/3 这是算法中最弱的 link,您可能需要更多调整
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');
如果没有图片,图像处理代码就毫无价值,所以这里是结果
[