c# - 从图像中裁剪空白/空空格
问题描述
您好,我有一个扫描仪应用程序,我将扫描的图像返回到位图,然后显示到图片框中。我有一个要求,包括自动裁剪图像并删除空白/空空格。例如,这是我在图片框上向用户展示的图像。
如您所见,扫描的图像是一张小卡片,图像是带有很多空格的全字母纸,我期望的是自动裁剪图像或使用按钮仅向用户显示红色边框部分。
在寻找解决方案时,我看到了一个类似的问题,并尝试使用此答案中的代码,但似乎没有按预期工作。
该代码有什么问题?有没有其他方法可以让我做我想做的事?
这是我尝试过的:
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=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 值,以查看它是否存在。
推荐阅读
- regex - 使用基于日志的指标和正则表达式创建分布指标
- c# - 如何在 AxWindowsMediaPlayer 屏幕上拖放 C#
- sql - 根据条件提取记录
- ios - 如何通过相同的 WI-Fi 连接将 iOS 应用程序中的视频投射到 Android TV 上?
- ios - 使用 UICollectionViewCompositionalLayout 的垂直全屏分页
- php - 显示 3 张卡片后,如何在 php while 循环中创建换行符?
- r - 与我在 R 中的绘图相关的错误消息是什么?
- java - 在 JSON 响应中获取实体而不是其 ID
- javascript - 在 Chrome DevTools 中顺序注入和运行 jQuery
- node.js - 我的网站是否可以在其他网站上执行请求?