更新到HyperLPR3版本

This commit is contained in:
tunmx
2023-02-27 15:47:55 +08:00
parent 7ae4d385e1
commit 0864e05f76
912 changed files with 8160 additions and 221461 deletions
@@ -0,0 +1,12 @@
//
// Created by Tunm-Air13 on 2022/12/30.
//
#ifndef ZEPHYRLPR_RECOGNITION_ALL_H
#define ZEPHYRLPR_RECOGNITION_ALL_H
#include "plate_recognition.h"
#include "recognition_commom.h"
#include "recognition_engine.h"
#endif //ZEPHYRLPR_RECOGNITION_ALL_H
@@ -0,0 +1,82 @@
//
// Created by Tunm-Air13 on 2022/12/30.
//
#include "plate_recognition.h"
#include <utility>
#include "utils.h"
#include "plate_recognition_tokenize.h"
namespace hyper {
PlateRecognition::PlateRecognition() = default;
int PlateRecognition::Initialize(const std::string& model_filename, cv::Size input_size, int threads, float confidence_threshold,
bool use_half) {
m_input_image_size_ = std::move(input_size);
m_confidence_threshold_ = confidence_threshold;
float mean[] = {127.5f, 127.5f, 127.5f};
float normal[] = {1.0 / 127.5f, 1.0 / 127.5f, 1.0 / 127.5f};
m_nn_adapter_ = std::make_shared<MNNAdapterInference>(model_filename, threads, mean, normal, use_half);
m_nn_adapter_->Initialization("data", "output", m_input_image_size_.width, m_input_image_size_.height);
return 0;
}
TextLine PlateRecognition::Inference(const cv::Mat &bgr_pad) {
std::vector<float> output = m_nn_adapter_->Invoking(bgr_pad);
// SLOG_INFO("out: {}", output.size());
auto line = decode(output);
return line;
}
TextLine PlateRecognition::decode(const std::vector<float>& tensor) {
int text_total_num = 24;
int classify_num = 75;
IndexList index_list;
std::vector<float> max_list;
for (int index = 0; index < text_total_num; ++index) {
std::vector<float> mapping;
mapping.reserve(classify_num);
for (int i = 0; i < classify_num; ++i) {
mapping.push_back(tensor[index * classify_num + i]);
}
auto max_index = argmax(mapping.begin(), mapping.end());
float max_value = mapping[max_index];
index_list.push_back(max_index);
max_list.push_back(max_value);
}
TextLine line;
line.code = "";
float total_ = 0.0f;
for (int i = 0; i < index_list.size(); ++i) {
auto &idx = index_list[i];
IndexList::const_iterator result = std::find(m_ignored_tokens_.begin(), m_ignored_tokens_.end(), idx);
if (result == m_ignored_tokens_.end()) {
if ((i > 0) && index_list[i - 1] == idx) {
continue; // remove_duplicate
}
// std::cout << "b " << idx << std::endl;
line.char_index.push_back(idx);
line.char_scores.push_back(max_list[i]);
line.code += TOKENIZE[idx];
// SLOG_INFO("{}", TOKENIZE[idx]);
total_ += max_list[i];
}
}
line.average_score = total_ / line.char_scores.size();
return line;
}
const cv::Size &PlateRecognition::getMInputImageSize() const {
return m_input_image_size_;
}
float PlateRecognition::getMConfidenceThreshold() const {
return m_confidence_threshold_;
}
}
@@ -0,0 +1,51 @@
//
// Created by Tunm-Air13 on 2022/12/30.
//
#pragma once
#ifndef ZEPHYRLPR_PLATE_RECOGNITION_H
#define ZEPHYRLPR_PLATE_RECOGNITION_H
#include "nn_module/mnn_adapter.h"
#include "configuration.h"
#include "recognition_commom.h"
#include "basic_types.h"
namespace hyper {
class PlateRecognition {
public:
PlateRecognition(const PlateRecognition &) = delete;
PlateRecognition &operator=(const PlateRecognition &) = delete;
explicit PlateRecognition();
int Initialize(const std::string& model_filename, cv::Size input_size = REC_INPUT_SIZE, int threads = 1,
float confidence_threshold = 0.5, bool use_half = false);
TextLine Inference(const cv::Mat &bgr_pad);
const cv::Size &getMInputImageSize() const;
float getMConfidenceThreshold() const;
private:
TextLine decode(const std::vector<float>& tensor);
private:
cv::Size m_input_image_size_{}; // 输入图像宽高
float m_confidence_threshold_{}; // 置信度阈值
std::shared_ptr<MNNAdapterInference> m_nn_adapter_; // 推理模块
IndexList m_ignored_tokens_ = {0, }; // 需要被忽略的索引
};
}
#endif //ZEPHYRLPR_PLATE_RECOGNITION_H
@@ -0,0 +1,17 @@
//
// Created by tunm on 2023/1/25.
//
#pragma once
#ifndef ZEPHYRLPR_PLATE_RECOGNITION_TOKENIZE_H
#define ZEPHYRLPR_PLATE_RECOGNITION_TOKENIZE_H
#include <iostream>
static const std::vector<std::string> TOKENIZE = {
"blank", "'", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "J",
"K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "使", ""};
#endif //ZEPHYRLPR_PLATE_RECOGNITION_TOKENIZE_H
@@ -0,0 +1,23 @@
//
// Created by Tunm-Air13 on 2022/12/30.
//
#ifndef ZEPHYRLPR_RECOGNITION_COMMOM_H
#define ZEPHYRLPR_RECOGNITION_COMMOM_H
#include "basic_types.h"
namespace hyper {
typedef struct TextLine {
IndexList char_index; ///< 索引列表
std::vector<float> char_scores; ///< 置信度列表
float average_score; ///< 平均置信度
std::string code; ///< 车牌字符串
};
typedef std::vector<TextLine> TextLines; ///< 多行文本表达
}
#endif //ZEPHYRLPR_RECOGNITION_COMMOM_H
@@ -0,0 +1,151 @@
//
// Created by tunm on 2023/2/6.
//
#include "recognition_engine.h"
#include <utility>
#include "utils.h"
#include "plate_recognition_tokenize.h"
#define INPUT_NAME "data"
namespace hyper {
RecognitionEngine::RecognitionEngine() = default;
int32_t RecognitionEngine::Initialize(const std::string& model_filename, cv::Size input_size, int threads, float confidence_threshold,
bool use_half) {
m_input_image_size_ = input_size;
m_confidence_threshold_ = confidence_threshold;
/* Set output tensor info */
m_output_tensor_info_list_.clear();
m_output_tensor_info_list_.push_back(OutputTensorInfo("output", TensorInfo::kTensorTypeFp32));
m_nn_infer_.reset(InferenceHelper::Create(InferenceHelper::kMnn));
if (m_nn_infer_->SetNumThreads(threads) != InferenceHelper::kRetOk) {
m_nn_infer_.reset();
return InferenceHelper::kRetErr;
}
if (m_nn_infer_->Initialize(model_filename, m_input_tensor_info_list_, m_output_tensor_info_list_) != InferenceHelper::kRetOk) {
m_nn_infer_.reset();
return InferenceHelper::kRetErr;
}
m_input_tensor_info_list_.clear();
InputTensorInfo input_tensor_info(INPUT_NAME, TensorInfo::kTensorTypeFp32, true);
input_tensor_info.tensor_dims = { 1, 3, m_input_image_size_.height, m_input_image_size_.width };
input_tensor_info.data_type = InputTensorInfo::kDataTypeImage;
input_tensor_info.normalize.mean[0] = 127.5f;
input_tensor_info.normalize.mean[1] = 127.5f;
input_tensor_info.normalize.mean[2] = 127.5f;
input_tensor_info.normalize.norm[0] = 0.007843137255f;
input_tensor_info.normalize.norm[1] = 0.007843137255f;
input_tensor_info.normalize.norm[2] = 0.007843137255f;
m_input_tensor_info_list_.push_back(input_tensor_info);
return InferenceHelper::kRetOk;
}
int32_t RecognitionEngine::Inference(const cv::Mat &bgr_pad, TextLine &line) {
InputTensorInfo& input_tensor_info = m_input_tensor_info_list_[0];
input_tensor_info.data = bgr_pad.data;
input_tensor_info.data_type = InputTensorInfo::kDataTypeImage;
input_tensor_info.image_info.width = bgr_pad.cols;
input_tensor_info.image_info.height = bgr_pad.rows;
input_tensor_info.image_info.channel = bgr_pad.channels();
input_tensor_info.image_info.crop_x = 0;
input_tensor_info.image_info.crop_y = 0;
input_tensor_info.image_info.crop_width = bgr_pad.cols;
input_tensor_info.image_info.crop_height = bgr_pad.rows;
input_tensor_info.image_info.is_bgr = true;
input_tensor_info.image_info.swap_color = false;
if (m_nn_infer_->PreProcess(m_input_tensor_info_list_) != InferenceHelper::kRetOk) {
return InferenceHelper::kRetErr;
}
if (m_nn_infer_->Process(m_output_tensor_info_list_) != InferenceHelper::kRetOk) {
return InferenceHelper::kRetErr;
}
std::vector<float> output_score_raw_list(m_output_tensor_info_list_[0].GetDataAsFloat(),
m_output_tensor_info_list_[0].GetDataAsFloat() +
m_output_tensor_info_list_[0].GetElementNum());
decode(output_score_raw_list, line);
return InferenceHelper::kRetOk;
}
const cv::Size &RecognitionEngine::getMInputImageSize() const {
return m_input_image_size_;
}
float RecognitionEngine::getMConfidenceThreshold() const {
return m_confidence_threshold_;
}
int32_t RecognitionEngine::decode(const std::vector<float> &tensor, TextLine &line) {
int text_total_num = REC_MAX_CHAR_NUM;
int classify_num = REC_CHAR_CLASS_NUM;
IndexList index_list;
std::vector<float> max_list;
for (int index = 0; index < text_total_num; ++index) {
std::vector<float> mapping;
mapping.reserve(classify_num);
for (int i = 0; i < classify_num; ++i) {
mapping.push_back(tensor[index * classify_num + i]);
}
auto max_index = argmax(mapping.begin(), mapping.end());
float max_value = mapping[max_index];
index_list.push_back(max_index);
max_list.push_back(max_value);
}
line.code = "";
float total_ = 0.0f;
for (int i = 0; i < index_list.size(); ++i) {
auto &idx = index_list[i];
IndexList::const_iterator result = std::find(m_ignored_tokens_.begin(), m_ignored_tokens_.end(), idx);
if (result == m_ignored_tokens_.end()) {
if ((i > 0) && index_list[i - 1] == idx) {
continue; // remove_duplicate
}
// std::cout << "b " << idx << std::endl;
line.char_index.push_back(idx);
line.char_scores.push_back(max_list[i]);
line.code += TOKENIZE[idx];
// SLOG_INFO("{}", TOKENIZE[idx]);
total_ += max_list[i];
}
}
line.average_score = total_ / line.char_scores.size();
return InferenceHelper::kRetOk;
}
RecognitionEngine::~RecognitionEngine() {
if (!m_nn_infer_) {
LOGD("Inference helper is not created\n");
return;
}
m_nn_infer_->Finalize();
m_nn_infer_.reset();
}
} // namespace
@@ -0,0 +1,58 @@
//
// Created by tunm on 2023/2/6.
//
#pragma once
#ifndef ZEPHYRLPR_RECOGNITION_ENGINE_H
#define ZEPHYRLPR_RECOGNITION_ENGINE_H
#include "inference_helper_module/inference_helper.h"
#include "configuration.h"
#include "recognition_commom.h"
#include "basic_types.h"
#include "opencv2/opencv.hpp"
namespace hyper {
class RecognitionEngine {
public:
RecognitionEngine(const RecognitionEngine &) = delete;
RecognitionEngine &operator=(const RecognitionEngine &) = delete;
explicit RecognitionEngine();
~RecognitionEngine();
int32_t Initialize(const std::string& model_filename, cv::Size input_size = REC_INPUT_SIZE, int threads = 1,
float confidence_threshold = 0.5, bool use_half = false);
int32_t Inference(const cv::Mat &bgr_pad, TextLine &line);
const cv::Size &getMInputImageSize() const;
float getMConfidenceThreshold() const;
private:
int32_t decode(const std::vector<float>& tensor, TextLine &line);
private:
cv::Size m_input_image_size_{}; // 输入图像宽高
float m_confidence_threshold_{}; // 置信度阈值
std::unique_ptr<InferenceHelper> m_nn_infer_; // 推理模块
IndexList m_ignored_tokens_ = {0, }; // 需要被忽略的索引
std::vector<InputTensorInfo> m_input_tensor_info_list_;
std::vector<OutputTensorInfo> m_output_tensor_info_list_;
};
} // namespace
#endif //ZEPHYRLPR_RECOGNITION_ENGINE_H