繁体   English   中英

如何判断图像是否包含“手写签名”?

[英]How to tell if an image contains a “handwritten signature”?

我有一个被扫描成TIF格式(黑/白)的表格(在表格的右下角画有一条线)。

有些人可能会在表格上签名,有些人不会。 那么,如何确定扫描的图像上是否包含签名? 建议的任何算法或任何现有的框架或库都可以实现这一目标?

谢谢!

您可以对图像进行阈值处理(将其转换为黑白图像),并总结出框区域内有多少个黑色像素。 您可以使用填充像素数的百分比作为基本测试,以了解签名字段的“绘制”程度。 这样做的缺点是,在定义阈值时,如果阈值过高,您可能会错过较浅的签名,或者将空白框误认为是填充的(过低)。 另外,所用笔的颜色是要考虑的因素。 但是,我们很幸运在此应用程序中,因为纯白框和手写体之间的鲜明对比将对我们有利。

一种类似的方法可以使用互相关来计算空白签名框与应该签名的空白框之间的差异,以获取两者之间的差异值。 与未签名的框相比,已签名的框可能会有更大的错误。

您可能已经熟悉光学字符识别(OCR),这是一种机器视觉的方法,它可以使计算机有意义地解释符号,但是用人工手写很难做到,因为这需要对系统进行“培训”,因为手写可能会发生变化非常。 人们喜欢用自己的签名制作风格的喇叭,使这一问题更加恶化。 但是,由于您实际上不需要在软件中注册签名的每个单个字符,因此这种方法可能会过大。

您还可以使用形态学(形状变化)技术,例如扩张,腐蚀或打开和关闭,以扩大签名框中的区域强度。 我们不必担心变形数据的形状,因为我们只在乎它们是否存在。 然后,您可以使用斑点计数来查看是否在边界内检测到了足够的量。

您应该尝试使用开放的图像处理工具箱(例如ImageJ)尝试使用可用的不同方法,该工具箱已预先打包了一些高级工具,您可以利用这些工具确定最佳的显示方式。 唯一的限制就是您的创造力!

这是我过去用于检查签名的代码。 假定图像的Bytes per pixel为3。

MAX_BLACK_VALUE数字来自像素颜色(255)的最大值乘以3(因为每个像素3个字节),然后减半。

该代码通过对签名图像中的像素数量进行求和来工作,如果该代码通过了MinPixelCount返回true,即已检测到签名。 否则它将返回false。

该代码还利用Lockbits一种方法来使图像处理更快,如果java具有类似的方法,只需确保始终像我在finally语句中一样调用UnlockBits

private const int MAX_BLACK_VALUE = 382; // ((255 * 3) / 2) rounded down

private bool CheckForSignature(string SignatureFile, int MinPixelCount)
{
    using (Bitmap bitmap = new Bitmap(SignatureFile))
    {
        int nBytesPerPixel = Bitmap.GetPixelFormatSize(bitmap.PixelFormat) / 8;
        System.Drawing.Imaging.BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, bitmap.PixelFormat);
        try
        {
            byte[] baPixels = new byte[bitmapData.Stride * bitmap.Height];
            System.Runtime.InteropServices.Marshal.Copy(bitmapData.Scan0, baPixels, 0, baPixels.Length);

            int nBlackPixels = 0;
            for (int h = 0; h < bitmap.Height; h++)
            {
                int nCurrentLine = h * bitmapData.Stride;
                for (int w = 0; w < (bitmap.Width * nBytesPerPixel); w += nBytesPerPixel)
                {
                    int nBlue = baPixels[nCurrentLine + w];
                    int nGreen = baPixels[nCurrentLine + w + 1];
                    int nRed = baPixels[nCurrentLine + w + 2];

                    if (nBlue + nGreen + nRed <= MAX_BLACK_VALUE)
                    {
                        nBlackPixels++;
                        if (nBlackPixels >= MinPixelCount)
                            return true;
                    }
                }
            }
        }
        finally
        {
            bitmap.UnlockBits(bitmapData);
        }
    }

    return false;
}

ps我意识到这是一个java问题,但是我只知道C#但是您应该可以将其转换。

我来看看OpenCV

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM