【问题标题】:reading a barcode with a webcam使用网络摄像头读取条形码
【发布时间】:2010-10-06 19:39:00
【问题描述】:

嘿,
我正在尝试从我的网络摄像头读取 EAN-13 条形码。
我已经写了一个类来完成这项工作。
我正在从我的网络摄像头拍照,并对其进行修剪以仅显示条形码,
并使用维基百科的代码表读取条形码。
由于某种原因,条码被修剪,但输出始终为“0-1-1-1-1-1-1-1-1-1-1-1-1”。
我想知道我是否犯了任何愚蠢的错误或误解了什么?

我不想使用任何第三方程序!

这是我现在的代码:

    public class BarcodeDecoder
{
    static string[] ligerade = new string[] { "0100111", "0110011", "0011011", "0100001", "0011101", "0000101", "0010001", "0001001", "0010111" };
    static string[] rechtsgerade = new string[ligerade.Length];
    static string[] liungerade = new string[ligerade.Length];
    static string[] GeradeUG = new string[] { "UUUUUU", "UUGUGG", "UUGGUG", "UUGGGU", "UGUUGG", "UGGUUG", "UGGGUU", "UGUGUG", "UGUGGU", "UGGUGU" };
    static int[] links;
    static int[] rechts;
    static string result;

    public static string Decode(Bitmap b)
    {
        result = "";
        Bitmap bb = CutOutOf(b, b.Height / 2);
        bb = trimBitmap(bb);
        int[] lgs = GetNumberOutOf(bb);
        int[][] rr = trimArray(lgs);
        links = rr[0];
        rechts = rr[1];
        FillArrays();
        BearbeiteLinks();
        BearbeiteRechts();
        return result;
    }
    static void BearbeiteLinks()
    {
        string GU = "";

        string[] zahlen = new string[6];
        zahlen[0] = OutOfArray(links, 0, 7);
        zahlen[1] = OutOfArray(links, 7, 7);
        zahlen[2] = OutOfArray(links, 14, 7);
        zahlen[3] = OutOfArray(links, 21, 7);
        zahlen[4] = OutOfArray(links, 28, 7);
        zahlen[5] = OutOfArray(links, 35, 7);

        foreach (string pq in zahlen)
        {
            bool gerade = ligerade.ToList().IndexOf(pq) > -1;
            if (gerade)
            {
                result += ligerade.ToList().IndexOf(pq).ToString();
                GU += "G";
            }
            else
            {
                result += liungerade.ToList().IndexOf(pq).ToString();
                GU += "U";
            }
        }
        result = GeradeUG.ToList().IndexOf(GU).ToString() + result;
    }
    static void BearbeiteRechts()
    {
        string[] zahlen = new string[6];
        zahlen[0] = OutOfArray(rechts, 0, 7);
        zahlen[1] = OutOfArray(rechts, 7, 7);
        zahlen[2] = OutOfArray(rechts, 14, 7);
        zahlen[3] = OutOfArray(rechts, 21, 7);
        zahlen[4] = OutOfArray(rechts, 28, 7);
        zahlen[5] = OutOfArray(rechts, 35, 7);

        foreach (string pq in zahlen)
        {
            result += rechtsgerade.ToList().IndexOf(pq).ToString();
        }
    }
    static string OutOfArray(int[] ar, int startindex, int length)
    {
        int[] gar = new int[length];
        Array.Copy(ar, startindex, gar, 0, length);
        StringBuilder bilder = new StringBuilder();
        for (int i = 0; i < gar.Length; i++)
        {
            bilder.Append(gar[i].ToString());
        }
        return bilder.ToString();
    }
    static Bitmap trimBitmap(Bitmap b)
    {
        bool alreadyBlack = false;
        int firstblack = 0;

        for (int i = 0; i < b.Width; i++)
        {
            Color gp = b.GetPixel(i, 0);
            if ((gp.R + gp.G + gp.B) / 3 < 128)
            {
                if (!alreadyBlack)
                {
                    alreadyBlack = true;
                    firstblack = i;
                }
            }
        }

        bool alreadyblack = false;
        int lastblack = 0;
        for (int i = b.Width -1; i > 0; i--)
        {
            Color gpp = b.GetPixel(i, 0);
            if ((gpp.R + gpp.G + gpp.B) / 3 < 128)
            {
                if (!alreadyblack)
                {
                    alreadyblack = true;
                    lastblack = i;
                }
            }
        }
        Bitmap result = new Bitmap(lastblack - firstblack, 1);
        for (int i = firstblack; i < lastblack; i++)
        {
            Color c = b.GetPixel(i, 0);
            result.SetPixel(i - firstblack, 0, c);
        }
        result.Save("C:\\result.bmp", System.Drawing.Imaging.ImageFormat.Bmp);
        return result;
    }
    static int[][] trimArray(int[] ar)
    {
        int[][] res = new int[2][];
        int[] resl = new int[6 * 7];
        int[] resr = new int[6 * 7];
        Array.Copy(ar, 2, resl, 0, 6 * 7);
        Array.Copy(ar, 2 + 6 * 7 + 5, resr, 0, 6 * 7);
        res[0] = resl;
        res[1] = resr;
        return res;
    }
    static void FillArrays()
    {
        for (int i = 0; i < ligerade.Length; i++)
        {
            rechtsgerade[i] = string.Concat(ligerade[i].Reverse());
        }
        for (int x = 0; x < liungerade.Length; x++)
        {
            liungerade[x] = Invert(rechtsgerade[x]);
        }
    }
    static string Invert(string xx)
    {
        string xs = "";
        for (int y = 0; y < xx.Length; y++)
        {
            int fd = int.Parse(xx[y].ToString());
            if (fd == 0)
                fd = 1;
            else
                fd = 0;
            xs += fd.ToString();
        }
        return xs;
    }
    static Bitmap CutOutOf(Bitmap b, int y)
    {
        Bitmap res = new Bitmap(b.Width, 1);

        for (int i = 0; i < b.Width; i++)
        {
            Color c = b.GetPixel(i, y);
            res.SetPixel(i, 0, c);
        }
        return res;
    }
    static int[] GetNumberOutOf(Bitmap bb)
    {
        List<int> intlst = new List<int>();
        float f = (float)bb.Width / 95.0f;
        float wd = f / 2.0f;
        for (float i = wd; i < bb.Width; i+=f)
        {
            Color c = bb.GetPixel((int)Math.Round(i,0), 0);
            intlst.Add(GetOutOfColor(c));
        }
        return intlst.ToArray();
    }
    static int GetOutOfColor(Color c)
    {
        if (c.A + c.B + c.R > 128 * 3)
        {
            return 0;
        }
        return 1;
    }
}

对不起,代码中的德国名字!

【问题讨论】:

  • 为什么不一次只调试一种方法?顺便说一句:trimArray 应该有一个类似 trimArray(int[] ar, out int[] res0, out int[] res1) 的签名并且不要经常使用公共静态成员
  • 一切正常,但静态 int[] GetNumerOutOf(Bitmap bb)... 返回垃圾!我不知道为什么。它应该返回一个带有条形码二进制代码的 Array[95]
  • 您确定您的网络摄像头具有足够高的分辨率来提取 EAN13 条形码。您正在使用什么 dpi / 分辨率,因为您需要能够从内存中识别 4 种不同的黑条宽度和 4 种不同的白条宽度。如果您在读取条形码时遇到问题,请尝试提高图像质量/分辨率,看看您是否可以获得正确的结果。
  • 我认为问题与分辨率无关,更多是因为我的网络摄像头没有自动对焦。我总是必须自己集中精力,这并不总是最完美的结果

标签: c# webcam barcode


【解决方案1】:

我看到两个问题:

1) 您只扫描图像最顶部的像素行(参见 GetPixel 的第二个参数)。您的条形码可能位于图像中间,而不是顶部。

Color c = bb.GetPixel((int)Math.Round(i,0), 0);

2) 代替绿色分量,您使用 alpha 分量将彩色像素转换为二进制值。由于 alpha 分量可能始终为 255,因此除非您有一个非常暗的像素,否则您总是得到 0。

if (c.A + c.B + c.R > 128 * 3)

【讨论】:

  • 是的,它是已经剪切的位图中最上面的一行。请参阅 trimBitmap()。第二个想法一点也不差。我试试看
猜你喜欢
  • 2012-02-01
  • 2012-02-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-11
  • 1970-01-01
  • 2015-07-08
  • 2017-04-22
相关资源
最近更新 更多