add intro to params

This commit is contained in:
cswccc 2024-11-19 19:29:30 +08:00
parent b77047fc08
commit e548e59cd5
4 changed files with 68 additions and 99 deletions

View File

@ -863,10 +863,9 @@ public:
};
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
DECODER_QRCODE = 0,// QRCODE
DECODER_PDF417 = 1,// PDF417
DECODER_DATAMATRIX = 2,// DATAMATRIX
};
typedef std::vector<DECODER_READER> vector_DECODER_READER;
@ -874,6 +873,17 @@ typedef std::vector<DECODER_READER> 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<DECODER_READER>& readers = std::vector<DECODER_READER>(),
@ -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);

View File

@ -325,93 +325,57 @@ std::vector<QBAR_RESULT> QBarDecoder::decode(Mat srcImage, std::vector<DetectInf
parallel_for_(Range(0, int(detect_results.size())), parallelDecode);
this->nms(results, iou_thres);
return results;
}
void QBarDecoder::nms(std::vector<QBAR_RESULT>& results, float NMS_THRESH) {
if (results.size() <= 1) return;
std::unordered_map<int, std::vector<QBAR_RESULT>> class_map;
for (const auto& result : results) {
class_map[result.typeID].push_back(result);
}
std::vector<bool> skip(results.size());
for (size_t i = 0; i < results.size(); ++i)
skip[i] = false;
std::vector<QBAR_RESULT> final_results;
// merge overlapped results
for (size_t i = 0; i < results.size(); ++i)
{
if (skip[i] || results[i].points.size() < 4)
continue;
skip[i] = true;
for (auto& pair : class_map) {
auto& class_results = pair.second;
for (size_t j = i + 1; j < results.size(); ++j)
{
if (skip[j] || results[j].points.size() < 4)
continue;
{
std::vector<Point2f> 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);
// 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<cv::Point2f> intersection;
cv::rotatedRectangleIntersection(cv::minAreaRect(pts_i), cv::minAreaRect(pts_j), intersection);
std::vector<float> 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);

View File

@ -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,

View File

@ -4883,7 +4883,7 @@ CodeDetectorWeChat::CodeDetectorWeChat(const std::string& detection_model_path_,
CV_Assert(ret == 0);
if (readers.empty()) {
std::dynamic_pointer_cast<PimplWeChat>(p)->qbarDecode_->setReaders({ONED_BARCODE, QRCODE, PDF417, DATAMATRIX});
std::dynamic_pointer_cast<PimplWeChat>(p)->qbarDecode_->setReaders({QRCODE, PDF417, DATAMATRIX});
}
else {
unordered_set<QBAR_READER> readers_;