QR-CODE : Weekly Report

Weekly Report on Jul.11th

by Zheng Qiushi

This week , I have done three tasks as follows:

	① Review the process of encoding and decoding 
	② Analyze the procedure of dectecting and decoding in opencv.
	③ Finish steps before the data infomation decoding 

In this report , I’m going to focus on the last two points.

The Procedure in Opencv

We can run the QR-code detector by calling the funtion " detectAndDecode( )" in modules/objdetect/src/qrcode.cpp .
Here is a flowchat of how it works.

detectAndDecode
detect
decode
fullDecodingProcess
checkQRInputImage
detect
decode
localization
fullDecodingProcess
computeTransformationPoints
getDecodeInformation
updatePerspective
versionDefinition
samplingForVersion
decodingProcess
detect

In detect( ) , this function is implemented by counting the exact pixels in the image and trying to match the Position Detection Pattern (abbreviated to PDP in this report ) .
according to the ration =>  light:dark:light:dark:light:dark = 1:1:1:3:1:1

In my opinion , this function can be optimized, because in reality , the proportion of the PDP in the picture will be distorted by the perspective bending .So the direct counting method does not work and the detection rate is pretty low.
the detection failed
Maybe we can use the method of finding the coutours.According to the contour level , we can find the contour of three layers and select it as a candidate.
Because my main task is to finish the decoder ,so I will do this optimization later.

decode

In decode( )
The main function is fullDecodingProcess( ),which calls other four procedures.

In updatePerspective( ): Correcting the image  by doing an affine transformation.
In versionDefinition( ): Estimate the version roughly by doing a floodFill method,
In samplingForVersion( ):Sampling the pixels into a data array .First, enlarging the image .And then colleting the pixels in the smallest unit of tile which is a n*n matrix. 
In decodingProcess( ) : Applied the third party Library "quirc".

My main task falls on the decodingProcess( ).

My code

quirc_decode
read_format
correct_format
read_format
read_data
codestream_ecc
decode_payload
get_format
correct_format
format_syndromes
hamming_detect
format_syndromes_again
Variable

Instead of using a uint16 to store data , I select Mat as the container,the length is equal to its cols.

    Mat mat_format(1,FORMAT_LENGTH,CV_8UC1,Scalar(0));

And the data can be easily get by calling

mat_format.ptr(0)[i]=...
Format Correction Method

In correct_format( ), I prefer to using hamming distance to correct the format infomation .

hamming detect
int hamming_detect(uint16_t fmt){
    int best_fmt = -1;
    int best_dist = 15;
    int test_dist;
    int index=0;
    for(;index<32;index++){
        uint16_t test_code=after_mask_format[index];
        test_dist=hamming_weight(fmt ^ test_code);
        /*find the smallest distance*/
        if (test_dist < best_dist){
            best_dist = test_dist;
            best_fmt = index;
        }
        /*can't match two components*/
        else if(test_dist == best_dist) {
            best_fmt = -1;
        }
    }
    cout<<"best_fmt : "<<best_fmt<<" best_dist : "<<best_dist<<endl;
    return best_fmt;
}

Because , the data string is only 5bits (2bits for ECC level and 3bits for mask pattern) with a fixed ECC generator ,so there are only 32 components in the look-up table ,which can be quickly matched. We don’t need to do a “berlekamp_massey” method as it used to .

the look-up table
static const uint16_t after_mask_format [32]={
         0x5412,0x5125,0x5e7c,0x5b4b,0x45f9,  0x40ce,0x4f97,0x4aa0,0x77c4,0x72f3,
         0x7daa,0x789d,0x662f,0x6318,0x6c41,  0x6976,0x1689,0x13be,0x1ce7,0x19d0,
         0x0762,0x0255,0x0d0c,0x083b,0x355f,  0x3068,0x3f31,0x3a06,0x24b4,0x2183,
         0x2eda,0x2bed
};
Encode Functions

Besides I also complete some functions to do the encode task.

rs_generator_poly

The generator can be implement by doing multiplication in GF.

g4(x) = (x - α0) (x - α1) (x - α2) (x - α3)
Mat rs_generator_poly(int nsym) {
    /*initialize the first item*/
    Mat g(1,nsym+1,CV_8UC1,Scalar(0));
    g.ptr(0)[0]=1;
    g.ptr(0)[1]=1;
    for(int i =1;i<nsym;i++){
    /*get n as item (x - α0)*/
        Mat n(1,2,CV_8UC1,Scalar(0));
        n.ptr(0)[0]=gf_pow(2, i); n.ptr(0)[1]=1;
        Mat r=gf_poly_mul(g, n);
        for(int j=0;j<r.cols;j++){
            g.ptr(0)[j]=r.ptr(0)[j];
        }
    }
    cout<<"rs_generator_poly : "<<show_poly(g)<<endl;
    return g;
}
gf_poly_div

This function is for getting the ECC for the data string ,which is implemented by doing a poly division.

/*                             12 da df
 *               -----------------------
 *01 0f 36 78 40 ) 12 34 56 00 00 00 00
 *               ^ 12 ee 2b 23 f4
 *              -------------------------
 *                   da 7d 23 f4 00
 *                 ^ da a2 85 79 84
 *                  ---------------------
 *                      df a6 8d 84 00
 *                    ^ df 91 6b fc d9
 *                    -------------------
 *                         37 e6 78 d9
 */

The divident is the data string ,the divisor is the generator and the remainder is the ECC.

Mat gf_poly_div(const Mat& dividend,const Mat& divisor) {
    /* Note that the processing starts from the item with high number of times, so item [total-i] is processed for the i-th round */
    int times=dividend.cols-(divisor.cols-1);
    int dividend_len=dividend.cols-1;
    int divisor_len=divisor.cols-1;
    /*Mat.ptr(0)[i] stores the coeffient of the x^i*/
    Mat r=dividend.clone();
    for(int i =0;i<times;i++){
        uint16_t coef=r.ptr(0)[dividend_len-i];
        if(coef!=0){
            for (int j = 0; j < divisor.cols; ++j) {
                if(divisor.ptr(0)[divisor_len-j]!=0){
                    r.ptr(0)[dividend_len-i-j]^=gf_mul(divisor.ptr(0)[divisor_len-j], coef);
                }
            }
        }
    }
    Mat ecc=r(Range(0,1),Range(0,10)).clone();
    return ecc;
}

2020.07.11

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值