【发布时间】:2020-06-24 21:08:10
【问题描述】:
您好,我有一个扫描仪应用程序,我将扫描的图像返回到位图,然后显示到图片框。我有一个要求,包括自动裁剪图像并删除空白/空空格。例如,这是我在图片框上向用户展示的图像。
如您所见,扫描的图像是一张小卡片,图像是带有很多空格的全字母纸,我希望自动裁剪图像或使用按钮仅显示给用户红色边框部分。
在寻找解决方案时,我看到了一个类似的问题,我尝试使用来自 this answer 的代码,但似乎没有像我预期的那样工作。
该代码有什么问题?有没有其他方法可以让我做我想做的事?
这是我尝试过的:
public Bitmap CropImage(Bitmap bitmap)
{
int w = bitmap.Width;
int h = bitmap.Height;
Func<int, bool> IsAllWhiteRow = row =>
{
for (int i = 0; i < w; i++)
{
if (bitmap.GetPixel(i, row).R != 255)
{
return false;
}
}
return true;
};
Func<int, bool> IsAllWhiteColumn = col =>
{
for (int i = 0; i < h; i++)
{
if (bitmap.GetPixel(col, i).R != 255)
{
return false;
}
}
return true;
};
int leftMost = 0;
for (int col = 0; col < w; col++)
{
if (IsAllWhiteColumn(col)) leftMost = col + 1;
else break;
}
int rightMost = w - 1;
for (int col = rightMost; col > 0; col--)
{
if (IsAllWhiteColumn(col)) rightMost = col - 1;
else break;
}
int topMost = 0;
for (int row = 0; row < h; row++)
{
if (IsAllWhiteRow(row)) topMost = row + 1;
else break;
}
int bottomMost = h - 1;
for (int row = bottomMost; row > 0; row--)
{
if (IsAllWhiteRow(row)) bottomMost = row - 1;
else break;
}
if (rightMost == 0 && bottomMost == 0 && leftMost == w && topMost == h)
{
return bitmap;
}
int croppedWidth = rightMost - leftMost + 1;
int croppedHeight = bottomMost - topMost + 1;
try
{
Bitmap target = new Bitmap(croppedWidth, croppedHeight);
using (Graphics g = Graphics.FromImage(target))
{
g.DrawImage(bitmap,
new RectangleF(0, 0, croppedWidth, croppedHeight),
new RectangleF(leftMost, topMost, croppedWidth, croppedHeight),
GraphicsUnit.Pixel);
}
return target;
}
catch (Exception ex)
{
throw new Exception(string.Format("Values are top={0} bottom={1} left={2} right={3}", topMost, bottomMost, leftMost, rightMost), ex);
}
}
【问题讨论】:
-
这里显示的图像是否完全代表您的输入?如果是这样,我可以发现一条黑色边界线,这意味着几乎没有任何行是完全白色的(好吧,或者红色,因为您只检查 R = 255)。也许您需要检查是否 > 95% 的行是白色的?
-
@SeanSkelly 你好,上图是扫描仪返回的真实尺寸,不过黑线和红线是我加的this is the original image
-
谢谢。有趣的是,灰色的“污迹”仍然存在。这对我来说意味着您的图像来自扫描仪并不完美。你有没有遍历这些行以确保它们都是真正的白色,R 值为 255?我想知道扫描仪是否只是返回非常接近白色的像素值,例如值为 254。
-
@SeanSkelly 我知道你在说哪条灰线,但是这条线对我来说不是一个真正的问题,所以即使我没有得到完美的代码,有没有办法让这段代码工作结果,例如与我期望的结果相似 90-95%?我会试试你说的,看看有没有变化
-
是的,例如,您可能应该修改“行或列为白色”的函数,以检查 90-95% 的像素是否在 255 的 90-95% 范围内。看来您的像素数据不是那么“纯”,您可以检查 所有 像素是否为 255。我敢打赌,它们中的大多数甚至不是 255,而是接近它。