[c++]根据二维码矩形特征定位识别位置

  1. 我们发现左上、左下、右上三个位置探测图形,在二维码的解码过程中,其实是分几个步骤的,首先就是要定位这个二维码确认其位置,然后才能取出里面的数据,而这个定位的点就是这三个。在距离二维码较远时,可能无法解析出完整的数据,但是却能定位这个二维码,通过定位点的信息,我们可以进行放大的操作,从而获取到更加精确的图像数据,也更有利于我们解析。

     
    二维码结构 
    /**
     * 没有查询到二维码结果,但是能基本能定位到二维码,根据返回的数据集,检验是否要放大
     *
     * @param result 二维码定位信息
     */
    void tryZoom(BarcodeReader.Result result) { int len = 0; float[] points = result.getPoints(); if (points.length > 3) { float point1X = points[0]; float point1Y = points[1]; float point2X = points[2]; float point2Y = points[3]; float xLen = Math.abs(point1X - point2X); float yLen = Math.abs(point1Y - point2Y); len = (int) Math.sqrt(xLen * xLen + yLen * yLen); } handleAutoZoom(len); } 
  1. 与微信的对比
    微信的扫一扫可以说是秒级的处理,特别是在iOS的设备上,更不可思议的是它好像没有距离的限制。经过我们的优化之后,我们的二维码可以在50cm内解析出来,但是与微信相差的还是太远,我们需要更好的处理图像数据,来定位二维码。
6. OpenCV 
识别距离

源文件.cpp

//
// Created by leoxae on 19-8-28.
//

#include "checkQrcode.h"

float checkQrcode::getDistance(Point pointO, Point pointA) {
    float distance;
    distance = powf((pointO.x - pointA.x), 2) + powf((pointO.y - pointA.y), 2);
    distance = sqrtf(distance);

    return distance;
}

void checkQrcode::check_center(vector<vector<Point> > c, vector<int> &index) {
    float dmin1 = 10000;
    float dmin2 = 10000;
    for (int i = 0; i < c.size(); ++i) {
        RotatedRect rect_i = minAreaRect(c[i]);
        for (int j = i + 1; j < c.size(); ++j) {
            RotatedRect rect_j = minAreaRect(c[j]);
            float d = getDistance(rect_i.center, rect_j.center);
            if (d < dmin2 && d > 10) {
                if (d < dmin1 && d > 10) {
                    dmin2 = dmin1;
                    dmin1 = d;
                    index[2] = index[0];
                    index[3] = index[1];
                    index[0] = i;
                    index[1] = j;

                } else {
                    dmin2 = d;
                    index[2] = i;
                    index[3] = j;
                }
            }
        }
    }
}


Rect checkQrcode::processData(const Mat gray, Rect resultRect) {
    Rect RoiRect;
//    Mat gray(h, w, CV_8UC4, data);
//    imwrite("/storage/emulated/0/scan/src.jpg", gray);

//    Mat filter;
//    bilateralFilter(gray, filter, 15, 150, 15, 4);
//    imwrite("/storage/emulated/0/scan/filter.jpg", filter);

    int w = gray.cols;
    int h = gray.rows;

    // 进行canny化,变成黑白线条构成的图片
    Mat binary;
    Canny(gray, binary, 100, 255, 3);
//    imwrite("/storage/emulated/0/scan/src_canny.jpg", binary);
    // detect rectangle now
    vector<vector<Point>> contours;
    vector<Vec4i> hierarchy;
    vector<int> found;
    vector<vector<Point>> found_contours;
    findContours(binary, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE);
//    Mat result = Mat::zeros(gray.size(), CV_8UC4);
    for (int t = 0; t < contours.size(); ++t) {
        double area = contourArea(contours[t]);
        if (area < 150) continue;

        RotatedRect rect = minAreaRect(contours[t]);
        // 根据矩形特征进行几何分析
        float rect_w = rect.size.width;
        float rect_h = rect.size.height;
        float rate = min(rect_w, rect_h) / max(rect_w, rect_h);
        if (rate > 0.65 && rect_w < (gray.cols >> 2) && rect_h < (gray.rows >> 2)) {
            int k = t;
            int c = 0;
            while (hierarchy[k][2] != -1) {
                k = hierarchy[k][2];
                c = c + 1;
            }
            if (c >= 1) {
                found.push_back(t);
                found_contours.push_back(contours[t]);
//                drawContours(result, contours, static_cast<int>(t), Scalar(255, 0, 0), 2, 8);
            }
        }
    }

//    imwrite("/storage/emulated/0/scan/src_patter_1.jpg", result);

    if (found.size() >= 3) {
        vector<int> indexs(4, -1);
        check_center(found_contours, indexs);
        vector<Point> final;
        for (int i = 0; i < 4; ++i) {
            if (indexs[i] == -1) {
                continue;
            }
            RotatedRect part_rect = minAreaRect(found_contours[indexs[i]]);
            Point2f p[4];
            part_rect.points(p);
            for (auto &j : p) {
                final.push_back(j);
            }
        }

        //region of qr
        Rect ROI = boundingRect(final);
//        if (ROI.empty()) {
//            return;
//        }
        int space = 0;
        if (ROI.width < ROI.height) {
            space = ROI.height - ROI.width;
            ROI = ROI + Size(space, 0);
        } else if (ROI.width > ROI.height) {
            space = ROI.width - ROI.height;
            ROI = ROI + Size(0, space);
        }

        Point left_top = ROI.tl();
        Point right_down = ROI.br();
        if (left_top.x >= 20 || left_top.y >= 20 || right_down.x <= w - 20 ||
            right_down.y <= h - 20) {
            ROI = ROI + Point(-20, -20) + Size(40, 40);
        }

        if (ROI.tl().x > 0 && ROI.tl().y > 0 && ROI.br().x < w && ROI.br().y < h) {
//            rectangle(result, ROI.tl(), ROI.br(), Scalar(0, 0, 255));
//            imwrite("/storage/emulated/0/scan/src_patter_2.jpg", result);
            RoiRect = ROI;
        }
    }
    return RoiRect;
}

 

头文件.h

//
// Created by leoxae on 19-8-28.
//

#ifndef KEEKOAIROBOT_CHECKQRCODE_H
#define KEEKOAIROBOT_CHECKQRCODE_H

#include "../../globals.h"
using namespace std;
using namespace cv;

class checkQrcode{
public:
    static float getDistance(Point pointO, Point pointA);

    static void check_center(vector<vector<Point> > c, vector<int> &index);

    static Rect processData(const Mat gray, Rect resultRect);
    
};

#endif //KEEKOAIROBOT_CHECKQRCODE_H

 

转载于:https://www.cnblogs.com/lx17746071609/p/11428758.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在使用OpenCV进行二维码回字定位时,需要通过图片处理技术将图像中的二维码区域分割出来,然后使用二维码定位模块进行二维码解码。但是,在解码之前,需要进行回字定位。回字定位主要是针对QR码而言,因为QR码中的定位图案是由一个大正方形和四个小正方形组成的,这四个小正方形构成的回字形的定位图案则用于确定QR码的方向。 回字定位需要首先找到QR码区域,因为QR码周围都有一圈白边,这个白边可以作为QR码的边界。当确定了QR码的边界之后,就可以在其内部找寻回字定位图案。最简单的方法是利用模板匹配,首先构建一个回字定位模板,然后将其与图像中的所有可能的位置进行匹配,找到匹配度最高的位置即为回字定位图案所在的位置。 找到回字定位图案之后,可以根据其方向确定QR码的方向,然后将其转正方向,进行解码即可。需要注意的是,回字定位模板的构建需要考虑到图像缩放、旋转等因素对模板匹配的影响,因此需要进行多角度、多尺度的模板匹配和加权平均处理。 ### 回答2: OpenCV是一个广泛使用的开源计算机视觉库,提供了许多强大的功能。二维码是一种储存信息的二维条码,常用于商品的跟踪和管理。回字定位二维码中间的一个特殊的黑白图案,可以用于定位二维码位置和方向。在OpenCV中,实现二维码回字定位需要以下几步: 1.图像预处理:将彩色图像转换成灰度图像,阈值化得到二值图像,然后进行形态学处理,去除噪声和平滑边缘。 2.轮廓检测:通过findContours函数得到二值图像中的轮廓,只保留面积最大的轮廓(即二维码的边缘)。 3.寻找回字定位:针对二维码回字定位的形状特征,可以使用霍夫变换进行检测。具体实现过程中,可以采用霍夫圆检测算法,得到回字定位的圆心和半径,进而确定二维码位置和方向。 4.绘制结果:将检测到的二维码位置和方向信息绘制在原始图像上,以便进行下一步操作。 总之,OpenCV提供了丰富的图像处理和计算机视觉算法,可以方便地实现二维码回字定位功能。但是,具体实现时需要针对不同的图像进行优化和调整,才能得到更好的检测效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值