Linux OpenCV + zBar 实现二维码识别
第一个版本
参考:https://blog.csdn.net/pyt1234567890/article/details/109597353
特点:实现简单、但局限于亮度 清晰度好,没有扭曲变形的情况。
main.cpp
#include "iostream"
#include "opencv2/opencv.hpp"
#include "zbar.h" using namespace std;
using namespace cv;
using namespace zbar;#define WINDOW_NAME "clor"
#define WINDOW_GARY_NAME "gary"int main()
{namedWindow(WINDOW_NAME, WINDOW_AUTOSIZE);namedWindow(WINDOW_GARY_NAME, WINDOW_AUTOSIZE);// 加载二维码图片Mat image;// image = imread("./picture/test.jpg");image = imread("./picture/QRcode.jpg");// image = imread("./picture/barCode.jpg");// image = imread("./picture/2Code.png");// image = Mat(240,320,CV_8UC3,Scalar(0,255,0));cout << "---------------- 图像参数 ------------------"<<endl;// 标志位cout << "flags:" << image.flags << endl;// 图像尺寸cout << "size:" << image.size << endl;// 列宽cout << "clos:" << image.cols<<endl;// 行高cout << "rows:" << image.rows << endl;// 维度cout << "dims:" << image.dims << endl;cout << "------------------------------------------"<<endl;imshow(WINDOW_NAME,image);// 灰度转换Mat imageGray;cvtColor(image, imageGray, COLOR_RGB2GRAY);imshow(WINDOW_GARY_NAME,imageGray);// 获取二进制数据int width = imageGray.cols;int height = imageGray.rows;uchar *raw = (uchar *)imageGray.data;Image imageZbar = Image(width, height, "Y800", raw, width * height);// 配置扫描器,开始扫描ImageScanner scanner;scanner.set_config(ZBAR_NONE, ZBAR_CFG_ENABLE, 1);scanner.scan(imageZbar); // 扫描结果打印if (imageZbar.symbol_begin() == imageZbar.symbol_end()){cout << "识别错误!" << endl;}// 遍历所有识别到的二维码后者条形码Image::SymbolIterator symbol = imageZbar.get_symbols();for (; symbol != imageZbar.symbol_end(); ++symbol){cout << "类型:\t" << symbol->get_type_name() << endl;cout << "条码:\t" << symbol->get_data() << endl << endl;}// 释放资源imageZbar.set_data(NULL, 0);waitKey(0);return 0;
}
第二个版本
参考:https://www.cnblogs.com/cjqbaba/p/9073908.html
特点:可以比较好的识别出二维码,但是检测效果有待优化。
/******************************************************
文件名 :main.cpp
描 述 :条形码,二维码的识别
语 言 :
作 者 :范泽华
修 改 :
日 期 :2018-05-19
说 明 :需要Zbar的支持
******************************************************/
#include <opencv2/opencv.hpp>
#include "opencv2/imgproc/types_c.h"
#include "opencv2/imgcodecs/legacy/constants_c.h"
#include "opencv2/imgproc/imgproc_c.h"
#include <iostream>
#include <zbar.h>using namespace cv;
using namespace std;
using namespace zbar;//using std::vector;class MyClass
{public:MyClass();MyClass(char** argv);~MyClass();void Dis_code(Mat image);void Run();void QrRun();Mat getGray(Mat image, bool show = false);//获取灰度图Mat getGass(Mat image, bool show = false);//高斯平滑滤波Mat getSobel(Mat image, bool show = false);//Sobel x—y梯度差Mat getBlur(Mat image, bool show = false);//均值滤波除高频噪声Mat getThold(Mat image, bool show = false);//二值化Mat getBys(Mat image, bool show = false);//闭运算Mat getErode(Mat image, bool show = false);//腐蚀Mat getDilate(Mat image, bool show = false);//膨胀Mat getRect(Mat image, Mat simage, bool show = false);//获取范围Mat getRotate(Mat image,double angle);bool IsCorrect(Point point[]);//判断是否正对Point Center_cal(std::vector<std::vector<Point> > contours, int i);void WriteFile(Mat image, String filename);
private:Mat srcimage;//原图Mat element;//核
};void MyClass::WriteFile(Mat image, String filename)
{filename += ".jpg";std::vector<uchar> vbuffer;std::vector<int> param = std::vector<int>(2);param[0] = CV_IMWRITE_JPEG_QUALITY;param[1] = 95; // default(95) 0-100cv::imencode(".jpg", image, vbuffer, param);FILE* pfd = fopen(filename.c_str(), "w+");if (NULL == pfd){perror("fopen failed!\n");return ;}fwrite(vbuffer.data(), vbuffer.size(), 1, pfd);fflush(pfd);fclose(pfd);String cmd = "chmod 777 ";cmd += filename;system(cmd.c_str());return;
}/******************************************************
函数名称: MyClass
函数功能: 初始化
传入参数:
返 回 值:
建立时间: 2018-05-19
修改时间:
建 立 人: 范泽华
修 改 人:
其它说明:
******************************************************/
MyClass::MyClass()
{srcimage = imread("core.jpg");//"F:\Pictures\qr.png""F:\Pictures\条形码.png"//srcimage = imread("F:\\Pictures\\qr测试.png");//srcimage = imread("条码.jpg");if (srcimage.empty()){printf("文件不存在");exit(1);}//resize(srcimage, srcimage, Size(srcimage.size().width/2, srcimage.size().height/2));element = getStructuringElement(0, Size(7, 7));//Dis_code(srcimage);
}
/******************************************************
函数名称: MyClass
函数功能: 初始化
传入参数: char* argv
返 回 值:
建立时间: 2018-05-19
修改时间:
建 立 人: 范泽华
修 改 人:
其它说明:
******************************************************/
MyClass::MyClass(char** argv)
{srcimage = imread(argv[1]);if (srcimage.empty()){printf("文件不存在");exit(1);}resize(srcimage, srcimage, Size(500, 500));element = getStructuringElement(0, Size(7, 7));
}
/******************************************************
函数名称: ~MyClass
函数功能: 释放空间
传入参数:
返 回 值:
建立时间: 2018-05-19
修改时间:
建 立 人: 范泽华
修 改 人:
其它说明:
******************************************************/
MyClass::~MyClass()
{}
/******************************************************
函数名称: Dis_Barcode
函数功能: 识别条形码和二维码
传入参数:
返 回 值:
建立时间: 2018-05-19
修改时间:
建 立 人: 范泽华
修 改 人:
其它说明:这里是借鉴其他人的代码:
原文链接:https://www.cnblogs.com/dengxiaojun/p/5278679.html
以下代码是经过改动的
******************************************************/
void MyClass::Dis_code(Mat image){Mat imageGray; // 所转化成的灰度图像 //定义一个扫描仪 ImageScanner scanner;scanner.set_config(ZBAR_NONE, ZBAR_CFG_ENABLE, 1);cvtColor(image, imageGray, CV_RGB2GRAY);//imshow("灰度图", imageGray);// 获取所摄取图像的长和宽 int width = imageGray.cols;int height = imageGray.rows;// 在Zbar中进行扫描时候,需要将OpenCV中的Mat类型转换为(uchar *)类型,raw中存放的是图像的地址;对应的图像需要转成Zbar中对应的图像zbar::Image uchar *raw = (uchar *)imageGray.data;Image imageZbar(width, height, "Y800", raw, width * height);// 扫描相应的图像imageZbar(imageZbar是zbar::Image类型,存储着读入的图像) scanner.scan(imageZbar); //扫描条码 Image::SymbolIterator symbol = imageZbar.symbol_begin();if (imageZbar.symbol_begin() == imageZbar.symbol_end()){cout << "查询条码失败,请检查图片!" << endl;}for (; symbol != imageZbar.symbol_end(); ++symbol){cout << "类型:" << endl << symbol->get_type_name() << endl << endl;cout << "条码:" << endl << symbol->get_data() << endl << endl;}//waitKey(); // 等待按下esc键,若需要延时1s则改用waitKey(1000); // 将图像中的数据置为0 imageZbar.set_data(NULL, 0);//system("pause");
}
/******************************************************
函数名称: Run
函数功能: 开始
传入参数:
返 回 值:
建立时间: 2018-05-19
修改时间:
建 立 人: 范泽华
修 改 人:
其它说明:
******************************************************/
void MyClass::Run(){Mat image;image = getGray(srcimage,true);//获取灰度图image = getGass(image, true);//高斯平滑滤波image = getSobel(image, true);//Sobel x—y梯度差image = getBlur(image, true);//均值滤波除高频噪声image = getThold(image, true);//二值化image = getBys(image, true);//闭运算image = getErode(image, true);//腐蚀image = getDilate(image, true);//膨胀image = getRect(image, srcimage, true);//获取ROI//imshow("最后的图", image);Dis_code(image);//waitKey();
}
/******************************************************
函数名称: QrRun
函数功能: 开始
传入参数:
返 回 值:
建立时间: 2018-05-19
修改时间:
建 立 人: 范泽华
修 改 人:
其它说明:
******************************************************/
void MyClass::QrRun(){RNG rng(12345);//imshow("原图", srcimage);Mat src_all = srcimage.clone();Mat src_gray;//灰度处理src_gray = getBlur(getGray(srcimage));WriteFile(src_gray, "getGray");//Mat image;//image = getGray(srcimage,true);//获取灰度图//image = getGass(image, true);//高斯平滑滤波//image = getSobel(image, true);//Sobel x—y梯度差//image = getBlur(image, true);//均值滤波除高频噪声//image = getThold(image, true);//二值化//image = getBys(image, true);//闭运算//image = getErode(image, true);//腐蚀//image = getDilate(image, true);//膨胀//image = getRect(image, srcimage, true);//获取ROI//imshow("最后的图", image);//Dis_code(image);Scalar color = Scalar(1, 1, 255);Mat threshold_output;std::vector<std::vector<Point> > contours, contours2;std::vector<Vec4i> hierarchy;Mat drawing = Mat::zeros(srcimage.size(), CV_8UC3);Mat drawing2 = Mat::zeros(srcimage.size(), CV_8UC3);Mat drawingAllContours = Mat::zeros(srcimage.size(), CV_8UC3);threshold_output = getThold(src_gray);WriteFile(threshold_output, "getThold");//threshold_output = getBys(threshold_output, true);//闭运算//threshold_output = getErode(threshold_output, true);//腐蚀//threshold_output = getDilate(threshold_output, true);//膨胀findContours(threshold_output, contours, hierarchy, CV_RETR_TREE, CHAIN_APPROX_NONE, Point(0, 0));int c = 0, ic = 0, k = 0, area = 0;// 边缘检测 //通过黑色定位角作为父轮廓,有两个子轮廓的特点,筛选出三个定位角 int parentIdx = -1;for (int i = 0; i< contours.size(); i++){//画出所有轮廓图 drawContours(drawingAllContours, contours, parentIdx, CV_RGB(255, 255, 255), 1, 8);if (hierarchy[i][2] != -1 && ic == 0){parentIdx = i;ic++;}else if (hierarchy[i][2] != -1){ic++;}else if (hierarchy[i][2] == -1){ic = 0;parentIdx = -1;}//特征轮廓检测 - 》//有两个子轮廓 if (ic >= 2){//保存找到的三个黑色定位角 contours2.push_back(contours[parentIdx]);//画出三个黑色定位角的轮廓 drawContours(drawing, contours, parentIdx, CV_RGB(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)), 1, 8);ic = 0;parentIdx = -1;}}//提取特征点 //填充的方式画出黑色定位角的轮廓WriteFile(drawing, "drawing");WriteFile(drawingAllContours, "drawingAllContours");for (int i = 0; i<contours2.size(); i++){drawContours(drawing2, contours2, i, CV_RGB(rng.uniform(100, 255), rng.uniform(100, 255), rng.uniform(100, 255)), -1, 4, hierarchy[k][2], 0, Point());}WriteFile(drawing2, "drawing2");//获取定位角的中心坐标 std::vector<Point> pointfind;for (int i = 0; i < contours2.size(); i++){pointfind.push_back(Center_cal(contours2, i));}//排除干扰点Mat dst;Point point[3]; double angle; Mat rot_mat;///选择合适的点-核心筛选if (pointfind.size()>3){double lengthA = 10000000000000000LLU, lengthB = 10000000000000000LLU;for (int i = 0; i < pointfind.size(); i++){for (int j = 0; j < pointfind.size(); j++){for (int k = 0; k < pointfind.size(); k++){if (i != j&&j != k&&i != k){double dxa, dxb,dya,dyb;double k1, k2, wa, wb;dxa = pointfind[i].x - pointfind[j].x;dxb = pointfind[i].x - pointfind[k].x;dya = pointfind[i].y - pointfind[j].y;dyb = pointfind[i].y - pointfind[k].y;if (dxa == 0 || dxb == 0)continue;k1 = dya/dxa;k2 = dyb/dxb ;wa = sqrt(pow(dya, 2) + pow(dya, 2));wb = sqrt(pow(dyb, 2) + pow(dxb, 2));double anglea = abs(atan(k1) * 180 / CV_PI) + abs(atan(k2) * 180 / CV_PI);if (int(anglea)>=85&&int(anglea)<=95&&wa<=lengthA&&wb<=lengthB){lengthA = wa;lengthB = wb;point[0] = pointfind[i];point[1] = pointfind[j];point[2] = pointfind[k];}}}}}}else{for (int i = 0; i < 3; i++){point[i] = pointfind[i];}}//绘制直角三角形 //计算轮廓的面积,计算定位角的面积,从而计算出边长 area = contourArea(contours2[0]);int area_side = cvRound(sqrt(double(area)));for (int i = 0; i < 3; i++){line(drawing2, point[i], point[(i + 1)%3], color, area_side / 2, 8);}WriteFile(drawing2, "line");//纠正旋转//判断是否正对if (!IsCorrect(point)){//进入修正环节double angle; Mat rot_mat;int start = 0;for (int i = 0; i < 3; i++){double k1, k2,kk;k1 = (point[i].y - point[(i + 1) % 3].y) / (point[i].x - point[(i + 1) % 3].x);k2 = (point[i].y - point[(i + 2) % 3].y) / (point[i].x - point[(i + 2) % 3].x);kk = k1*k2;if (k1*k2 <0){start = i;}}double ax, ay, bx, by;ax = point[(start + 1) % 3].x;ay = point[(start + 1) % 3].y;bx = point[(start + 2) % 3].x;by = point[(start + 2) % 3].y;Point2f center(abs(ax - bx) / 2, abs(ay -by)/ 2);double dy = ay - by;double dx = ax - bx;double k3 = dy / dx;angle =atan(k3) * 180 / CV_PI;//转化角度rot_mat = getRotationMatrix2D(center, angle, 1.0);warpAffine(src_all, dst, rot_mat, src_all.size(), 1, 0, 0);//旋转原图查看warpAffine(drawing2, drawing2, rot_mat, src_all.size(), 1, 0, 0);//旋转连线图warpAffine(src_all, src_all, rot_mat, src_all.size(), 1, 0, 0);//旋转原图//namedWindow("Dst");//imshow("Dst", dst);}//namedWindow("DrawingAllContours");//imshow("DrawingAllContours", drawingAllContours);//namedWindow("Drawing2");//imshow("Drawing2", drawing2);//namedWindow("Drawing");//imshow("Drawing", drawing);//提取ROI//接下来要框出这整个二维码 Mat gray_all, threshold_output_all;std::vector<std::vector<Point> > contours_all;std::vector<Vec4i> hierarchy_all;cvtColor(drawing2, gray_all, CV_BGR2GRAY);WriteFile(gray_all, "gray_all");threshold(gray_all, threshold_output_all, 45, 255, THRESH_BINARY);WriteFile(threshold_output_all, "threshold_output_all");findContours(threshold_output_all, contours_all, hierarchy_all, RETR_EXTERNAL, CHAIN_APPROX_NONE, Point(0, 0));//RETR_EXTERNAL表示只寻找最外层轮廓 Point2f fourPoint2f[4];//求最小包围矩形//std::vector<Point2f> contours_tmp;RotatedRect rectPoint = minAreaRect(contours_all[0]);//pointfind.size()-3//将rectPoint变量中存储的坐标值放到 fourPoint的数组中 rectPoint.points(fourPoint2f);int maxx = 0, maxy = 0, minx = 100000, miny = 100000;for (int i = 0; i < 4; i++){if (maxx < fourPoint2f[i].x)maxx = fourPoint2f[i].x;if (maxy < fourPoint2f[i].y)maxy = fourPoint2f[i].y;if (minx > fourPoint2f[i].x)minx = fourPoint2f[i].x;if (miny > fourPoint2f[i].y)miny = fourPoint2f[i].y;line(src_all, fourPoint2f[i % 4], fourPoint2f[(i + 1) % 4], Scalar(0), 3);}//namedWindow("Src_all");///边际处理int set_inter = 1;while (false){minx -= set_inter;miny -= set_inter;maxx += set_inter;maxy += set_inter;if (maxx > srcimage.size().width || maxy > srcimage.size().height || minx < 0 || miny < 0){minx += set_inter;miny += set_inter;maxx -= set_inter;maxy -= set_inter;set_inter--;}else{break;}}//imshow("Src_all", src_all(Rect(minx, miny, maxx - minx, maxy - miny)));//ROIMat fout = src_all(Rect(minx, miny, maxx - minx, maxy - miny));//ROIWriteFile(fout, "fout");//识别Dis_code(fout);//waitKey(0);//destroyAllWindows();
}
/******************************************************
函数名称: getGray
函数功能: 灰度处理
传入参数: Mat image
返 回 值:
建立时间: 2018-05-19
修改时间:
建 立 人: 范泽华
修 改 人:
其它说明:
******************************************************/
Mat MyClass::getGray(Mat image, bool show){Mat cimage;cvtColor(image, cimage, CV_RGBA2GRAY);//if (show)//imshow("灰度图", cimage);return cimage;
}
/******************************************************
函数名称: getGass
函数功能: 高斯滤波处理
传入参数: Mat image
返 回 值:
建立时间: 2018-05-19
修改时间:
建 立 人: 范泽华
修 改 人:
其它说明:
******************************************************/
Mat MyClass::getGass(Mat image, bool show){Mat cimage;GaussianBlur(image, cimage, Size(3, 3), 0);//if (show)//imshow("高斯滤波图", cimage);return cimage;
}
/******************************************************
函数名称: getSobel
函数功能: Sobel处理
传入参数: Mat image
返 回 值:
建立时间: 2018-05-19
修改时间:
建 立 人: 范泽华
修 改 人:
其它说明:
******************************************************/
Mat MyClass::getSobel(Mat image, bool show){Mat cimageX16s, cimageY16s, imageSobelX, imageSobelY, out;Sobel(image, cimageX16s, CV_16S, 1, 0, 3, 1, 0, 4);Sobel(image, cimageY16s, CV_16S, 0, 1, 3, 1, 0, 4);convertScaleAbs(cimageX16s, imageSobelX, 1, 0);convertScaleAbs(cimageY16s, imageSobelY, 1, 0);out = imageSobelX - imageSobelY;//if (show)//imshow("Sobelx-y差 图", out);return out;
}
/******************************************************
函数名称: getThold
函数功能: 二值化处理
传入参数: Mat image
返 回 值:
建立时间: 2018-05-19
修改时间:
建 立 人: 范泽华
修 改 人:
其它说明:
******************************************************/
Mat MyClass::getThold(Mat image, bool show){Mat cimage;threshold(image, cimage, 112, 255, CV_THRESH_BINARY);//if (show)//imshow("二值化图", cimage);return cimage;
}
/******************************************************
函数名称: getBys
函数功能: 闭运算处理
传入参数: Mat image
返 回 值:
建立时间: 2018-05-19
修改时间:
建 立 人: 范泽华
修 改 人:
其它说明:
******************************************************/
Mat MyClass::getBys(Mat image, bool show){morphologyEx(image, image, MORPH_CLOSE, element);//if (show)//imshow("闭运算图", image);return image;
}
/******************************************************
函数名称: getBlur
函数功能: 均值滤波处理
传入参数: Mat image
返 回 值:
建立时间: 2018-05-19
修改时间:
建 立 人: 范泽华
修 改 人:
其它说明:
******************************************************/
Mat MyClass::getBlur(Mat image, bool show){Mat cimage;blur(image, cimage, Size(3, 3));//if (show)//imshow("均值滤波图", cimage);return cimage;
}
/******************************************************
函数名称: getErode
函数功能: 腐蚀处理
传入参数: Mat image
返 回 值:
建立时间: 2018-05-19
修改时间:
建 立 人: 范泽华
修 改 人:
其它说明:
******************************************************/
Mat MyClass::getErode(Mat image, bool show){//Mat cimage;erode(image, image, element);//if (show)//imshow("腐蚀图", image);return image;
}
/******************************************************
函数名称: getDilate
函数功能: 膨胀处理
传入参数: Mat image
返 回 值:
建立时间: 2018-05-19
修改时间:
建 立 人: 范泽华
修 改 人:
其它说明:
******************************************************/
Mat MyClass::getDilate(Mat image, bool show){for (int i = 0; i < 3; i++)dilate(image, image, element);//if (show)//imshow("膨胀图", image);return image;
}
/******************************************************
函数名称: getRect
函数功能: 获取码的区域
传入参数: Mat image, Mat simage原图
返 回 值:
建立时间: 2018-05-19
修改时间:
建 立 人: 范泽华
修 改 人:
其它说明:
******************************************************/
Mat MyClass::getRect(Mat image, Mat simage, bool show){std::vector<std::vector<Point>> contours;std::vector<Vec4i> hiera;Mat cimage;findContours(image, contours, hiera, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);std::vector<float>contourArea;for (int i = 0; i < contours.size(); i++){contourArea.push_back(cv::contourArea(contours[i]));}//找出面积最大的轮廓double maxValue; Point maxLoc;minMaxLoc(contourArea, NULL, &maxValue, NULL, &maxLoc);//计算面积最大的轮廓的最小的外包矩形RotatedRect minRect = minAreaRect(contours[maxLoc.x]);//为了防止找错,要检查这个矩形的偏斜角度不能超标//如果超标,那就是没找到if (minRect.angle<2.0){//找到了矩形的角度,但是这是一个旋转矩形,所以还要重新获得一个外包最小矩形Rect myRect = boundingRect(contours[maxLoc.x]);//把这个矩形在源图像中画出来//rectangle(srcImage,myRect,Scalar(0,255,255),3,LINE_AA);//看看显示效果,找的对不对//imshow(windowNameString,srcImage);//将扫描的图像裁剪下来,并保存为相应的结果,保留一些X方向的边界,所以对rect进行一定的扩张myRect.x = myRect.x - (myRect.width / 20);myRect.width = myRect.width*1.1;Mat resultImage = Mat(srcimage, myRect);return resultImage;}for (int i = 0; i<contours.size(); i++){Rect rect = boundingRect((Mat)contours[i]);//cimage = simage(rect);rectangle(simage, rect, Scalar(0), 2);//if (show)//imshow("转变图", simage);}return simage;
}
/******************************************************
函数名称: getRect
函数功能: 获取轮廓的中心点
传入参数: vector<vector<Point> > contours, int i
返 回 值:
建立时间: 2018-05-19
修改时间:
建 立 人: 范泽华
修 改 人:
其它说明:
******************************************************/
Point MyClass::Center_cal(std::vector<std::vector<Point> > contours, int i)
{int centerx = 0, centery = 0, n = contours[i].size();//在提取的小正方形的边界上每隔周长个像素提取一个点的坐标, //求所提取四个点的平均坐标(即为小正方形的大致中心) centerx = (contours[i][n / 4].x + contours[i][n * 2 / 4].x + contours[i][3 * n / 4].x + contours[i][n - 1].x) / 4;centery = (contours[i][n / 4].y + contours[i][n * 2 / 4].y + contours[i][3 * n / 4].y + contours[i][n - 1].y) / 4;Point point1 = Point(centerx, centery);return point1;
}
/******************************************************
函数名称: getRotate
函数功能: 旋转保留原画
传入参数:
返 回 值:
建立时间: 2018-05-19
修改时间:
建 立 人: 范泽华
修 改 人:
其它说明:
******************************************************/
Mat MyClass::getRotate(Mat image, double angle)
{IplImage imgTmp = cvIplImage(image);IplImage *img = cvCloneImage(&imgTmp);double a = sin(angle), b = cos(angle);int width = img->width, height = img->height;//旋转后的新图尺寸 int width_rotate = int(height * fabs(a) + width * fabs(b));int height_rotate = int(width * fabs(a) + height * fabs(b));IplImage* img_rotate = cvCreateImage(cvSize(width_rotate, height_rotate), img->depth, img->nChannels);cvZero(img_rotate);//保证原图可以任意角度旋转的最小尺寸 int tempLength = sqrt((double)width * width + (double)height *height) + 10;int tempX = (tempLength + 1) / 2 - width / 2;int tempY = (tempLength + 1) / 2 - height / 2;IplImage* temp = cvCreateImage(cvSize(tempLength, tempLength), img->depth, img->nChannels);cvZero(temp);//将原图复制到临时图像tmp中心 cvSetImageROI(temp, cvRect(tempX, tempY, width, height));cvCopy(img, temp, NULL);cvResetImageROI(temp);//旋转数组map // [ m0 m1 m2 ] ===> [ A11 A12 b1 ] // [ m3 m4 m5 ] ===> [ A21 A22 b2 ] float m[6];int w = temp->width;int h = temp->height;m[0] = b;m[1] = a;m[3] = -m[1];m[4] = m[0];// 将旋转中心移至图像中间 m[2] = w * 0.5f;m[5] = h * 0.5f;CvMat M = cvMat(2, 3, CV_32F, m);cvGetQuadrangleSubPix(temp, img_rotate, &M);cvReleaseImage(&temp);Mat out=cvarrToMat(img_rotate);return out;
}
/******************************************************
函数名称: IsCorrect
函数功能: 旋转保留原画
传入参数:
返 回 值:
建立时间: 2018-05-19
修改时间:
建 立 人: 范泽华
修 改 人:
其它说明:
******************************************************/
bool MyClass::IsCorrect(Point point[]){for (int i = 0; i < 3; i++){if (point[i].x == point[(i + 1) % 3].x&&point[i].y == point[(i + 2) % 3].y)return true;if (point[i].y == point[(i + 1) % 3].y&&point[i].x == point[(i + 2) % 3].x)return true;}return false;
}
int main(int argc, char **argv)
{if (argc < 2){MyClass *myclass = new MyClass();//myclass->Run();myclass->QrRun();delete myclass;}else{MyClass *myclass = new MyClass(argv);myclass->Run();myclass->QrRun();delete myclass;}return 0;
}
Makefile
```bash
TOP_DIR=$(shell pwd)/..MAIN_DIR:=$(shell pwd)
EXE_NAME:=$(MAIN_DIR)/mainCROSS_COMPILE=arm-himix100-linux-CC=$(CROSS_COMPILE)gcc
CXX=$(CROSS_COMPILE)g++
CPP=$(CC) -E
LD=$(CROSS_COMPILE)ld
AS=$(CROSS_COMPILE)as
STRIP:=$(CROSS_COMPILE)stripCFLAGS:= -Werror -std=c++11CFLAGS += -O0 -gLDFLAGS:=
MAKE=make##############################################################
# 源文件 && 库文件
##############################################################
PROJECT_SRC:=
PROJECT_INC:=
STATIC_LIB_LIST:=#-------------------------- main -----------------------------
PROJECT_SRC += $(MAIN_DIR)/main.cpp#************************ MODULE *******************************####################################################################
# 静态库
#####################################################################------------------------- opencv ----------------------------
STATIC_LIB_LIST+=opencv/install/lib/libopencv_features2d.a
STATIC_LIB_LIST+=opencv/install/lib/libopencv_imgcodecs.a
STATIC_LIB_LIST+=opencv/install/lib/libopencv_video.a
STATIC_LIB_LIST+=opencv/install/lib/libopencv_imgproc.a
STATIC_LIB_LIST+=opencv/install/lib/libopencv_highgui.a
STATIC_LIB_LIST+=opencv/install/lib/libopencv_core.a
STATIC_LIB_LIST+=opencv/install/lib/opencv4/3rdparty/liblibjpeg-turbo.a
STATIC_LIB_LIST+=opencv/install/lib/opencv4/3rdparty/liblibpng.a
STATIC_LIB_LIST+=opencv/install/lib/opencv4/3rdparty/libzlib.a
STATIC_LIB_LIST+=opencv/install/lib/opencv4/3rdparty/libittnotify.a
STATIC_LIB_LIST+=opencv/install/lib/opencv4/3rdparty/liblibopenjp2.a
STATIC_LIB_LIST+=opencv/install/lib/opencv4/3rdparty/libquirc.a
PROJECT_INC += -Iopencv/install/include/opencv4#------------------------- zbar ----------------------------
STATIC_LIB_LIST+=zbar-0.10/installxyy/lib/libzbar.a
PROJECT_INC += -Izbar-0.10/installxyy/include# sensor
#LDFLAGS += -L$(RS_SENSORLIB_DIR)/lib/$(GCC_TYPE)/$(CPU_TYPE) -lsensor# static libs
LDFLAGS += $(STATIC_LIB_LIST)LDFLAGS += -lpthread -lm -ldlCFLAGS += $(PROJECT_INC)OBJECTS_DIR:=$(MAIN_DIR)/object
DEPFILE:=$(MAIN_DIR)/deps
OBJECT_FILE:=$(addprefix $(OBJECTS_DIR)/, $(addsuffix .o, $(basename $(notdir $(PROJECT_SRC))))).PHONY:all
all: $(DEPFILE) $(EXE_NAME)$(DEPFILE): $(PROJECT_SRC) Makefile@echo "Generating new dependency file ...";@-rm -f $(DEPFILE)@for f in $(PROJECT_SRC); do \OBJ=$(OBJECTS_DIR)/`basename $$f|sed -e 's/\.cpp/\.o/' -e 's/\.c/\.o/'`; \echo $$OBJ: $$f>> $(DEPFILE); \echo ' @$(CXX) $$(CFLAGS) -c -o $$@ $$^; echo "[`date '+%H:%M:%S.%N'`] $(CXX) -> $$(notdir $$@)"'>> $(DEPFILE); \done-include $(DEPFILE)############################################
$(EXE_NAME): $(OBJECT_FILE)@echo "linking all objects ..."@$(CXX) $(CFLAGS) $(OBJECT_FILE) -o "$@" $(LDFLAGS); echo "[`date '+%H:%M:%S.%N'`] $(CXX) -> $@"@chmod 777 $(MAIN_DIR)/main.PHONY:clean
clean:@rm -rf $(EXE_NAME)@rm -rf $(DEPFILE)@rm -rf $(OBJECTS_DIR)/*.o
Linux OpenCV + zBar 实现二维码识别相关推荐
- OpenCV+Zbar扫描二维码
之前做了个opencv识别二维码数据上传云数据库端,虽然后买呢拿扫码枪做了,还是记录下,二维码解码我用的zbar,zbar解码出来中文会有乱码,需要转码,我找了网上的方法转码,有的可以转码成功有的还是 ...
- 利用Opencv+Python 实现二维码识别
准备工作: 二维码图片,我这里直接打印在了一张A4纸上,或者直接在草料网站上生成 草料二维码生成器,存放在手机上进行显示.在安装条码扫描库的时候大家注意:zbar库只针对 python2 版本有支持, ...
- 【OpenCV】二维码识别
文章目录 前言 一.OpenCV自带二维码识别功能 二.使用pyzbar识别 三.串口发送数据 四.播放音乐 总结 前言 最终实现视频动态识别二维码. 一.OpenCV自带二维码识别功能 import ...
- C语言的二维码识别驱动
二维码识别驱动是一种软件,它用于识别二维码图像中包含的信息.在 C 语言中,你可以使用一些图像处理库,如 OpenCV 来实现二维码识别驱动.首先,你需要读取图像并将其转换为可以处理的灰度图像.然后, ...
- 二维码识别 基于stm32 ov7725
二维码识别 基于stm32 ov7725 二维码识别技术在我们的生活中应用的很方便了,但基本都是基于手机的,目前在公交车上也存在了扫描二维码的机器,上次坏了之后,发现一只小企鹅,原来是基于linux的 ...
- Jetson nano 摄像头二维码识别 Opencv zbar QT
环境以及前言 环境 jetson nano Linux ubuntu 18.4 QT版本 QT5.98 摄像头 Csi摄像头 Opencv Jetson nano 自带的-.- 应该是4.1?不太清楚 ...
- 基于ZBar,OpenCV和Python的二维码识别
0 前言 今天分享一个之前做过的二维码识别,参考:https://www.pyimagesearch.com/2018/05/21/an-opencv-barcode-and-qr-code-scan ...
- Opencv+Zbar二维码识别(二维码校正)
二维码和车牌识别基本都会涉及到图像的校正,主要是形变和倾斜角度的校正,一种二维码的畸变如下图: 这个码用微信扫了一下,识别不出来,但是用Zbar还是可以准确识别的~~. 这里介绍一种二维码校正方法,通 ...
- Python基于pyzbar、opencv、pyqt5库,实现二维码识别 gui 应用程序开发
二维码组成结构基本介绍 二维码识别背景介绍 视觉的方法可以用来估计位置和姿态.最容易想到的是在目标上布置多个容易识别的特征,这样使用opencv相机标定和.相机畸变矫正.轮廓提取.solvepnp来获 ...
最新文章
- 【效率】微软开源最强Python自动化神器!不用写一行代码!
- pagefooter如何不占位置_小卫生间如何装修?照着小浴室装修效果图这样装
- 牛客-小w的魔术扑克【并查集】
- 【Python基础入门系列】第04天:Python 流程控制
- yarn vite vue3.x
- c语言结构引用6,C语言6结构体练习题6
- linux ps elf,Linux中ps -elf和ps aux的区别
- python treeview显示多列_Python Gtk TreeView列数据显示
- 关于windows server 2016 更新CVE-2020-1472漏洞补丁的问题
- php生成 优惠券 激活码
- 问题及解决 —— 浏览器问题
- 好看流光风格个人主页源码
- 药店零售管理php系统,医药POS零售管理系统
- 双网卡设置一个外网一个内网(两张网卡同时上内外网设置)
- 利用不共线三点求解并联机构动系在定系中的位姿
- Mono 3.2 测试NPinyin 中文转换拼音代码
- Chrome 浏览器
- 云服务器带宽解释及下载速度分析
- 德语翻译公司的前景及翻译公司推荐
- 轻量的web框架Bottle