1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-29 15:23:05 +04:00

Merge branch 4.x

This commit is contained in:
Alexander Smorkalov
2023-07-12 13:42:01 +03:00
128 changed files with 9936 additions and 932 deletions
+223
View File
@@ -0,0 +1,223 @@
#include <iostream>
#include "opencv2/objdetect.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
using namespace cv;
using namespace std;
static const Scalar greenColor(0, 255, 0);
static const Scalar redColor(0, 0, 255);
static const Scalar yellowColor(0, 255, 255);
static Scalar randColor()
{
RNG &rng = theRNG();
return Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
}
//==============================================================================
struct TheApp
{
Ptr<barcode::BarcodeDetector> bardet;
//! [output]
vector<Point> corners;
vector<string> decode_info;
vector<string> decode_type;
//! [output]
bool detectOnly;
void cleanup()
{
corners.clear();
decode_info.clear();
decode_type.clear();
}
inline string modeString() const
{
return detectOnly ? "<detect>" : "<detectAndDecode>";
}
void drawResults(Mat &frame) const
{
//! [visualize]
for (size_t i = 0; i < corners.size(); i += 4)
{
const size_t idx = i / 4;
const bool isDecodable = idx < decode_info.size()
&& idx < decode_type.size()
&& !decode_type[idx].empty();
const Scalar lineColor = isDecodable ? greenColor : redColor;
// draw barcode rectangle
vector<Point> contour(corners.begin() + i, corners.begin() + i + 4);
const vector< vector<Point> > contours {contour};
drawContours(frame, contours, 0, lineColor, 1);
// draw vertices
for (size_t j = 0; j < 4; j++)
circle(frame, contour[j], 2, randColor(), -1);
// write decoded text
if (isDecodable)
{
ostringstream buf;
buf << "[" << decode_type[idx] << "] " << decode_info[idx];
putText(frame, buf.str(), contour[1], FONT_HERSHEY_COMPLEX, 0.8, yellowColor, 1);
}
}
//! [visualize]
}
void drawFPS(Mat &frame, double fps) const
{
ostringstream buf;
buf << modeString()
<< " (" << corners.size() / 4 << "/" << decode_type.size() << "/" << decode_info.size() << ") "
<< cv::format("%.2f", fps) << " FPS ";
putText(frame, buf.str(), Point(25, 25), FONT_HERSHEY_COMPLEX, 0.8, redColor, 2);
}
inline void call_decode(Mat &frame)
{
cleanup();
if (detectOnly)
{
//! [detect]
bardet->detectMulti(frame, corners);
//! [detect]
}
else
{
//! [detectAndDecode]
bardet->detectAndDecodeWithType(frame, decode_info, decode_type, corners);
//! [detectAndDecode]
}
}
int liveBarCodeDetect()
{
VideoCapture cap(0);
if (!cap.isOpened())
{
cout << "Cannot open a camera" << endl;
return 2;
}
Mat frame;
Mat result;
cap >> frame;
cout << "Image size: " << frame.size() << endl;
cout << "Press 'd' to switch between <detect> and <detectAndDecode> modes" << endl;
cout << "Press 'ESC' to exit" << endl;
for (;;)
{
cap >> frame;
if (frame.empty())
{
cout << "End of video stream" << endl;
break;
}
if (frame.channels() == 1)
cvtColor(frame, frame, COLOR_GRAY2BGR);
TickMeter timer;
timer.start();
call_decode(frame);
timer.stop();
drawResults(frame);
drawFPS(frame, timer.getFPS());
imshow("barcode", frame);
const char c = (char)waitKey(1);
if (c == 'd')
{
detectOnly = !detectOnly;
cout << "Mode switched to " << modeString() << endl;
}
else if (c == 27)
{
cout << "'ESC' is pressed. Exiting..." << endl;
break;
}
}
return 0;
}
int imageBarCodeDetect(const string &in_file, const string &out_file)
{
Mat frame = imread(in_file, IMREAD_COLOR);
cout << "Image size: " << frame.size() << endl;
cout << "Mode is " << modeString() << endl;
const int count_experiments = 100;
TickMeter timer;
for (size_t i = 0; i < count_experiments; i++)
{
timer.start();
call_decode(frame);
timer.stop();
}
cout << "FPS: " << timer.getFPS() << endl;
drawResults(frame);
if (!out_file.empty())
{
cout << "Saving result: " << out_file << endl;
imwrite(out_file, frame);
}
imshow("barcode", frame);
cout << "Press any key to exit ..." << endl;
waitKey(0);
return 0;
}
};
//==============================================================================
int main(int argc, char **argv)
{
const string keys = "{h help ? | | print help messages }"
"{i in | | input image path (also switches to image detection mode) }"
"{detect | false | detect 1D barcode only (skip decoding) }"
"{o out | | path to result file (only for single image decode) }"
"{sr_prototxt| | super resolution prototxt path }"
"{sr_model | | super resolution model path }";
CommandLineParser cmd_parser(argc, argv, keys);
cmd_parser.about("This program detects the 1D barcodes from camera or images using the OpenCV library.");
if (cmd_parser.has("help"))
{
cmd_parser.printMessage();
return 0;
}
const string in_file = cmd_parser.get<string>("in");
const string out_file = cmd_parser.get<string>("out");
const string sr_prototxt = cmd_parser.get<string>("sr_prototxt");
const string sr_model = cmd_parser.get<string>("sr_model");
if (!cmd_parser.check())
{
cmd_parser.printErrors();
return -1;
}
TheApp app;
app.detectOnly = cmd_parser.has("detect") && cmd_parser.get<bool>("detect");
//! [initialize]
try
{
app.bardet = makePtr<barcode::BarcodeDetector>(sr_prototxt, sr_model);
}
catch (const std::exception& e)
{
cout <<
"\n---------------------------------------------------------------\n"
"Failed to initialize super resolution.\n"
"Please, download 'sr.*' from\n"
"https://github.com/WeChatCV/opencv_3rdparty/tree/wechat_qrcode\n"
"and put them into the current directory.\n"
"Or you can leave sr_prototxt and sr_model unspecified.\n"
"---------------------------------------------------------------\n";
cout << e.what() << endl;
return -1;
}
//! [initialize]
if (in_file.empty())
return app.liveBarCodeDetect();
else
return app.imageBarCodeDetect(in_file, out_file);
}
+12 -4
View File
@@ -12,6 +12,7 @@ using namespace cv;
static int liveQRCodeDetect();
static int imageQRCodeDetect(const string& in_file);
static bool g_useArucoBased = false;
static bool g_modeMultiQR = false;
static bool g_detectOnly = false;
@@ -35,6 +36,7 @@ int main(int argc, char *argv[])
const string keys =
"{h help ? | | print help messages }"
"{i in | | input image path (also switches to image detection mode) }"
"{aruco_based | false | use Aruco-based QR code detector instead of contour-based }"
"{detect | false | detect QR code only (skip decoding) }"
"{m multi | | use detect for multiple qr-codes }"
"{o out | qr_code.png | path to result file }"
@@ -75,6 +77,7 @@ int main(int argc, char *argv[])
g_modeMultiQR = cmd_parser.has("multi") && cmd_parser.get<bool>("multi");
g_detectOnly = cmd_parser.has("detect") && cmd_parser.get<bool>("detect");
g_useArucoBased = cmd_parser.has("aruco_based") && cmd_parser.get<bool>("aruco_based");
g_saveDetections = cmd_parser.has("save_detections") && cmd_parser.get<bool>("save_detections");
g_saveAll = cmd_parser.has("save_all") && cmd_parser.get<bool>("save_all");
@@ -157,7 +160,7 @@ void drawQRCodeResults(Mat& frame, const vector<Point>& corners, const vector<cv
static
void runQR(
QRCodeDetector& qrcode, const Mat& input,
const GraphicalCodeDetector& qrcode, const Mat& input,
vector<Point>& corners, vector<cv::String>& decode_info
// +global: bool g_modeMultiQR, bool g_detectOnly
)
@@ -191,7 +194,7 @@ void runQR(
}
static
double processQRCodeDetection(QRCodeDetector& qrcode, const Mat& input, Mat& result, vector<Point>& corners)
double processQRCodeDetection(const GraphicalCodeDetector& qrcode, const Mat& input, Mat& result, vector<Point>& corners)
{
if (input.channels() == 1)
cvtColor(input, result, COLOR_GRAY2BGR);
@@ -229,7 +232,9 @@ int liveQRCodeDetect()
cout << "Press 'd' to switch between decoder and detector" << endl;
cout << "Press ' ' (space) to save result into images" << endl;
cout << "Press 'ESC' to exit" << endl;
QRCodeDetector qrcode;
GraphicalCodeDetector qrcode = QRCodeDetector();
if (g_useArucoBased)
qrcode = QRCodeDetectorAruco();
for (;;)
{
@@ -310,7 +315,10 @@ int imageQRCodeDetect(const string& in_file)
<< " on image: " << input.size() << " (" << typeToString(input.type()) << ")"
<< endl;
QRCodeDetector qrcode;
GraphicalCodeDetector qrcode = QRCodeDetector();
if (g_useArucoBased)
qrcode = QRCodeDetectorAruco();
vector<Point> corners;
vector<cv::String> decode_info;