reading a barcode with a webcam

2019-03-16 18:08发布

问题:

Hey,
I'm trying to read a EAN-13 barcode from my webcam.
I already wrote a class to do that work.
I'm taking a picture from my webcam, trimming it to show ONLY the barcode,
and reading the barcode with the code tables from wikipedia.
For some reason, the barcode gets trimmed, but the output is always "0-1-1-1-1-1-1-1-1-1-1-1-1".
I wonder if i did any stupid mistake or misunderstood something?

I do not want to use ANY third-party programs!

this is my code for now:

    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;
    }
}

Sorry for german names in the code!

回答1:

I see two problems:

1) You only scan the top most pixel row of your image (see the second parameter of GetPixel). Your barcode is probably in the middle of the image and not at the top.

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

2) Instead of the green component, you take the alpha component to convert the colored pixel into a binary value. Since the alpha component is probably always 255, you always get 0 unless you have a very dark pixel.

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