更新vs工程到端到端模型

This commit is contained in:
iss
2019-07-02 19:47:23 +08:00
parent 33b6f6e346
commit 846d4c7a29
27 changed files with 628 additions and 300 deletions
+2 -2
View File
@@ -1,5 +1,5 @@
//
// Created by 庾金科 on 21/10/2017.
// Created by Jack Yu on 21/10/2017.
//
#include "../include/CNNRecognizer.h"
@@ -16,4 +16,4 @@ namespace pr{
net.setInput(inputBlob,"data");
return net.forward();
}
}
}
+5 -30
View File
@@ -1,19 +1,17 @@
//
// Created by 庾金科 on 02/10/2017.
// Created by Jack Yu on 02/10/2017.
//
#include "FastDeskew.h"
#include <../include/FastDeskew.h>
namespace pr{
const int ANGLE_MIN = 30 ;
const int ANGLE_MIN = 30 ;
const int ANGLE_MAX = 150 ;
const int PLATE_H = 36;
const int PLATE_W = 136;
int angle(float x,float y)
{
return atan2(x,y)*180/3.1415;
@@ -51,59 +49,38 @@ namespace pr{
cv::Mat correctPlateImage(cv::Mat skewPlate,float angle,float maxAngle)
{
cv::Mat dst;
cv::Size size_o(skewPlate.cols,skewPlate.rows);
int extend_padding = 0;
// if(angle<0)
extend_padding = static_cast<int>(skewPlate.rows*tan(cv::abs(angle)/180* 3.14) );
// else
// extend_padding = static_cast<int>(skewPlate.rows/tan(cv::abs(angle)/180* 3.14) );
// std::cout<<"extend:"<<extend_padding<<std::endl;
extend_padding = static_cast<int>(skewPlate.rows*tan(cv::abs(angle)/180* 3.14) );
cv::Size size(skewPlate.cols + extend_padding ,skewPlate.rows);
float interval = abs(sin((angle /180) * 3.14)* skewPlate.rows);
// std::cout<<interval<<std::endl;
cv::Point2f pts1[4] = {cv::Point2f(0,0),cv::Point2f(0,size_o.height),cv::Point2f(size_o.width,0),cv::Point2f(size_o.width,size_o.height)};
if(angle>0) {
cv::Point2f pts2[4] = {cv::Point2f(interval, 0), cv::Point2f(0, size_o.height),
cv::Point2f(size_o.width, 0), cv::Point2f(size_o.width - interval, size_o.height)};
cv::Mat M = cv::getPerspectiveTransform(pts1,pts2);
cv::warpPerspective(skewPlate,dst,M,size);
}
else {
cv::Point2f pts2[4] = {cv::Point2f(0, 0), cv::Point2f(interval, size_o.height), cv::Point2f(size_o.width-interval, 0),
cv::Point2f(size_o.width, size_o.height)};
cv::Mat M = cv::getPerspectiveTransform(pts1,pts2);
cv::warpPerspective(skewPlate,dst,M,size,cv::INTER_CUBIC);
}
return dst;
}
cv::Mat fastdeskew(cv::Mat skewImage,int blockSize){
const int FILTER_WINDOWS_SIZE = 5;
std::vector<float> angle_list(180);
memset(angle_list.data(),0,angle_list.size()*sizeof(int));
cv::Mat bak;
skewImage.copyTo(bak);
if(skewImage.channels() == 3)
cv::cvtColor(skewImage,skewImage,cv::COLOR_RGB2GRAY);
if(skewImage.channels() == 1)
{
cv::Mat eigen;
cv::cornerEigenValsAndVecs(skewImage,eigen,blockSize,5);
for( int j = 0; j < skewImage.rows; j+=blockSize )
{ for( int i = 0; i < skewImage.cols; i+=blockSize )
@@ -112,12 +89,10 @@ namespace pr{
float y2 = eigen.at<cv::Vec6f>(j, i)[5];
int angle_cell = angle(x2,y2);
angle_list[(angle_cell + 180)%180]+=1.0;
}
}
}
std::vector<float> filtered = avgfilter(angle_list,5);
int maxPos = std::max_element(filtered.begin(),filtered.end()) - filtered.begin() + FILTER_WINDOWS_SIZE/2;
if(maxPos>ANGLE_MAX)
maxPos = (-maxPos+90+180)%180;
+5 -40
View File
@@ -1,12 +1,8 @@
//
// Created by 庾金科 on 22/09/2017.
//
#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)
{
@@ -65,31 +61,21 @@ namespace pr{
}
cv::Mat FineMapping::FineMappingVertical(cv::Mat InputProposal,int sliceNum,int upper,int lower,int windows_size){
cv::Mat PreInputProposal;
cv::Mat proposal;
cv::resize(InputProposal,PreInputProposal,cv::Size(FINEMAPPING_W,FINEMAPPING_H));
if(InputProposal.channels() == 3)
cv::cvtColor(PreInputProposal,proposal,cv::COLOR_BGR2GRAY);
else
PreInputProposal.copyTo(proposal);
// proposal = PreInputProposal;
// this will improve some sen
cv::Mat kernal = cv::getStructuringElement(cv::MORPH_ELLIPSE,cv::Size(1,3));
// cv::erode(proposal,proposal,kernal);
float diff = static_cast<float>(upper-lower);
diff/=static_cast<float>(sliceNum-1);
cv::Mat binary_adaptive;
std::vector<cv::Point> line_upper;
std::vector<cv::Point> line_lower;
int contours_nums=0;
for(int i = 0 ; i < sliceNum ; i++)
{
std::vector<std::vector<cv::Point> > contours;
@@ -106,7 +92,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);
@@ -115,9 +100,6 @@ namespace pr{
}
}
}
std:: cout<<"contours_nums "<<contours_nums<<std::endl;
if(contours_nums<41)
{
cv::bitwise_not(InputProposal,InputProposal);
@@ -130,14 +112,11 @@ namespace pr{
else
proposal = bak;
int contours_nums=0;
for(int i = 0 ; i < sliceNum ; i++)
{
std::vector<std::vector<cv::Point> > contours;
float k =lower + i*diff;
cv::adaptiveThreshold(proposal,binary_adaptive,255,cv::ADAPTIVE_THRESH_MEAN_C,cv::THRESH_BINARY,windows_size,k);
// cv::imshow("image",binary_adaptive);
// cv::waitKey(0);
cv::Mat draw;
binary_adaptive.copyTo(draw);
cv::findContours(binary_adaptive,contours,cv::RETR_EXTERNAL,cv::CHAIN_APPROX_SIMPLE);
@@ -158,30 +137,19 @@ namespace pr{
}
}
}
// std:: cout<<"contours_nums "<<contours_nums<<std::endl;
}
cv::Mat rgb;
cv::copyMakeBorder(PreInputProposal, rgb, 30, 30, 0, 0, cv::BORDER_REPLICATE);
// cv::imshow("rgb",rgb);
// cv::waitKey(0);
//
cv::copyMakeBorder(PreInputProposal, rgb, PADDING_UP_DOWN, PADDING_UP_DOWN, 0, 0, cv::BORDER_REPLICATE);
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;
int rightyA = B.second;
int cols = rgb.cols;
int rows = rgb.rows;
// pts_map1 = np.float32([[cols - 1, rightyA], [0, leftyA],[cols - 1, rightyB], [0, leftyB]])
// pts_map2 = np.float32([[136,36],[0,36],[136,0],[0,0]])
// mat = cv2.getPerspectiveTransform(pts_map1,pts_map2)
// image = cv2.warpPerspective(rgb,mat,(136,36),flags=cv2.INTER_CUBIC)
std::vector<cv::Point2f> corners(4);
corners[0] = cv::Point2f(cols - 1, rightyA);
corners[1] = cv::Point2f(0, leftyA);
@@ -196,10 +164,7 @@ namespace pr{
cv::Mat quad = cv::Mat::zeros(36, 136, CV_8UC3);
cv::warpPerspective(rgb, quad, transform, quad.size());
return quad;
}
}
+85 -1
View File
@@ -1 +1,85 @@
////
//
// Created by Jack Yu on 23/10/2017.
//
#include "../include/Pipeline.h"
namespace pr {
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 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() {
delete plateDetection;
delete fineMapping;
delete plateSegmentation;
delete generalRecognizer;
delete segmentationFreeRecognizer;
}
std::vector<PlateInfo> PipelinePR:: RunPiplineAsImage(cv::Mat plateImage,int method) {
std::vector<PlateInfo> results;
std::vector<pr::PlateInfo> 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);
//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));
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(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));
plateinfo.setPlateImage(image_finemapping);
std::pair<std::string,float> res = segmentationFreeRecognizer->SegmentationFreeForSinglePlate(plateinfo.getPlateImage(),pr::CH_PLATE_CODE);
plateinfo.confidence = res.second;
plateinfo.setPlateName(res.first);
}
results.push_back(plateinfo);
}
return results;
}//namespace pr
}
+5 -34
View File
@@ -1,45 +1,24 @@
//
// Created by 庾金科 on 20/09/2017.
//
#include "../include/PlateDetection.h"
#include "util.h"
namespace pr{
PlateDetection::PlateDetection(std::string filename_cascade){
cascade.load(filename_cascade);
};
void PlateDetection::plateDetectionRough(cv::Mat InputImage,std::vector<pr::PlateInfo> &plateInfos,int min_w,int max_w){
cv::Mat processImage;
cv::cvtColor(InputImage,processImage,cv::COLOR_BGR2GRAY);
cv::cvtColor(InputImage,processImage,cv::COLOR_BGR2GRAY);
std::vector<cv::Rect> platesRegions;
// std::vector<PlateInfo> plates;
cv::Size minSize(min_w,min_w/4);
cv::Size maxSize(max_w,max_w/4);
// cv::imshow("input",InputImage);
// cv::waitKey(0);
cascade.detectMultiScale( processImage, platesRegions,
1.1, 3, cv::CASCADE_SCALE_IMAGE,minSize,maxSize);
for(auto plate:platesRegions)
{
// extend rects
// x -= w * 0.14
// 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;
@@ -50,12 +29,4 @@ namespace pr{
}
}
// std::vector<pr::PlateInfo> PlateDetection::plateDetectionRough(cv::Mat InputImage,cv::Rect roi,int min_w,int max_w){
// cv::Mat roi_region = util::cropFromImage(InputImage,roi);
// return plateDetectionRough(roi_region,min_w,max_w);
// }
}//namespace pr
+18 -16
View File
@@ -1,5 +1,5 @@
//
// Created by 庾金科 on 16/10/2017.
// Created by Jack Yu on 16/10/2017.
//
#include "../include/PlateSegmentation.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);
@@ -110,7 +110,7 @@ namespace pr{
cv::Rect bdbox = cv::boundingRect(contour);
cv::Point center(bdbox.x+(bdbox.width>>1),bdbox.y + (bdbox.height>>1));
int dist = (center.x - boxCenter.x)*(center.x - boxCenter.x);
if(dist<final_dist && bdbox.height > rows>>1)
if(dist<final_dist && bdbox.height > rows>>1)
{ final_dist =dist;
final_center = center;
final_bdbox = bdbox;
@@ -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++ ){
@@ -246,13 +246,10 @@ namespace pr{
if(cp7_p5>=cols)
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]);
// 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]);
// 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]);
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)
{
@@ -284,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);
@@ -348,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;
+11 -14
View File
@@ -1,26 +1,23 @@
//
// Created by 庾金科 on 22/10/2017.
// Created by Jack Yu on 22/10/2017.
//
#include "../include/Recognizer.h"
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,89 @@
//
// Created by Jack Yu 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::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 (seq_decode_res.size()>1 && 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]];
}
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);
}
}
+4 -15
View File
@@ -1,20 +1,16 @@
//
// Created by 庾金科 on 04/04/2017.
// Created by Jack Yu on 04/04/2017.
//
#include <opencv2/opencv.hpp>
namespace util{
template <class T> void swap ( T& a, T& b )
{
T c(a); a=b; b=c;
}
template <class T> T min(T& a,T& b )
{
return a>b?b:a;
}
cv::Mat cropFromImage(const cv::Mat &image,cv::Rect rect){
@@ -57,23 +53,16 @@ namespace util{
int histSize = 256;
float range[] = {0,255};
const float* histRange = {range};
cv::calcHist( &hsv_planes[0], 1, 0, cv::Mat(), hist, 1, &histSize, &histRange,true, true);
return hist;
}
float computeSimilir(const cv::Mat &A,const cv::Mat &B)
{
cv::Mat histA,histB;
histA = calcHist(A);
histB = calcHist(B);
return cv::compareHist(histA,histB,CV_COMP_CORREL);
// return cv::compareHist(histA,histB,CV_COMP_CORREL);
return cv::compareHist(histA, histB, 0);
}
}//namespace util