From 846d4c7a292507e2b21be3961c577da954d9960a Mon Sep 17 00:00:00 2001 From: iss Date: Tue, 2 Jul 2019 19:47:23 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0vs=E5=B7=A5=E7=A8=8B=E5=88=B0?= =?UTF-8?q?=E7=AB=AF=E5=88=B0=E7=AB=AF=E6=A8=A1=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Prj-Win/Prj-Win/Prj-Win.vcxproj | 23 +- Prj-Win/Prj-Win/Prj-Win.vcxproj.filters | 9 + Prj-Win/lpr/include/CNNRecognizer.h | 2 +- Prj-Win/lpr/include/Pipeline.h | 145 +++++------ Prj-Win/lpr/include/PlateDetection.h | 2 +- Prj-Win/lpr/include/PlateInfo.h | 19 +- Prj-Win/lpr/include/PlateSegmentation.h | 4 - Prj-Win/lpr/include/Recognizer.h | 2 + .../lpr/include/SegmentationFreeRecognizer.h | 28 ++ Prj-Win/lpr/include/niBlackThreshold.h | 8 +- Prj-Win/lpr/model/README.md | 4 +- Prj-Win/lpr/res/test.jpg | Bin 0 -> 31623 bytes Prj-Win/lpr/src/CNNRecognizer.cpp | 4 +- Prj-Win/lpr/src/FastDeskew.cpp | 35 +-- Prj-Win/lpr/src/FineMapping.cpp | 45 +--- Prj-Win/lpr/src/Pipeline.cpp | 86 ++++++- Prj-Win/lpr/src/PlateDetection.cpp | 39 +-- Prj-Win/lpr/src/PlateSegmentation.cpp | 34 +-- Prj-Win/lpr/src/Recognizer.cpp | 25 +- .../lpr/src/SegmentationFreeRecognizer.cpp | 89 +++++++ Prj-Win/lpr/src/util.h | 19 +- Prj-Win/lpr/tests/test_fastdeskew.cpp | 2 +- Prj-Win/lpr/tests/test_finemapping.cpp | 4 +- Prj-Win/lpr/tests/test_pipeline.cpp | 239 ++++++++++++++++-- Prj-Win/lpr/tests/test_recognization.cpp | 3 +- Prj-Win/lpr/tests/test_segmentation.cpp | 4 +- Prj-Win/lpr/tests/test_segmentationFree.cpp | 54 ++++ 27 files changed, 628 insertions(+), 300 deletions(-) create mode 100644 Prj-Win/lpr/include/SegmentationFreeRecognizer.h create mode 100644 Prj-Win/lpr/res/test.jpg create mode 100644 Prj-Win/lpr/src/SegmentationFreeRecognizer.cpp create mode 100644 Prj-Win/lpr/tests/test_segmentationFree.cpp diff --git a/Prj-Win/Prj-Win/Prj-Win.vcxproj b/Prj-Win/Prj-Win/Prj-Win.vcxproj index 35affa2..1e8cc08 100644 --- a/Prj-Win/Prj-Win/Prj-Win.vcxproj +++ b/Prj-Win/Prj-Win/Prj-Win.vcxproj @@ -1,5 +1,5 @@  - + Debug @@ -22,32 +22,32 @@ {69FAD143-D7C9-4804-A186-90254BD80549} Win32Proj PrjWin - 8.1 + 10.0.17763.0 Application true - v140 + v141 Unicode Application false - v140 + v141 true Unicode Application true - v140 + v141 Unicode Application false - v140 + v141 true Unicode @@ -76,9 +76,9 @@ true - D:\Prj-Win\lpr\include;D:\opencv\build\include\opencv2;D:\opencv\build\include\opencv;D:\opencv\build\include;$(IncludePath) - D:\opencv\build\x64\vc14\lib;$(LibraryPath) - $(SolutionDir)Build + D:\Prj-Win\lpr\include;D:\opencv\build\include;D:\opencv\build\include\opencv2;$(IncludePath) + D:\opencv\build\x64\vc15\lib;$(LibraryPath) + $(SolutionDir)Build\ false @@ -112,7 +112,7 @@ Console true - opencv_world330d.lib;%(AdditionalDependencies) + opencv_world400d.lib;opencv_world400.lib;%(AdditionalDependencies) @@ -161,15 +161,18 @@ + + + diff --git a/Prj-Win/Prj-Win/Prj-Win.vcxproj.filters b/Prj-Win/Prj-Win/Prj-Win.vcxproj.filters index cea3788..94d12dd 100644 --- a/Prj-Win/Prj-Win/Prj-Win.vcxproj.filters +++ b/Prj-Win/Prj-Win/Prj-Win.vcxproj.filters @@ -48,6 +48,9 @@ 源文件 + + 头文件 + @@ -71,5 +74,11 @@ 源文件\test + + 源文件 + + + 源文件 + \ No newline at end of file diff --git a/Prj-Win/lpr/include/CNNRecognizer.h b/Prj-Win/lpr/include/CNNRecognizer.h index ad491a0..a577733 100644 --- a/Prj-Win/lpr/include/CNNRecognizer.h +++ b/Prj-Win/lpr/include/CNNRecognizer.h @@ -1,5 +1,5 @@ // -// Created by 庾金科 on 21/10/2017. +// Created by Jack Yu on 21/10/2017. // #ifndef SWIFTPR_CNNRECOGNIZER_H diff --git a/Prj-Win/lpr/include/Pipeline.h b/Prj-Win/lpr/include/Pipeline.h index 53e4580..ed078b1 100644 --- a/Prj-Win/lpr/include/Pipeline.h +++ b/Prj-Win/lpr/include/Pipeline.h @@ -1,85 +1,60 @@ -// -// Created by �׽�� on 22/10/2017. -// - -#ifndef SWIFTPR_PIPLINE_H -#define SWIFTPR_PIPLINE_H - -#include "PlateDetection.h" -#include "PlateSegmentation.h" -#include "CNNRecognizer.h" -#include "PlateInfo.h" -#include "FastDeskew.h" -#include "FineMapping.h" -#include "Recognizer.h" - -namespace pr{ - class PipelinePR{ - public: - GeneralRecognizer *generalRecognizer; - PlateDetection *plateDetection; - PlateSegmentation *plateSegmentation; - FineMapping *fineMapping; - 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 - ) { - 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); - } - - ~PipelinePR() { - - delete plateDetection; - delete fineMapping; - delete plateSegmentation; - delete generalRecognizer; - } - - std::vector 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" }; - - std::vector plateRes; - std::vector RunPiplineAsImage(cv::Mat plateImage) { - std::vector results; - std::vector plates; - plateDetection->plateDetectionRough(plateImage, plates); - - for (pr::PlateInfo plateinfo : plates) { - - cv::Mat image_finemapping = plateinfo.getPlateImage(); - image_finemapping = fineMapping->FineMappingVertical(image_finemapping); - image_finemapping = pr::fastdeskew(image_finemapping, 5); - image_finemapping = fineMapping->FineMappingHorizon(image_finemapping, 2, 5); - cv::resize(image_finemapping, image_finemapping, cv::Size(136, 36)); - plateinfo.setPlateImage(image_finemapping); - std::vector 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) { - // std::cout << str << std::endl; - // } - return results; - } - - - - - }; - - -} -#endif //SWIFTPR_PIPLINE_H +// +// Created by ׽ on 22/10/2017. +// + +#ifndef SWIFTPR_PIPLINE_H +#define SWIFTPR_PIPLINE_H + +#include "PlateDetection.h" +#include "PlateSegmentation.h" +#include "CNNRecognizer.h" +#include "PlateInfo.h" +#include "FastDeskew.h" +#include "FineMapping.h" +#include "Recognizer.h" +#include "SegmentationFreeRecognizer.h" + +namespace pr{ + + const std::vector 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 segmentationfree_proto,std::string segmentationfree_caffemodel + ); + ~PipelinePR(); + + + + std::vector plateRes; + std::vector RunPiplineAsImage(cv::Mat plateImage,int method); + + + + + + + + }; + + +} +#endif //SWIFTPR_PIPLINE_H diff --git a/Prj-Win/lpr/include/PlateDetection.h b/Prj-Win/lpr/include/PlateDetection.h index f4cf567..71ad9af 100644 --- a/Prj-Win/lpr/include/PlateDetection.h +++ b/Prj-Win/lpr/include/PlateDetection.h @@ -6,7 +6,7 @@ #define SWIFTPR_PLATEDETECTION_H #include -#include "PlateInfo.h" +#include #include namespace pr{ class PlateDetection{ diff --git a/Prj-Win/lpr/include/PlateInfo.h b/Prj-Win/lpr/include/PlateInfo.h index ee1e5da..f500bb5 100644 --- a/Prj-Win/lpr/include/PlateInfo.h +++ b/Prj-Win/lpr/include/PlateInfo.h @@ -10,17 +10,14 @@ namespace pr { typedef std::vector 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> plateChars; + std::vector> plateChars; std::vector> 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)< SegmentationFreeForSinglePlate(cv::Mat plate,std::vector mapping_table); + + + private: + cv::dnn::Net net; + + }; + +} +#endif //SWIFTPR_SEGMENTATIONFREERECOGNIZER_H diff --git a/Prj-Win/lpr/include/niBlackThreshold.h b/Prj-Win/lpr/include/niBlackThreshold.h index 5ad7e14..54ac06d 100644 --- a/Prj-Win/lpr/include/niBlackThreshold.h +++ b/Prj-Win/lpr/include/niBlackThreshold.h @@ -62,8 +62,9 @@ void niBlackThreshold( InputArray _src, OutputArray _dst, double maxValue, thresh = mean + static_cast(k) * sqrtVarianceMeanSum; break; default: - CV_Error( CV_StsBadArg, "Unknown binarization method" ); - break; +// CV_Error( CV_StsBadArg, "Unknown binarization method" ); + CV_Error(-5, "Unknown binarization method"); + break; } thresh.convertTo(thresh, src.depth()); @@ -99,7 +100,8 @@ void niBlackThreshold( InputArray _src, OutputArray _dst, double maxValue, src.copyTo(dst, mask); break; default: - CV_Error( CV_StsBadArg, "Unknown threshold type" ); +// CV_Error( CV_StsBadArg, "Unknown threshold type" ); + CV_Error(-5, "Unknown threshold type"); break; } } diff --git a/Prj-Win/lpr/model/README.md b/Prj-Win/lpr/model/README.md index 2c524eb..3085edf 100644 --- a/Prj-Win/lpr/model/README.md +++ b/Prj-Win/lpr/model/README.md @@ -10,8 +10,8 @@ HorizonalFinemapping.caffemodel HorizonalFinemapping.prototxt -Segmentation.caffemodel +SegmentationFree.caffemodel -Segmentation.prototxt +SegmentationFree.prototxt 放置在该目录 \ No newline at end of file diff --git a/Prj-Win/lpr/res/test.jpg b/Prj-Win/lpr/res/test.jpg new file mode 100644 index 0000000000000000000000000000000000000000..342a5d988da8f0d778b59c754dbaa88ece38399d GIT binary patch literal 31623 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 literal 0 HcmV?d00001 diff --git a/Prj-Win/lpr/src/CNNRecognizer.cpp b/Prj-Win/lpr/src/CNNRecognizer.cpp index 909753c..252bd7c 100644 --- a/Prj-Win/lpr/src/CNNRecognizer.cpp +++ b/Prj-Win/lpr/src/CNNRecognizer.cpp @@ -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(); } -} \ No newline at end of file +} diff --git a/Prj-Win/lpr/src/FastDeskew.cpp b/Prj-Win/lpr/src/FastDeskew.cpp index bf46f29..58c8eb3 100644 --- a/Prj-Win/lpr/src/FastDeskew.cpp +++ b/Prj-Win/lpr/src/FastDeskew.cpp @@ -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(skewPlate.rows*tan(cv::abs(angle)/180* 3.14) ); -// else -// extend_padding = static_cast(skewPlate.rows/tan(cv::abs(angle)/180* 3.14) ); - -// std::cout<<"extend:"<(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<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 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(j, i)[5]; int angle_cell = angle(x2,y2); angle_list[(angle_cell + 180)%180]+=1.0; - } } } std::vector 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; diff --git a/Prj-Win/lpr/src/FineMapping.cpp b/Prj-Win/lpr/src/FineMapping.cpp index 6890eff..2032b15 100644 --- a/Prj-Win/lpr/src/FineMapping.cpp +++ b/Prj-Win/lpr/src/FineMapping.cpp @@ -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(upper-lower); diff/=static_cast(sliceNum-1); cv::Mat binary_adaptive; std::vector line_upper; std::vector line_lower; int contours_nums=0; - for(int i = 0 ; i < sliceNum ; i++) { std::vector > 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; 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 "< A; std::pair 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 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; - } - - } diff --git a/Prj-Win/lpr/src/Pipeline.cpp b/Prj-Win/lpr/src/Pipeline.cpp index fad9e19..95ae658 100644 --- a/Prj-Win/lpr/src/Pipeline.cpp +++ b/Prj-Win/lpr/src/Pipeline.cpp @@ -1 +1,85 @@ -//// //// Created by �׽�� on 23/10/2017. //// // //#include "../include/Pipeline.h" // // //namespace pr { // // //std::vector 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" }; // // std::vector 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" }; // // // 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) { // 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); // } // // PipelinePR::~PipelinePR() { // // delete plateDetection; // delete fineMapping; // delete plateSegmentation; // delete generalRecognizer; // // } // // std::vector PipelinePR:: RunPiplineAsImage(cv::Mat plateImage) { // std::vector results; // std::vector plates; // plateDetection->plateDetectionRough(plateImage,plates); // // for (pr::PlateInfo plateinfo:plates) { // // cv::Mat image_finemapping = plateinfo.getPlateImage(); // image_finemapping = fineMapping->FineMappingVertical(image_finemapping); // image_finemapping = pr::fastdeskew(image_finemapping, 5); // image_finemapping = fineMapping->FineMappingHorizon(image_finemapping, 2, 5); // cv::resize(image_finemapping, image_finemapping, cv::Size(136, 36)); // plateinfo.setPlateImage(image_finemapping); // std::vector 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) { //// std::cout << str << std::endl; //// } // return results; // // }//namespace pr // // // //} \ No newline at end of file +// +// 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 PipelinePR:: RunPiplineAsImage(cv::Mat plateImage,int method) { + std::vector results; + std::vector 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 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 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 + + + +} diff --git a/Prj-Win/lpr/src/PlateDetection.cpp b/Prj-Win/lpr/src/PlateDetection.cpp index b207190..a25f4db 100644 --- a/Prj-Win/lpr/src/PlateDetection.cpp +++ b/Prj-Win/lpr/src/PlateDetection.cpp @@ -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 &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 platesRegions; -// std::vector 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(plate.width*0.28); - int zeroadd_h = static_cast(plate.height*1.2); - int zeroadd_x = static_cast(plate.width*0.14); - int zeroadd_y = static_cast(plate.height*0.6); + int zeroadd_w = static_cast(plate.width*0.30); + int zeroadd_h = static_cast(plate.height*2); + int zeroadd_x = static_cast(plate.width*0.15); + int zeroadd_y = static_cast(plate.height*1); plate.x-=zeroadd_x; plate.y-=zeroadd_y; plate.height += zeroadd_h; @@ -50,12 +29,4 @@ namespace pr{ } } -// std::vector 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 diff --git a/Prj-Win/lpr/src/PlateSegmentation.cpp b/Prj-Win/lpr/src/PlateSegmentation.cpp index 94da476..6c454e5 100644 --- a/Prj-Win/lpr/src/PlateSegmentation.cpp +++ b/Prj-Win/lpr/src/PlateSegmentation.cpp @@ -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> 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 rows>>1) + if(dist 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< 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); + } } - - - } -} \ No newline at end of file +} diff --git a/Prj-Win/lpr/src/SegmentationFreeRecognizer.cpp b/Prj-Win/lpr/src/SegmentationFreeRecognizer.cpp new file mode 100644 index 0000000..369f63b --- /dev/null +++ b/Prj-Win/lpr/src/SegmentationFreeRecognizer.cpp @@ -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 decodeResults(cv::Mat code_table,std::vector 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 seq(sequencelength); + std::vector> 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 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 res; + res.second = sum_confidence/plate_lenghth; + res.first = name; + return res; + + } + std::string decodeResults(cv::Mat code_table,std::vector 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 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 SegmentationFreeRecognizer::SegmentationFreeForSinglePlate(cv::Mat Image,std::vector 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); + } +} diff --git a/Prj-Win/lpr/src/util.h b/Prj-Win/lpr/src/util.h index 76a452f..67e21ce 100644 --- a/Prj-Win/lpr/src/util.h +++ b/Prj-Win/lpr/src/util.h @@ -1,20 +1,16 @@ // -// Created by 庾金科 on 04/04/2017. +// Created by Jack Yu on 04/04/2017. // #include - namespace util{ - template void swap ( T& a, T& b ) { T c(a); a=b; b=c; } - template 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 diff --git a/Prj-Win/lpr/tests/test_fastdeskew.cpp b/Prj-Win/lpr/tests/test_fastdeskew.cpp index faa0d93..3740147 100644 --- a/Prj-Win/lpr/tests/test_fastdeskew.cpp +++ b/Prj-Win/lpr/tests/test_fastdeskew.cpp @@ -1,5 +1,5 @@ // -// Created by 庾金科 on 02/10/2017. +// Created by Jack Yu on 02/10/2017. // diff --git a/Prj-Win/lpr/tests/test_finemapping.cpp b/Prj-Win/lpr/tests/test_finemapping.cpp index 4893efd..dd7e26f 100644 --- a/Prj-Win/lpr/tests/test_finemapping.cpp +++ b/Prj-Win/lpr/tests/test_finemapping.cpp @@ -1,5 +1,5 @@ // -// Created by 庾金科 on 24/09/2017. +// Created by Jack Yu on 24/09/2017. // #include "FineMapping.h" @@ -22,4 +22,4 @@ int main() return 0 ; -} \ No newline at end of file +} diff --git a/Prj-Win/lpr/tests/test_pipeline.cpp b/Prj-Win/lpr/tests/test_pipeline.cpp index fccdf1f..647cbe7 100644 --- a/Prj-Win/lpr/tests/test_pipeline.cpp +++ b/Prj-Win/lpr/tests/test_pipeline.cpp @@ -1,42 +1,229 @@ -// -// Created by 庾金科 on 23/10/2017. +// +// Created by Jack Yu on 23/10/2017. // #include "../include/Pipeline.h" -using namespace pr; +#include +#include -void TEST_PIPELINE(){ - pr::PipelinePR prc("../lpr/model/cascade.xml", - "../lpr/model/HorizonalFinemapping.prototxt","../lpr/model/HorizonalFinemapping.caffemodel", - "../lpr/model/Segmentation.prototxt","../lpr/model/Segmentation.caffemodel", - "../lpr/model/CharacterRecognization.prototxt","../lpr/model/CharacterRecognization.caffemodel" - ); - cv::Mat image = cv::imread("../6.jpg"); - cv::imshow("image",image); - cv::waitKey(0); +using namespace std; - std::vector res = prc.RunPiplineAsImage(image); - float conf = 0 ; - for(auto st:res) { - if(st.confidence>0.1) { - std::cout << st.getPlateName() << " " << st.confidence << std::endl; - conf += st.confidence; - } - } - std::cout< +static unsigned int levenshtein_distance(const T &s1, const T &s2) { + const size_t len1 = s1.size(), len2 = s2.size(); + std::vector col(len2 + 1), prevCol(len2 + 1); + for (unsigned int i = 0; i < prevCol.size(); i++) prevCol[i] = i; + for (unsigned int i = 0; i < len1; i++) { + col[0] = i + 1; + for (unsigned int j = 0; j < len2; j++) + col[j + 1] = min( + min(prevCol[1 + j] + 1, col[j] + 1), + prevCol[j] + (s1[i] == s2[j] ? 0 : 1)); + col.swap(prevCol); + } + return prevCol[len2]; } -int main() + + +void TEST_CAM() { + cv::VideoCapture capture("test1.mp4"); + cv::Mat frame; + pr::PipelinePR prc("../lpr/model/cascade.xml", + "../lpr/model/HorizonalFinemapping.prototxt", "../lpr/model/HorizonalFinemapping.caffemodel", + "../lpr/model/Segmentation.prototxt", "../lpr/model/Segmentation.caffemodel", + "../lpr/model/CharacterRecognization.prototxt", "../lpr/model/CharacterRecognization.caffemodel", + "../lpr/model/SegmentationFree.prototxt", "../lpr/model/SegmentationFree.caffemodel" + ); + while (1) { + //读取下一帧 + if (!capture.read(frame)) { + std::cout << "读取视频失败" << std::endl; + exit(1); + } + // + // cv::transpose(frame,frame); + // cv::flip(frame,frame,2); + + // cv::resize(frame,frame,cv::Size(frame.cols/2,frame.rows/2)); + + + std::vector res = prc.RunPiplineAsImage(frame, pr::SEGMENTATION_FREE_METHOD); + + for (auto st : res) { + if (st.confidence > 0.75) { + std::cout << st.getPlateName() << " " << st.confidence << std::endl; + cv::Rect region = st.getPlateRect(); + + cv::rectangle(frame, 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", frame); + cv::waitKey(1); + } +} + + +void TEST_ACC() { + + pr::PipelinePR prc("../lpr/model/cascade.xml", + "../lpr/model/HorizonalFinemapping.prototxt", "../lpr/model/HorizonalFinemapping.caffemodel", + "../lpr/model/Segmentation.prototxt", "../lpr/model/Segmentation.caffemodel", + "../lpr/model/CharacterRecognization.prototxt", "../lpr/model/CharacterRecognization.caffemodel", + "../lpr/model/SegmentationFree.prototxt", "../lpr/model/SegmentationFree.caffemodel" + ); + + ifstream file; + string imagename; + int n = 0, correct = 0, j = 0, sum = 0; + char filename[] = "/Users/yujinke/Downloads/general_test/1.txt"; + string pathh = "/Users/yujinke/Downloads/general_test/"; + file.open(filename, ios::in); + while (!file.eof()) + { + file >> imagename; + string imgpath = pathh + imagename; + std::cout << "------------------------------------------------" << endl; + cout << "图片名:" << imagename << endl; + cv::Mat image = cv::imread(imgpath); + // cv::imshow("image", image); + // cv::waitKey(0); + + std::vector res = prc.RunPiplineAsImage(image, pr::SEGMENTATION_FREE_METHOD); + + float conf = 0; + vector con; + vector name; + for (auto st : res) { + if (st.confidence > 0.1) { + //std::cout << st.getPlateName() << " " << st.confidence << std::endl; + con.push_back(st.confidence); + name.push_back(st.getPlateName()); + //conf += st.confidence; + } + else + cout << "no string" << endl; + } + // std::cout << conf << std::endl; + int num = con.size(); + float max = 0; + string platestr, chpr, ch; + int diff = 0, dif = 0; + for (int i = 0; i < num; i++) { + + if (con.at(i) > max) + { + max = con.at(i); + platestr = name.at(i); + } + + } + // cout << "max:"< res = prc.RunPiplineAsImage(image, pr::SEGMENTATION_FREE_METHOD); + for (auto st : res) { + if (st.confidence > 0.75) { + std::cout << st.getPlateName() << " " << st.confidence << std::endl; + cv::Rect region = st.getPlateRect(); -} \ No newline at end of file + 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); + +} + + + + +/*void TEST_CAM() +{ + + cv::VideoCapture capture("test1.mp4"); + cv::Mat frame; + + pr::PipelinePR prc("../lpr/model/cascade.xml", + "../lpr/model/HorizonalFinemapping.prototxt", "../lpr/model/HorizonalFinemapping.caffemodel", + "../lpr/model/Segmentation.prototxt", "../lpr/model/Segmentation.caffemodel", + "../lpr/model/CharacterRecognization.prototxt", "../lpr/model/CharacterRecognization.caffemodel", + "../lpr/model/SegmentationFree.prototxt", "../lpr/model/SegmentationFree.caffemodel" + ); + while (1) { + //读取下一帧 + if (!capture.read(frame)) { + std::cout << "读取视频失败" << std::endl; + exit(1); + } + // + // cv::transpose(frame,frame); + // cv::flip(frame,frame,2); + + // cv::resize(frame,frame,cv::Size(frame.cols/2,frame.rows/2)); + + + + std::vector res = prc.RunPiplineAsImage(frame, pr::SEGMENTATION_FREE_METHOD); + + for (auto st : res) { + if (st.confidence > 0.75) { + std::cout << st.getPlateName() << " " << st.confidence << std::endl; + cv::Rect region = st.getPlateRect(); + + cv::rectangle(frame, 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", frame); + cv::waitKey(1); + } +}*/ + + +int main() +{ + // TEST_ACC(); + + // TEST_CAM(); + TEST_PIPELINE(); + return 0; +} diff --git a/Prj-Win/lpr/tests/test_recognization.cpp b/Prj-Win/lpr/tests/test_recognization.cpp index 6d6fe84..9244f95 100644 --- a/Prj-Win/lpr/tests/test_recognization.cpp +++ b/Prj-Win/lpr/tests/test_recognization.cpp @@ -1,5 +1,5 @@ // -// Created by 庾金科 on 23/10/2017. +// Created by Jack Yu on 23/10/2017. // #include "../include/CNNRecognizer.h" @@ -16,6 +16,7 @@ void getMaxClass(cv::Mat &probBlob, int *classId, double *classProb) cv::Point classNumber; cv::minMaxLoc(probBlob, NULL, classProb, NULL, &classNumber); + *classId = classNumber.x; } diff --git a/Prj-Win/lpr/tests/test_segmentation.cpp b/Prj-Win/lpr/tests/test_segmentation.cpp index e903636..b379406 100644 --- a/Prj-Win/lpr/tests/test_segmentation.cpp +++ b/Prj-Win/lpr/tests/test_segmentation.cpp @@ -1,5 +1,5 @@ // -// Created by 庾金科 on 16/10/2017. +// Created by Jack Yu on 16/10/2017. // @@ -40,4 +40,4 @@ int main(){ TEST_SLIDINGWINDOWS_EVAL(); return 0; -} \ No newline at end of file +} diff --git a/Prj-Win/lpr/tests/test_segmentationFree.cpp b/Prj-Win/lpr/tests/test_segmentationFree.cpp new file mode 100644 index 0000000..4f948d2 --- /dev/null +++ b/Prj-Win/lpr/tests/test_segmentationFree.cpp @@ -0,0 +1,54 @@ +// +// Created by Jack Yu on 29/11/2017. +// +#include "../include/SegmentationFreeRecognizer.h" +#include "../include/Pipeline.h" + +#include "../include/PlateInfo.h" + + + +std::string decodeResults(cv::Mat code_table,std::vector 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 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< res = recognizr.SegmentationFreeForSinglePlate(image,pr::CH_PLATE_CODE); + std::cout<