詳細なQRコード(下)

オリジナル: QRコード説明(下)

高速応答コード(下)

ブックは、後半に継続するために、背面に接続されています。

誤り訂正符号

シンボルが破損した場合に回収することができるように、誤り訂正アルゴリズムの誤り訂正符号語を使用して生成されたQRコード系列は、データコード語列の後に追加されます。彼らは欠陥がある場合でも、2次元コードを掃き出すことができる理由です。任意の欠陥がなければ、我々はまた、不完全な作成、それを一掃する必要があり、私たちは、二次元バーコードの中間のベルトアイコンをたくさん見てきたと信じています。

誤り訂正符号語は、(エラーコードワードの位置が未知である)の両方エラーの種類、NOREADエラー(エラーコードワードの位置が知られている)と代替誤差を補正することができます。NOREAD間違いがない記号文字を解読するスキャンまたはない、記号文字置換エラーはコーディング間違っています。欠陥のあるモジュールはとても暗い光モジュールになったときに、モジュールが暗い又は光モジュールであり、記号文字が誤って置換誤差を生じる、異なるコードワードにデコードされ、エラーようなデータは代替を必要とします2つのエラー訂正コード語を訂正します。

誤り訂正レベル

誤り訂正は、以下の表に示す4種類に対応した誤り訂正能力の4つのレベルがあります。

誤り訂正レベル L M Q H
誤り訂正能力、%(概算) 7 15 25 30

ユーザーがアプリケーションの要件を満たすために、エラー訂正の適切なレベルを決定する必要があります。四つの異なるレベルを提供するために、LからHへの容量検出と訂正は徐々にデータシンボル長徐々に増加を示す所定のサイズのコストで増加されます。例えば、20-Qシンボルデータのバージョンは、符号語485、誤り訂正がより低いレベルを受け入れることができる場合、同じデータはまた、バージョン15-Lシンボリック表現(523ヤードの正確なデータ容量であってもよい含むことができ言葉)。

以下の要因に関連した誤り訂正レベルを選択します。

  1. 品質レベルが署名することが期待されています。記号は、品質等級を下げることが予想され、高い誤り訂正レベルが適用されるべきです。
  2. 第1の読取率の重要性。
  3. 誤読をスキャンした後、再びチャンスをスキャンできませんでした。
  4. スペースは、印刷されたシンボルより高い誤り訂正レベルの使用を制限します。

[L]レベルの誤り訂正符号は、シンボルが必要なデータが可能な限り最小の場合を与えていることを示し、および/またはそれに適した品質を有します。[M]レベルが「標準」レベルであると考えられる、より小さなサイズ及びより高い信頼性を有します。[Q]はいくつかの重要な相違点シンボル印刷品質やケースに適用学年「高信頼性」を有する、最も高い信頼性を提供するために、[H]レベルを達成することができます。

生成されたエラー訂正コードワード

:リードソロモン符号に関連するリードソロモン符号QRコードを用いた誤り訂正は、あなたはこの記事を参照することができhttp://article.iotxfd.cn/RFID/Reed%20Solomon%20Codesここで私は唯一の計算プロセスの概要を説明することができます。

誤り訂正コード語の生成多項式

誤り訂正符号語の誤り訂正符号は、データ符号語に加えて得られた剰余多項式です。エラー訂正機能のQRコードシンボルのバージョン:私たちがルックアップすることができますテーブルが来誤り訂正符号多項式は、まず以下の表3をご確認ください。ここで私はテーブルGB / T 18284から2000表9を参照してください。完全なデータのほんの一部をリストアップ。

表3:誤り訂正特性の各バージョンのQRコードシンボル

前記(C、K、R):C =コードワードの総数であり、k =データコードワード; R =誤り訂正能力。

[1]実施例1は、誤り訂正符号語を得るために、バージョン1-H、ルックアップテーブルを用いて決定継続する前に:17(表フレーム部分を赤)。コードワード26の総数は、QRコードのバージョンを収容することができる総データ量を示す符号語9を表す前記データ、17誤り訂正符号語アカウント。そして、多項式を見つけるために、誤り訂正コード語17に従って。GB / T 18284-2000検索の付録Aの生成多項式、誤り訂正符号語テーブルとすることができる、使用してもよい多項式工具生成するためにそれを作成するために、表4だけ小さい部分に記載されています。

表4:誤り訂正特性の各バージョンのQRコードシンボル

C#でのリード・ソロモン符号

あなたはどのようにああ除いて、この多項式で、以前に生成されたエラー訂正コード語を頼むかもしれませんか?直接添加は、確かに最初の多項式で発見されるすべての数字の対応するセットに変換できません。[1、119、66、83、120、119、22、197、83、249、41、143、134、85、53、125、99、79:テーブルに生成多項式に対応する17に変換することができます]。これは、デジタルデータのコードワードの残りのセットは、誤り訂正符号の私達の言葉で除したものです。もちろん、このプロセスが完了するまでにプログラムを使用しています。リードソロモン符号化この記事では、この機能を実現するためのPythonを使用する方法を詳細に説明しています。私はC#に変換されたコードを使用する必要があります。

using System;

namespace QRHelper
{
    class ECC
    {
        const int PRIM = 0x11d;

        private static byte[] gfExp = new byte[512]; //逆对数(指数)表
        private static byte[] gfLog = new byte[256]; //对数表

        static ECC()
        {
            byte x = 1;
            for (int i = 0; i <= 255; i++)
            {
                gfExp[i] = x;
                gfLog[x] = (byte)i;
                x = Gf_MultNoLUT(x, 2);
            }

            for (int i = 255; i < 512; i++)
            {
                gfExp[i] = gfExp[i - 255];
            }
        }

        //伽罗华域乘法
        private static byte Gf_MultNoLUT(int x, int y)
        {
            int r = 0;
            while (y != 0)
            {
                if ((y & 1) != 0)
                {
                    r ^= x;
                }
                y >>= 1;
                x <<= 1;
                if ((x & 256) != 0)
                {
                    x ^= PRIM;
                }
            }
            return (byte)r;
        }

        //伽罗华域乘法
        private static byte GfMul(byte x, byte y)
        {
            if (x == 0 || y == 0)
            {
                return 0;
            }
            return gfExp[gfLog[x] + gfLog[y]];
        }

        //伽罗华域幂
        private static byte GfPow(byte x, int power)
        {
            return gfExp[(gfLog[x] * power) % 255];
        }

        //多项式 乘法
        private static byte[] GfPolyMul(byte[] p, byte[] q)
        {
            byte[] r = new byte[p.Length + q.Length - 1];
            for (int j = 0; j < q.Length; j++)
            {
                for (int i = 0; i < p.Length; i++)
                {
                    r[i + j] ^= GfMul(p[i], q[j]);
                }
            }
            return r;
        }

        /// <summary>
        /// 获取纠错码字的生成多项式
        /// </summary>
        /// <param name="nsym">纠错码字数</param>
        /// <returns>由一组数字表示的生成多项式</returns>
        public static byte[] RsGeneratorPoly(int nsym)
        {
            byte[] g = { 1 };
            for (int i = 0; i < nsym; i++)
            {
                g = GfPolyMul(g, new byte[] { 1, GfPow(2, i) });
            }
            return g;
        }

        /// <summary>
        /// 生成纠错码,并添加在数据码字之后
        /// </summary>
        /// <param name="msgIn">数据码字</param>
        /// <param name="nsym">纠错码字数</param>
        /// <returns>数据码字+纠错码字</returns>
        public static byte[] RsEncodeMsg(byte[] msgIn, int nsym)
        {
            if (msgIn.Length + nsym > 255)
            {
                throw new ArgumentException("数组长度超过 255!");
            }
            //byte[] gen = generators[(byte)nsym];
            byte[] gen = RsGeneratorPoly(nsym);
            byte[] msgOut = new byte[msgIn.Length + gen.Length - 1];
            Array.Copy(msgIn, 0, msgOut, 0, msgIn.Length);

            for (int i = 0; i < msgIn.Length; i++)
            {
                byte coef = msgOut[i];
                if (coef != 0)
                {
                    for (int j = 1; j < gen.Length; j++)
                    {
                        msgOut[i + j] ^= GfMul(gen[j], coef);
                    }
                }
            }
            Array.Copy(msgIn, 0, msgOut, 0, msgIn.Length);

            return msgOut;
        }
    }
}

コードの量が非常に小さいああです!アルゴリズムパッケージなしでインターネットをサーフィンすることよります。あなたはQRコードを大量に描画する必要がある場合は、実際の開発では、全31生成多項式がコレクションに格納され、変換結果することができ完了する、大幅に生産速度をスピードアップすることができ、直接クエリを導出することができます。上記のコードRsGeneratorPoly()生成多項式のための方法、それは大規模な一時的な配列を生成します。コードでは、私たちは私たちの前の例を続けることができます。

[実施例2] 1続く:完全なコードワードを生成します

前の例1は、我々はデータコード語を生成した継続的な[1]:
00010000,00100000,00001100,01010110,01100001,10000000,11101100,00010001,11101100

進表現として:0x10を、0x20に、0x0Cの、0x56、の0x61、0x80を、0xEC、0x11を、0xEC

その後、完全なコードワードを生成するために、次のコードを使用します。

byte[] msgin = { 0x10, 0x20, 0x0C, 0x56, 0x61, 0x80, 0xEC, 0x11, 0xEC };
byte[] msg = ECC.RsEncodeMsg(msgin, 17);

結果を取得します:0x10を0x20に0x0Cの0x56の0x61 0x80の0xEC 0x11を0xEC 0x0Eの0x9D 0x02の0xC8に0xC2 0x94 0xF3 0xA7 0xADの0x8D 0x0Aの0xE2 0xF4 0xA5の0x2Bを0xACの0xDF

そして、我々はすべてのQRコードパターンに26ヤードの単語を埋めるために持っていること。最初の9つのコードワードのデータは、17誤り訂正符号語の後に、プログラムが自動的に、より良い接続するために私たちを支援してきました。

最終的な符号系列構成情報

実施形態では、単にデータコードワードの誤り訂正符号語を連結する唯一の補正のブロック数は、へデータを形成するように接続されています。大部分のバージョンでは、誤り訂正コードブロック数が複数存在します。以下は、構成オフエラー訂正コードブロックの複数の説明図です。

実施例5-Hのバージョンでは、ルックアップテーブル部5のバージョン3は、次の通り:

バージョン5-Hコードワードは、ワードの総数は2ヤード33、11はデータコードワードと誤り訂正符号語22を含む、請求項4に分割され、他の2ヤードをワード34の総数を、データを含む12 22コードワードと誤り訂正符号語。データの最初の11個のコードワードは、最初のデータコードワード、計算の誤り訂正符号語22が除去され、データ・ブロックを形成するように接続され、次いで、データ生成部2符号語から11の符号語を取ることは、コードワードからデータをフェッチし続けます12コードワードデータ生成部3は、データの最後の12個のコードワードを取り出し、データ生成部4れます。

文字のテーブルにおける各ブロックは、テーブルの各行は(DNとして示される)コードワード・データ・ブロックと対応するブロックの(JAとして表される)誤り訂正符号語に対応する、配置しました。

:符号語系列のシンボルの最終バージョンは、5-Hで
のDI、D12、D23、D35、D13、D24、D36、... D11、D22、D33、D45、D34、D46、のD2、E1、E23 ,, E45、E67 、E2、E24、E46、E68 、E22 ...、E44、E66、E88。モジュールのコード領域の残りのビット数を満たすために必要ないくつかのバージョン、3、4または7において、この時間は、最後のコードワードプラス残りのビット(0)の背後にすることができます。

フォーマット情報

誤り訂正符号の構成指標2 + 3 +基準マスクパターン10によって、店舗情報、誤り訂正レベルとマスク情報、データ15、誤り訂正に使用される形式。

計算されたフォーマット情報

第1の誤り訂正インジケータは、それぞれ以下の表5にデジタル誤り訂正レベルに対応し、2ビットで表されます。

誤り訂正レベル L M Q H
バイナリインジケータ 01 00 11 10
表5:エラー訂正レベル・インジケータ

後資料のマスクバイナリ3ビットに変換することができる0から7までの数で表される3ビットを使用して、基準マスクパターンは、今知っているライン上の3ビットを占有する必要があります。

将 2位纠错指示符 + 3位掩模图形参考,得到 5 位数据码,并使用 BCH(15,5) 编码计算得到纠错码。

BCH 码

BCH 码和 Reed–Solomon 码类似,可以参考 Reed–Solomon 编码这篇文章。Reed–Solomon 码使用多项式除法得出纠错码序列,而 BCH 码就简单得多,它按位运算得出纠错码。BCH(15,5) 表示 BCH 码总长度为 15 位,其中数据码为 5 位,纠错码 10 位。Reed–Solomon 码有生成多项式,BCH 码使用的是生成码:10100110111。使用数据码除以生成码,所得余数就是纠错码。由于 BCH 码的运算很简单,下面演示数据码 00101 的演算过程。

  1. 将数据码左移 10 位,凑够 15 位,得到二进制数字:001010000000000
  2. 将上面数字除以 10100110111(0x537),使用长除法,如下图所示:

上图中的余数取 10 位即为纠错码:0011011100

  1. 将 5 位数据码 00101 与纠错码相连,即得到最终格式信息码:001010011011100(0x14DC)

使用程序实现非常简单,在ECC类中添加如下代码:

 //生成 BCH 码
private static int CheckFormat(int fmt)
{
    int g = 0x537;
    for (int i = 4; i >= 0; i--)
    {
        if ((fmt & (1 << (i + 10))) != 0)
        {
            fmt ^= g << i;
        }
    }
    return fmt;
}

/// <summary>
/// 生成 BCH(15,5) 纠错码,并返回完整格式信息码
/// </summary>
/// <param name="data">数据码</param>
/// <returns>返回完整格式信息码</returns>
public static int BCH_15_To_5_Encode(int data)
{
    data <<= 10;
    return data ^ CheckFormat(data);
}

使用以下代码生成完整格式信息码:

int code = ECC.BCH_15_To_5_Encode(5);

结果为:5340(0x14DC)

格式信息的掩模

为确保纠错等级和掩模图形参考(稍后介绍)合在一起的结果不全是 0,需将 15 位格式信息与掩模图形 101010000010010(0x5412)进行异或运算。

格式信息的绘制

QR 码中有专门的区域绘制格式信息,见下图:

由于格式信息的正确译码对整个符号的译至关重要,它会在 QR 码中绘制两次以提供冗余。格式信息的最低位模块编号为 0,最高位编号为 14。为避免混淆,下表标示了之前生成格式信息与掩模图形以及两者进行 XOR 运算之后的结果的各个位编号。

左上角绘制区域编号 8、9 之间和 5、6 之间的深色模块被定位图形使用,不用于绘制格式信息。左下角编号 8 上的 Dark Module 永远为深色模块,不用于存放任何信息。

接下来我们将 XOR 后的结果绘制到 QR 码中的格式信息区域,如下图所示:

图中绿色区域为格式信息区域,其中浅绿色表示浅色模块,深绿色表示深色模块。

【例 1 续 3】:生成格式信息

接下来我继续【例 1】,添加格式信息:

  1. 之前【例 1】中我们选择了纠错等级为 H,查表 5,得到数字:10
  2. 假设我们选择的掩模图形参考为 011,则最终数据码为:10011
  3. 使用之前的程序将 10011 生成完整格式信息码:100110111000010(0x4DC2)
  4. 将生成的格式信息码与 101010000010010(0x5412)进行异或运算,结果为:
    001100111010000(0x19D0)
  5. 将结果绘制到格式信息区域中,最终结果如下图所示:

版本信息

版本信息用于存放 QR 码的版本号。其中,6 位数据位,12 位通过 BCH(18,6) 编码计算出的纠错位。只有版本 7~40 的符号包含版本信息。版本 0~6 无需绘制版本号。

版本信息的计算

版本信息的计算和格式信息类似,也是使用长除法。只是这一次使用的生成码为:1111100100101(0x1F25)。以下为 BCH(18,6) 的 C# 代码:

public static int BCH_18_6_Encode(int data)
{
    int g = 0x1F25;
    int fmt = data << 12;
    for (int i = 5; i >= 0; i--)
    {
        if ((fmt & (1 << (i + 12))) != 0)
        {
            fmt ^= g << i;
        }
    }
    return (data << 12) ^ fmt;
}

下面以版本号 7 为例,计算版本信息码:

  1. 版本号 7 转换为 6 位二进制数据码:000111
  2. 将以上数据码左移 12 位,凑够 18 位:000111000000000000
  3. 将上面数字除以生成码 1111100100101(0x1F25),得到余数:110010010100
  4. 将数据码与得到的余数相连,得到最终版本信息码:000111110010010100

与格式信息不同,版本信息码生成后不再需要单独进行掩模运算。

版本信息的绘制

由于版本信息的正确译码是整个符号正确译码的关键,因此版本信息在符号中出现两次以提供冗余。第一个存放位置在定位图形上面,由6行×3列模块组成,其右紧临右上角位置探测图形的分隔符;第二个存放位置在定位图形左侧,其下边紧临左下角位置探测图形的分隔符,如下图的蓝色部分所示:

格式信息的最低位模块编号为 0,最高位编号为 17。接下来我们将之前计算的版本 7 的版本信息码绘制到 QR 码中的版本信息区域。效果如下图所示,红色部分为版本信息,其中,深红色代表深色模块,粉红色代表浅色模块。:

至此,所有功能图形以及格式图形都已经绘制完毕,并已全部显示在这上图中。接下来,终于可以开始绘制数据码字了。

符号字符的布置

在 QR 码符号的编码区域中,符号字符以 2 个模块宽的纵列从符号右下角开始布置,并自右向左,且交替地从下向上或从上向下安排。GB/T 18284-2000 用了很长一段篇幅讲解编码布置规则,其实很简单,就是以两列为单位向上或向下布置,列内蛇形走位,遇障碍跳过。为方便大家学习,我在《QR助手程序》中加入了绘制走位路线的功能,下图是版本1和版本7的走位路线:

这飘忽不定的神仙步伐,销魂啊!从右下角开始,延着一条不中断的线一直到左下角结束,将最终数据码流从左到右,按这条线的方向布置在沿途遇到的粉红色模块中,即完成符号字符的布置。相信大家一眼就能看懂。我之所以要实现这个走位路线的绘制功能,一方面是手绘这两张图太痛苦了,另一方面也是为了方便验证走位算法是否存在错误。

【例 1 续 4】:布置符号字符

【例 1 续 2】中我们生成了最终的数据码字为:
0x10 0x20 0x0C 0x56 0x61 0x80 0xEC 0x11 0xEC 0x0E 0x9D 0x02 0xC8 0xC2 0x94 0xF3 0xA7 0xAD 0x8D 0xE2 0x0A 0xF4 0xA5 0x2B 0xAC 0xDF

现在终于可以将其依照之前的路线填入编码区域中了。效果如下图所示:

图中粉红色模块就是我们刚才填入的数据。终于可以庆祝一下了,放松一下可以,但不能端酒!事情还没完!

掩模

QR 码中如果出现大面积的空白或黑块,会导致扫描器识别困难。为了让 QR 图形看起来尽可能凌乱,且尽可能避免位置探测图形中的位图 1011101 的出现,需对 QR 图形进行掩模操作,步骤如下:

  1. 掩模不用于功能图形及格式图形:寻像图形、定位图形、校正图形、位置探测图形分隔符、格式信息和版本信息。
  2. 数据码字与掩模图形进行 XOR 操作后再进行绘制。
  3. 对每个结果图形的不合要求的部分记分,以评估这些结果。
  4. 选择得分最低的图形。

掩模图形

下表给出了掩模图形的参考和掩模图形生成的条件。掩模图形是通过将编码区域(不包括格式信息和版本信息)内那些条件为真的模块定义为深色而产生的。所示的条件中,i 代表模块的行的位置,j 代表模块的列的位置,(i,j)=(0,0)代表符号中左上角的位置。

掩模图形参考 条件
000 (i + j) mod 2 = 0
001 i mod 2 = 0
010 j mod 3 = 0
011 (i + j) mod 3 = 0
100 ((i/2)+(j/3)) mod 2 = 0
101 (i × j) mod 2 + (i × j) mod 3 = 0
110 ((i × j) mod 2 + (i × j) mod 3) mod 2 = 0
111 ((i × j) mod 3 + (i + j) mod 2) mod 2 = 0

下图显示了所有掩模图形的外观:

下面是掩模后的效果,我们可以看到整块的数据掩模后变得比较零散了。

【例 1 续 5】:加入掩模图形

最后,我们将【例 1 续 4】得到的图案中的粉红色模块同掩模图案进行 XOR 运算。将所有深色图案用黑色替换,浅色图案用白色替换,得到最终的二维码。激动啊!终于完工!下图是使用所有 8 种掩模得到的结果,每个 QR 码都可以扫出 01234567。

到现在我才知道程序没有写错,在没写完文章之前,根本没办法测试,心里的一块石头终于落地了。要是最终图案扫码失败,真不知道上哪找错误去。文章终于写完,真不容易,学习、查资料、写作,还得 Coding。还好,文章总算变成成品了,不过程序还没写完。现在的程序只够写文章用,还要加好多东西。休息,慢慢来吧。

おすすめ

転載: www.cnblogs.com/lonelyxmas/p/12114641.html