在图像上绘制一条水平线,其行对应于最大数量的暗像素
Draw a horizontal line on an image whose row corresponds to the largest count of dark pixels
我想在 MATLAB 中的二值图像上画一条水平线,它具有最大数量的黑色像素。例如这个词:
...我必须找出像素最多的水平线。
我知道我可以打开二进制图像变量编辑器,并绘制一个具有最大零的行,但这似乎不起作用。
我必须像这样为这个词做一个基线:
...作为输出,假设最大像素位于我画线的位置。
纯粹按照您的定义,您想找出具有最多黑色像素的行。只需对每一行的所有列求和并找到最大值。完成后,找到计数最大的行并将此行设置为红色。
想到了这样的事情。我将直接从 Whosebug 读取您的图像,并使用图像处理工具箱来帮助我进行此分析:
%// 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);
第一张图片直接从SO中读入图片,放入MATLAB工作区。下一行将图像阈值化为二进制以使分析更容易。我们还保留了原始图像的副本,以便我们可以用红色标记基线。之后的下一行使用 sum
and sums over every column of each row individually and adds up the black pixels. This is achieved by inverting the binary image so that dark pixels become bright to facilitate the summing. We then use max
找出总和最大的行,这是通过查看 max
的第二个输出来完成的。一旦我们找到这个位置,我们就使用这一行并将这一行中的所有像素设置为红色,或 RGB = (255,0,0)
。
我得到这张图片:
现在上面的代码从左到右画了一条线。如果你想限制这个并且只在有文本的地方画一条红线,也许找到最左边和最右边的暗像素并为它们添加一点呼吸空间,然后画一条线穿过......这样的事情来了记住:
%// 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),然后在其中设置像素线区域变为红色。
我们得到:
现在,您希望找到总和第二高的行并在该行上画另一条线。这样做还不错。然而,这将需要一些 post-processing 因为每个字符的外边缘不是单个像素厚...所以第二高的总和实际上可能仍然给你一个围绕第一个最大值的行。因此,我建议稍微缩小文本,然后再次应用行总和逻辑。您可以使用 morphological binary erosion with a small structuring element... say, a 3 x 3 square. This can be done with imerode
for the erosion and using 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);
如您所见,大部分逻辑都是相同的。我真正改变的唯一一件事是我侵蚀了图像,按降序对行总和进行排序并提取了前两个最高的位置。然后我重复了在这一行中画一条线的逻辑,但现在我们有两行而不是一行。
我们得到:
我想在 MATLAB 中的二值图像上画一条水平线,它具有最大数量的黑色像素。例如这个词:
...我必须找出像素最多的水平线。
我知道我可以打开二进制图像变量编辑器,并绘制一个具有最大零的行,但这似乎不起作用。
我必须像这样为这个词做一个基线:
...作为输出,假设最大像素位于我画线的位置。
纯粹按照您的定义,您想找出具有最多黑色像素的行。只需对每一行的所有列求和并找到最大值。完成后,找到计数最大的行并将此行设置为红色。
想到了这样的事情。我将直接从 Whosebug 读取您的图像,并使用图像处理工具箱来帮助我进行此分析:
%// 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);
第一张图片直接从SO中读入图片,放入MATLAB工作区。下一行将图像阈值化为二进制以使分析更容易。我们还保留了原始图像的副本,以便我们可以用红色标记基线。之后的下一行使用 sum
and sums over every column of each row individually and adds up the black pixels. This is achieved by inverting the binary image so that dark pixels become bright to facilitate the summing. We then use max
找出总和最大的行,这是通过查看 max
的第二个输出来完成的。一旦我们找到这个位置,我们就使用这一行并将这一行中的所有像素设置为红色,或 RGB = (255,0,0)
。
我得到这张图片:
现在上面的代码从左到右画了一条线。如果你想限制这个并且只在有文本的地方画一条红线,也许找到最左边和最右边的暗像素并为它们添加一点呼吸空间,然后画一条线穿过......这样的事情来了记住:
%// 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),然后在其中设置像素线区域变为红色。
我们得到:
现在,您希望找到总和第二高的行并在该行上画另一条线。这样做还不错。然而,这将需要一些 post-processing 因为每个字符的外边缘不是单个像素厚...所以第二高的总和实际上可能仍然给你一个围绕第一个最大值的行。因此,我建议稍微缩小文本,然后再次应用行总和逻辑。您可以使用 morphological binary erosion with a small structuring element... say, a 3 x 3 square. This can be done with imerode
for the erosion and using 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);
如您所见,大部分逻辑都是相同的。我真正改变的唯一一件事是我侵蚀了图像,按降序对行总和进行排序并提取了前两个最高的位置。然后我重复了在这一行中画一条线的逻辑,但现在我们有两行而不是一行。
我们得到: