| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223 |
- #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);
- }
|