计算机视觉:如何通过熵最小的线将图像水平分割?

9
我有一张图片,其中有一些非白色(例如段落但不涉及OCR)的区域。这些区域之间的空隙有点规律,人们看到这张图像时能够看到这些区域之间有白色空隙。
我的计划是找到所有区域的顶部和底部角落,从底部角落开始到下一个区域的顶部角落,获取每个水平线的熵,选取熵最低的那条线,并返回该线的Y位置。 enter image description here
[region] <--- maximum corner coordinates identified
[line with lowest entropy] <--- return Y position starting from above region's bottom corner's Y coordinate.
[region]<--- stop at Y coordinate of this region's top corner.

我打算做的是裁剪这些区域。

另一种方法是使用直方图来识别最低点,并找到该最低柱的位置。


如果您能展示一个示例图片,那将非常好,这样我们就可以更好地帮助您。 - Tae-Sung Shin
乐谱将是这个的完美例子。 - KJW
为什么需要计算熵?你的目标是仅提取非白色区域吗?你正在使用哪种编程语言? - FvD
Python,SimpleCV实际上。目标是提取这些区域,有时这些区域之间的空格会有交叉的文本,因此我唯一能告诉白色空格线的方法是获取告诉我该行有多混乱的值。 - KJW
我会使用Imagemagick的liquidRescaleImage(height,width,0,25)来缩小它,避免所有编码方面的麻烦。 - Alvin K.
1个回答

4
我不确定这是否是您要找的内容(我不确定您要找什么),如果我错了,请写更多细节,我会尝试更新我的答案。现在我认为您正在寻找白色区域,这些区域最适合用于分割纸张,因为您不想切到任何重要的东西。
最简单的实现方法是计算每行和下一行的总和,并检查这些值之间的差是否为0(或其他小值)。以下是一个简单的代码:
Mat m = imread(pathToFile);
cvtColor(m, m, CV_BGR2GRAY); //just to make sure
for (int i = 0; i < m.rows - 1; i++)
{
    Scalar s = sum(Mat(m, Rect(0, i, m.cols - 1, 1)));
    Scalar s2 = sum(Mat(m, Rect(0, i + 1, m.cols - 1, 1)));
    Scalar s3 = s - s2;
    if ((int)s3[0] == 0)
        printf("Empty line: %d\n", i);
}

实际上,您还应该检查此行是否为白色,或者您可能只是找到了两条非常相似的非白色线 - 因此只需将一些测试添加到此代码中,例如if ((int)s [0] < someValue) {//it's ok} else {//it's bad}。当然,这不是很有效的解决方案,因为您必须计算每行(几乎每行)两次的总和,这是浪费时间。更快的解决方案是在变量中记住行的总和,甚至可以将所有总和放在向量/数组等中以便以后使用。
最有效的计算方法可能是使用积分图像 - 计算整个图像的总和,然后从i+1行的最后一个元素中减去i行的最后一个元素。当然,积分图像已在openCV中实现 - 请参见此处

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接