您好,我有一个扫描仪应用程序,我将扫描的图像返回到位图中,然后显示在图片框中。我有一个要求,其中包括自动裁剪图像并删除空白/空空白。例如,这是我在图片框上显示给用户的图像。
如您所见,扫描的图像是一张小卡片,并且图像是带有很多空格的全字母包装纸,我希望是自动裁剪图像或使用仅向用户显示按钮的图像红色边框。
在寻找解决方案时,我遇到了类似的问题,并尝试使用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);
}
}
答案 0 :(得分:0)
如果在白色区域(R = G = B = 255)中的图像不是真正的“纯白色”,我建议将IsAllWhiteRow的功能修改为类似以下内容:
int thresholdValue = 250;
double percentAllowedBelowThreshold = 0.95;
Func<int, bool> IsAllWhiteRow = row =>
{
int numberPixelsBelowThreshold = 0;
for (int i = 0; i < w; i++)
{
if (bitmap.GetPixel(i, row).R < thresholdValue)
{
numberPixelsBelowThreshold++;
}
}
return (numberPixelsBelowThreshold / w) > percentAllowedBelowThreshold;
};
然后对列执行类似的操作。 您可能需要更改阈值,具体取决于图像输入。例如,如果图像的真实部分中有很多白色,则可能需要0.98或更高的阈值!另外,此代码未经过优化等。
您还需要逐步浏览图像,以查看我为250选择的值是否合理;我还没有查看位图的“白色”区域中的实际RGB值,以查看是否为真。