在图像上绘制一条水平线,其行对应于最大的暗像素数

时间:2015-09-24 04:47:30

标签: image matlab image-processing line

我想在MATLAB中的二进制图像上绘制一条水平线,它具有最大的黑色像素。所以在这个词中例如:

...我必须识别大多数像素的水平线。

据我所知,我可以打开二进制图像变量编辑器,并绘制一个最大零的行,但这似乎不起作用。

我必须像这样写下这个词的基线:

...作为输出,假设最大像素位于我画线的位置。

1 个答案:

答案 0 :(得分:2)

Purely going by your definition, you want to figure out the row that has the largest amount of black pixels. Simply sum over all columns of each row and find the maximum. Then when you're done, locate the row with the largest count and set this line to red.

Something like this comes to mind. I'm going to read your image from StackOverflow directly and am going to use the image processing toolbox to help me with this analysis:

%// Read image from SO
im = imread('http://s15.postimg.org/cwg2sxnwr/mathworksss.png');

%// Keep a copy of a binary version
im_bw = im2bw(im);

%// Sum over all of the columns and look for dark pixels
row_sums = sum(~im_bw, 2);

%// Find row with max sum
[~,row_max] = max(row_sums);

%// Draw a red line through the original image as it's in RGB
im(row_max,:,1) = 255;
im(row_max,:,2:3) = 0;

%// Show the image
imshow(im);

The first image reads in the image directly from SO and puts it into the MATLAB workspace. The next line thresholds the image to binary to allow the analysis to be easier. We also keep a copy of the original image so we can mark the baseline with red. The next line after that uses sum内添加图像地图区域,并分别对每行的每一列求和,并将黑色像素相加。这是通过反转二进制图像来实现的,以便暗像素变亮以便于求和。然后,我们使用max找出具有最大总和的行,并通过查看max的第二个输出来完成。找到此位置后,我们会使用此行并将此行中的所有像素设置为红色,或RGB = (255,0,0)

我得到这张图片:

enter image description here

现在上面的代码从左到右绘制一条线。如果你想限制这个并且只在有文字的地方画一条红线,也许找到最左边和最右边的黑暗像素并给它们增加一点呼吸空间,然后划一条直线......就像这样来了记住:

%// Read image from SO
im = imread('http://s15.postimg.org/cwg2sxnwr/mathworksss.png');

%// Keep a copy of a binary version
im_bw = im2bw(im);

%// Sum over all of the columns and look for dark pixels
row_sums = sum(~im_bw, 2);

%// Find row with max sum
[~,row_max] = max(row_sums);

%// Find left most and right most black columns
[~,left_most] = find(~im_bw,1,'first');
[~,right_most] = find(~im_bw,1,'last');

%// Buffer for drawing the line before the first and after the last column
buf = 20;

%// Draw the line
im(row_max,left_most-buf:right_most+buf,1) = 255;
im(row_max,left_most-buf:right_most+buf,2:3) = 0;

%// Show the image
imshow(im);

正如您所看到的,大多数代码保持不变(在图像中读取,阈值处理,列求和和max)但最后,我使用find来查找第一个和最后一个相对于列的黑色像素的实例。然后我使用前面找到的相同最大行的这些列,然后减去最左边的黑色列像素位置,并按缓冲量添加最右边的黑色列像素位置(我在这里选择了20),然后在此范围内设置像素线区域变为红色。

我们得到:

enter image description here

现在,您希望找到具有第二高总和的行,并在该行中绘制另一条线。这样做并不坏。但是,这将需要一些后处理,因为每个字符的外边缘不是单个像素厚...所以第二个最高的总和实际上仍然可以给你一个大约第一个最大值的行。因此,我建议稍微缩小文本,然后再次应用行和逻辑。您可以使用morphological binary erosion和一个小的结构元素来执行此操作...例如,一个3 x 3的正方形。这可以使用imerode进行侵蚀,并使用strel指定方形结构元素。

您将行和逻辑应用于此新图像,但随后使用这些结果并在原始图像上绘制。你不想对这个新图像进行操作,因为看起来文本的某些区域是单像素厚的,这些区域在侵蚀后会被消除。

想到这样的事情:

%// Read image from SO
im = imread('http://s15.postimg.org/cwg2sxnwr/mathworksss.png');

%// Keep a copy of a binary version - also invert for ease
im_bw = ~im2bw(im);

%// Slightly erode the text
im_bw = imerode(im_bw, strel('square', 3));

%// Sum over all of the columns and look for dark pixels
row_sums = sum(im_bw, 2);

%// Sort the column sums in descending order and figure out the two highest sums
[~,ind_sort] = sort(row_sums,'descend');

%// First highest sum is the bottom - mark as red
red_row1 = ind_sort(1);

%// Second highest sum is the middle - mark as red too
red_row2 = ind_sort(2);

%// Find left most and right most black columns
[~,left_most] = find(im_bw,1,'first');
[~,right_most] = find(im_bw,1,'last');

%// Buffer for drawing the line before the first and after the last column
buf = 20;

%// Draw the two red lines
im(red_row1,left_most-buf:right_most+buf,1) = 255;
im(red_row1,left_most-buf:right_most+buf,2:3) = 0;

im(red_row2,left_most-buf:right_most+buf,1) = 255;
im(red_row2,left_most-buf:right_most+buf,2:3) = 0;

%// Show the image
imshow(im);

如您所见,大多数逻辑是相同的。我唯一真正改变的是我侵蚀了图像,按降序排列行总和并提取了最高的前两个位置。然后我重复逻辑在行中绘制一条线,但是现在我们有两行而不是一行。

我们得到:

enter image description here