From e548e59cd5ec5eb50ad8c926908727a03343abb7 Mon Sep 17 00:00:00 2001 From: cswccc <3344767250@qq.com> Date: Tue, 19 Nov 2024 19:29:30 +0800 Subject: [PATCH] add intro to params --- .../objdetect/include/opencv2/objdetect.hpp | 35 +++++- modules/objdetect/src/qbardecoder.cpp | 104 ++++++------------ modules/objdetect/src/qbarstruct.hpp | 26 +---- modules/objdetect/src/qrcode.cpp | 2 +- 4 files changed, 68 insertions(+), 99 deletions(-) diff --git a/modules/objdetect/include/opencv2/objdetect.hpp b/modules/objdetect/include/opencv2/objdetect.hpp index 0bbf21bf3f..23395559de 100644 --- a/modules/objdetect/include/opencv2/objdetect.hpp +++ b/modules/objdetect/include/opencv2/objdetect.hpp @@ -862,11 +862,10 @@ public: CV_WRAP void setArucoParameters(const aruco::DetectorParameters& params); }; -enum DECODER_READER{ - // DECODER_ONED_BARCODE = 1,// barcode, which includes UPC_A, UPC_E, EAN_8, EAN_13, CODE_39, CODE_93, CODE_128, ITF, CODABAR - DECODER_QRCODE = 2,// QRCODE - DECODER_PDF417 = 3,// PDF417 - DECODER_DATAMATRIX = 4,// DATAMATRIX +enum DECODER_READER { + DECODER_QRCODE = 0,// QRCODE + DECODER_PDF417 = 1,// PDF417 + DECODER_DATAMATRIX = 2,// DATAMATRIX }; typedef std::vector vector_DECODER_READER; @@ -874,6 +873,17 @@ typedef std::vector vector_DECODER_READER; class CV_EXPORTS_W_SIMPLE CodeDetectorWeChat : public GraphicalCodeDetector { public: + /** @brief Initialize the CodeDetectorWeChat. + * + * Parameters allow to load _optional_ Detection and Super Resolution DNN model for better quality. + * @param detection_model_path_ model file path for the detection model + * @param super_resolution_model_path_ model file path for the super resolution model + * @param readers decoder readers + * @param detector_iou_thres nms iou threshold for detection part + * @param decoder_iou_thres nms iou threshold for decoding part + * @param score_thres score threshold for detection part + * @param reference_size the length of the image to align during pre-processing before detection + */ CV_WRAP CodeDetectorWeChat(const std::string& detection_model_path_ = "", const std::string& super_resolution_model_path_ = "", const std::vector& readers = std::vector(), @@ -882,9 +892,24 @@ public: const float score_thres = 0.3, const int reference_size = 512); + /** @brief Set the reference size during the pre-processing before detection. + * @param reference_size the length of the image to align during pre-processing before detection + */ CV_WRAP void setDetectorReferenceSize(int reference_size); + + /** @brief Set the score threshold during the processing of detection results. + * @param score_thres score threshold for detection part + */ CV_WRAP void setDetectorScoreThres(float score_thres); + + /** @brief Set the detector iou threshold during the processing of detection results. + * @param detector_iou_thres nms iou threshold for detection part + */ CV_WRAP void setDetectorIouThres(float iou_thres); + + /** @brief Set the detector iou threshold during the processing of decoding results. + * @param detector_iou_thres nms iou threshold for decoding part + */ CV_WRAP void setDecoderIouThres(float iou_thres); diff --git a/modules/objdetect/src/qbardecoder.cpp b/modules/objdetect/src/qbardecoder.cpp index 2084b3f1b9..3f3186aaff 100644 --- a/modules/objdetect/src/qbardecoder.cpp +++ b/modules/objdetect/src/qbardecoder.cpp @@ -324,94 +324,58 @@ std::vector QBarDecoder::decode(Mat srcImage, std::vectornms(results, iou_thres); return results; } void QBarDecoder::nms(std::vector& results, float NMS_THRESH) { if (results.size() <= 1) return; - std::unordered_map> class_map; - for (const auto& result : results) { - class_map[result.typeID].push_back(result); - } + std::vector skip(results.size()); + for (size_t i = 0; i < results.size(); ++i) + skip[i] = false; + + // merge overlapped results + for (size_t i = 0; i < results.size(); ++i) + { + if (skip[i] || results[i].points.size() < 4) + continue; + skip[i] = true; - std::vector final_results; + for (size_t j = i + 1; j < results.size(); ++j) + { + if (skip[j] || results[j].points.size() < 4) + continue; + { + std::vector pts_i, pts_j; + for (const auto& pt : results[i].points) + pts_i.emplace_back(pt.x, pt.y); + for (const auto& pt : results[j].points) + pts_j.emplace_back(pt.x, pt.y); - for (auto& pair : class_map) { - auto& class_results = pair.second; - - // leftup: p1 rightdown: p3 - std::sort(class_results.begin(), class_results.end(), [](const QBAR_RESULT& a, const QBAR_RESULT& b) { - int widthA = a.points[3].x - a.points[1].x + 1; - int heightA = a.points[3].y - a.points[1].y + 1; - int widthB = b.points[3].x - b.points[1].x + 1; - int heightB = b.points[3].y - b.points[1].y + 1; - return (widthA * heightA) > (widthB * heightB); - }); + float area1 = cv::contourArea(pts_i); + float area2 = cv::contourArea(pts_j); + float intersectionArea = 0.0; + std::vector intersection; + cv::rotatedRectangleIntersection(cv::minAreaRect(pts_i), cv::minAreaRect(pts_j), intersection); - std::vector vArea(class_results.size()); - for (size_t i = 0; i < class_results.size(); ++i) { - vArea[i] = (class_results[i].points[3].x - class_results[i].points[1].x + 1) * (class_results[i].points[3].y - class_results[i].points[1].y + 1); - } + if (!intersection.empty()) + intersectionArea = cv::contourArea(intersection); - for (size_t i = 0; i < class_results.size(); ++i) { - final_results.push_back(class_results[i]); - if (class_results[i].typeID == 0) continue; - // skip oned - if (class_results[i].typeID != 6 && class_results[i].typeID != 11 && class_results[i].typeID != 12) continue; - - for (size_t j = i + 1; j < class_results.size();) { - float xx1 = std::max(class_results[i].points[1].x, class_results[j].points[1].x); - float yy1 = std::max(class_results[i].points[1].y, class_results[j].points[1].y); - float xx2 = std::min(class_results[i].points[3].x, class_results[j].points[3].x); - float yy2 = std::min(class_results[i].points[3].y, class_results[j].points[3].y); - - float w = std::max(0.0f, xx2 - xx1 + 1); - float h = std::max(0.0f, yy2 - yy1 + 1); - float inter = w * h; - - float ovr = inter / (vArea[i] + vArea[j] - inter); - float cover = inter / std::min(vArea[i], vArea[j]); - - if (ovr >= NMS_THRESH) { - class_results.erase(class_results.begin() + j); - vArea.erase(vArea.begin() + j); - } else if (cover >= 0.96) { - if (vArea[i] > vArea[j]) { - class_results.erase(class_results.begin() + j); - vArea.erase(vArea.begin() + j); - } else { - class_results[i].points[1] = class_results[j].points[1]; - class_results[i].points[3] = class_results[j].points[3]; - class_results.erase(class_results.begin() + j); - vArea.erase(vArea.begin() + j); - } - } else { - j++; + double iou = intersectionArea / (area1 + area2 - intersectionArea); + double cover = intersectionArea / min(area1, area2); + if (iou > NMS_THRESH || cover > 0.96) { + skip[j] = true; + results[j].data = ""; } } } } - - results = final_results; } void QBarDecoder::addFormatsToDecodeHints(zxing::DecodeHints &hints) { - if (readers_.count(QBAR_READER::ONED_BARCODE)) - { - hints.addFormat(BarcodeFormat::CODE_25); - hints.addFormat(BarcodeFormat::CODE_39); - hints.addFormat(BarcodeFormat::CODE_93); - hints.addFormat(BarcodeFormat::CODE_128); - hints.addFormat(BarcodeFormat::ITF); - hints.addFormat(BarcodeFormat::CODABAR); - hints.addFormat(BarcodeFormat::UPC_A); - hints.addFormat(BarcodeFormat::UPC_E); - hints.addFormat(BarcodeFormat::EAN_8); - hints.addFormat(BarcodeFormat::EAN_13); - hints.addFormat(BarcodeFormat::RSS_14); - } if (readers_.count(QBAR_READER::QRCODE)) { hints.addFormat(BarcodeFormat::QR_CODE); diff --git a/modules/objdetect/src/qbarstruct.hpp b/modules/objdetect/src/qbarstruct.hpp index e57bebe874..79ed7b22da 100644 --- a/modules/objdetect/src/qbarstruct.hpp +++ b/modules/objdetect/src/qbarstruct.hpp @@ -107,10 +107,9 @@ struct QBAR_MODE // reader config, if not set, try all reader enum QBAR_READER{ - ONED_BARCODE = 1, // barcode, which includes UPC_A, UPC_E, EAN_8, EAN_13, CODE_39, CODE_93, CODE_128, ITF, CODABAR - QRCODE = 2, // QRCODE - PDF417 = 3, // PDF417 - DATAMATRIX = 4, // DATAMATRIX + QRCODE = 0, // QRCODE + PDF417 = 1, // PDF417 + DATAMATRIX = 2, // DATAMATRIX }; ///////////////////////////// result struct @@ -255,25 +254,6 @@ enum QBAR_CODE_FORMAT{ FMT_CODE25 = 18, }; -/////////////////////////////////// debug -// enum QBAR_BINARIZER -// { -// Hybrid = 0, -// FastWindow = 1, -// SimpleAdaptive = 2, -// GlobalHistogram=3, -// OTSU=4, -// Niblack=5, -// Adaptive=6, -// HistogramBackground=7 -// }; - - -// struct QBAR_DEBUG -// { -// QBAR_BINARIZER binarizer; -// }; - enum QBAR_CONFIG_TYPE{ CONFIG_RESERVED0 = 0, CONFIG_RESERVED1 = 1, diff --git a/modules/objdetect/src/qrcode.cpp b/modules/objdetect/src/qrcode.cpp index 6b747719a5..908992b625 100644 --- a/modules/objdetect/src/qrcode.cpp +++ b/modules/objdetect/src/qrcode.cpp @@ -4883,7 +4883,7 @@ CodeDetectorWeChat::CodeDetectorWeChat(const std::string& detection_model_path_, CV_Assert(ret == 0); if (readers.empty()) { - std::dynamic_pointer_cast(p)->qbarDecode_->setReaders({ONED_BARCODE, QRCODE, PDF417, DATAMATRIX}); + std::dynamic_pointer_cast(p)->qbarDecode_->setReaders({QRCODE, PDF417, DATAMATRIX}); } else { unordered_set readers_;