up e2e cpp
This commit is contained in:
@@ -1,37 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.6)
|
||||
project(SwiftPR)
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
add_library( lib_opencv SHARED IMPORTED )
|
||||
|
||||
|
||||
find_library( # Sets the name of the path variable.
|
||||
log-lib
|
||||
|
||||
# Specifies the name of the NDK library that
|
||||
# you want CMake to locate.
|
||||
log )
|
||||
|
||||
|
||||
include_directories(/Users/yujinke/Downloads/OpenCV-android-sdk-3.3/sdk/native/jni/include)
|
||||
include_directories(include)
|
||||
|
||||
set_target_properties(lib_opencv PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libopencv_java3.so)
|
||||
|
||||
set(SRC_DETECTION src/PlateDetection.cpp src/util.h include/PlateDetection.h)
|
||||
|
||||
set(SRC_FINEMAPPING src/FineMapping.cpp )
|
||||
|
||||
set(SRC_FASTDESKEW src/FastDeskew.cpp )
|
||||
|
||||
set(SRC_SEGMENTATION src/PlateSegmentation.cpp )
|
||||
|
||||
set(SRC_RECOGNIZE src/Recognizer.cpp src/CNNRecognizer.cpp)
|
||||
|
||||
set(SRC_PIPLINE src/Pipeline.cpp)
|
||||
|
||||
|
||||
|
||||
add_library(hyperlpr SHARED ${SRC_DETECTION} ${SRC_FINEMAPPING} ${SRC_FASTDESKEW} ${SRC_SEGMENTATION} ${SRC_RECOGNIZE} ${SRC_PIPLINE} javaWarpper.cpp)
|
||||
|
||||
target_link_libraries(hyperlpr lib_opencv ${log-lib})
|
||||
@@ -12,25 +12,40 @@
|
||||
#include "FastDeskew.h"
|
||||
#include "FineMapping.h"
|
||||
#include "Recognizer.h"
|
||||
#include "SegmentationFreeRecognizer.h"
|
||||
|
||||
namespace pr{
|
||||
|
||||
const std::vector<std::string> CH_PLATE_CODE{"京", "沪", "津", "渝", "冀", "晋", "蒙", "辽", "吉", "黑", "苏", "浙", "皖", "闽", "赣", "鲁", "豫", "鄂", "湘", "粤", "桂",
|
||||
"琼", "川", "贵", "云", "藏", "陕", "甘", "青", "宁", "新", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A",
|
||||
"B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "P", "Q", "R", "S", "T", "U", "V", "W", "X",
|
||||
"Y", "Z","港","学","使","警","澳","挂","军","北","南","广","沈","兰","成","济","海","民","航","空"};
|
||||
|
||||
|
||||
|
||||
const int SEGMENTATION_FREE_METHOD = 0;
|
||||
const int SEGMENTATION_BASED_METHOD = 1;
|
||||
|
||||
class PipelinePR{
|
||||
public:
|
||||
GeneralRecognizer *generalRecognizer;
|
||||
PlateDetection *plateDetection;
|
||||
PlateSegmentation *plateSegmentation;
|
||||
FineMapping *fineMapping;
|
||||
SegmentationFreeRecognizer *segmentationFreeRecognizer;
|
||||
|
||||
PipelinePR(std::string detector_filename,
|
||||
std::string finemapping_prototxt,std::string finemapping_caffemodel,
|
||||
std::string segmentation_prototxt,std::string segmentation_caffemodel,
|
||||
std::string charRecognization_proto,std::string charRecognization_caffemodel
|
||||
std::string charRecognization_proto,std::string charRecognization_caffemodel,
|
||||
std::string segmentationfree_proto,std::string segmentationfree_caffemodel
|
||||
);
|
||||
~PipelinePR();
|
||||
|
||||
|
||||
|
||||
std::vector<std::string> plateRes;
|
||||
std::vector<PlateInfo> RunPiplineAsImage(cv::Mat plateImage);
|
||||
std::vector<PlateInfo> RunPiplineAsImage(cv::Mat plateImage,int method);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -10,17 +10,14 @@ namespace pr {
|
||||
typedef std::vector<cv::Mat> Character;
|
||||
|
||||
enum PlateColor { BLUE, YELLOW, WHITE, GREEN, BLACK,UNKNOWN};
|
||||
enum CharType {CHINESE,LETTER,LETTER_NUMS};
|
||||
enum CharType {CHINESE,LETTER,LETTER_NUMS,INVALID};
|
||||
|
||||
|
||||
class PlateInfo {
|
||||
public:
|
||||
std::vector<std::pair<CharType,cv::Mat>> plateChars;
|
||||
std::vector<std::pair<CharType,cv::Mat>> plateChars;
|
||||
std::vector<std::pair<CharType,cv::Mat>> plateCoding;
|
||||
|
||||
float confidence = 0;
|
||||
|
||||
|
||||
PlateInfo(const cv::Mat &plateData, std::string plateName, cv::Rect plateRect, PlateColor plateType) {
|
||||
licensePlate = plateData;
|
||||
name = plateName;
|
||||
@@ -93,17 +90,21 @@ namespace pr {
|
||||
|
||||
}
|
||||
|
||||
if(plate.first == LETTER) {
|
||||
else if(plate.first == LETTER) {
|
||||
decode += mappingTable[std::max_element(prob+41,prob+65)- prob];
|
||||
confidence+=*std::max_element(prob+41,prob+65);
|
||||
}
|
||||
|
||||
if(plate.first == LETTER_NUMS) {
|
||||
else if(plate.first == LETTER_NUMS) {
|
||||
decode += mappingTable[std::max_element(prob+31,prob+65)- prob];
|
||||
confidence+=*std::max_element(prob+31,prob+65);
|
||||
// std::cout<<*std::max_element(prob+31,prob+65)<<std::endl;
|
||||
|
||||
}
|
||||
else if(plate.first == INVALID)
|
||||
{
|
||||
decode+='*';
|
||||
}
|
||||
|
||||
}
|
||||
name = decode;
|
||||
@@ -113,12 +114,10 @@ namespace pr {
|
||||
return decode;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private:
|
||||
cv::Mat licensePlate;
|
||||
cv::Rect ROI;
|
||||
std::string name;
|
||||
std::string name ;
|
||||
PlateColor Type;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -13,7 +13,9 @@ namespace pr{
|
||||
class GeneralRecognizer{
|
||||
public:
|
||||
virtual label recognizeCharacter(cv::Mat character) = 0;
|
||||
// virtual cv::Mat SegmentationFreeForSinglePlate(cv::Mat plate) = 0;
|
||||
void SegmentBasedSequenceRecognition(PlateInfo &plateinfo);
|
||||
void SegmentationFreeSequenceRecognition(PlateInfo &plateInfo);
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
//
|
||||
// Created by 庾金科 on 28/11/2017.
|
||||
//
|
||||
|
||||
#ifndef SWIFTPR_SEGMENTATIONFREERECOGNIZER_H
|
||||
#define SWIFTPR_SEGMENTATIONFREERECOGNIZER_H
|
||||
|
||||
#include "Recognizer.h"
|
||||
namespace pr{
|
||||
|
||||
|
||||
class SegmentationFreeRecognizer{
|
||||
public:
|
||||
const int CHAR_INPUT_W = 14;
|
||||
const int CHAR_INPUT_H = 30;
|
||||
const int CHAR_LEN = 84;
|
||||
|
||||
SegmentationFreeRecognizer(std::string prototxt,std::string caffemodel);
|
||||
std::pair<std::string,float> SegmentationFreeForSinglePlate(cv::Mat plate,std::vector<std::string> mapping_table);
|
||||
|
||||
|
||||
private:
|
||||
cv::dnn::Net net;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
#endif //SWIFTPR_SEGMENTATIONFREERECOGNIZER_H
|
||||
@@ -5,8 +5,8 @@
|
||||
#include "FineMapping.h"
|
||||
namespace pr{
|
||||
|
||||
const int FINEMAPPING_H = 50;
|
||||
const int FINEMAPPING_W = 120;
|
||||
const int FINEMAPPING_H = 60 ;
|
||||
const int FINEMAPPING_W = 140;
|
||||
const int PADDING_UP_DOWN = 30;
|
||||
void drawRect(cv::Mat image,cv::Rect rect)
|
||||
{
|
||||
@@ -71,12 +71,10 @@ namespace pr{
|
||||
cv::Mat proposal;
|
||||
|
||||
cv::resize(InputProposal,PreInputProposal,cv::Size(FINEMAPPING_W,FINEMAPPING_H));
|
||||
int x = InputProposal.channels();
|
||||
// cv::imwrite("res/cache/finemapping.jpg",PreInputProposal);
|
||||
|
||||
if(InputProposal.channels() == 3)
|
||||
cv::cvtColor(PreInputProposal,proposal,cv::COLOR_BGR2GRAY);
|
||||
else if(InputProposal.channels() == 4)
|
||||
cv::cvtColor(PreInputProposal,proposal,cv::COLOR_BGRA2GRAY);
|
||||
else
|
||||
PreInputProposal.copyTo(proposal);
|
||||
|
||||
@@ -110,7 +108,6 @@ namespace pr{
|
||||
if (( lwRatio>0.7&&bdbox.width*bdbox.height>100 && bdboxAera<300)
|
||||
|| (lwRatio>3.0 && bdboxAera<100 && bdboxAera>10))
|
||||
{
|
||||
|
||||
cv::Point p1(bdbox.x, bdbox.y);
|
||||
cv::Point p2(bdbox.x + bdbox.width, bdbox.y + bdbox.height);
|
||||
line_upper.push_back(p1);
|
||||
@@ -120,7 +117,6 @@ namespace pr{
|
||||
}
|
||||
}
|
||||
|
||||
std:: cout<<"contours_nums "<<contours_nums<<std::endl;
|
||||
|
||||
if(contours_nums<41)
|
||||
{
|
||||
@@ -166,7 +162,7 @@ namespace pr{
|
||||
}
|
||||
|
||||
cv::Mat rgb;
|
||||
cv::copyMakeBorder(PreInputProposal, rgb, 30, 30, 0, 0, cv::BORDER_REPLICATE);
|
||||
cv::copyMakeBorder(PreInputProposal, rgb, PADDING_UP_DOWN, PADDING_UP_DOWN, 0, 0, cv::BORDER_REPLICATE);
|
||||
// cv::imshow("rgb",rgb);
|
||||
// cv::waitKey(0);
|
||||
//
|
||||
@@ -174,8 +170,8 @@ namespace pr{
|
||||
|
||||
std::pair<int, int> A;
|
||||
std::pair<int, int> B;
|
||||
A = FitLineRansac(line_upper, -2);
|
||||
B = FitLineRansac(line_lower, 2);
|
||||
A = FitLineRansac(line_upper, -1);
|
||||
B = FitLineRansac(line_lower, 1);
|
||||
int leftyB = A.first;
|
||||
int rightyB = A.second;
|
||||
int leftyA = B.first;
|
||||
|
||||
@@ -7,18 +7,20 @@
|
||||
|
||||
namespace pr {
|
||||
|
||||
std::vector<std::string> chars_code{"京","沪","津","渝","冀","晋","蒙","辽","吉","黑","苏","浙","皖","闽","赣","鲁","豫","鄂","湘","粤","桂","琼","川","贵","云","藏","陕","甘","青","宁","新","0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F","G","H","J","K","L","M","N","P","Q","R","S","T","U","V","W","X","Y","Z"};
|
||||
|
||||
|
||||
|
||||
const int HorizontalPadding = 4;
|
||||
PipelinePR::PipelinePR(std::string detector_filename,
|
||||
std::string finemapping_prototxt, std::string finemapping_caffemodel,
|
||||
std::string segmentation_prototxt, std::string segmentation_caffemodel,
|
||||
std::string charRecognization_proto, std::string charRecognization_caffemodel) {
|
||||
std::string charRecognization_proto, std::string charRecognization_caffemodel,
|
||||
std::string segmentationfree_proto,std::string segmentationfree_caffemodel) {
|
||||
plateDetection = new PlateDetection(detector_filename);
|
||||
fineMapping = new FineMapping(finemapping_prototxt, finemapping_caffemodel);
|
||||
plateSegmentation = new PlateSegmentation(segmentation_prototxt, segmentation_caffemodel);
|
||||
generalRecognizer = new CNNRecognizer(charRecognization_proto, charRecognization_caffemodel);
|
||||
segmentationFreeRecognizer = new SegmentationFreeRecognizer(segmentationfree_proto,segmentationfree_caffemodel);
|
||||
|
||||
}
|
||||
|
||||
PipelinePR::~PipelinePR() {
|
||||
@@ -27,42 +29,64 @@ namespace pr {
|
||||
delete fineMapping;
|
||||
delete plateSegmentation;
|
||||
delete generalRecognizer;
|
||||
delete segmentationFreeRecognizer;
|
||||
|
||||
|
||||
}
|
||||
|
||||
std::vector<PlateInfo> PipelinePR:: RunPiplineAsImage(cv::Mat plateImage) {
|
||||
std::vector<PlateInfo> PipelinePR:: RunPiplineAsImage(cv::Mat plateImage,int method) {
|
||||
std::vector<PlateInfo> results;
|
||||
std::vector<pr::PlateInfo> plates;
|
||||
plateDetection->plateDetectionRough(plateImage,plates);
|
||||
plateDetection->plateDetectionRough(plateImage,plates,36,700);
|
||||
|
||||
for (pr::PlateInfo plateinfo:plates) {
|
||||
|
||||
cv::Mat image_finemapping = plateinfo.getPlateImage();
|
||||
|
||||
image_finemapping = fineMapping->FineMappingVertical(image_finemapping);
|
||||
|
||||
image_finemapping = pr::fastdeskew(image_finemapping, 5);
|
||||
//
|
||||
// cv::imshow("image_finemapping", image_finemapping);
|
||||
|
||||
|
||||
|
||||
//Segmentation-based
|
||||
|
||||
if(method==SEGMENTATION_BASED_METHOD)
|
||||
{
|
||||
image_finemapping = fineMapping->FineMappingHorizon(image_finemapping, 2, HorizontalPadding);
|
||||
cv::resize(image_finemapping, image_finemapping, cv::Size(136+HorizontalPadding, 36));
|
||||
// cv::imshow("image_finemapping",image_finemapping);
|
||||
// cv::waitKey(0);
|
||||
plateinfo.setPlateImage(image_finemapping);
|
||||
std::vector<cv::Rect> rects;
|
||||
|
||||
image_finemapping = fineMapping->FineMappingHorizon(image_finemapping, 2, 5);
|
||||
plateSegmentation->segmentPlatePipline(plateinfo, 1, rects);
|
||||
plateSegmentation->ExtractRegions(plateinfo, rects);
|
||||
cv::copyMakeBorder(image_finemapping, image_finemapping, 0, 0, 0, 20, cv::BORDER_REPLICATE);
|
||||
plateinfo.setPlateImage(image_finemapping);
|
||||
generalRecognizer->SegmentBasedSequenceRecognition(plateinfo);
|
||||
plateinfo.decodePlateNormal(pr::CH_PLATE_CODE);
|
||||
|
||||
}
|
||||
//Segmentation-free
|
||||
else if(method==SEGMENTATION_FREE_METHOD)
|
||||
{
|
||||
|
||||
image_finemapping = fineMapping->FineMappingHorizon(image_finemapping, 4, HorizontalPadding+3);
|
||||
|
||||
cv::resize(image_finemapping, image_finemapping, cv::Size(136+HorizontalPadding, 36));
|
||||
// cv::imwrite("./test.png",image_finemapping);
|
||||
// cv::imshow("image_finemapping",image_finemapping);
|
||||
// cv::waitKey(0);
|
||||
plateinfo.setPlateImage(image_finemapping);
|
||||
// std::vector<cv::Rect> rects;
|
||||
|
||||
std::pair<std::string,float> res = segmentationFreeRecognizer->SegmentationFreeForSinglePlate(plateinfo.getPlateImage(),pr::CH_PLATE_CODE);
|
||||
plateinfo.confidence = res.second;
|
||||
plateinfo.setPlateName(res.first);
|
||||
}
|
||||
|
||||
cv::resize(image_finemapping, image_finemapping, cv::Size(136, 36));
|
||||
plateinfo.setPlateImage(image_finemapping);
|
||||
std::vector<cv::Rect> rects;
|
||||
plateSegmentation->segmentPlatePipline(plateinfo, 1, rects);
|
||||
plateSegmentation->ExtractRegions(plateinfo, rects);
|
||||
|
||||
cv::copyMakeBorder(image_finemapping, image_finemapping, 0, 0, 0, 20, cv::BORDER_REPLICATE);
|
||||
|
||||
plateinfo.setPlateImage(image_finemapping);
|
||||
generalRecognizer->SegmentBasedSequenceRecognition(plateinfo);
|
||||
plateinfo.decodePlateNormal(chars_code);
|
||||
results.push_back(plateinfo);
|
||||
std::cout << plateinfo.getPlateName() << std::endl;
|
||||
|
||||
|
||||
}
|
||||
|
||||
// for (auto str:results) {
|
||||
|
||||
@@ -36,10 +36,10 @@ namespace pr{
|
||||
// w += w * 0.28
|
||||
// y -= h * 0.6
|
||||
// h += h * 1.1;
|
||||
int zeroadd_w = static_cast<int>(plate.width*0.28);
|
||||
int zeroadd_h = static_cast<int>(plate.height*1.2);
|
||||
int zeroadd_x = static_cast<int>(plate.width*0.14);
|
||||
int zeroadd_y = static_cast<int>(plate.height*0.6);
|
||||
int zeroadd_w = static_cast<int>(plate.width*0.30);
|
||||
int zeroadd_h = static_cast<int>(plate.height*2);
|
||||
int zeroadd_x = static_cast<int>(plate.width*0.15);
|
||||
int zeroadd_y = static_cast<int>(plate.height*1);
|
||||
plate.x-=zeroadd_x;
|
||||
plate.y-=zeroadd_y;
|
||||
plate.height += zeroadd_h;
|
||||
|
||||
@@ -94,7 +94,7 @@ namespace pr{
|
||||
cv::Mat roi_thres;
|
||||
// cv::threshold(roiImage,roi_thres,0,255,cv::THRESH_OTSU|cv::THRESH_BINARY);
|
||||
|
||||
niBlackThreshold(roiImage,roi_thres,255,cv::THRESH_BINARY,15,0.3,BINARIZATION_NIBLACK);
|
||||
niBlackThreshold(roiImage,roi_thres,255,cv::THRESH_BINARY,15,0.27,BINARIZATION_NIBLACK);
|
||||
|
||||
std::vector<std::vector<cv::Point>> contours;
|
||||
cv::findContours(roi_thres,contours,cv::RETR_LIST,cv::CHAIN_APPROX_SIMPLE);
|
||||
@@ -220,7 +220,7 @@ namespace pr{
|
||||
|
||||
|
||||
int cp_list[7];
|
||||
float loss_selected = -1;
|
||||
float loss_selected = -10;
|
||||
|
||||
for(int start = 0 ; start < 20 ; start+=2)
|
||||
for(int width = windowsWidth-5; width < windowsWidth+5 ; width++ ){
|
||||
@@ -248,14 +248,9 @@ namespace pr{
|
||||
continue;
|
||||
// float loss = ch_prob[cp1_ch]+
|
||||
// engNum_prob[cp2_p0] +engNum_prob[cp3_p1]+engNum_prob[cp4_p2]+engNum_prob[cp5_p3]+engNum_prob[cp6_p4] +engNum_prob[cp7_p5]
|
||||
// + (false_prob[md2]+false_prob[md3]+false_prob[md4]+false_prob[md5]+false_prob[md5] + false_prob[md6]
|
||||
// );
|
||||
|
||||
// + (false_prob[md2]+false_prob[md3]+false_prob[md4]+false_prob[md5]+false_prob[md5] + false_prob[md6]);
|
||||
float loss = ch_prob[cp1_ch]*3 -(false_prob[cp3_p1]+false_prob[cp4_p2]+false_prob[cp5_p3]+false_prob[cp6_p4]+false_prob[cp7_p5]);
|
||||
|
||||
|
||||
|
||||
|
||||
if(loss>loss_selected)
|
||||
{
|
||||
loss_selected = loss;
|
||||
@@ -286,15 +281,15 @@ namespace pr{
|
||||
void PlateSegmentation::segmentPlateBySlidingWindows(cv::Mat &plateImage,int windowsWidth,int stride,cv::Mat &respones){
|
||||
|
||||
|
||||
cv::resize(plateImage,plateImage,cv::Size(136,36));
|
||||
// cv::resize(plateImage,plateImage,cv::Size(136,36));
|
||||
|
||||
cv::Mat plateImageGray;
|
||||
cv::cvtColor(plateImage,plateImageGray,cv::COLOR_BGR2GRAY);
|
||||
|
||||
int padding = plateImage.cols-136 ;
|
||||
// int padding = 0 ;
|
||||
int height = plateImage.rows - 1;
|
||||
int width = plateImage.cols - 1;
|
||||
|
||||
for(int i = 0 ; i < plateImage.cols - windowsWidth +1 ; i +=stride)
|
||||
int width = plateImage.cols - 1 - padding;
|
||||
for(int i = 0 ; i < width - windowsWidth +1 ; i +=stride)
|
||||
{
|
||||
cv::Rect roi(i,0,windowsWidth,height);
|
||||
cv::Mat roiImage = plateImageGray(roi);
|
||||
@@ -350,6 +345,11 @@ namespace pr{
|
||||
cv::Mat respones; //three response of every sub region from origin image .
|
||||
segmentPlateBySlidingWindows(plateImage,DEFAULT_WIDTH,1,respones);
|
||||
templateMatchFinding(respones,DEFAULT_WIDTH/stride,sections);
|
||||
for(int i = 0; i < sections.second.size() ; i++)
|
||||
{
|
||||
sections.second[i]*=stride;
|
||||
|
||||
}
|
||||
|
||||
// std::cout<<sections<<std::endl;
|
||||
|
||||
|
||||
@@ -6,17 +6,20 @@
|
||||
|
||||
namespace pr{
|
||||
void GeneralRecognizer::SegmentBasedSequenceRecognition(PlateInfo &plateinfo){
|
||||
|
||||
|
||||
for(auto char_instance:plateinfo.plateChars)
|
||||
{
|
||||
|
||||
|
||||
std::pair<CharType,cv::Mat> res;
|
||||
cv::Mat code_table= recognizeCharacter(char_instance.second);
|
||||
res.first = char_instance.first;
|
||||
code_table.copyTo(res.second);
|
||||
plateinfo.appendPlateCoding(res);
|
||||
if(char_instance.second.rows*char_instance.second.cols>40) {
|
||||
label code_table = recognizeCharacter(char_instance.second);
|
||||
res.first = char_instance.first;
|
||||
code_table.copyTo(res.second);
|
||||
plateinfo.appendPlateCoding(res);
|
||||
} else{
|
||||
res.first = INVALID;
|
||||
plateinfo.appendPlateCoding(res);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
//
|
||||
// Created by 庾金科 on 28/11/2017.
|
||||
//
|
||||
#include "../include/SegmentationFreeRecognizer.h"
|
||||
|
||||
namespace pr {
|
||||
SegmentationFreeRecognizer::SegmentationFreeRecognizer(std::string prototxt, std::string caffemodel) {
|
||||
net = cv::dnn::readNetFromCaffe(prototxt, caffemodel);
|
||||
}
|
||||
|
||||
|
||||
inline int judgeCharRange(int id)
|
||||
{return id<31 || id>63;
|
||||
}
|
||||
|
||||
|
||||
std::pair<std::string,float> decodeResults(cv::Mat code_table,std::vector<std::string> mapping_table,float thres)
|
||||
{
|
||||
// cv::imshow("imagea",code_table);
|
||||
// cv::waitKey(0);
|
||||
|
||||
cv::MatSize mtsize = code_table.size;
|
||||
int sequencelength = mtsize[2];
|
||||
int labellength = mtsize[1];
|
||||
cv::transpose(code_table.reshape(1,1).reshape(1,labellength),code_table);
|
||||
std::string name = "";
|
||||
|
||||
|
||||
std::vector<int> seq(sequencelength);
|
||||
std::vector<std::pair<int,float>> seq_decode_res;
|
||||
|
||||
for(int i = 0 ; i < sequencelength; i++) {
|
||||
float *fstart = ((float *) (code_table.data) + i * labellength );
|
||||
int id = std::max_element(fstart,fstart+labellength) - fstart;
|
||||
seq[i] =id;
|
||||
}
|
||||
|
||||
float sum_confidence = 0;
|
||||
|
||||
int plate_lenghth = 0 ;
|
||||
|
||||
|
||||
for(int i = 0 ; i< sequencelength ; i++)
|
||||
{
|
||||
if(seq[i]!=labellength-1 && (i==0 || seq[i]!=seq[i-1]))
|
||||
{
|
||||
float *fstart = ((float *) (code_table.data) + i * labellength );
|
||||
float confidence = *(fstart+seq[i]);
|
||||
std::pair<int,float> pair_(seq[i],confidence);
|
||||
seq_decode_res.push_back(pair_);
|
||||
//
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
|
||||
if(judgeCharRange(seq_decode_res[0].first) && judgeCharRange(seq_decode_res[1].first))
|
||||
{
|
||||
i=2;
|
||||
int c = seq_decode_res[0].second<seq_decode_res[1].second;
|
||||
name+=mapping_table[seq_decode_res[c].first];
|
||||
sum_confidence+=seq_decode_res[c].second;
|
||||
plate_lenghth++;
|
||||
}
|
||||
|
||||
for(; i < seq_decode_res.size();i++)
|
||||
{
|
||||
name+=mapping_table[seq_decode_res[i].first];
|
||||
sum_confidence +=seq_decode_res[i].second;
|
||||
plate_lenghth++;
|
||||
}
|
||||
|
||||
|
||||
std::pair<std::string,float> res;
|
||||
|
||||
res.second = sum_confidence/plate_lenghth;
|
||||
res.first = name;
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
std::string decodeResults(cv::Mat code_table,std::vector<std::string> mapping_table)
|
||||
{
|
||||
cv::MatSize mtsize = code_table.size;
|
||||
int sequencelength = mtsize[2];
|
||||
int labellength = mtsize[1];
|
||||
cv::transpose(code_table.reshape(1,1).reshape(1,labellength),code_table);
|
||||
std::string name = "";
|
||||
std::vector<int> seq(sequencelength);
|
||||
for(int i = 0 ; i < sequencelength; i++) {
|
||||
float *fstart = ((float *) (code_table.data) + i * labellength );
|
||||
int id = std::max_element(fstart,fstart+labellength) - fstart;
|
||||
seq[i] =id;
|
||||
}
|
||||
for(int i = 0 ; i< sequencelength ; i++)
|
||||
{
|
||||
if(seq[i]!=labellength-1 && (i==0 || seq[i]!=seq[i-1]))
|
||||
name+=mapping_table[seq[i]];
|
||||
}
|
||||
|
||||
std::cout<<name;
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::pair<std::string,float> SegmentationFreeRecognizer::SegmentationFreeForSinglePlate(cv::Mat Image,std::vector<std::string> mapping_table) {
|
||||
cv::transpose(Image,Image);
|
||||
cv::Mat inputBlob = cv::dnn::blobFromImage(Image, 1 / 255.0, cv::Size(40,160));
|
||||
net.setInput(inputBlob, "data");
|
||||
cv::Mat char_prob_mat = net.forward();
|
||||
return decodeResults(char_prob_mat,mapping_table,0.00);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -44,7 +44,7 @@ HyperLPR是一个使用深度学习针对对中文车牌识别的实现,与较
|
||||
|
||||
+ Win工程中若需要使用静态库,需单独编译
|
||||
+ 本项目的C++实现和Python实现无任何关联,都为单独实现
|
||||
+ 在编译C++工程的时候必须要使用OpenCV 3.3(DNN 库),否则无法编译
|
||||
+ 在编译C++工程的时候必须要使用OpenCV 3.3(DNN 库),否则无法编译
|
||||
|
||||
### Python 依赖
|
||||
|
||||
@@ -81,6 +81,43 @@ cmake ../
|
||||
sudo make -j
|
||||
```
|
||||
|
||||
### CPP demo
|
||||
|
||||
```cpp
|
||||
#include "../include/Pipeline.h"
|
||||
int main(){
|
||||
pr::PipelinePR prc("model/cascade.xml",
|
||||
"model/HorizonalFinemapping.prototxt","model/HorizonalFinemapping.caffemodel",
|
||||
"model/Segmentation.prototxt","model/Segmentation.caffemodel",
|
||||
"model/CharacterRecognization.prototxt","model/CharacterRecognization.caffemodel",
|
||||
"model/SegmentationFree.prototxt","model/SegmentationFree.caffemodel"
|
||||
);
|
||||
//定义模型文件
|
||||
|
||||
cv::Mat image = cv::imread("/Users/yujinke/ClionProjects/cpp_ocr_demo/test.png");
|
||||
std::vector<pr::PlateInfo> res = prc.RunPiplineAsImage(image,pr::SEGMENTATION_FREE_METHOD);
|
||||
//使用端到端模型模型进行识别 识别结果将会保存在res里面
|
||||
|
||||
for(auto st:res) {
|
||||
if(st.confidence>0.75) {
|
||||
std::cout << st.getPlateName() << " " << st.confidence << std::endl;
|
||||
//输出识别结果 、识别置信度
|
||||
cv::Rect region = st.getPlateRect();
|
||||
//获取车牌位置
|
||||
cv::rectangle(image,cv::Point(region.x,region.y),cv::Point(region.x+region.width,region.y+region.height),cv::Scalar(255,255,0),2);
|
||||
//画出车牌位置
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
cv::imshow("image",image);
|
||||
cv::waitKey(0);
|
||||
return 0 ;
|
||||
}
|
||||
```
|
||||
|
||||
###
|
||||
|
||||
### 可识别和待支持的车牌的类型
|
||||
|
||||
- [x] 单行蓝牌
|
||||
@@ -130,3 +167,4 @@ sudo make -j
|
||||
|
||||
+ HyperLPR讨论QQ群:673071218, 加前请备注HyperLPR交流。
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user