Refactor project structure
This commit is contained in:
136
modules/ANSLPR/src/Levenshtein.cpp
Normal file
136
modules/ANSLPR/src/Levenshtein.cpp
Normal file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
// Line.h: interface for the C_Line class.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
*/
|
||||
// Levenshtein.cpp: implementation of the Levenshtein class.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "../include/Levenshtein.h"
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
Levenshtein::Levenshtein()
|
||||
{
|
||||
}
|
||||
Levenshtein::~Levenshtein()
|
||||
{
|
||||
}
|
||||
//****************************************************
|
||||
// Compute Levenshtein distance
|
||||
// This code is based on the work by Michael Gilleland
|
||||
//
|
||||
// It uses dynamic arrays which allows any std::string size.
|
||||
//****************************************************
|
||||
int Levenshtein::Get2 (char const *s, char const *t)
|
||||
{
|
||||
return Get2(s, strlen(s), t, strlen(t) );
|
||||
}
|
||||
int Levenshtein::Get2 (const char *s, size_t n, const char* t, size_t dst)
|
||||
{
|
||||
int *d; // pointer to matrix
|
||||
size_t i; // iterates through s
|
||||
size_t j; // iterates through t
|
||||
//char s_i; // ith character of s
|
||||
char t_j; // jth character of t
|
||||
int cost; // cost
|
||||
int result; // result
|
||||
int cell; // contents of target cell
|
||||
int above; // contents of cell immediately above
|
||||
int left; // contents of cell immediately to left
|
||||
int diag; // contents of cell immediately above and to left
|
||||
size_t sz; // number of cells in matrix
|
||||
// Step 1
|
||||
if (n == 0) {
|
||||
return static_cast<int>(dst);
|
||||
}
|
||||
if (dst == 0) {
|
||||
return static_cast<int>(n);
|
||||
}
|
||||
sz = (n+1) * (dst+1) * sizeof (int);
|
||||
d = static_cast<int*>(malloc(sz));
|
||||
// Step 2
|
||||
for (i = 0; i <= n; i++) {
|
||||
PutAt (d, i, 0, n, static_cast<int>(i));
|
||||
}
|
||||
for (j = 0; j <= dst; j++) {
|
||||
PutAt (d, 0, j, n, static_cast<int>(j));
|
||||
}
|
||||
// Step 3
|
||||
for (i = 1; i <= n; i++) {
|
||||
char s_i; // ith character of s
|
||||
s_i = s[i-1];
|
||||
// Step 4
|
||||
for (j = 1; j <= dst; j++) {
|
||||
t_j = t[j-1];
|
||||
// Step 5
|
||||
if (s_i == t_j) {
|
||||
cost = 0;
|
||||
}
|
||||
else {
|
||||
cost = 1;
|
||||
}
|
||||
// Step 6
|
||||
above = GetAt (d,i-1,j, n);
|
||||
left = GetAt (d,i, j-1, n);
|
||||
diag = GetAt (d, i-1,j-1, n);
|
||||
cell = Minimum (above + 1, left + 1, diag + cost);
|
||||
PutAt (d, i, j, n, cell);
|
||||
}
|
||||
}
|
||||
// Step 7
|
||||
result = GetAt (d, n, dst, n);
|
||||
free (d);
|
||||
return result;
|
||||
}
|
||||
/*****************************************************
|
||||
* Second implementation of the Levenshtein algorithm.
|
||||
* A static array is used with length MAXLINE. Make
|
||||
* sure that your strings are no longer! Otherwise use
|
||||
* the algorithm above.
|
||||
*/
|
||||
#define MAXLINE 128
|
||||
int Levenshtein::Get(const char *a, const char *b)
|
||||
{
|
||||
return Get(a, strlen(a), b, strlen(b));
|
||||
}
|
||||
int Levenshtein::Get(const char *a, size_t aLen, const char *b, size_t bLen)
|
||||
{
|
||||
int arr[MAXLINE][MAXLINE];
|
||||
int i,j,l,dst,n,add;
|
||||
// MAXLINE is the limit! If the strings are longer use the other implementation
|
||||
if (aLen > MAXLINE || bLen > MAXLINE)
|
||||
{
|
||||
return Get2(a, aLen, b, bLen);
|
||||
}
|
||||
for (i=0;i<=aLen;i++)
|
||||
{
|
||||
arr[0][i]=i;
|
||||
}
|
||||
for (j=0;j<=bLen;j++)
|
||||
{
|
||||
arr[j][0]=j;
|
||||
}
|
||||
for (j=1;j<=bLen;j++)
|
||||
{
|
||||
for (i=1;i<=aLen;i++)
|
||||
{
|
||||
if (a[i-1] == b[j-1])
|
||||
{
|
||||
add=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
add=1;
|
||||
}
|
||||
dst = 1+arr[j-1][i];
|
||||
l = 1+arr[j][i-1];
|
||||
n = add+arr[j-1][i-1];
|
||||
arr[j][i] = (dst < l ? (dst < n ? dst : n): (l < n ? l : n));
|
||||
}
|
||||
}
|
||||
return arr[bLen][aLen];
|
||||
}
|
||||
195
modules/ANSLPR/src/Line.cpp
Normal file
195
modules/ANSLPR/src/Line.cpp
Normal file
@@ -0,0 +1,195 @@
|
||||
//************************************************************************
|
||||
/*
|
||||
************************************************************************
|
||||
// Copyright (C) 2003-2006, LPReditor SARL, all rights reserved.
|
||||
// author : Raphael Poulenard.
|
||||
************************************************************************
|
||||
// Line.h: interface for the C_Line class.
|
||||
//
|
||||
This program is free software : you can redistribute itand /or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
|
||||
GNU General Public License for more details.
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
*/
|
||||
// Line.cpp: implementation of the C_Line class.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
#include "Line.h"
|
||||
#ifdef _WINDOWS
|
||||
#endif //_WINDOWS
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
C_Line::C_Line():a(0.0f),b(0.0f)
|
||||
{
|
||||
}
|
||||
//constructeur a partir de deux pts
|
||||
C_Line::C_Line(const cv::Point2f& A,const cv::Point2f& B)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
//assert(A.x!=B.x);
|
||||
#endif //_DEBUG
|
||||
if(fabsf(A.x-B.x)<FLT_EPSILON) {
|
||||
a=(A.y-B.y)/(A.x-B.x+FLT_EPSILON);
|
||||
b=0.0f;
|
||||
}
|
||||
else {a=(A.y-B.y)/(A.x-B.x);
|
||||
b=A.y-(a*A.x);
|
||||
}
|
||||
}
|
||||
C_Line::C_Line(const C_Line & line_)
|
||||
{
|
||||
a=line_.a;
|
||||
b=line_.b;
|
||||
}
|
||||
C_Line::C_Line(const float & a_,const float & b_):a(a_),b(b_)
|
||||
{
|
||||
}
|
||||
C_Line::~C_Line()
|
||||
{
|
||||
}
|
||||
//retourne le pt d'inter de C_Line avec la dte horiz y=ordonnee
|
||||
float C_Line::get_abs(const int ordonnee) const
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
assert(a!=0.0f);
|
||||
#endif //_DEBUG
|
||||
return (ordonnee-b)/a;
|
||||
}
|
||||
float C_Line::get_abs(const float ordonnee) const
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
assert(a!=0.0f);
|
||||
#endif //_DEBUG
|
||||
return (ordonnee-b)/a;
|
||||
}
|
||||
//retourne l'image de abscisse par la fonction affi,e definie par la droite
|
||||
int C_Line::get_image_entiere(const int abscisse) const
|
||||
{
|
||||
float ordonnee(a*abscisse+b);
|
||||
int ordonne_floor=static_cast<int>(floorf(ordonnee));
|
||||
if (ordonnee-ordonne_floor>0.5f) {
|
||||
//le point le plus proche de la droite est situe au dessus.
|
||||
ordonne_floor++;
|
||||
#ifdef _DEBUG
|
||||
assert(ordonne_floor-ordonnee<0.5f);
|
||||
#endif //_DEBUG
|
||||
}
|
||||
return ordonne_floor;
|
||||
}
|
||||
//retourne l'image de abscisse par la fonction affi,e definie par la droite
|
||||
float C_Line::get_image(const float & abscisse) const
|
||||
{
|
||||
return a*abscisse+b;
|
||||
}
|
||||
//retourne l'image de abscisse par la fonction affi,e definie par la droite
|
||||
float C_Line::get_image(const int abscisse) const
|
||||
{
|
||||
return a*abscisse+b;
|
||||
}
|
||||
bool C_Line::is_nearly_the_same(const C_Line & right_op) const
|
||||
{
|
||||
return (fabs(a-right_op.a)<FLT_EPSILON
|
||||
&& fabs(b-right_op.b)<FLT_EPSILON);
|
||||
}
|
||||
bool C_Line::is_nearly_horiz() const
|
||||
{
|
||||
return (a+0.000001>0.0 && a<0.000001);
|
||||
}
|
||||
void C_Line::reset()
|
||||
{
|
||||
a=0.0f;b=0.0f;
|
||||
}
|
||||
float C_Line::dist_y(const cv::Point& pt) const
|
||||
{
|
||||
//true if the line doesnot have too large slope and not large ordonnee a l'origine
|
||||
if (is_valid()) {
|
||||
return fabsf(pt.y - a * static_cast<float>(pt.x) - b);
|
||||
}
|
||||
else return .0f;
|
||||
}
|
||||
float C_Line::dist_y(const cv::Point2f& pt) const
|
||||
{
|
||||
//true if the line doesnot have too large slope and not large ordonnee a l'origine
|
||||
if (is_valid()) {
|
||||
return fabsf(pt.y - a * static_cast<float>(pt.x) - b);
|
||||
}
|
||||
else return .0f;
|
||||
}
|
||||
//retourne la distance du point
|
||||
// sa projection verticale de la droite
|
||||
float C_Line::difference_y(const cv::Point2f& pt) const
|
||||
{
|
||||
return (pt.y - a * pt.x - b);
|
||||
}
|
||||
//returns the distance of the center point of a box from its vertical projection on the line
|
||||
float C_Line::dist_y_from_center(const cv::Rect& box) const
|
||||
{
|
||||
cv::Point2f pt(box.x + box.width / 2.0f, box.y + box.height / 2.0f);
|
||||
return dist_y(pt);
|
||||
}
|
||||
float C_Line::difference_y_from_center(const cv::Rect& box) const
|
||||
{
|
||||
cv::Point2f pt(box.x + box.width / 2.0f, box.y + box.height / 2.0f);
|
||||
return difference_y(pt);
|
||||
}
|
||||
float C_Line::dist_y_from_center(const std::list<cv::Rect>& boxes) const
|
||||
{
|
||||
float dist = 0.0f;
|
||||
std::list<cv::Rect>::const_iterator it(boxes.begin());
|
||||
while (it != boxes.end()) {
|
||||
dist += dist_y_from_center(*it);
|
||||
it++;
|
||||
}
|
||||
return dist;
|
||||
}
|
||||
float C_Line::difference_y_from_center(const std::list<cv::Rect>& boxes) const
|
||||
{
|
||||
float dist = 0.0f;
|
||||
std::list<cv::Rect>::const_iterator it(boxes.begin());
|
||||
while (it != boxes.end()) {
|
||||
dist += difference_y_from_center(*it);
|
||||
it++;
|
||||
}
|
||||
return dist;
|
||||
}
|
||||
//returns sum of distances of a list of points from their vertical projections on the line
|
||||
float C_Line::dist_y(const std::list<cv::Point2f>& points) const
|
||||
{
|
||||
float dist = 0.0f;
|
||||
std::list<cv::Point2f>::const_iterator it(points.begin());
|
||||
while (it != points.end()) {
|
||||
dist += dist_y(*it);
|
||||
it++;
|
||||
}
|
||||
return dist;
|
||||
}
|
||||
float C_Line::dist_y(const std::list<cv::Point>& points) const
|
||||
{
|
||||
float dist = 0.0f;
|
||||
std::list<cv::Point>::const_iterator it(points.begin());
|
||||
while (it != points.end()) {
|
||||
dist += dist_y(*it);
|
||||
it++;
|
||||
}
|
||||
return dist;
|
||||
}
|
||||
float C_Line::error(const std::list<cv::Rect>& boxes) const
|
||||
{
|
||||
if (boxes.size()) {
|
||||
return dist_y_from_center(boxes) / static_cast<float>(boxes.size());
|
||||
}
|
||||
else return 0.0f;
|
||||
}
|
||||
float C_Line::error(const std::list<cv::Point2f>& points) const
|
||||
{
|
||||
if (points.size()) {
|
||||
return dist_y(points) / static_cast<float>(points.size());
|
||||
}
|
||||
else return 0.0f;
|
||||
}
|
||||
367
modules/ANSLPR/src/ONNX_detector.cpp
Normal file
367
modules/ANSLPR/src/ONNX_detector.cpp
Normal file
@@ -0,0 +1,367 @@
|
||||
/*
|
||||
// Line.h: interface for the C_Line class.
|
||||
//
|
||||
*/
|
||||
#include "ONNX_detector.h"
|
||||
#include <iostream>
|
||||
#include <opencv2/core.hpp>
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include <opencv2/dnn/dnn.hpp>
|
||||
#include <filesystem>
|
||||
OnnxDetector::OnnxDetector(Ort::Env& env_, const ORTCHAR_T* model_path, const Ort::SessionOptions& options) : env(env_), sessionOptions(options), session(env_, model_path, options) {
|
||||
dump();
|
||||
}
|
||||
OnnxDetector::OnnxDetector(Ort::Env& env_, const void* model_data, size_t model_data_length, const Ort::SessionOptions& options) : env(env_),sessionOptions(options),
|
||||
session(env_, model_data, model_data_length, options)
|
||||
{
|
||||
dump();
|
||||
}
|
||||
void OnnxDetector::dump() const {
|
||||
//std::cout << "Available execution providers:\n";
|
||||
//for (const auto& s : Ort::GetAvailableProviders()) std::cout << '\t' << s << '\n';
|
||||
Ort::AllocatorWithDefaultOptions allocator;
|
||||
size_t numInputNodes = session.GetInputCount();
|
||||
size_t numOutputNodes = session.GetOutputCount();
|
||||
//std::cout << "Number of Input Nodes: " << numInputNodes << std::endl;
|
||||
//std::cout << "Number of Output Nodes: " << numOutputNodes << std::endl;
|
||||
//const char* inputName = session.GetInputName(0, allocator);
|
||||
//std::cout << "Input Name: " << inputName << std::endl;
|
||||
Ort::TypeInfo inputTypeInfo = session.GetInputTypeInfo(0);
|
||||
auto inputTensorInfo = inputTypeInfo.GetTensorTypeAndShapeInfo();
|
||||
ONNXTensorElementDataType inputType = inputTensorInfo.GetElementType();
|
||||
//std::cout << "Input Type: " << inputType << std::endl;
|
||||
std::vector<int64_t> inputDims = inputTensorInfo.GetShape();
|
||||
//std::cout << "Input Dimensions: " << inputDims << std::endl;
|
||||
//for (size_t i = 0; i < inputDims.size() - 1; i++)
|
||||
// std::cout << inputDims[i] << std::endl;
|
||||
//std::cout << std::endl;
|
||||
//const char* outputName = session.GetOutputName(0, allocator);
|
||||
//std::cout << "Output Name: " << outputName << std::endl;
|
||||
Ort::TypeInfo outputTypeInfo = session.GetOutputTypeInfo(0);
|
||||
auto outputTensorInfo = outputTypeInfo.GetTensorTypeAndShapeInfo();
|
||||
ONNXTensorElementDataType outputType = outputTensorInfo.GetElementType();
|
||||
//std::cout << "Output Type: " << outputType << std::endl;
|
||||
std::vector<int64_t> outputDims = outputTensorInfo.GetShape();//1 25200 41
|
||||
#ifdef _DEBUG
|
||||
if (std::string(outputName) == "modelOutput" && std::string(inputName) == "modelInput"
|
||||
|| std::string(outputName) == "platesTypeOutput" && std::string(inputName) == "inputImage") {
|
||||
assert(inputDims.size() == 4);
|
||||
assert(inputDims[0] == 1);
|
||||
assert(inputDims[1] == 3);
|
||||
assert(inputDims[2] == 80);
|
||||
assert(inputDims[3] == 200);
|
||||
for (size_t i = 0; i < inputDims.size(); i++)
|
||||
std::cout << inputDims[i] << std::endl;
|
||||
assert(outputDims.size() == 2);
|
||||
assert(outputDims[0] == 1);
|
||||
assert(outputDims[1] == 502);//502 types of lps
|
||||
}
|
||||
else {
|
||||
assert(outputDims.size() == 3);
|
||||
assert(outputDims[0] == 1);
|
||||
assert(outputDims[2] == 103);// 0,1,2,3 ->box,4->confidence,1 -> output classes = 36 characters+pays 61 + 1 vehicle= 98 classes =4+1+36+61+1=103
|
||||
}
|
||||
#endif //_DEBUG
|
||||
// std::cout << "Output Dimensions: " << std::endl;
|
||||
// for (size_t i = 0; i < outputDims.size(); i++)
|
||||
// std::cout << outputDims[i] << std::endl;
|
||||
// std::cout << std::endl;
|
||||
}
|
||||
//returns the maximum size of input image (ie width or height of dnn input layer)
|
||||
int64_t OnnxDetector::max_image_size() const {
|
||||
std::vector<std::vector<Detection>> result;
|
||||
cv::Mat resizedImageRGB, resizedImage, preprocessedImage;
|
||||
Ort::TypeInfo inputTypeInfo = session.GetInputTypeInfo(0);
|
||||
auto inputTensorInfo = inputTypeInfo.GetTensorTypeAndShapeInfo();
|
||||
std::vector<int64_t> inputDims = inputTensorInfo.GetShape();
|
||||
int64_t max_size = inputDims.at(2);// width;
|
||||
if (max_size < inputDims.at(3))//height
|
||||
max_size = inputDims.at(3);
|
||||
return max_size;
|
||||
}
|
||||
std::vector<std::vector<Detection>>
|
||||
OnnxDetector::Run(const cv::Mat& img, float conf_threshold, float iou_threshold, bool preserve_aspect_ratio) {
|
||||
std::vector<std::vector<Detection>> result;
|
||||
cv::Mat resizedImageRGB, resizedImage, preprocessedImage;
|
||||
Ort::TypeInfo inputTypeInfo = session.GetInputTypeInfo(0);
|
||||
auto inputTensorInfo = inputTypeInfo.GetTensorTypeAndShapeInfo();
|
||||
std::vector<int64_t> inputDims = inputTensorInfo.GetShape();
|
||||
//cv::Mat img = cv::imread(imageFilepath, cv::ImreadModes::IMREAD_COLOR);
|
||||
int channels_ = img.channels();
|
||||
if (
|
||||
img.size().width &&
|
||||
img.size().height && ((channels_ == 1) || (channels_ == 3) || (channels_ == 4))) {
|
||||
if (channels_ == 1) {
|
||||
cv::cvtColor(img, resizedImageRGB,
|
||||
cv::ColorConversionCodes::COLOR_GRAY2RGB);
|
||||
}
|
||||
else if (channels_ == 4) {
|
||||
cv::cvtColor(img, resizedImageRGB,
|
||||
cv::ColorConversionCodes::COLOR_BGRA2RGB);
|
||||
}
|
||||
else if (channels_ == 3) {
|
||||
int type = img.type();
|
||||
cv::cvtColor(img, resizedImageRGB,
|
||||
cv::ColorConversionCodes::COLOR_BGR2RGB);
|
||||
}
|
||||
float pad_w = -1.0f, pad_h = -1.0f, scale = -1.0f;
|
||||
if (preserve_aspect_ratio) {
|
||||
// keep the original image for visualization purpose
|
||||
std::vector<float> pad_info = LetterboxImage(resizedImageRGB, resizedImageRGB, cv::Size(static_cast<int>(inputDims.at(2)), static_cast<int>(inputDims.at(3))));
|
||||
//pad_w is the left (and also right) border width in the square image feeded to the model
|
||||
pad_w = pad_info[0];
|
||||
pad_h = pad_info[1];
|
||||
scale = pad_info[2];
|
||||
}
|
||||
else {
|
||||
cv::resize(resizedImageRGB, resizedImageRGB,
|
||||
cv::Size(static_cast<int>(inputDims.at(2)), static_cast<int>(inputDims.at(3))),
|
||||
cv::InterpolationFlags::INTER_CUBIC);
|
||||
}
|
||||
resizedImageRGB.convertTo(resizedImage, CV_32FC3, 1.0f / 255.0f);
|
||||
// HWC to CHW
|
||||
cv::dnn::blobFromImage(resizedImage, preprocessedImage);
|
||||
int64_t inputTensorSize = vectorProduct(inputDims);
|
||||
std::vector<float> inputTensorValues(inputTensorSize);
|
||||
inputTensorValues.assign(preprocessedImage.begin<float>(),
|
||||
preprocessedImage.end<float>());
|
||||
Ort::TypeInfo outputTypeInfo = session.GetOutputTypeInfo(0);
|
||||
auto outputTensorInfo = outputTypeInfo.GetTensorTypeAndShapeInfo();
|
||||
ONNXTensorElementDataType outputType = outputTensorInfo.GetElementType();//1
|
||||
#ifdef _DEBUG
|
||||
assert(outputType == 1);
|
||||
#endif //_DEBUG
|
||||
std::vector<int64_t> outputDims = outputTensorInfo.GetShape();//1 25200 41
|
||||
#ifdef _DEBUG
|
||||
assert(outputDims.size() == 3);
|
||||
assert(outputDims[0] == 1);
|
||||
//assert(outputDims[1] == 25200);
|
||||
assert(outputDims[2] == 103);// 0,1,2,3 ->box,4->confidence,1 -> output classes = 36 characters+pays 61 + 1 vehicle= 98 classes =4+1+36+61+1=103
|
||||
#endif //_DEBUG
|
||||
int64_t outputTensorSize = vectorProduct(outputDims);
|
||||
std::vector<float> outputTensorValues(outputTensorSize);
|
||||
Ort::AllocatorWithDefaultOptions allocator;
|
||||
std::vector<const char*> inputNames;
|
||||
std::vector<Ort::AllocatedStringPtr> inputNodeNameAllocatedStrings; // <-- newly added
|
||||
std::vector<const char*> outputNames;
|
||||
std::vector<Ort::AllocatedStringPtr> outputNodeNameAllocatedStrings; // <-- newly added
|
||||
inputNames.clear();
|
||||
outputNames.clear();
|
||||
|
||||
auto inputName = session.GetInputNameAllocated(0, allocator);//session.GetInputName(0, allocator);
|
||||
inputNodeNameAllocatedStrings.push_back(std::move(inputName));
|
||||
inputNames.push_back(inputNodeNameAllocatedStrings.back().get());
|
||||
|
||||
|
||||
auto outputName = session.GetOutputNameAllocated(0, allocator);
|
||||
outputNodeNameAllocatedStrings.push_back(std::move(outputName));
|
||||
outputNames.push_back(outputNodeNameAllocatedStrings.back().get());
|
||||
|
||||
std::vector<Ort::Value> inputTensors;
|
||||
std::vector<Ort::Value> outputTensors;
|
||||
Ort::MemoryInfo memoryInfo = Ort::MemoryInfo::CreateCpu(
|
||||
OrtAllocatorType::OrtArenaAllocator, OrtMemType::OrtMemTypeDefault);
|
||||
inputTensors.push_back(Ort::Value::CreateTensor<float>(
|
||||
memoryInfo, inputTensorValues.data(), inputTensorSize, inputDims.data(),
|
||||
inputDims.size()));
|
||||
outputTensors.push_back(Ort::Value::CreateTensor<float>(
|
||||
memoryInfo, outputTensorValues.data(), outputTensorSize,
|
||||
outputDims.data(), outputDims.size()));
|
||||
// https://github.com/microsoft/onnxruntime/blob/rel-1.6.0/include/onnxruntime/core/session/onnxruntime_cxx_api.h#L353
|
||||
session.Run(Ort::RunOptions{ nullptr }, inputNames.data(), inputTensors.data(), 1, outputNames.data(), outputTensors.data(), 1);
|
||||
size_t dimensionsCount = outputTensorInfo.GetDimensionsCount();//3
|
||||
#ifdef _DEBUG
|
||||
assert(dimensionsCount == 3);
|
||||
#endif //_DEBUG
|
||||
float* output = outputTensors[0].GetTensorMutableData<float>(); // output of onnx runtime ->>> 1,25200,85
|
||||
size_t size = outputTensors[0].GetTensorTypeAndShapeInfo().GetElementCount(); // 1x25200x85=2142000
|
||||
int64_t dimensions = outputDims[2]; // 0,1,2,3 ->box,4->confidence,5-85 -> output classes = 35 characters+pays 60 = 95 classes confidence
|
||||
#ifdef _DEBUG
|
||||
assert(dimensions >= 41);// 0,1,2,3 ->box,4->confidence,5-85 -> output classes = 35 characters+pays 60 = 95 classes confidence
|
||||
#endif //_DEBUG
|
||||
const cv::Size& out_size = cv::Size(static_cast<int>(inputDims[3]), static_cast<int>(inputDims[3]));
|
||||
std::vector<std::vector<Detection>> detections;
|
||||
if (preserve_aspect_ratio) {
|
||||
// keep the original image for visualization purpose
|
||||
detections = (
|
||||
PostProcessing(
|
||||
output, // output of onnx runtime ->>> 1,25200,85
|
||||
dimensionsCount,
|
||||
size, // 1x25200x85=2142000
|
||||
static_cast<int>(dimensions),
|
||||
//pad_w is the left (and also right) border width in the square image feeded to the model
|
||||
pad_w, pad_h, scale, img.size(),
|
||||
conf_threshold, iou_threshold));
|
||||
}
|
||||
else {
|
||||
detections = (PostProcessing(
|
||||
output, // output of onnx runtime ->>> 1,25200,85
|
||||
dimensionsCount,
|
||||
size, // 1x25200x85=2142000
|
||||
static_cast<int>(dimensions),
|
||||
static_cast<float>(out_size.width), static_cast<float>(out_size.height), img.size(),
|
||||
conf_threshold, iou_threshold));
|
||||
}
|
||||
#ifdef _DEBUG
|
||||
std::list<cv::Rect> true_boxes; std::list<int> classesId;
|
||||
std::vector<Detection>::const_iterator it(detections[0].begin());
|
||||
while (it != detections[0].end()) {
|
||||
true_boxes.push_back(it->bbox);
|
||||
classesId.push_back(it->class_idx);
|
||||
it++;
|
||||
}
|
||||
#endif //_DEBUG
|
||||
return detections;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
std::list<std::vector<std::vector<Detection>>>
|
||||
OnnxDetector::Run(const cv::Mat& img
|
||||
//, float conf_threshold
|
||||
, float iou_threshold
|
||||
) {
|
||||
std::list<std::vector<std::vector<Detection>>> result;
|
||||
cv::Mat resizedImageRGB, resizedImage, preprocessedImage;
|
||||
Ort::TypeInfo inputTypeInfo = session.GetInputTypeInfo(0);
|
||||
auto inputTensorInfo = inputTypeInfo.GetTensorTypeAndShapeInfo();
|
||||
std::vector<int64_t> inputDims = inputTensorInfo.GetShape();
|
||||
//cv::Mat img = cv::imread(imageFilepath, cv::ImreadModes::IMREAD_COLOR);
|
||||
int channels_ = img.channels();
|
||||
if (
|
||||
img.size().width &&
|
||||
img.size().height && ((channels_ == 1) || (channels_ == 3) || (channels_ == 4))) {
|
||||
if (channels_ == 1) {
|
||||
cv::cvtColor(img, resizedImageRGB,
|
||||
cv::ColorConversionCodes::COLOR_GRAY2RGB);
|
||||
}
|
||||
else if (channels_ == 4) {
|
||||
cv::cvtColor(img, resizedImageRGB,
|
||||
cv::ColorConversionCodes::COLOR_BGRA2RGB);
|
||||
}
|
||||
else if (channels_ == 3) {
|
||||
int type = img.type();
|
||||
cv::cvtColor(img, resizedImageRGB,
|
||||
cv::ColorConversionCodes::COLOR_BGR2RGB);
|
||||
}
|
||||
bool preserve_aspect_ratio = true;
|
||||
float pad_w = -1.0f, pad_h = -1.0f, scale = -1.0f;
|
||||
// keep the original image for visualization purpose
|
||||
std::vector<float> pad_info = LetterboxImage(resizedImageRGB, resizedImageRGB, cv::Size(static_cast<int>(inputDims.at(2)), static_cast<int>(inputDims.at(3))));
|
||||
//pad_w is the left (and also right) border width in the square image feeded to the model
|
||||
pad_w = pad_info[0];
|
||||
pad_h = pad_info[1];
|
||||
scale = pad_info[2];
|
||||
resizedImageRGB.convertTo(resizedImage, CV_32FC3, 1.0f / 255.0f);
|
||||
// HWC to CHW
|
||||
cv::dnn::blobFromImage(resizedImage, preprocessedImage);
|
||||
int64_t inputTensorSize = vectorProduct(inputDims);
|
||||
std::vector<float> inputTensorValues(inputTensorSize);
|
||||
inputTensorValues.assign(preprocessedImage.begin<float>(),
|
||||
preprocessedImage.end<float>());
|
||||
Ort::TypeInfo outputTypeInfo = session.GetOutputTypeInfo(0);
|
||||
auto outputTensorInfo = outputTypeInfo.GetTensorTypeAndShapeInfo();
|
||||
ONNXTensorElementDataType outputType = outputTensorInfo.GetElementType();//1
|
||||
#ifdef _DEBUG
|
||||
assert(outputType == 1);
|
||||
#endif //_DEBUG
|
||||
std::vector<int64_t> outputDims = outputTensorInfo.GetShape();//1 25200 41
|
||||
#ifdef _DEBUG
|
||||
assert(outputDims.size() == 3);
|
||||
assert(outputDims[0] == 1);
|
||||
//assert(outputDims[1] == 25200);
|
||||
assert(outputDims[2] == 103);// 0,1,2,3 ->box,4->confidence,1 -> output classes = 36 characters+pays 61 + 1 vehicle= 98 classes =4+1+36+61+1=103
|
||||
#endif //_DEBUG
|
||||
int64_t outputTensorSize = vectorProduct(outputDims);
|
||||
std::vector<float> outputTensorValues(outputTensorSize);
|
||||
Ort::AllocatorWithDefaultOptions allocator;
|
||||
|
||||
std::vector<const char*> inputNames;
|
||||
std::vector<Ort::AllocatedStringPtr> inputNodeNameAllocatedStrings; // <-- newly added
|
||||
std::vector<const char*> outputNames;
|
||||
std::vector<Ort::AllocatedStringPtr> outputNodeNameAllocatedStrings; // <-- newly added
|
||||
inputNames.clear();
|
||||
outputNames.clear();
|
||||
|
||||
auto inputName = session.GetInputNameAllocated(0, allocator);//session.GetInputName(0, allocator);
|
||||
inputNodeNameAllocatedStrings.push_back(std::move(inputName));
|
||||
inputNames.push_back(inputNodeNameAllocatedStrings.back().get());
|
||||
|
||||
|
||||
auto outputName = session.GetOutputNameAllocated(0, allocator);
|
||||
outputNodeNameAllocatedStrings.push_back(std::move(outputName));
|
||||
outputNames.push_back(outputNodeNameAllocatedStrings.back().get());
|
||||
|
||||
|
||||
std::vector<Ort::Value> inputTensors;
|
||||
std::vector<Ort::Value> outputTensors;
|
||||
Ort::MemoryInfo memoryInfo = Ort::MemoryInfo::CreateCpu(
|
||||
OrtAllocatorType::OrtArenaAllocator, OrtMemType::OrtMemTypeDefault);
|
||||
inputTensors.push_back(Ort::Value::CreateTensor<float>(
|
||||
memoryInfo, inputTensorValues.data(), inputTensorSize, inputDims.data(),
|
||||
inputDims.size()));
|
||||
outputTensors.push_back(Ort::Value::CreateTensor<float>(
|
||||
memoryInfo, outputTensorValues.data(), outputTensorSize,
|
||||
outputDims.data(), outputDims.size()));
|
||||
// https://github.com/microsoft/onnxruntime/blob/rel-1.6.0/include/onnxruntime/core/session/onnxruntime_cxx_api.h#L353
|
||||
session.Run(Ort::RunOptions{ nullptr }, inputNames.data(), inputTensors.data(), 1, outputNames.data(), outputTensors.data(), 1);
|
||||
size_t dimensionsCount = outputTensorInfo.GetDimensionsCount();//3
|
||||
#ifdef _DEBUG
|
||||
assert(dimensionsCount == 3);
|
||||
#endif //_DEBUG
|
||||
float* output = outputTensors[0].GetTensorMutableData<float>(); // output of onnx runtime ->>> 1,25200,85
|
||||
size_t size = outputTensors[0].GetTensorTypeAndShapeInfo().GetElementCount(); // 1x25200x85=2142000
|
||||
int64_t dimensions = outputDims[2]; // 0,1,2,3 ->box,4->confidence,5-85 -> output classes = 35 characters+pays 60 = 95 classes confidence
|
||||
#ifdef _DEBUG
|
||||
assert(dimensions >= 41);// 0,1,2,3 ->box,4->confidence,5-85 -> output classes = 35 characters+pays 60 = 95 classes confidence
|
||||
#endif //_DEBUG
|
||||
const cv::Size& out_size = cv::Size(static_cast<int>(inputDims[3]), static_cast<int>(inputDims[3]));
|
||||
const int nb_passes = 10;
|
||||
const float conf_threshold_min = 0.1f;
|
||||
for (int conf_threshold_step = 0; conf_threshold_step < nb_passes; conf_threshold_step++)
|
||||
{
|
||||
float conf_threshold = conf_threshold_min + static_cast<float>(conf_threshold_step) * (1.0f - 2.0f * conf_threshold_min) / (static_cast<float>(nb_passes));
|
||||
// keep the original image for visualization purpose
|
||||
std::vector<std::vector<Detection>> current_detections = (
|
||||
PostProcessing(
|
||||
output, // output of onnx runtime ->>> 1,25200,85
|
||||
dimensionsCount,
|
||||
size, // 1x25200x85=2142000
|
||||
static_cast<int>(dimensions),
|
||||
//pad_w is the left (and also right) border width in the square image feeded to the model
|
||||
pad_w, pad_h, scale, img.size(),
|
||||
conf_threshold, iou_threshold));
|
||||
result.push_back(current_detections);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
//non max suppession algorithm to select boxes
|
||||
void nms(const std::vector<cv::Rect>& srcRects, std::vector<cv::Rect>& resRects, std::vector<int>& resIndexs, float thresh) {
|
||||
resRects.clear();
|
||||
const size_t size = srcRects.size();
|
||||
if (!size) return;
|
||||
// Sort the bounding boxes by the bottom - right y - coordinate of the bounding box
|
||||
std::multimap<int, size_t> idxs;
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
idxs.insert(std::pair<int, size_t>(srcRects[i].br().y, i));
|
||||
}
|
||||
// keep looping while some indexes still remain in the indexes list
|
||||
while (idxs.size() > 0) {
|
||||
// grab the last rectangle
|
||||
auto lastElem = --std::end(idxs);
|
||||
const cv::Rect& last = srcRects[lastElem->second];
|
||||
resIndexs.push_back(static_cast<int>(lastElem->second));
|
||||
resRects.push_back(last);
|
||||
idxs.erase(lastElem);
|
||||
for (auto pos = std::begin(idxs); pos != std::end(idxs); ) {
|
||||
// grab the current rectangle
|
||||
const cv::Rect& current = srcRects[pos->second];
|
||||
float intArea = static_cast<float>((last & current).area());
|
||||
float unionArea = last.area() + current.area() - intArea;
|
||||
float overlap = intArea / unionArea;
|
||||
// if there is sufficient overlap, suppress the current bounding box
|
||||
if (overlap > thresh) pos = idxs.erase(pos);
|
||||
else ++pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
256
modules/ANSLPR/src/StatSommesX_Y_H_dbl.cpp
Normal file
256
modules/ANSLPR/src/StatSommesX_Y_H_dbl.cpp
Normal file
@@ -0,0 +1,256 @@
|
||||
//*
|
||||
// StatSommesX_Y_H_dbl.cpp: implementation of the C_SumsRegLineXYHDbl class.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
#ifndef GITHUB
|
||||
#include "StatSommesX_Y_H_dbl.h"
|
||||
#include <cmath>
|
||||
#include <climits>
|
||||
#ifdef _WINDOWS
|
||||
#endif //_WINDOWS
|
||||
#ifdef _DEBUG
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#define new DEBUG_NEW
|
||||
#endif
|
||||
inline float divise_par_zero(const float& numerateur, // Modif PN passage de float en double
|
||||
const bool denominateur_positif = true) {
|
||||
if (denominateur_positif) {
|
||||
if (numerateur > 0.0f) {
|
||||
if (numerateur < FLT_EPSILON) return 0.0f;
|
||||
else return FLT_MAX;
|
||||
}
|
||||
else {
|
||||
if (FLT_EPSILON + numerateur > 0.0f) return 0.0f;
|
||||
else return -FLT_MAX;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (numerateur > 0.0f) {
|
||||
if (numerateur < FLT_EPSILON) return 0.0f;
|
||||
else return -FLT_MAX;
|
||||
}
|
||||
else {
|
||||
if (FLT_EPSILON + numerateur > 0.0f) return 0.0f;
|
||||
else return FLT_MAX;
|
||||
}
|
||||
}
|
||||
};
|
||||
C_SumsRegLineXYHDbl::C_SumsRegLineXYHDbl() : somme_x(0.0f)
|
||||
, somme_y(0.0f)
|
||||
, produit_xy(0.0f)
|
||||
, somme_carre_x(0.0f)
|
||||
, somme_hauteurs(0)
|
||||
{
|
||||
}
|
||||
C_SumsRegLineXYHDbl::C_SumsRegLineXYHDbl(const int somme_hauteurs_) : somme_x(0.0f)
|
||||
, somme_y(0.0f)
|
||||
, produit_xy(0.0f)
|
||||
, somme_carre_x(0.0f)
|
||||
, somme_hauteurs(somme_hauteurs_)
|
||||
{
|
||||
}
|
||||
C_SumsRegLineXYHDbl::~C_SumsRegLineXYHDbl()
|
||||
{
|
||||
}
|
||||
#ifdef _DEBUG
|
||||
bool C_SumsRegLineXYHDbl::debug(const float& somme_x_,
|
||||
const float& somme_y_,
|
||||
const float& produit_xy_,
|
||||
const float& somme_carre_x_) const
|
||||
{
|
||||
#ifdef LPR_DOUBLE_PRECISION
|
||||
return (fabsf(somme_x - somme_x_) < FLT_EPSILON
|
||||
&& fabsf(somme_y - somme_y_) < FLT_EPSILON
|
||||
&& fabsf((produit_xy - produit_xy_)) < FLT_EPSILON
|
||||
&& fabsf((somme_carre_x - somme_carre_x_)) < FLT_EPSILON
|
||||
);
|
||||
#else // LPR_DOUBLE_PRECISION
|
||||
bool ok = fabsf(somme_x - somme_x_) < FLT_EPSILON
|
||||
&& fabsf(somme_y - somme_y_) < FLT_EPSILON;
|
||||
if (produit_xy + produit_xy_ > FLT_EPSILON)
|
||||
ok = ok && fabsf((produit_xy - produit_xy_)) < FLT_EPSILON * (produit_xy + produit_xy_);
|
||||
else ok = ok && fabsf((produit_xy - produit_xy_)) < FLT_EPSILON;
|
||||
if (somme_carre_x + somme_carre_x_ > FLT_EPSILON)
|
||||
ok = ok && fabsf((somme_carre_x - somme_carre_x_)) < FLT_EPSILON * (somme_carre_x + somme_carre_x_);
|
||||
else ok = ok && fabsf((somme_carre_x - somme_carre_x_)) < FLT_EPSILON;
|
||||
return ok;
|
||||
#endif // LPR_DOUBLE_PRECISION
|
||||
}
|
||||
bool C_SumsRegLineXYHDbl::debug(const float& somme_x_,
|
||||
const float& somme_y_,
|
||||
const float& produit_xy_,
|
||||
const float& somme_carre_x_,
|
||||
const int heigth_) const
|
||||
{
|
||||
/*
|
||||
return (somme_x== somme_x_ && somme_y==somme_y_ &&
|
||||
produit_xy==produit_xy_ && somme_carre_x==somme_carre_x_ && somme_hauteurs==heigth_);
|
||||
*/
|
||||
#ifdef LPR_DOUBLE_PRECISION
|
||||
return (fabsf(somme_x - somme_x_) < FLT_EPSILON
|
||||
&& fabsf(somme_y - somme_y_) < FLT_EPSILON
|
||||
&& fabsf((produit_xy - produit_xy_)) < FLT_EPSILON
|
||||
&& fabsf((somme_carre_x - somme_carre_x_)) < FLT_EPSILON
|
||||
&& somme_hauteurs == heigth_);
|
||||
#else // LPR_DOUBLE_PRECISION
|
||||
return (fabsf(somme_x - somme_x_) < FLT_EPSILON
|
||||
&& fabsf(somme_y - somme_y_) < FLT_EPSILON
|
||||
&& fabsf((produit_xy - produit_xy_)) < FLT_EPSILON * (produit_xy + produit_xy_)
|
||||
&& fabsf((somme_carre_x - somme_carre_x_)) < FLT_EPSILON * (somme_carre_x + somme_carre_x_)
|
||||
&& somme_hauteurs == heigth_);
|
||||
#endif // LPR_DOUBLE_PRECISION
|
||||
}
|
||||
#endif //_DEBUG
|
||||
float C_SumsRegLineXYHDbl::pente(const int nb_elements) const
|
||||
{//calcul de la moyenne des xi
|
||||
//calcul de la moyenne des yi
|
||||
#ifdef _DEBUG
|
||||
assert(nb_elements > 1);
|
||||
#endif //_DEBUG
|
||||
if (nb_elements == 1) return 0.0f;
|
||||
else if (nb_elements > 1) {
|
||||
float moyenne_x = somme_x / nb_elements;
|
||||
float moyenne_y = somme_y / nb_elements;
|
||||
//calcul de la std_deviation(X)
|
||||
float variance = (somme_carre_x)-somme_x * moyenne_x;
|
||||
if (fabsf(variance) < FLT_EPSILON) return FLT_MAX;
|
||||
//calcul de la Covariance(X,Y)
|
||||
float Covariance = (produit_xy)-moyenne_x * somme_y;
|
||||
//calcul de la pente p=Covariance(X,Y)/variance(X)
|
||||
#ifdef _DEBUG
|
||||
assert(variance > -FLT_EPSILON);
|
||||
#endif //_DEBUG
|
||||
float pente_;
|
||||
if (variance != 0.0f) pente_ = Covariance / variance;
|
||||
else pente_ = divise_par_zero(Covariance);
|
||||
#ifdef _DEBUG
|
||||
const float pi = 3.1415926535897932384626433832795f;
|
||||
#ifdef _DEBUG
|
||||
assert(atanf(pente_) <= pi / 2 && (atanf(pente_) + pi / 2) > -FLT_EPSILON);
|
||||
#endif //_DEBUG
|
||||
#endif
|
||||
return pente_;
|
||||
}
|
||||
else return 0.0f;
|
||||
}
|
||||
cv::Point2f C_SumsRegLineXYHDbl::barycenter(const int nb_points)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
assert(nb_points > 1);
|
||||
#endif //_DEBUG
|
||||
if (nb_points <= 0) return cv::Point2f(FLT_MAX, FLT_MAX);
|
||||
else if (nb_points == 0) {
|
||||
float moyenne_x = somme_x;
|
||||
float moyenne_y = somme_y;
|
||||
return cv::Point2f(moyenne_x, moyenne_y);
|
||||
}
|
||||
else {
|
||||
#ifdef _DEBUG
|
||||
assert(nb_points > 1);
|
||||
#endif //_DEBUG
|
||||
float moyenne_x = somme_x / nb_points;
|
||||
float moyenne_y = somme_y / nb_points;
|
||||
return cv::Point2f(moyenne_x, moyenne_y);
|
||||
}
|
||||
}
|
||||
C_Line C_SumsRegLineXYHDbl::regression_line(const int nb_elements)
|
||||
{
|
||||
if (nb_elements == 0) return C_Line();
|
||||
else if (nb_elements == 1) return C_Line(0.0, somme_y);
|
||||
else if (nb_elements > 1) {
|
||||
float moyenne_x = somme_x / nb_elements;
|
||||
float moyenne_y = somme_y / nb_elements;
|
||||
//calcul de la std_deviation(X)
|
||||
float variance = (somme_carre_x)-somme_x * moyenne_x;
|
||||
if (fabsf(variance) < FLT_EPSILON) return C_Line(FLT_MAX, FLT_MAX);
|
||||
//calcul de la Covariance(X,Y)
|
||||
float Covariance = (produit_xy)-moyenne_x * somme_y;
|
||||
//calcul de la pente_ p=Covariance(X,Y)/variance(X)
|
||||
float pente_ = Covariance / variance;
|
||||
//calcul du coefficient q ( y=px+q )
|
||||
float ordonnee_origine = moyenne_y - pente_ * moyenne_x;
|
||||
#ifdef _DEBUG
|
||||
const float pi = 3.1415926535897932384626433832795f;
|
||||
assert(atanf(pente_) <= pi / 2 && (atanf(pente_) + pi / 2) > -FLT_EPSILON);
|
||||
#endif //_DEBUG
|
||||
C_Line regression_line(pente_, ordonnee_origine);
|
||||
#ifdef _DEBUG
|
||||
//calcul de la moyenne des xi
|
||||
//calcul de la moyenne des yi
|
||||
//ce sont les coordonnees du centre de gravit du fond principal
|
||||
float moyenne_x_ = somme_x / nb_elements;
|
||||
float moyenne_y_ = somme_y / nb_elements;
|
||||
//calcul de la std_deviation(X)
|
||||
float variance_ = (somme_carre_x - somme_x * moyenne_x_);
|
||||
//calcul de la Covariance(X,Y)
|
||||
float Covariance_ = (produit_xy - moyenne_x_ * somme_y);
|
||||
//calcul de la pente p=Covariance(X,Y)/variance(X)
|
||||
#ifdef _DEBUG
|
||||
assert(variance > -FLT_EPSILON);
|
||||
#endif //_DEBUG
|
||||
float pente__;
|
||||
if (variance_ > FLT_EPSILON) pente__ = Covariance_ / variance_;
|
||||
else {
|
||||
pente__ = divise_par_zero(Covariance_);//calcul du coefficient q ( y=px+q )
|
||||
}
|
||||
float ordonnee_origine_ = moyenne_y_ - pente__ * moyenne_x_;
|
||||
#ifdef _DEBUG
|
||||
assert(fabsf(regression_line.a - pente__) < FLT_EPSILON && fabsf(regression_line.b - ordonnee_origine_) < 0.001f);
|
||||
#endif //_DEBUG
|
||||
float diff_ = regression_line.a - pente__;
|
||||
diff_ = regression_line.b - ordonnee_origine_;
|
||||
#endif //_DEBUG
|
||||
return regression_line;
|
||||
}
|
||||
else return C_Line();
|
||||
}
|
||||
bool C_SumsRegLineXYHDbl::operator ==(const C_SumsRegLineXYHDbl& right_op) const
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
double somme_x_r = right_op.somme_x;
|
||||
double somme_y_r = right_op.somme_y;
|
||||
double produit_xy_r = right_op.produit_xy;
|
||||
double somme_carre_x_r = right_op.somme_carre_x;
|
||||
double produit_xy_ = produit_xy;
|
||||
double somme_carre_x_ = somme_carre_x;
|
||||
assert(fabsf(somme_x - right_op.somme_x) < FLT_EPSILON
|
||||
&& fabsf(somme_y - right_op.somme_y) < FLT_EPSILON
|
||||
&& somme_hauteurs == right_op.somme_hauteurs);
|
||||
#ifdef LPR_DOUBLE_PRECISION
|
||||
assert(fabsf((produit_xy - right_op.produit_xy)) <
|
||||
FLT_EPSILON * (produit_xy + right_op.produit_xy)
|
||||
&& fabsf((somme_carre_x - right_op.somme_carre_x)) < FLT_EPSILON *
|
||||
(somme_carre_x + right_op.somme_carre_x));
|
||||
#else // LPR_DOUBLE_PRECISION
|
||||
assert(fabsf((produit_xy - right_op.produit_xy)) / (produit_xy + right_op.produit_xy) < FLT_EPSILON
|
||||
&& fabsf((somme_carre_x - right_op.somme_carre_x)) / (somme_carre_x + right_op.somme_carre_x) < FLT_EPSILON);
|
||||
#endif // LPR_DOUBLE_PRECISION
|
||||
float dif = fabsf(somme_x - right_op.somme_x);
|
||||
dif = fabsf(somme_y - right_op.somme_y);
|
||||
dif = fabsf((produit_xy - right_op.produit_xy));
|
||||
dif = fabsf((somme_carre_x - right_op.somme_carre_x));
|
||||
#endif
|
||||
#ifdef LPR_DOUBLE_PRECISION
|
||||
return (fabsf(somme_x - right_op.somme_x) < FLT_EPSILON
|
||||
&& fabsf(somme_y - right_op.somme_y) < FLT_EPSILON
|
||||
&& fabsf((produit_xy - right_op.produit_xy)) < FLT_EPSILON * fabsf((produit_xy + right_op.produit_xy))
|
||||
&& fabsf((somme_carre_x - right_op.somme_carre_x)) < FLT_EPSILON * (somme_carre_x + right_op.somme_carre_x)
|
||||
&& somme_hauteurs == right_op.somme_hauteurs);
|
||||
#else // LPR_DOUBLE_PRECISION
|
||||
return (fabsf(somme_x - right_op.somme_x) < FLT_EPSILON
|
||||
&& fabsf(somme_y - right_op.somme_y) < FLT_EPSILON
|
||||
&& fabsf((produit_xy - right_op.produit_xy)) < FLT_EPSILON * (produit_xy + right_op.produit_xy)
|
||||
&& fabsf((somme_carre_x - right_op.somme_carre_x)) < FLT_EPSILON * (somme_carre_x + right_op.somme_carre_x)
|
||||
&& somme_hauteurs == right_op.somme_hauteurs);
|
||||
#endif // LPR_DOUBLE_PRECISION
|
||||
}
|
||||
void C_SumsRegLineXYHDbl::clear()
|
||||
{
|
||||
somme_x = 0.0f;
|
||||
somme_y = 0.0f;
|
||||
produit_xy = 0.0f;
|
||||
somme_carre_x = 0.0f;
|
||||
somme_hauteurs = 0;
|
||||
}
|
||||
#endif //GITHUB
|
||||
2902
modules/ANSLPR/src/utils_alpr_detect.cpp
Normal file
2902
modules/ANSLPR/src/utils_alpr_detect.cpp
Normal file
File diff suppressed because it is too large
Load Diff
171
modules/ANSLPR/src/utils_image_file.cpp
Normal file
171
modules/ANSLPR/src/utils_image_file.cpp
Normal file
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
// Line.h: interface for the C_Line class.
|
||||
*/
|
||||
#include "../include/utils_image_file.h"
|
||||
#include <opencv2/opencv.hpp>
|
||||
#include <filesystem>
|
||||
#include "../include/utils_alpr_detect.h"
|
||||
#define NUMBER_OF_CARACTERS_LATIN_NUMBERPLATE 36
|
||||
|
||||
/**
|
||||
@brief
|
||||
returns the true license plate number out of a filename
|
||||
you must place the true license plate number in the image filename this way : number+underscore+license plate number,
|
||||
for instance filename 0000000001_3065WWA34.jpg will be interpreted as an image with the license plate 3065WWA34 in it.
|
||||
@param filename: the image filename that contains in it the true registration number
|
||||
@return the lpn contained in the image filename
|
||||
@see
|
||||
*/
|
||||
std::string getTrueLPN(const std::string& filename, const bool& vrai_lpn_after_underscore)
|
||||
{
|
||||
std::string analysing_string = filename;
|
||||
if (analysing_string == "")
|
||||
return std::string();
|
||||
char sep_underscore = '_';
|
||||
size_t index = 0;
|
||||
index = (analysing_string.find(sep_underscore));
|
||||
if (index != -1)
|
||||
{
|
||||
std::string subanalysing_string;//la sous chaine
|
||||
if (!vrai_lpn_after_underscore) {
|
||||
subanalysing_string = analysing_string.substr(0, index);//la sous chaine
|
||||
}
|
||||
else {
|
||||
subanalysing_string = analysing_string.substr(index + 1, analysing_string.length() - (index + 1));//la sous chaine
|
||||
}
|
||||
if (could_be_lpn(subanalysing_string))
|
||||
return subanalysing_string;
|
||||
else return std::string();
|
||||
}
|
||||
else {
|
||||
if (could_be_lpn(filename))
|
||||
return filename;
|
||||
else return std::string();
|
||||
}
|
||||
}
|
||||
/**
|
||||
@brief
|
||||
//checks if the characters contained in lpn are compatible with the alphabet
|
||||
@param lpn: the registration of the vehicle as a string
|
||||
@return
|
||||
@see
|
||||
*/
|
||||
//extracts from a test directory all images files
|
||||
void load_images_filenames(const std::string& dir, std::list<std::string>& image_filenames)
|
||||
{
|
||||
std::filesystem::path p(dir);
|
||||
std::vector<std::filesystem::directory_entry> v; // To save the file names in a vector.
|
||||
if (is_directory(p))
|
||||
{
|
||||
const std::string dir_path = p.string();
|
||||
std::filesystem::directory_iterator b(p), e;
|
||||
for (auto i = b; i != e; ++i)
|
||||
{
|
||||
if (std::filesystem::is_regular_file(*i)) {
|
||||
std::filesystem::path fe = i->path().extension();
|
||||
std::string extension = fe.string();
|
||||
if (extension == ".bmp" || extension == ".BMP" || extension == ".jpg" || extension == ".JPG" || extension == ".jpeg")
|
||||
{
|
||||
std::filesystem::path p_(i->path());
|
||||
//if you want to select images that have the true license plate number in the image filename
|
||||
const bool select_images_with_lpn = true;
|
||||
if (select_images_with_lpn) {
|
||||
bool vrai_lpn_after_underscore = true;
|
||||
//returns the true license plate number out of a filename
|
||||
//you must place the true license plate number in the image filename this way : number + underscore + license plate number,
|
||||
//for instance filename 0000000001_3065WWA34.jpg will be interpreted as an image with the license plate 3065WWA34 in it.
|
||||
std::string ExactLPN(getTrueLPN(p_.stem().string(), vrai_lpn_after_underscore));
|
||||
if (ExactLPN.size() > 3 && ExactLPN.size() < 11) {
|
||||
image_filenames.push_back(i->path().string());
|
||||
}
|
||||
}
|
||||
else {//take all images files -- output stats impossible
|
||||
image_filenames.push_back(i->path().string());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
@brief
|
||||
//return the ascii character that corresponds to index class output by the dnn
|
||||
@param classe : integer index = class identifier, output by the object detection dnn
|
||||
@return an ascii character
|
||||
@see
|
||||
*/
|
||||
char get_char(const int classe) {
|
||||
char _LATIN_LETTERS_LATIN_DIGITS[NUMBER_OF_CARACTERS_LATIN_NUMBERPLATE] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J','K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
|
||||
'Y', 'Z','0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
|
||||
if (classe >= 0 && classe < NUMBER_OF_CARACTERS_LATIN_NUMBERPLATE)
|
||||
return _LATIN_LETTERS_LATIN_DIGITS[classe];
|
||||
else return '?';
|
||||
}
|
||||
//retourne l'index du caractere LPChar
|
||||
int get_index(const char LPChar)
|
||||
{
|
||||
switch (LPChar) {
|
||||
case 'A': {return 0; } break;
|
||||
case 'B': {return 1; } break;
|
||||
case 'C': {return 2; } break;
|
||||
case 'D': {return 3; } break;
|
||||
case 'E': {return 4; } break;
|
||||
case 'F': {return 5; } break;
|
||||
case 'G': {return 6; } break;
|
||||
case 'H': {return 7; } break;
|
||||
case 'I': {return 8; } break;
|
||||
case 'J': {return 9; } break;
|
||||
case 'K': {return 10; } break;
|
||||
case 'L': {return 11; } break;
|
||||
case 'M': {return 12; } break;
|
||||
case 'N': {return 13; } break;
|
||||
case 'O': {return 14; } break;
|
||||
case 'P': {return 15; } break;
|
||||
case 'Q': {return 16; } break;
|
||||
case 'R': {return 17; } break;
|
||||
case 'S': {return 18; } break;
|
||||
case 'T': {return 19; } break;
|
||||
case 'U': {return 20; } break;
|
||||
case 'V': {return 21; } break;
|
||||
case 'W': {return 22; } break;
|
||||
case 'X': {return 23; } break;
|
||||
case 'Y': {return 24; } break;
|
||||
case 'Z': {return 25; } break;
|
||||
case '0': {return 26; } break;
|
||||
case '1': {return 27; } break;
|
||||
case '2': {return 28; } break;
|
||||
case '3': {return 29; } break;
|
||||
case '4': {return 30; } break;
|
||||
case '5': {return 31; } break;
|
||||
case '6': {return 32; } break;
|
||||
case '7': {return 33; } break;
|
||||
case '8': {return 34; } break;
|
||||
case '9': {return 35; } break;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
//checks if the characters contained in lpn are compatible with the alphabet
|
||||
/**
|
||||
@brief
|
||||
//checks if the characters contained in lpn are compatible with the alphabet
|
||||
@param lpn: the registration of the vehicle as a string
|
||||
@return
|
||||
@see
|
||||
*/
|
||||
bool could_be_lpn(const std::string& lpn) {
|
||||
char _LATIN_LETTERS_LATIN_DIGITS[NUMBER_OF_CARACTERS_LATIN_NUMBERPLATE] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J','K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
|
||||
'Y', 'Z','0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
|
||||
std::string::const_iterator it(lpn.begin());
|
||||
std::list<char> chars;
|
||||
while (it != lpn.end()) {
|
||||
int i;
|
||||
for (i = 0; i < NUMBER_OF_CARACTERS_LATIN_NUMBERPLATE; i++) {
|
||||
if (*it == _LATIN_LETTERS_LATIN_DIGITS[i]) break;
|
||||
}
|
||||
if (i < NUMBER_OF_CARACTERS_LATIN_NUMBERPLATE) {
|
||||
it++;
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
5509
modules/ANSLPR/src/utils_opencv.cpp
Normal file
5509
modules/ANSLPR/src/utils_opencv.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1994
modules/ANSLPR/src/yolov5_alpr_onnx_detector.cpp
Normal file
1994
modules/ANSLPR/src/yolov5_alpr_onnx_detector.cpp
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user