QR code 定位

QR code 定位

QR code is now widely used in our daily life because it is small and can contain lots of information. QR code can also be used in positioning as it usually has three blocks to determine the position of QR code. Just like the following one, top left corner, top right corner and lower left corner are corresponding blocks to confirm the location of QR code. Of course there are other areas containing different information, but I won’t use them when positioning the location of QR code.
在这里插入图片描述

Contours extraction

We should do some pretreatment before contours extraction. First transfer the BGR image to gray image, then use Gaussian blur to suppress the noise, and use Canny algorithm to obtain the edge image. Let’s see the result of Canny. Result is good and we can easily distinguish the edge of QR code.
在这里插入图片描述
Now we are going to proceed contours extractions. As edges have been detected, contours are easily confirmed because contours are just closed loop which is made of certain edges. In OpenCV we just need to use ‘findContours’ function to do the job. But there are lots of contours in QR code and how can we just find out those three blocks to determine the location of QR code?

Position blocks extraction

To find out the position blocks from so many contours in QR code, the easiest way is to distinguish them by the nested layers. What does that mean? If there is no contour in the area which is surrounded by this contour, then we can say there is no nested layer of this contour. But if there is one contour being surrounded by another contour, then the nested layer of the latter is one. For example, the nested layers of out contour is three because there are three contours surrounded by it.
在这里插入图片描述
So if we observe the positioning blocks of QR code, we can find that the outmost rectangle usually have 4, 5 or 6 nested layer which is much more than other contours. We have to notice that one rectangle in findContours function is seen as two contours which means both two sides of a loop is considered as a contour. But how do know the nested layer of each contour? Well, findContours function also give us the answer. This function will return back a tree structure which contains the child and father information. The child means the surrounded contour by this contour and father means this contour is surrounded by another contour. So with this tree structure, we can easily determine the nested layer of one contour. Then we can give a threshold such as 4, 5 or 6 and determined the nested layers above this value is considered as positioning location. The exact number of threshold is influenced by the quality of edge image. If the edge image is very clear, then this threshold can be 6. On the opposite threshold can be 4 because the minimum contour may not be recognized if the image is too vague. The result is shown as below, and it meets our hope.
在这里插入图片描述

QR code Center positioning

Although the positioning blocks have been extracted, we still need to confirm the center of QR code to quantify the location of QR code. There are usually two ways to do that:

  1. Find the minimum rectangle which contains these three QR code, and if we have the information of four points of a rectangle, the center is easily obtained.
  2. Find the farthest distance between the points on the three positioning blocks. Then the line which is formed by corresponding pair of points is exactly diagonal of QR code, and the center is midpoint of this diagonal.
    In ordinary situation these two ways can be both useful and the former solution can be more easily to be realized by OpenCV. But if the QR code is tilt with some angle, the former way can be wrong because the rectangle can be rotated. Let’s see two examples:
    在这里插入图片描述
    So I decided to take the second solution though there is no ready-made solution. It’s a classical getting maximum value problem and we can use four circulation to get our purpose. Now let’s see the result, the center is surrounded by a circle to emphasize and the corresponding two farthest points are also marked.
    在这里插入图片描述
    Some other results:
    在这里插入图片描述在这里插入图片描述在这里插入图片描述

Code

#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;

int main(){
    Mat image_input=imread("1.jpg",IMREAD_UNCHANGED);
    Mat image_gray;
    Mat image_Gaussian;
    Mat image_final;
    cvtColor(image_input,image_gray,COLOR_BGR2GRAY);
    image_final=image_input;
    GaussianBlur(image_gray,image_Gaussian,Size(5,5),0,0);
    imshow("image_Gaussian",image_Gaussian);
    imshow("image_color",image_input);
    Mat image_canny;
    Canny(image_Gaussian,image_canny,10,50,3,true);
    imshow("image_canny",image_canny);
    vector<vector<Point>> contours;
    vector<Vec4i> hierarchy;
    Mat image_contours=Mat::zeros(image_canny.size(),CV_8UC1);
    Mat Contours=Mat::zeros(image_canny.size(),CV_8UC1);

    findContours(image_canny,contours,hierarchy,RETR_TREE,CHAIN_APPROX_NONE);
    //find out all outlines

    int k,c;
    vector<int> edge;
    for(int i=0;i<contours.size();i++){
        k=i;
        c=1;
        while(hierarchy[k][2]!=-1){
            k=hierarchy[k][2];
            c++;
        }
        if(c>=4){
            edge.push_back(i);
        }
    }
    //find out the outline whose nested layers is more than 5 which will be the location code of QR code

    cout<<edge.size()<<endl;
    for(int i=0;i<edge.size();i++){
        cout<<edge[i]<<endl;
    }
    int maxsum=0,minsum=1000000,maxdis=0;
    Point pt1,pt2,center;
    for(int i=0;i<edge.size();i++){
        for(int j=i+1;j<edge.size();j++){
            for(int m=0;m<contours[edge[i]].size();m++){
                for(int n=0;n<contours[edge[j]].size();n++){
                    int dis=pow(contours[edge[i]][m].x-contours[edge[j]][n].x,2)+pow(contours[edge[i]][m].y-contours[edge[j]][n].y,2);
                    cout<<dis<<endl;
                    if(dis>maxdis){
                        maxdis=dis;
                        pt1=contours[edge[i]][m];
                        pt2=contours[edge[j]][n];
                        cout<<pt1.x<<' '<<pt1.y<<endl;
                        cout<<pt2.x<<' '<<pt2.y<<endl;
                    }
                }
            }
        }
    }
    //find out the most farthest point of location code

    cout<<pt1.x<<' '<<pt1.y<<endl;
    cout<<pt2.x<<' '<<pt2.y<<endl;
    center.x=(pt1.x+pt2.x)/2;
    center.y=(pt1.y+pt2.y)/2;
    //center of two farthest points is the center of QR code

    circle(image_final,pt1,5,Scalar(0,0,255),0.6,8);
    circle(image_final,pt2,5,Scalar(0,0,255),0.6,8);
    circle(image_final,Point(center.x,center.y),5,Scalar(0,0,255),2,8);
    for(int j=0;j<edge.size();j++){
        /*for(int j=0;j<contours[i].size();j++){
            Point P=Point(contours[i][j].x,contours[i][j].y);
            Contours.at<uchar>(P)=255;
        }*/
       // cout<<i<<' '<<hierarchy[i]<<endl;
       int i=edge[j];
        drawContours(image_final,contours,i,Scalar(0,0,255),2,8);
    }
    // draw the location code;
   // imshow("image_contours",image_contours);
   // imshow("Contours",Contours);
    namedWindow("image_final",WINDOW_NORMAL);
    cvResizeWindow("image_final",1000,1000);
    imshow("image_final",image_final);
    waitKey(0);
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值