-
Notifications
You must be signed in to change notification settings - Fork 202
/
Copy pathdemo.cpp
192 lines (155 loc) · 7.17 KB
/
demo.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/wechat_qrcode.hpp>
#include <string>
#include <vector>
class WeChatQRCode {
public:
WeChatQRCode(const std::string& detect_prototxt,
const std::string& detect_model,
const std::string& sr_prototxt, const std::string& sr_model,
int backend_target_index)
: backend_target_index_(backend_target_index) {
const std::vector<std::pair<int, int>> backend_target_pairs = {
{cv::dnn::DNN_BACKEND_OPENCV, cv::dnn::DNN_TARGET_CPU},
{cv::dnn::DNN_BACKEND_CUDA, cv::dnn::DNN_TARGET_CUDA},
{cv::dnn::DNN_BACKEND_CUDA, cv::dnn::DNN_TARGET_CUDA_FP16},
{cv::dnn::DNN_BACKEND_TIMVX, cv::dnn::DNN_TARGET_NPU},
{cv::dnn::DNN_BACKEND_CANN, cv::dnn::DNN_TARGET_NPU}};
if (backend_target_index_ < 0 ||
backend_target_index_ >= backend_target_pairs.size()) {
throw std::invalid_argument("Invalid backend-target index");
}
// initialize detector
detector_ = cv::makePtr<cv::wechat_qrcode::WeChatQRCode>(
detect_prototxt, detect_model, sr_prototxt, sr_model);
}
std::pair<std::vector<std::string>, std::vector<cv::Mat>> detect(
const cv::Mat& image) {
std::vector<std::string> results;
std::vector<cv::Mat> points;
results = detector_->detectAndDecode(image, points);
return {results, points};
}
cv::Mat visualize(const cv::Mat& image,
const std::vector<std::string>& results,
const std::vector<cv::Mat>& points,
cv::Scalar points_color = cv::Scalar(0, 255, 0),
cv::Scalar text_color = cv::Scalar(0, 255, 0),
double fps = -1) const {
cv::Mat output = image.clone();
if (fps >= 0) {
cv::putText(output, "FPS: " + std::to_string(fps), cv::Point(0, 15),
cv::FONT_HERSHEY_SIMPLEX, 0.5, text_color);
}
double fontScale = 0.5;
int fontSize = 1;
for (size_t i = 0; i < results.size(); ++i) {
const auto& p = points[i];
for (int r = 0; r < p.rows; ++r) {
cv::Point point(p.at<float>(r, 0), p.at<float>(r, 1));
cv::circle(output, point, 10, points_color, -1);
}
int qrcode_center_x = (p.at<float>(0, 0) + p.at<float>(2, 0)) / 2;
int qrcode_center_y = (p.at<float>(0, 1) + p.at<float>(2, 1)) / 2;
int baseline = 0;
cv::Size text_size =
cv::getTextSize(results[i], cv::FONT_HERSHEY_DUPLEX, fontScale,
fontSize, &baseline);
cv::Point text_pos(qrcode_center_x - text_size.width / 2,
qrcode_center_y + text_size.height / 2);
cv::putText(output, results[i], text_pos, cv::FONT_HERSHEY_DUPLEX,
fontScale, text_color, fontSize);
}
return output;
}
private:
int backend_target_index_;
cv::Ptr<cv::wechat_qrcode::WeChatQRCode> detector_;
};
int main(int argc, char** argv) {
cv::CommandLineParser parser(
argc, argv,
"{help h | | Show this help message.}"
"{input i | | Set path to the input image. Omit for using default camera.}"
"{detect_prototxt_path | detect_2021nov.prototxt | Set path to detect.prototxt.}"
"{detect_model_path | detect_2021nov.caffemodel | Set path to detect.caffemodel.}"
"{sr_prototxt_path | sr_2021nov.prototxt | Set path to sr.prototxt.}"
"{sr_model_path | sr_2021nov.caffemodel | Set path to sr.caffemodel.}"
"{backend_target bt | 0 | Choose one of the backend-target pairs to run this demo.}"
"{save s | false | Specify to save file with results.}"
"{vis v | false | Specify to open a new window to show results.}");
if (parser.has("help")) {
parser.printMessage();
return 0;
}
// get paths
std::string detect_prototxt = parser.get<std::string>("detect_prototxt_path");
std::string detect_model = parser.get<std::string>("detect_model_path");
std::string sr_prototxt = parser.get<std::string>("sr_prototxt_path");
std::string sr_model = parser.get<std::string>("sr_model_path");
int backend_target_index = parser.get<int>("backend_target");
// input check
std::string input_path = parser.get<std::string>("input");
bool save_result = parser.get<bool>("save");
bool visualize_result = parser.get<bool>("vis");
try {
WeChatQRCode qrDetector(detect_prototxt, detect_model, sr_prototxt,
sr_model, backend_target_index);
if (!input_path.empty()) {
// process image
cv::Mat image = cv::imread(input_path);
if (image.empty()) {
std::cerr << "Could not read the image" << std::endl;
return -1;
}
std::pair<std::vector<std::string>, std::vector<cv::Mat>> detectionResult = qrDetector.detect(image);
auto& results = detectionResult.first;
auto& points = detectionResult.second;
for (const auto& result : results) {
std::cout << result << std::endl;
}
cv::Mat result_image = qrDetector.visualize(image, results, points);
if (save_result) {
cv::imwrite("result.jpg", result_image);
std::cout << "Results saved to result.jpg" << std::endl;
}
if (visualize_result) {
cv::imshow(input_path, result_image);
cv::waitKey(0);
}
} else {
// process camera
cv::VideoCapture cap(0);
if (!cap.isOpened()) {
std::cerr << "Error opening camera" << std::endl;
return -1;
}
cv::Mat frame;
cv::TickMeter tm;
while (true) {
cap >> frame;
if (frame.empty()) {
std::cout << "No frames grabbed" << std::endl;
break;
}
std::pair<std::vector<std::string>, std::vector<cv::Mat>> detectionResult = qrDetector.detect(frame);
auto& results = detectionResult.first;
auto& points = detectionResult.second;
tm.start();
double fps = tm.getFPS();
tm.stop();
cv::Mat result_frame = qrDetector.visualize(
frame, results, points, cv::Scalar(0, 255, 0),
cv::Scalar(0, 255, 0), fps);
cv::imshow("WeChatQRCode Demo", result_frame);
tm.reset();
if (cv::waitKey(1) >= 0) break;
}
}
} catch (const std::exception& ex) {
std::cerr << "Error: " << ex.what() << std::endl;
return -1;
}
return 0;
}