qq_39368753 2019-12-11 17:45
浏览 482

小白求助!!!关于利用Zbar进行二维码扫描程序的问题

构建openCV3.4.0+zbar 64位+VS2015的环境 (zbar貌似只支持32位系统因此我又自己找了64位的库)
这个程序就是利用调用摄像头扫描二维码,然后通过数学计算测量摄像头与二维码的实时距离
是按照原博主的这篇文章https://zhou-yuxin.github.io/articles/2017/%E5%9F%BA%E4%BA%8E%E4%BA%8C%E7%BB%B4%E7%A0%81%E7%9A%84%E5%AE%A4%E5%86%85%E5%AE%9A%E4%BD%8D%E6%8A%80%E6%9C%AF%EF%BC%88%E4%BA%8C%EF%BC%89%E2%80%94%E2%80%94%E5%AE%9E%E7%8E%B0/index.html参考的
又请了师兄将其中openCV老版本的语句换成了我这个版本的
本来应该按照原博的示例是这样的
图片说明
但是我运行过后变成了这样

图片说明
打印出来的三个变量不对 而且都是乱码
我上网搜索也没有发现相关资料和问题 真的很着急 求各位大神指教 是不是我的ZBAR安装的有问题? 真的快急哭了 求救!!!

代码如下
QRLocation.h
#ifndef QRLOCATION_H
#define QRLOCATION_H

/*
二维码的内容必须符合格式:
QRLocation,
其中是一个实数,表示二维码边长
*/

#include
#include
#include
#include
//二维码倾斜阈值
#define QRLOCATION_INCLINATION_THRESHOLD 0.1
//调试窗口标题
#define QRLOCATION_DEBUGUI_TITLE "debugui"

//二维码位姿
typedef struct QRPose
{
//二维码中心所在铅垂线与O点构成的平面和Z轴形成的夹角
double a;
//二维码所在平面与X轴构成的夹角
double b;
//二维码中心到XOY平面的距离
double z;
}
QRPose_t;

//二维码定位算法
class QRLocation
{

public:
//初始化,第一个参数为摄像头编号,第二个参数为摄像头上下视角,第三个参数为是否开启调试窗口
bool init(int webcamIndex, double hViewAngle, bool debugUI);
//获取二维码位姿
bool getQRPose(QRPose_t* qrPose);
//销毁
bool destroy();

private:

//摄像头
cv::VideoCapture capture;
//摄像头上下视角
double hViewAngle;
//是否开启调试窗口
bool debugUI;
//灰度图
cv::Mat grayFrame;
//图片扫描器
zbar::ImageScanner scanner;

private:
//计算位姿(格式合法性判断)
bool getQRPose(zbar::Image::SymbolIterator symbol, QRPose_t* qrPose);
//计算位姿(算法)
bool getQRPose(zbar::Image::SymbolIterator symbol, double qrSize, QRPose_t* qrPose);

};

#endif

QRLocation.cpp
#include
#include
#include "QRLocation.h"
#include
#include
using namespace std;
using namespace zbar;

bool QRLocation::init(int webcamIndex, double hViewAngle, bool debugUI)
{
//打开摄像头
capture.open(webcamIndex);
//摄像头不存在
if (!capture.isOpened()) {
printf("camera open error \n");
return false;
}
//printf("point 2 \n");
this->hViewAngle = hViewAngle;
this->debugUI = debugUI;
//grayFrame=0;
//配置zbar图片扫描器
scanner.set_config(zbar::ZBAR_NONE, zbar::ZBAR_CFG_ENABLE, 1);
//printf("point 3 \n");
//如果开启调试,则创建窗口,名称为“debugui”,自动调整大小
if (debugUI) {
cv::namedWindow(QRLOCATION_DEBUGUI_TITLE, CV_WINDOW_AUTOSIZE);
}
//printf("point 4 \n");

return 1;
}

bool QRLocation::getQRPose(QRPose_t* qrPose)
{
//从摄像头中抓取一帧
cv::Mat frame;

capture.read(frame);;
//图像为空
if (frame.empty())
{
printf("read frame is empty!\n");
return false;
}
//printf("point 6 \n");
//如果灰度图没有创建,就创建一个和原图一样大小的灰度图(8位色深,单通道)
//if (grayFrame.empty()) {
grayFrame = cv::Mat(frame.size(), IPL_DEPTH_8U, 1);
//}
//原图转灰度图
//cv::cvtColor(frame, grayFrame, cv::COLOR_BGR2GRAY);
cvtColor(frame, grayFrame, CV_RGB2GRAY);

//printf("point 9 \n");
//如果开启调试,则显示灰度图
if (debugUI)
{
cv::imshow(QRLOCATION_DEBUGUI_TITLE, grayFrame);
char c = cv::waitKey(30);
}
//printf("point 8 \n");
//创建zbar图像
uchar* data = frame.data;
void *new_data = static_cast(data);
Image image(frame.size().width, frame.size().height, "Y800", new_data, frame.size().width*frame.size().height);
//printf("point 7 \n");
//扫描图像,识别二维码,获取个数
int symbolCount = scanner.scan(image);
//获取第一个二维码
Image::SymbolIterator symbol = image.symbol_begin();
//遍历所有识别出来的二维码
while (symbolCount--)
{
//能够识别
if (getQRPose(symbol, qrPose))
return true;
//下一个二维码
++symbol;
}
return false;
}

bool QRLocation::getQRPose(Image::SymbolIterator symbol, QRPose_t* qrPose)
{
//首先得是一个二维码
if (symbol->get_type_name() != "QR-Code")
printf("this is shit");
//获取内容
char data[128];
strncpy_s(data, symbol->get_data().c_str(), sizeof(data) - 1);
data[sizeof(data) - 1] = 0;
//内容得是以“QRLocation,”开头
if (strncmp(data, "QRLocation,", 11) != 0)
return false;
//获取二维码边长
double qrSize = 0;
sscanf_s(data + 11, "%lf", &qrSize);
if (qrSize == 0)
return false;
//计算位姿
return getQRPose(symbol, qrSize, qrPose);
}

bool QRLocation::getQRPose(Image::SymbolIterator symbol, double qrSize, QRPose_t* qrPose)
{
//获得四个点的坐标
double x0 = symbol->get_location_x(0);
double y0 = symbol->get_location_y(0);
double x1 = symbol->get_location_x(1);
double y1 = symbol->get_location_y(1);
double x2 = symbol->get_location_x(2);
double y2 = symbol->get_location_y(2);
double x3 = symbol->get_location_x(3);
double y3 = symbol->get_location_y(3);
//左边沿纵向差
double leftH = y1 - y0;
//右边沿纵向差
double rightH = y2 - y3;
//必须保证0点高于1点,3点高于2点
if (leftH return false;
//左边沿横向差
double leftW = abs(x0 - x1);
//右边沿横向差
double rightW = abs(x2 - x3);
//不能太倾斜
if (max(leftW / leftH, rightW / rightH)>QRLOCATION_INCLINATION_THRESHOLD)
return false;
//上下视角一半的正切值,因为一直要用,所以先计算出来
double tanHalfView = tan(hViewAngle / 2);
double leftLen = sqrt(leftH*leftH + leftW*leftW);
double rightLen = sqrt(rightH*rightH + rightW*rightW);
//左边沿的深度
double leftZ = grayFrame.size().height*qrSize / tanHalfView / 2 / leftLen;
//右边沿的深度
double rightZ = grayFrame.size().height*qrSize / tanHalfView / 2 / rightLen;
//得到中心点的深度
double z = (leftZ + rightZ) / 2;
//计算b的正弦值
double sinB = (leftZ - rightZ) / qrSize;
if (sinB>1)
return false;
//得到b
double b = asin(sinB);
//两条对角线的系数和偏移
double k1 = (y2 - y0) / (x2 - x0);
double b1 = (x2*y0 - x0*y2) / (x2 - x0);
double k2 = (y3 - y1) / (x3 - x1);
double b2 = (x3*y1 - x1*y3) / (x3 - x1);
//两条对角线交点的X坐标
double crossX = -(b1 - b2) / (k1 - k2);
//计算a的正切值
double tanA = tanHalfView*(2 * crossX - grayFrame.size().width) / grayFrame.size().width;
//得到a
double a = atan(tanA);
qrPose->a = a;
qrPose->b = b;
qrPose->z = z;
return true;
}

//bool QRLocation::destroy()
//{
//释放灰度图
//cvReleaseImage(&grayFrame);
//销毁窗口
//cvDestroyWindow(QRLOCATION_DEBUGUI_TITLE);
//释放内存
//cvReleaseCapture(&capture);
//}

QRLocationTest.cpp
#include "QRLocation.h"
#include

int main(int argc, char* argv[])
{
//printf("point 1 \n");
QRLocation qrLoc;
if (!qrLoc.init(0, 0.60, true)) {
return 1;
}
//printf("point 5 \n");
QRPose_t pose;
while (true)
{
if (qrLoc.getQRPose(&pose))
{
double aInDegree = pose.a * 180 / 3.1415;
double bInDegree = pose.b * 180 / 3.1415;
printf("a=%.2lf,b=%.2lf,z=%.2lf\n", aInDegree, bInDegree, pose.z);
}
}
}

  • 写回答

0条回答

    报告相同问题?

    悬赏问题

    • ¥15 MATLAB怎么通过柱坐标变换画开口是圆形的旋转抛物面?
    • ¥15 寻一个支付宝扫码远程授权登录的软件助手app
    • ¥15 解riccati方程组
    • ¥15 display:none;样式在嵌套结构中的已设置了display样式的元素上不起作用?
    • ¥30 用arduino开发esp32控制ps2手柄一直报错
    • ¥15 使用rabbitMQ 消息队列作为url源进行多线程爬取时,总有几个url没有处理的问题。
    • ¥15 Ubuntu在安装序列比对软件STAR时出现报错如何解决
    • ¥50 树莓派安卓APK系统签名
    • ¥65 汇编语言除法溢出问题
    • ¥15 Visual Studio问题