下载模型 https://github.com/WeChatCV/opencv_3rdparty
opencv 4.5
头文件
#ifndef LANDROIDQRCODE_HPP
#define LANDROIDQRCODE_HPP
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <opencv2/opencv.hpp>
#include <opencv2/objdetect.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/wechat_qrcode.hpp>
#define HIGH_RESOLUTION true
#define DECODE_IMG_UNDISTORT true
#define USE_WECHAT_DECODE true
#ifdef ON_ARM
#define CAM_ID 3
#define DECODE_IMG_VISUALIZATION false
#endif
#ifdef ON_X86
#define CAM_ID 2
#define DECODE_IMG_VISUALIZATION true
#endif
struct SsidPass
{
std::string ssid;
std::string pass;
std::string otid;
};
class LandroidQRcode
{
public:
LandroidQRcode();
~LandroidQRcode(){};
bool wechatQRDecode();
bool decodeFrameQR(SsidPass &);
bool decodeImageQR(SsidPass &);
void QRCodeShow(cv::Mat &img, std::vector<cv::Point> &points) const;
template <typename T>
void initPub();
void decodePublish();
void connectWifi();
bool EnableQRcode();
bool ScanQRcode(SsidPass &);
bool ScanQRcode(SsidPass &ssid_pass,cv::Mat &img_in);
bool SaveQRcode() const;
bool DisableQRcode();
cv::VideoCapture cap_;
std::string data_;
private:
const int img_width_ = (HIGH_RESOLUTION) ? 1920 : 640;
const int img_height_ = (HIGH_RESOLUTION) ? 1080 : 360;
cv::Mat frame_;
cv::Mat map1_, map2_;
cv::QRCodeDetector decoder_ = cv::QRCodeDetector();
std::vector<cv::Point> points_;
std::string ssid_, psk_;
};
#endif
函数
#include "LandroidQRcode.hpp"
std::string id_end="\"psk\": \"";
LandroidQRcode::LandroidQRcode()
{
ssid_ = "";
psk_ = "";
cv::Mat K, D;
if (HIGH_RESOLUTION)
{
K = (cv::Mat_<double>(3, 3) << 947.32408, 0.0, 1011.14141, 0.0, 951.18813, 590.92158, 0.0, 0.0, 1.0);
D = (cv::Mat_<double>(5, 1) << -0.335576, 0.085014, 0.001744, -0.003825, 0.000000);
}
else
{
K = (cv::Mat_<double>(3, 3) << 319.1774094207188, 0.0, 315.9695951747343, 0.0, 319.5137994758127, 199.07306955419622, 0.0, 0.0, 1.0);
D = (cv::Mat_<double>(5, 1) << -0.3204769598908819, 0.07196729379479753, -0.0019994529282904004, 0.0008377275431221735, 0.0);
}
cv::Size img_size(img_width_, img_height_);
const double alpha = 1;
// cv::Mat NewCameraMatrix = getOptimalNewCameraMatrix(K, D, img_size, alpha, img_size, 0);
initUndistortRectifyMap(K, D, cv::Mat(), K, img_size, CV_16SC2, map1_, map2_);
}
bool LandroidQRcode::wechatQRDecode()
{
cv::Ptr<cv::wechat_qrcode::WeChatQRCode> wechat_detector;
std::string detect_prototxt = "./wechat_lib/detect.prototxt";
std::string detect_caffe_model = "./wechat_lib/detect.caffemodel";
std::string sr_prototxt = "./wechat_lib/sr.prototxt";
std::string sr_caffe_model = "./wechat_lib/sr.caffemodel";
try
{
wechat_detector = cv::makePtr<cv::wechat_qrcode::WeChatQRCode>(
detect_prototxt, detect_caffe_model, sr_prototxt, sr_caffe_model);
}
catch (const std::exception &e)
{
std::cout << e.what() << std::endl;
}
std::vector<cv::Mat> points;
std::vector<std::string> res = wechat_detector->detectAndDecode(frame_, points);
if (res.size())
{
data_ = res[0];
return true;
}
else
return false;
}
bool LandroidQRcode::decodeFrameQR(SsidPass &ssid_pass)
{
if (DECODE_IMG_UNDISTORT)
{
cv::Mat UndistortImage;
remap(frame_, UndistortImage, map1_, map2_, cv::INTER_LINEAR);
frame_ = UndistortImage;
// cv::imwrite("UndistortImage.png", frame_);
}
if (DECODE_IMG_VISUALIZATION)
{
cv::imshow("to detect img", frame_);
cv::waitKey(1);
}
bool if_detected = false;
if (USE_WECHAT_DECODE)
if_detected = wechatQRDecode();
else
{
data_ = decoder_.detectAndDecode(frame_, points_);
if (!points_.empty())
if_detected = true;
}
if (if_detected)
{
//std::cout << "QR raw data: " << data_ << std::endl;
if ((!data_.empty()) && data_[0] == '{')
{
int index=data_.find(id_end,10);
//std::cout<<"*****************"<<index<<std::endl;
ssid_pass.ssid=data_.substr(10,index-13);
ssid_pass.pass=data_.substr(index+8,data_.length()-index-8-2);
return true;
}
if (DECODE_IMG_VISUALIZATION && (not USE_WECHAT_DECODE))
QRCodeShow(frame_, points_);
}
else
return false;
}
bool LandroidQRcode::decodeImageQR(SsidPass &ssid_pass)
{
frame_ = cv::imread("test.jpg");
return decodeFrameQR(ssid_pass);
}
void LandroidQRcode::QRCodeShow(cv::Mat &img, std::vector<cv::Point> &points) const
{
for (int i = 0; i < points.size(); i++)
{
cv::Point pt1 = points[i];
cv::Point pt2 = points[(i + 1) % 4];
line(img, pt1, pt2, cv::Scalar(255, 0, 0), 3);
}
imshow("Detected QR code", img);
cv::waitKey(2);
}
bool LandroidQRcode::EnableQRcode()
{
cap_ = cv::VideoCapture(CAM_ID);
std::cout << "Video captured." << std::endl;
cap_.set(cv::CAP_PROP_FRAME_WIDTH, img_width_);
cap_.set(cv::CAP_PROP_FRAME_HEIGHT, img_height_);
cv::TickMeter meter;
meter.start();
if (!cap_.isOpened())
{
std::cerr << "Couldn't open video capture device" << CAM_ID << std::endl;
return false;
}
else
{
meter.stop();
std::cout << "Detector initialized in " << std::fixed << std::setprecision(3)
<< meter.getTimeSec() << "s"
<< ", " << cap_.get(cv::CAP_PROP_FRAME_WIDTH)
<< "x" << cap_.get(cv::CAP_PROP_FRAME_HEIGHT) << " @"
<< cap_.get(cv::CAP_PROP_FPS) << "FPS" << std::endl;
meter.reset();
return true;
}
}
bool LandroidQRcode::ScanQRcode(SsidPass &ssid_pass)
{
cap_ >> frame_;
return decodeFrameQR(ssid_pass);
}
bool LandroidQRcode::ScanQRcode(SsidPass &ssid_pass,cv::Mat &img_in)
{
frame_=img_in;
return decodeFrameQR(ssid_pass);
}
bool LandroidQRcode::DisableQRcode()
{
cap_.release();
cv::destroyAllWindows();
std::cout << "Cam " << CAM_ID << " released." << std::endl;
return true;
}
执行
#include "LandroidQRcode.hpp"
#include <unistd.h>
int main()
{
LandroidQRcode QR_decoder;
SsidPass ssid_pass;
cv::Mat my_img;
if (!QR_decoder.EnableQRcode())//打开相机
return 0;
// scan QR by cam video
while (1)
{
QR_decoder.cap_>>my_img;//将相机存入图片,可将图片存入
if(QR_decoder.ScanQRcode(ssid_pass,my_img))
std::cout << "QR detected:"
<< ssid_pass.ssid<<"/"<< ssid_pass.pass << std::endl;
usleep(100000);
}
QR_decoder.DisableQRcode();//断开相机
return 0;
}
cmake文件
cmake_minimum_required(VERSION 3.1)
project( LandroidQRcode LANGUAGES C CXX)
include_directories(include)
find_package(Boost REQUIRED)
set (ON_ARM "OFF")
if(ON_ARM)
add_definitions(-DON_ARM)
else()
add_definitions(-DON_X86)
endif()
find_package( OpenCV REQUIRED)
add_executable( QR_main src/QR_main.cpp src/LandroidQRcode.cpp)
target_link_libraries( QR_main ${OpenCV_LIBS})
install(TARGETS QR_main RUNTIME DESTINATION bin)