【问题标题】:C# how to read a low quality barcode?C#如何读取低质量的条形码?
【发布时间】:2020-09-09 11:46:43
【问题描述】:

目标:

我的目标是读取质量较差的条码。如果条形码质量最高,则代码可以正常工作。

图片:

代码:

裁剪条码:

    private Point LocationXY;
    private Point LocationX1Y1;

    private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
            LocationXY = e.Location;
    }

    private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
        {
            LocationX1Y1 = e.Location;
            pictureBox1.Invalidate();
        }
    }

    private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
        {
            LocationX1Y1 = e.Location;

            pictureBox1.Invalidate();
            pictureBox2.Invalidate();
        }
    }

    private void pictureBox1_Paint(object sender, PaintEventArgs e)
    {
        Rectangle currentSelection = GetRect();
        if (currentSelection != Rectangle.Empty)
        {
            e.Graphics.DrawRectangle(Pens.Red, currentSelection);
        }
    }

    private void pictureBox2_Paint(object sender, PaintEventArgs e)
    {
        var src = GetRect();

        if (src == Rectangle.Empty) return;

        var des = new Rectangle(0, 0, src.Width, src.Height);

        e.Graphics.DrawImage(pictureBox1.Image,
            des, src, GraphicsUnit.Pixel);
    }

    private Rectangle GetRect()
    {
        return new Rectangle(
            Math.Min(LocationXY.X, LocationX1Y1.X),
            Math.Min(LocationXY.Y, LocationX1Y1.Y),
            Math.Abs(LocationXY.X - LocationX1Y1.X),
            Math.Abs(LocationXY.Y - LocationX1Y1.Y)
            );
    }


    private Bitmap GetCroppedImage()
    {
        var des = GetRect();

        if (des == Rectangle.Empty) return null;

        var b = new Bitmap(des.Width, des.Height);

        using (var g = Graphics.FromImage(b))
        {
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;
            g.SmoothingMode = SmoothingMode.HighQuality;
            g.DrawImage(pictureBox1.Image, new Rectangle(0, 0, des.Width, des.Height), des, GraphicsUnit.Pixel);
        }
        return b;


    }

保存图片并能返回图片的类:

public class BarcodeImage
{
    private static Image _image;

    public static Image _Image
    {
        get
        {
            return _image;
        }
        set
        {
            _image = value;
        }
    }
}

这里我点击一个按钮将图像保存到类并检查条形码:

   private void checkBarcode_Click(object sender, EventArgs e)
    {
        BarcodeImage._Image = GetCroppedImage();

        ZXing.BarcodeReader reader = new ZXing.BarcodeReader();
        var result = reader.Decode((Bitmap)BarcodeImage._Image);
        if (result != null)
        {
            MessageBox.Show(result.ToString());
        }
    }

使用代码:

这里我突出显示条形码并将其保存到picturebox2

接下来点击checkBarcode_Click,它应该会显示条形码值 - 但事实并非如此。因为画质。

我已经用高质量的条形码图像对其进行了测试,效果很好!

问题:

如何提高裁剪图像的质量并将条形码值返回给我?

编辑:2020 年 5 月 29 日

我在这个社区提出了一个新问题,看看我是否可以增加裁剪图像的大小。但这并没有改善任何事情:

https://stackoverflow.com/a/62068397/12485722

高质量条码:

图片是从特定程序中取出来的。

我将图像打印在屏幕上,它们必须是这样的:

但它没有检测到条形码。

这是在程序上使用 2 倍放大的图像:

很遗憾,我无法使用 x2 放大选项,因为某些数据会在图像上移动,无法提供准确的最终图像。最重要的是,条形码被识别!

【问题讨论】:

标签: c# barcode zxing


【解决方案1】:

您在这里看到太多的亚像素数据丢失,无法使用任何软件读取此条码。

条码使用条的相对宽度工作 - 他们非常聪明地知道如何做到这一点,并且有一些容忍空间,但只有少量。

这是您的原始条形码、放大版和可读版:

如果您查看最右边的条与可读条码,您会发现它们的大小不相等 - 它们应该是,但事实并非如此。

只有当原始图像具有足够的分辨率以正确捕获所有条形的相对尺寸时,它才是足够的。

您需要从任何来源获得更好的数据。

编辑:

根据您的 cmets,您说您正在拍摄调酒师标签的打印屏幕 - 您没有理由不能缩放以获得更高分辨率的打印屏幕,但如果您不能,那么您可以将标签打印到文件/图像(例如 PDF)并使用它。

还值得注意的是,BarTender 有一个 .NET API,如果需要,您可以直接与之对话,并且 BarTender 的数据可以导出为 Excel/CSV 格式(假设您将其用作驱动程序条形码输出)。

您还提到您想要检查数据库中是否已经存在条形码 - 您可以改用 API 来执行此操作。

我真的不能告诉你更多,因为我不知道你从什么数据生成标签,或者标签是否都是临时的;但我知道,如果您将图像放大到足以让足够的像素使各个条码条相对于它们的全宽正确呈现 - 这是重要的一点!

【讨论】:

  • 我从没想过——我只是看了一下原始版本的条形码并放大了。与原始版本相比,最后 2 个条形变平了..
  • 因此您可以缩小此条码的大小以防止更改打印时的相对大小...
  • @LeszekMazur 正确 - 但我们已经使用条形码扫描仪测试了标签上所有不同形状和尺寸的标签,它们都被识别出来了。
【解决方案2】:

所以...如果您将获得 x2 缩放图像,将其水平除以 2,然后裁剪条形码,zxing 将为您提供信息!所以你所需要的 - 没有任何扭曲的裁剪。 因此,您完成任务所需要做的就是找到条形码的边界(我认为如果您一直使用相同的格式,它可能是硬编码的)。如果没有 - 很容易扫描图像并通过右下角的黑色像素找到它。

文字版代码:

static void Main(string[] args)
    {
        var barcodeFull = Bitmap.FromFile("barcode-x2-zoomed-dividedx2.jpg");
        var cropFromPoint = new Point(64, 578);
        var cropSize = new Size(360, 142);

        var barcode = CropAtRect((Bitmap)barcodeFull, new Rectangle(cropFromPoint, cropSize));
        ZXing.BarcodeReader reader = new ZXing.BarcodeReader();
        var result = reader.Decode(barcode);
        if (result != null)
        {
            Console.WriteLine("result : "+result.Text);
        }

        Console.ReadLine();
    }

    public static Bitmap CropAtRect(Bitmap b, Rectangle r)
    {
        Bitmap nb = new Bitmap(r.Width, r.Height);
        using (Graphics g = Graphics.FromImage(nb))
        {
            g.DrawImage(b, -r.X, -r.Y);
            return nb;
        }
    }

【讨论】:

    猜你喜欢
    • 2012-01-27
    • 2011-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-03
    • 1970-01-01
    • 2010-12-06
    相关资源
    最近更新 更多