@@ -1,3 +1,3 @@ | |||
cmake_minimum_required(VERSION 3.6) | |||
project(HyperLPR) | |||
add_subdirectory(hyperlpr) | |||
add_subdirectory(lpr) |
@@ -3,49 +3,15 @@ project(SwiftPR) | |||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") | |||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) | |||
find_package(OpenCV 3.3.0 REQUIRED) | |||
find_package(OpenCV 3.4.3 REQUIRED) | |||
include_directories( ${OpenCV_INCLUDE_DIRS}) | |||
include_directories(include) | |||
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_DETECTION src/PlateDetection.cpp) | |||
set(SRC_FINETUNE src/FineTune.cpp) | |||
set(SRC_RECOGNIZE src/PlateRecognation.cpp) | |||
set(SRC_PIPLINE src/Pipeline.cpp) | |||
set(SRC_SEGMENTATIONFREE src/SegmentationFreeRecognizer.cpp ) | |||
#set(SOURCE_FILES main.cpp) | |||
#add_executable(HyperLPR_cpp ${SOURCE_FILES}) | |||
#TEST_DETECTION | |||
add_executable(TEST_Detection ${SRC_DETECTION} tests/test_detection.cpp) | |||
target_link_libraries(TEST_Detection ${OpenCV_LIBS}) | |||
#TEST_FINEMAPPING | |||
add_executable(TEST_FINEMAPPING ${SRC_FINEMAPPING} tests/test_finemapping.cpp) | |||
target_link_libraries(TEST_FINEMAPPING ${OpenCV_LIBS}) | |||
#TEST_DESKEW | |||
add_executable(TEST_FASTDESKEW ${SRC_FASTDESKEW} tests/test_fastdeskew.cpp) | |||
target_link_libraries(TEST_FASTDESKEW ${OpenCV_LIBS}) | |||
#TEST_SEGMENTATION | |||
add_executable(TEST_SEGMENTATION ${SRC_SEGMENTATION} ${SRC_RECOGNIZE} tests/test_segmentation.cpp) | |||
target_link_libraries(TEST_SEGMENTATION ${OpenCV_LIBS}) | |||
#TEST_RECOGNIZATION | |||
add_executable(TEST_RECOGNIZATION ${SRC_RECOGNIZE} tests/test_recognization.cpp) | |||
target_link_libraries(TEST_RECOGNIZATION ${OpenCV_LIBS}) | |||
#TEST_SEGMENTATIONFREE | |||
add_executable(TEST_SEGMENTATIONFREE ${SRC_SEGMENTATIONFREE} tests/test_segmentationFree.cpp) | |||
target_link_libraries(TEST_SEGMENTATIONFREE ${OpenCV_LIBS}) | |||
#TEST_PIPELINE | |||
add_executable(TEST_PIPLINE ${SRC_DETECTION} ${SRC_FINEMAPPING} ${SRC_FASTDESKEW} ${SRC_SEGMENTATION} ${SRC_RECOGNIZE} ${SRC_PIPLINE} ${SRC_SEGMENTATIONFREE} tests/test_pipeline.cpp) | |||
add_executable(TEST_PIPLINE ${SRC_DETECTION} ${SRC_FINETUNE} ${SRC_RECOGNIZE} ${SRC_PIPLINE} tests/testPipeLine.cpp) | |||
target_link_libraries(TEST_PIPLINE ${OpenCV_LIBS}) |
@@ -1,24 +0,0 @@ | |||
// | |||
// Created by Jack Yu on 21/10/2017. | |||
// | |||
#ifndef SWIFTPR_CNNRECOGNIZER_H | |||
#define SWIFTPR_CNNRECOGNIZER_H | |||
#include "Recognizer.h" | |||
namespace pr{ | |||
class CNNRecognizer: public GeneralRecognizer{ | |||
public: | |||
const int CHAR_INPUT_W = 14; | |||
const int CHAR_INPUT_H = 30; | |||
CNNRecognizer(std::string prototxt,std::string caffemodel); | |||
label recognizeCharacter(cv::Mat character); | |||
private: | |||
cv::dnn::Net net; | |||
}; | |||
} | |||
#endif //SWIFTPR_CNNRECOGNIZER_H |
@@ -1,18 +0,0 @@ | |||
// | |||
// Created by 庾金科 on 22/09/2017. | |||
// | |||
#ifndef SWIFTPR_FASTDESKEW_H | |||
#define SWIFTPR_FASTDESKEW_H | |||
#include <math.h> | |||
#include <opencv2/opencv.hpp> | |||
namespace pr{ | |||
cv::Mat fastdeskew(cv::Mat skewImage,int blockSize); | |||
// cv::Mat spatialTransformer(cv::Mat skewImage); | |||
}//namepace pr | |||
#endif //SWIFTPR_FASTDESKEW_H |
@@ -1,32 +0,0 @@ | |||
// | |||
// Created by 庾金科 on 22/09/2017. | |||
// | |||
#ifndef SWIFTPR_FINEMAPPING_H | |||
#define SWIFTPR_FINEMAPPING_H | |||
#include <opencv2/opencv.hpp> | |||
#include <opencv2/dnn.hpp> | |||
#include <string> | |||
namespace pr{ | |||
class FineMapping{ | |||
public: | |||
FineMapping(); | |||
FineMapping(std::string prototxt,std::string caffemodel); | |||
static cv::Mat FineMappingVertical(cv::Mat InputProposal,int sliceNum=15,int upper=0,int lower=-50,int windows_size=17); | |||
cv::Mat FineMappingHorizon(cv::Mat FinedVertical,int leftPadding,int rightPadding); | |||
private: | |||
cv::dnn::Net net; | |||
}; | |||
} | |||
#endif //SWIFTPR_FINEMAPPING_H |
@@ -0,0 +1,18 @@ | |||
#ifndef _FINETUNE_H_ | |||
#define _FINETUNE_H_ | |||
#include<vector> | |||
#include<opencv2/dnn.hpp> | |||
#include<opencv2/opencv.hpp> | |||
namespace pr { | |||
class FineTune { | |||
public: | |||
FineTune(std::string finetune_prototxt, std::string finetune_caffemodel); | |||
void Finetune(cv::Mat img, cv::Mat &resImg); | |||
void to_refine(cv::Mat img, std::vector<cv::Point> pts, cv::Mat &out); | |||
void affine_crop(cv::Mat img, std::vector<cv::Point> pts, cv::Mat &out); | |||
private: | |||
cv::dnn::Net FTNet; | |||
}; | |||
}//namespace pr | |||
#endif // !_FINETUNE_H_ |
@@ -1,60 +1,40 @@ | |||
// | |||
// 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<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 segmentationfree_proto,std::string segmentationfree_caffemodel | |||
); | |||
~PipelinePR(); | |||
std::vector<std::string> plateRes; | |||
std::vector<PlateInfo> RunPiplineAsImage(cv::Mat plateImage,int method); | |||
}; | |||
#pragma warning(disable:4430) | |||
#ifndef _PIPLINE_H | |||
#define _PIPLINE_H | |||
#include <vector> | |||
#include "Finetune.h" | |||
#include "Platedetect.h" | |||
#include "PlateRecognation.h" | |||
//#include "PlateColor.h" | |||
using namespace std; | |||
using namespace cv; | |||
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","港","学","使","警","澳","挂","军","北","南","广","沈","兰","成","济","海","民","航","空" }; | |||
class PipelinePR { | |||
public: | |||
PlateDetection *platedetection; | |||
FineTune *finetune; | |||
PlateRecognation *platerecognation; | |||
DBDetection *dbdetection; | |||
PipelinePR(std::string detect_prototxt, std::string detect_caffemodel, | |||
std::string finetune_prototxt, std::string finetune_caffemodel, | |||
std::string platerec_prototxt, std::string platerec_caffemodel, | |||
std::string dbstring); | |||
~PipelinePR(); | |||
std::vector<std::string> plateRes; | |||
std::vector<PlateInfo> RunPiplineAsImage(cv::Mat srcImage,int IsDB); | |||
}; | |||
} | |||
#endif //SWIFTPR_PIPLINE_H | |||
#endif // !SWIFTPR_PIPLINE_H |
@@ -1,25 +0,0 @@ | |||
// | |||
// Created by 庾金科 on 20/09/2017. | |||
// | |||
#ifndef SWIFTPR_PLATEDETECTION_H | |||
#define SWIFTPR_PLATEDETECTION_H | |||
#include <opencv2/opencv.hpp> | |||
#include <PlateInfo.h> | |||
#include <vector> | |||
namespace pr{ | |||
class PlateDetection{ | |||
public: | |||
PlateDetection(std::string filename_cascade); | |||
PlateDetection(); | |||
void LoadModel(std::string filename_cascade); | |||
void plateDetectionRough(cv::Mat InputImage,std::vector<pr::PlateInfo> &plateInfos,int min_w=36,int max_w=800); | |||
private: | |||
cv::CascadeClassifier cascade; | |||
}; | |||
}// namespace pr | |||
#endif //SWIFTPR_PLATEDETECTION_H | |||
@@ -1,14 +1,14 @@ | |||
// | |||
// Created by 庾金科 on 20/09/2017. | |||
// | |||
#ifndef SWIFTPR_PLATEINFO_H | |||
#define SWIFTPR_PLATEINFO_H | |||
#include <opencv2/opencv.hpp> | |||
namespace pr { | |||
typedef std::vector<cv::Mat> Character; | |||
enum PlateColor { BLUE, YELLOW, WHITE, GREEN, BLACK,UNKNOWN}; | |||
enum CharType {CHINESE,LETTER,LETTER_NUMS,INVALID}; | |||
class PlateInfo { | |||
public: | |||
std::vector<std::pair<CharType,cv::Mat>> plateChars; | |||
@@ -58,7 +58,11 @@ namespace pr { | |||
int getPlateType() { | |||
return Type; | |||
} | |||
int setPlateType(PlateColor platetype) | |||
{ | |||
Type = platetype; | |||
return 0; | |||
} | |||
void appendPlateChar(const std::pair<CharType,cv::Mat> &plateChar) | |||
{ | |||
plateChars.push_back(plateChar); | |||
@@ -68,6 +72,10 @@ namespace pr { | |||
plateCoding.push_back(charProb); | |||
} | |||
// cv::Mat getPlateChars(int id) { | |||
// if(id<PlateChars.size()) | |||
// return PlateChars[id]; | |||
// } | |||
std::string decodePlateNormal(std::vector<std::string> mappingTable) { | |||
std::string decode; | |||
for(auto plate:plateCoding) { | |||
@@ -76,6 +84,10 @@ namespace pr { | |||
decode += mappingTable[std::max_element(prob,prob+31) - prob]; | |||
confidence+=*std::max_element(prob,prob+31); | |||
// std::cout<<*std::max_element(prob,prob+31)<<std::endl; | |||
} | |||
else if(plate.first == LETTER) { | |||
@@ -86,16 +98,22 @@ namespace pr { | |||
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; | |||
confidence/=7; | |||
return decode; | |||
} | |||
private: | |||
cv::Mat licensePlate; | |||
cv::Rect ROI; | |||
@@ -0,0 +1,15 @@ | |||
#ifndef _PLATERECOGNATION_H_ | |||
#define _PLATERECOGNATION_H_ | |||
#include <opencv2/dnn.hpp> | |||
#include "PlateInfo.h" | |||
namespace pr { | |||
class PlateRecognation { | |||
public: | |||
PlateRecognation(std::string Rec_prototxt, std::string Rec_cafffemodel); | |||
void segmentation_free_recognation(cv::Mat src, pr::PlateInfo &plateinfo); | |||
private: | |||
cv::dnn::Net RecNet; | |||
}; | |||
}//namespace pr | |||
#endif // !_PLATERECOGNATION_H_ | |||
@@ -1,35 +0,0 @@ | |||
#ifndef SWIFTPR_PLATESEGMENTATION_H | |||
#define SWIFTPR_PLATESEGMENTATION_H | |||
#include "opencv2/opencv.hpp" | |||
#include <opencv2/dnn.hpp> | |||
#include "PlateInfo.h" | |||
namespace pr{ | |||
class PlateSegmentation{ | |||
public: | |||
const int PLATE_NORMAL = 6; | |||
const int PLATE_NORMAL_GREEN = 7; | |||
const int DEFAULT_WIDTH = 20; | |||
PlateSegmentation(std::string phototxt,std::string caffemodel); | |||
PlateSegmentation(){} | |||
void segmentPlatePipline(PlateInfo &plateInfo,int stride,std::vector<cv::Rect> &Char_rects); | |||
void segmentPlateBySlidingWindows(cv::Mat &plateImage,int windowsWidth,int stride,cv::Mat &respones); | |||
void templateMatchFinding(const cv::Mat &respones,int windowsWidth,std::pair<float,std::vector<int>> &candidatePts); | |||
void refineRegion(cv::Mat &plateImage,const std::vector<int> &candidatePts,const int padding,std::vector<cv::Rect> &rects); | |||
void ExtractRegions(PlateInfo &plateInfo,std::vector<cv::Rect> &rects); | |||
cv::Mat classifyResponse(const cv::Mat &cropped); | |||
private: | |||
cv::dnn::Net net; | |||
// RefineRegion() | |||
}; | |||
}//namespace pr | |||
#endif //SWIFTPR_PLATESEGMENTATION_H |
@@ -0,0 +1,23 @@ | |||
#ifndef _PLATEDETECT_H_ | |||
#define _PLATEDETECT_H_ | |||
#include <opencv2/opencv.hpp> | |||
#include <vector> | |||
#include "PlateInfo.h" | |||
namespace pr | |||
{ | |||
class PlateDetection { | |||
public: | |||
PlateDetection(std::string ssd_prototxt, std::string ssd_caffe_model); | |||
void Detectssd(cv::Mat inputImg, std::vector<pr::PlateInfo> &plateInfos); | |||
private: | |||
cv::dnn::Net ssdNet; | |||
}; | |||
class DBDetection{ | |||
public: | |||
DBDetection(std::string cascadestring); | |||
void DBDetect(cv::Mat inputImg,std::vector<pr::PlateInfo> &plateInfos,int min_w,int max_w); | |||
private: | |||
cv::CascadeClassifier dbcascade; | |||
}; | |||
}//namespace pr | |||
#endif // !_PLATEDETECT_H_ |
@@ -1,23 +0,0 @@ | |||
// | |||
// Created by 庾金科 on 20/10/2017. | |||
// | |||
#ifndef SWIFTPR_RECOGNIZER_H | |||
#define SWIFTPR_RECOGNIZER_H | |||
#include "PlateInfo.h" | |||
#include "opencv2/dnn.hpp" | |||
namespace pr{ | |||
typedef cv::Mat label; | |||
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); | |||
}; | |||
} | |||
#endif //SWIFTPR_RECOGNIZER_H |
@@ -1,28 +0,0 @@ | |||
// | |||
// 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 |
@@ -1,103 +0,0 @@ | |||
// | |||
// Created by 庾金科 on 26/10/2017. | |||
// | |||
#ifndef SWIFTPR_NIBLACKTHRESHOLD_H | |||
#define SWIFTPR_NIBLACKTHRESHOLD_H | |||
#include <opencv2/opencv.hpp> | |||
using namespace cv; | |||
enum LocalBinarizationMethods{ | |||
BINARIZATION_NIBLACK = 0, //!< Classic Niblack binarization. See @cite Niblack1985 . | |||
BINARIZATION_SAUVOLA = 1, //!< Sauvola's technique. See @cite Sauvola1997 . | |||
BINARIZATION_WOLF = 2, //!< Wolf's technique. See @cite Wolf2004 . | |||
BINARIZATION_NICK = 3 //!< NICK technique. See @cite Khurshid2009 . | |||
}; | |||
void niBlackThreshold( InputArray _src, OutputArray _dst, double maxValue, | |||
int type, int blockSize, double k, int binarizationMethod ) | |||
{ | |||
// Input grayscale image | |||
Mat src = _src.getMat(); | |||
CV_Assert(src.channels() == 1); | |||
CV_Assert(blockSize % 2 == 1 && blockSize > 1); | |||
if (binarizationMethod == BINARIZATION_SAUVOLA) { | |||
CV_Assert(src.depth() == CV_8U); | |||
} | |||
type &= THRESH_MASK; | |||
// Compute local threshold (T = mean + k * stddev) | |||
// using mean and standard deviation in the neighborhood of each pixel | |||
// (intermediate calculations are done with floating-point precision) | |||
Mat test; | |||
Mat thresh; | |||
{ | |||
// note that: Var[X] = E[X^2] - E[X]^2 | |||
Mat mean, sqmean, variance, stddev, sqrtVarianceMeanSum; | |||
double srcMin, stddevMax; | |||
boxFilter(src, mean, CV_32F, Size(blockSize, blockSize), | |||
Point(-1,-1), true, BORDER_REPLICATE); | |||
sqrBoxFilter(src, sqmean, CV_32F, Size(blockSize, blockSize), | |||
Point(-1,-1), true, BORDER_REPLICATE); | |||
variance = sqmean - mean.mul(mean); | |||
sqrt(variance, stddev); | |||
switch (binarizationMethod) | |||
{ | |||
case BINARIZATION_NIBLACK: | |||
thresh = mean + stddev * static_cast<float>(k); | |||
break; | |||
case BINARIZATION_SAUVOLA: | |||
thresh = mean.mul(1. + static_cast<float>(k) * (stddev / 128.0 - 1.)); | |||
break; | |||
case BINARIZATION_WOLF: | |||
minMaxIdx(src, &srcMin,NULL); | |||
minMaxIdx(stddev, NULL, &stddevMax); | |||
thresh = mean - static_cast<float>(k) * (mean - srcMin - stddev.mul(mean - srcMin) / stddevMax); | |||
break; | |||
case BINARIZATION_NICK: | |||
sqrt(variance + sqmean, sqrtVarianceMeanSum); | |||
thresh = mean + static_cast<float>(k) * sqrtVarianceMeanSum; | |||
break; | |||
default: | |||
CV_Error( CV_StsBadArg, "Unknown binarization method" ); | |||
break; | |||
} | |||
thresh.convertTo(thresh, src.depth()); | |||
thresh.convertTo(test, src.depth()); | |||
} | |||
// Prepare output image | |||
_dst.create(src.size(), src.type()); | |||
Mat dst = _dst.getMat(); | |||
CV_Assert(src.data != dst.data); // no inplace processing | |||
// Apply thresholding: ( pixel > threshold ) ? foreground : background | |||
Mat mask; | |||
switch (type) | |||
{ | |||
case THRESH_BINARY: // dst = (src > thresh) ? maxval : 0 | |||
case THRESH_BINARY_INV: // dst = (src > thresh) ? 0 : maxval | |||
compare(src, thresh, mask, (type == THRESH_BINARY ? CMP_GT : CMP_LE)); | |||
dst.setTo(0); | |||
dst.setTo(maxValue, mask); | |||
break; | |||
case THRESH_TRUNC: // dst = (src > thresh) ? thresh : src | |||
compare(src, thresh, mask, CMP_GT); | |||
src.copyTo(dst); | |||
thresh.copyTo(dst, mask); | |||
break; | |||
case THRESH_TOZERO: // dst = (src > thresh) ? src : 0 | |||
case THRESH_TOZERO_INV: // dst = (src > thresh) ? 0 : src | |||
compare(src, thresh, mask, (type == THRESH_TOZERO ? CMP_GT : CMP_LE)); | |||
dst.setTo(0); | |||
src.copyTo(dst, mask); | |||
break; | |||
default: | |||
CV_Error( CV_StsBadArg, "Unknown threshold type" ); | |||
break; | |||
} | |||
} | |||
#endif //SWIFTPR_NIBLACKTHRESHOLD_H |
@@ -1,123 +0,0 @@ | |||
input: "data" | |||
input_dim: 1 | |||
input_dim: 1 | |||
input_dim: 30 | |||
input_dim: 14 | |||
layer { | |||
name: "conv2d_1" | |||
type: "Convolution" | |||
bottom: "data" | |||
top: "conv2d_1" | |||
convolution_param { | |||
num_output: 32 | |||
bias_term: true | |||
pad: 0 | |||
kernel_size: 3 | |||
stride: 1 | |||
} | |||
} | |||
layer { | |||
name: "activation_1" | |||
type: "ReLU" | |||
bottom: "conv2d_1" | |||
top: "activation_1" | |||
} | |||
layer { | |||
name: "max_pooling2d_1" | |||
type: "Pooling" | |||
bottom: "activation_1" | |||
top: "max_pooling2d_1" | |||
pooling_param { | |||
pool: MAX | |||
kernel_size: 2 | |||
stride: 2 | |||
pad: 0 | |||
} | |||
} | |||
layer { | |||
name: "conv2d_2" | |||
type: "Convolution" | |||
bottom: "max_pooling2d_1" | |||
top: "conv2d_2" | |||
convolution_param { | |||
num_output: 64 | |||
bias_term: true | |||
pad: 0 | |||
kernel_size: 3 | |||
stride: 1 | |||
} | |||
} | |||
layer { | |||
name: "activation_2" | |||
type: "ReLU" | |||
bottom: "conv2d_2" | |||
top: "activation_2" | |||
} | |||
layer { | |||
name: "max_pooling2d_2" | |||
type: "Pooling" | |||
bottom: "activation_2" | |||
top: "max_pooling2d_2" | |||
pooling_param { | |||
pool: MAX | |||
kernel_size: 2 | |||
stride: 2 | |||
pad: 0 | |||
} | |||
} | |||
layer { | |||
name: "conv2d_3" | |||
type: "Convolution" | |||
bottom: "max_pooling2d_2" | |||
top: "conv2d_3" | |||
convolution_param { | |||
num_output: 128 | |||
bias_term: true | |||
pad: 0 | |||
kernel_size: 2 | |||
stride: 1 | |||
} | |||
} | |||
layer { | |||
name: "activation_3" | |||
type: "ReLU" | |||
bottom: "conv2d_3" | |||
top: "activation_3" | |||
} | |||
layer { | |||
name: "flatten_1" | |||
type: "Flatten" | |||
bottom: "activation_3" | |||
top: "flatten_1" | |||
} | |||
layer { | |||
name: "dense_1" | |||
type: "InnerProduct" | |||
bottom: "flatten_1" | |||
top: "dense_1" | |||
inner_product_param { | |||
num_output: 256 | |||
} | |||
} | |||
layer { | |||
name: "relu2" | |||
type: "ReLU" | |||
bottom: "dense_1" | |||
top: "relu2" | |||
} | |||
layer { | |||
name: "dense2" | |||
type: "InnerProduct" | |||
bottom: "relu2" | |||
top: "dense2" | |||
inner_product_param { | |||
num_output: 65 | |||
} | |||
} | |||
layer { | |||
name: "prob" | |||
type: "Softmax" | |||
bottom: "dense2" | |||
top: "prob" | |||
} |
@@ -0,0 +1,11 @@ | |||
将/hyperlpr_pip_pkg/hyperlpr/models/dnn/目录下的 | |||
mininet_ssd_v1.caffemodel | |||
mininet_ssd_v1.prototxt | |||
refinenet.caffemodel | |||
refinenet.prototxt | |||
SegmenationFree-Inception.caffemodel | |||
SegmenationFree-Inception.prototxt | |||
放置在该目录 |
@@ -1,114 +0,0 @@ | |||
input: "data" | |||
input_dim: 1 | |||
input_dim: 1 | |||
input_dim: 22 | |||
input_dim: 22 | |||
layer { | |||
name: "conv2d_12" | |||
type: "Convolution" | |||
bottom: "data" | |||
top: "conv2d_12" | |||
convolution_param { | |||
num_output: 16 | |||
bias_term: true | |||
pad: 0 | |||
kernel_size: 3 | |||
stride: 1 | |||
} | |||
} | |||
layer { | |||
name: "activation_18" | |||
type: "ReLU" | |||
bottom: "conv2d_12" | |||
top: "activation_18" | |||
} | |||
layer { | |||
name: "max_pooling2d_10" | |||
type: "Pooling" | |||
bottom: "activation_18" | |||
top: "max_pooling2d_10" | |||
pooling_param { | |||
pool: MAX | |||
kernel_size: 2 | |||
stride: 2 | |||
pad: 0 | |||
} | |||
} | |||
layer { | |||
name: "conv2d_13" | |||
type: "Convolution" | |||
bottom: "max_pooling2d_10" | |||
top: "conv2d_13" | |||
convolution_param { | |||
num_output: 16 | |||
bias_term: true | |||
pad: 0 | |||
kernel_size: 3 | |||
stride: 1 | |||
} | |||
} | |||
layer { | |||
name: "activation_19" | |||
type: "ReLU" | |||
bottom: "conv2d_13" | |||
top: "activation_19" | |||
} | |||
layer { | |||
name: "max_pooling2d_11" | |||
type: "Pooling" | |||
bottom: "activation_19" | |||
top: "max_pooling2d_11" | |||
pooling_param { | |||
pool: MAX | |||
kernel_size: 2 | |||
stride: 2 | |||
pad: 0 | |||
} | |||
} | |||
layer { | |||
name: "flatten_6" | |||
type: "Flatten" | |||
bottom: "max_pooling2d_11" | |||
top: "flatten_6" | |||
} | |||
layer { | |||
name: "dense_9" | |||
type: "InnerProduct" | |||
bottom: "flatten_6" | |||
top: "dense_9" | |||
inner_product_param { | |||
num_output: 256 | |||
} | |||
} | |||
layer { | |||
name: "dropout_9" | |||
type: "Dropout" | |||
bottom: "dense_9" | |||
top: "dropout_9" | |||
dropout_param { | |||
dropout_ratio: 0.5 | |||
} | |||
} | |||
layer { | |||
name: "activation_20" | |||
type: "ReLU" | |||
bottom: "dropout_9" | |||
top: "activation_20" | |||
} | |||
layer { | |||
name: "dense_10" | |||
type: "InnerProduct" | |||
bottom: "activation_20" | |||
top: "dense_10" | |||
inner_product_param { | |||
num_output: 3 | |||
} | |||
} | |||
layer { | |||
name: "prob" | |||
type: "Softmax" | |||
bottom: "dense_10" | |||
top: "prob" | |||
} |
@@ -0,0 +1,504 @@ | |||
<?xml version="1.0"?> | |||
<opencv_storage> | |||
<cascade> | |||
<stageType>BOOST</stageType> | |||
<featureType>LBP</featureType> | |||
<height>24</height> | |||
<width>44</width> | |||
<stageParams> | |||
<boostType>GAB</boostType> | |||
<minHitRate>9.9599999189376831e-01</minHitRate> | |||
<maxFalseAlarm>5.0000000000000000e-01</maxFalseAlarm> | |||
<weightTrimRate>9.4999999999999996e-01</weightTrimRate> | |||
<maxDepth>1</maxDepth> | |||
<maxWeakCount>28</maxWeakCount></stageParams> | |||
<featureParams> | |||
<maxCatCount>256</maxCatCount> | |||
<featSize>1</featSize></featureParams> | |||
<stageNum>11</stageNum> | |||
<stages> | |||
<!-- stage 0 --> | |||
<_> | |||
<maxWeakCount>3</maxWeakCount> | |||
<stageThreshold>-1.1049392223358154e+00</stageThreshold> | |||
<weakClassifiers> | |||
<_> | |||
<internalNodes> | |||
0 -1 17 -3334 -513 -573452048 -1057 -1 -267777 -1 -1025</internalNodes> | |||
<leafValues> | |||
-9.4297146797180176e-01 7.8370976448059082e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 36 -262198 -12062208 -169869377 -674954752 -7602177 | |||
-16781941 -67109937 -1073</internalNodes> | |||
<leafValues> | |||
-8.8537323474884033e-01 7.2940820455551147e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 9 1431697887 1431687647 -545270049 -262145 1413609965 | |||
1364250775 -1065985 -67108865</internalNodes> | |||
<leafValues> | |||
-8.3008646965026855e-01 7.2340542078018188e-01</leafValues></_></weakClassifiers></_> | |||
<!-- stage 1 --> | |||
<_> | |||
<maxWeakCount>3</maxWeakCount> | |||
<stageThreshold>-1.0404651165008545e+00</stageThreshold> | |||
<weakClassifiers> | |||
<_> | |||
<internalNodes> | |||
0 -1 19 -524289 -136314913 1360393719 -2097153 -134219777 | |||
-4194817 274068735 -1</internalNodes> | |||
<leafValues> | |||
-8.5476654767990112e-01 8.4671354293823242e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 29 -16515073 -150929664 -1 -8650881 -8388609 -11403265 | |||
-1 -2097153</internalNodes> | |||
<leafValues> | |||
-7.7620923519134521e-01 7.8929436206817627e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 1 2013233135 2147450879 -45760593 2147474943 2146959359 | |||
2104754047 2080374783 2147417087</internalNodes> | |||
<leafValues> | |||
-8.9144438505172729e-01 5.9051072597503662e-01</leafValues></_></weakClassifiers></_> | |||
<!-- stage 2 --> | |||
<_> | |||
<maxWeakCount>3</maxWeakCount> | |||
<stageThreshold>-1.1397969722747803e+00</stageThreshold> | |||
<weakClassifiers> | |||
<_> | |||
<internalNodes> | |||
0 -1 15 -1041 -8225 -546308113 -1 -33554433 -394753 -2359297 | |||
-1</internalNodes> | |||
<leafValues> | |||
-8.5447394847869873e-01 7.4388968944549561e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 27 -1053970 -17 -35651601 -1048625 -345331574 -5247030 | |||
-74453009 -1</internalNodes> | |||
<leafValues> | |||
-8.6756819486618042e-01 6.3549250364303589e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 43 -1050897 -1025 -71304209 -134219793 -1033 -559948801 | |||
-67110929 1996976642</internalNodes> | |||
<leafValues> | |||
-8.6068797111511230e-01 5.8224511146545410e-01</leafValues></_></weakClassifiers></_> | |||
<!-- stage 3 --> | |||
<_> | |||
<maxWeakCount>3</maxWeakCount> | |||
<stageThreshold>-9.8026764392852783e-01</stageThreshold> | |||
<weakClassifiers> | |||
<_> | |||
<internalNodes> | |||
0 -1 12 -1077953601 -1 -1073758273 -16387 -147457 -1 | |||
-1073758209 -1</internalNodes> | |||
<leafValues> | |||
-8.2477015256881714e-01 7.1671992540359497e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 47 -4345 -989855745 -271062524 -319815697 -134742265 | |||
1423962843 -134218173 -1</internalNodes> | |||
<leafValues> | |||
-7.4230498075485229e-01 7.3275351524353027e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 37 -22347778 -3477554 -33554433 -2066 -9438209 -65537 | |||
-1 -1048577</internalNodes> | |||
<leafValues> | |||
-8.3125960826873779e-01 5.8680748939514160e-01</leafValues></_></weakClassifiers></_> | |||
<!-- stage 4 --> | |||
<_> | |||
<maxWeakCount>5</maxWeakCount> | |||
<stageThreshold>-1.2986627817153931e+00</stageThreshold> | |||
<weakClassifiers> | |||
<_> | |||
<internalNodes> | |||
0 -1 4 -8388737 -262273 -10485761 -137 -8388745 -129 -262273 | |||
-1</internalNodes> | |||
<leafValues> | |||
-8.7727063894271851e-01 6.1173391342163086e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 20 -1 -10241 1431688703 -1 -1 -1042 1163263999 | |||
2002780159</internalNodes> | |||
<leafValues> | |||
-8.2954949140548706e-01 5.9151750802993774e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 3 -44786212 -33726467 -268509185 -17409 -657175332 | |||
-2270500 -1198986500 -1148450934</internalNodes> | |||
<leafValues> | |||
-7.6026451587677002e-01 5.8319890499114990e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 28 -15794258 -78643282 -821817846 -552742962 -653344834 | |||
-91750417 -1622147105 -7340065</internalNodes> | |||
<leafValues> | |||
-7.6077878475189209e-01 5.5891805887222290e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 30 1427232247 357954767 1971310559 2012602108 | |||
-202375953 -44049 -4456789 -18</internalNodes> | |||
<leafValues> | |||
-6.7643576860427856e-01 6.0950380563735962e-01</leafValues></_></weakClassifiers></_> | |||
<!-- stage 5 --> | |||
<_> | |||
<maxWeakCount>5</maxWeakCount> | |||
<stageThreshold>-1.3029408454895020e+00</stageThreshold> | |||
<weakClassifiers> | |||
<_> | |||
<internalNodes> | |||
0 -1 39 -134218753 -1 -1 -202899593 -1 -4194305 -67108865 | |||
-527497</internalNodes> | |||
<leafValues> | |||
-7.5626724958419800e-01 7.5137990713119507e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 6 -8388737 -8388737 -1 -1 -8421505 -129 -8388737 -1</internalNodes> | |||
<leafValues> | |||
-7.7118909358978271e-01 6.3570922613143921e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 45 -825233914 -654313761 -589830738 -35651585 -16778427 | |||
-83886281 -151000316 -1056964737</internalNodes> | |||
<leafValues> | |||
-7.2490030527114868e-01 5.7298541069030762e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 18 2002780159 2136866815 -67109377 -19969 2147344383 | |||
2101472763 2108680957 2147450607</internalNodes> | |||
<leafValues> | |||
-8.5162043571472168e-01 4.5608481764793396e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 16 -7472470 -3505654 -29841 -65536 -1166086177 | |||
-67109121 -288690177 -32085</internalNodes> | |||
<leafValues> | |||
-7.9073858261108398e-01 5.0315058231353760e-01</leafValues></_></weakClassifiers></_> | |||
<!-- stage 6 --> | |||
<_> | |||
<maxWeakCount>5</maxWeakCount> | |||
<stageThreshold>-1.3164747953414917e+00</stageThreshold> | |||
<weakClassifiers> | |||
<_> | |||
<internalNodes> | |||
0 -1 41 -1 -1025 -1 -2228225 -8432299 -571189899 -139265 -1</internalNodes> | |||
<leafValues> | |||
-7.8127676248550415e-01 6.5899217128753662e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 2 -34275329 -198665 -2113 -12289 -573243396 -590292744 | |||
-1049857 -277</internalNodes> | |||
<leafValues> | |||
-7.3563832044601440e-01 6.3897633552551270e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 14 -1565523969 -1347420193 -277086209 -1342177313 | |||
-134217729 -263169 -285212673 -1459618305</internalNodes> | |||
<leafValues> | |||
-8.1234931945800781e-01 4.9628043174743652e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 33 -1079312417 -83826176 -33686017 -570426508 | |||
-1627464961 -5377 -277761 -17</internalNodes> | |||
<leafValues> | |||
-7.0463657379150391e-01 5.2093976736068726e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 25 -66 -4116 1607291240 -5298489 -9847160 2011036101 | |||
357852669 1476259327</internalNodes> | |||
<leafValues> | |||
-8.2066470384597778e-01 4.9184983968734741e-01</leafValues></_></weakClassifiers></_> | |||
<!-- stage 7 --> | |||
<_> | |||
<maxWeakCount>5</maxWeakCount> | |||
<stageThreshold>-1.1098697185516357e+00</stageThreshold> | |||
<weakClassifiers> | |||
<_> | |||
<internalNodes> | |||
0 -1 44 -134217949 -167773185 -404750589 -1 -134744525 | |||
-1846018321 -2097357 -1</internalNodes> | |||
<leafValues> | |||
-7.6240319013595581e-01 6.8946647644042969e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 7 -12633797 -524321 1058880319 -129 -50790401 -262405 | |||
-1075052545 -5</internalNodes> | |||
<leafValues> | |||
-7.1431988477706909e-01 6.2125796079635620e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 24 -144703501 -10486797 -134217729 -136317057 | |||
-271646721 -174069583 -168952849 -1072726014</internalNodes> | |||
<leafValues> | |||
-6.5710061788558960e-01 6.1531358957290649e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 38 -134218774 -149487872 -33554433 -537927872 -69209089 | |||
-145228029 -2360849 -524449</internalNodes> | |||
<leafValues> | |||
-7.3570650815963745e-01 4.9681660532951355e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 5 -136380419 -8390657 -2228225 -196707 1565810157 | |||
2147048386 -268702725 2080373485</internalNodes> | |||
<leafValues> | |||
-7.2735637426376343e-01 5.2713739871978760e-01</leafValues></_></weakClassifiers></_> | |||
<!-- stage 8 --> | |||
<_> | |||
<maxWeakCount>5</maxWeakCount> | |||
<stageThreshold>-2.0547957420349121e+00</stageThreshold> | |||
<weakClassifiers> | |||
<_> | |||
<internalNodes> | |||
0 -1 13 -11141121 -44695553 -1 -11144193 -9217 -321 | |||
-335811841 -4216577</internalNodes> | |||
<leafValues> | |||
-7.3916637897491455e-01 6.7595410346984863e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 26 -369104657 -4194321 -1061429013 -67114529 -251662085 | |||
-138412033 3334395 -234882305</internalNodes> | |||
<leafValues> | |||
-6.9217604398727417e-01 5.4744583368301392e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 11 1373590751 1373632511 -262169 -33859589 -572533249 | |||
-572524625 -135266305 -32833</internalNodes> | |||
<leafValues> | |||
-7.1100026369094849e-01 5.3469187021255493e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 23 -3148053 -1054802 -1 -5 -7340125 -3689942 -74448917 | |||
-687087094</internalNodes> | |||
<leafValues> | |||
-5.6383520364761353e-01 6.3540917634963989e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 8 245501180 -1615197700 -46219265 -1075925028 | |||
-307580929 -373826 -1076187139 -1343746644</internalNodes> | |||
<leafValues> | |||
-5.8823972940444946e-01 6.1824375391006470e-01</leafValues></_></weakClassifiers></_> | |||
<!-- stage 9 --> | |||
<_> | |||
<maxWeakCount>6</maxWeakCount> | |||
<stageThreshold>-1.6300759315490723e+00</stageThreshold> | |||
<weakClassifiers> | |||
<_> | |||
<internalNodes> | |||
0 -1 42 -1 -4129 -8193 -135795737 -1 -6417 -1 -137887866</internalNodes> | |||
<leafValues> | |||
-7.7990013360977173e-01 6.1912822723388672e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 31 -12845643 -1934361103 -581837313 -1644167171 | |||
-1175537153 -1392516625 -1681655299 -1358963807</internalNodes> | |||
<leafValues> | |||
-7.1357387304306030e-01 5.6909996271133423e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 34 288428543 -34262659 1976906747 -42117703 858797567 | |||
-4965441 2008290292 -1146080848</internalNodes> | |||
<leafValues> | |||
-6.7784935235977173e-01 5.4983222484588623e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 22 -25297611 -100663553 -9830515 -570556417 -53741251 | |||
-36570627 -67437302 -12583252</internalNodes> | |||
<leafValues> | |||
-6.3567954301834106e-01 5.9044981002807617e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 46 -403706354 82769839 -446830048 -989858098 -8921600 | |||
1087893408 -100663520 -134217729</internalNodes> | |||
<leafValues> | |||
-7.0569902658462524e-01 5.4874616861343384e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 0 -965744853 -420544541 -8392718 -1569784218 -192940313 | |||
1744830335 -9 -1003227661</internalNodes> | |||
<leafValues> | |||
-5.7118493318557739e-01 6.4167028665542603e-01</leafValues></_></weakClassifiers></_> | |||
<!-- stage 10 --> | |||
<_> | |||
<maxWeakCount>5</maxWeakCount> | |||
<stageThreshold>-2.1370947360992432e+00</stageThreshold> | |||
<weakClassifiers> | |||
<_> | |||
<internalNodes> | |||
0 -1 40 -673196033 -2144789 287251423 -538968593 -1399068449 | |||
-73535505 -13631489 -526857</internalNodes> | |||
<leafValues> | |||
-7.2344118356704712e-01 6.8316829204559326e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 32 -214216429 -2112561 -445819937 1964790555 -17185861 | |||
-303183720 -357832229 -3148837</internalNodes> | |||
<leafValues> | |||
-7.1031409502029419e-01 5.4083776473999023e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 10 -9043969 -36118539 2147450623 -4194305 -2246657 | |||
-102721404 1073685759 -1366622208</internalNodes> | |||
<leafValues> | |||
-5.8772116899490356e-01 6.4753490686416626e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 35 1167938037 16237049 -1120535169 1029034397 9567155 | |||
-2001626128 -1146622977 -1142248004</internalNodes> | |||
<leafValues> | |||
-6.4004391431808472e-01 5.6415843963623047e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 21 -70126622 -134227061 -536243648 188013035 | |||
-1234960385 1416625375 -486868997 62913535</internalNodes> | |||
<leafValues> | |||
-8.8218396902084351e-01 4.1129270195960999e-01</leafValues></_></weakClassifiers></_></stages> | |||
<features> | |||
<_> | |||
<rect> | |||
0 1 1 6</rect></_> | |||
<_> | |||
<rect> | |||
1 0 8 3</rect></_> | |||
<_> | |||
<rect> | |||
1 4 8 3</rect></_> | |||
<_> | |||
<rect> | |||
1 6 13 2</rect></_> | |||
<_> | |||
<rect> | |||
2 1 5 2</rect></_> | |||
<_> | |||
<rect> | |||
2 4 9 2</rect></_> | |||
<_> | |||
<rect> | |||
3 2 5 2</rect></_> | |||
<_> | |||
<rect> | |||
4 0 11 3</rect></_> | |||
<_> | |||
<rect> | |||
4 21 9 1</rect></_> | |||
<_> | |||
<rect> | |||
7 1 5 5</rect></_> | |||
<_> | |||
<rect> | |||
7 7 6 2</rect></_> | |||
<_> | |||
<rect> | |||
10 0 3 5</rect></_> | |||
<_> | |||
<rect> | |||
11 1 9 3</rect></_> | |||
<_> | |||
<rect> | |||
11 2 11 4</rect></_> | |||
<_> | |||
<rect> | |||
12 0 4 3</rect></_> | |||
<_> | |||
<rect> | |||
14 2 5 2</rect></_> | |||
<_> | |||
<rect> | |||
14 6 3 3</rect></_> | |||
<_> | |||
<rect> | |||
15 1 5 4</rect></_> | |||
<_> | |||
<rect> | |||
16 0 9 4</rect></_> | |||
<_> | |||
<rect> | |||
17 3 4 5</rect></_> | |||
<_> | |||
<rect> | |||
17 6 4 3</rect></_> | |||
<_> | |||
<rect> | |||
18 12 3 2</rect></_> | |||
<_> | |||
<rect> | |||
19 0 3 3</rect></_> | |||
<_> | |||
<rect> | |||
19 3 2 6</rect></_> | |||
<_> | |||
<rect> | |||
19 4 2 4</rect></_> | |||
<_> | |||
<rect> | |||
19 12 2 4</rect></_> | |||
<_> | |||
<rect> | |||
21 2 2 5</rect></_> | |||
<_> | |||
<rect> | |||
22 5 3 4</rect></_> | |||
<_> | |||
<rect> | |||
22 14 3 3</rect></_> | |||
<_> | |||
<rect> | |||
24 1 6 5</rect></_> | |||
<_> | |||
<rect> | |||
25 3 4 5</rect></_> | |||
<_> | |||
<rect> | |||
25 6 6 1</rect></_> | |||
<_> | |||
<rect> | |||
26 1 2 5</rect></_> | |||
<_> | |||
<rect> | |||
26 3 5 4</rect></_> | |||
<_> | |||
<rect> | |||
26 21 6 1</rect></_> | |||
<_> | |||
<rect> | |||
27 1 5 1</rect></_> | |||
<_> | |||
<rect> | |||
29 3 4 6</rect></_> | |||
<_> | |||
<rect> | |||
30 0 4 5</rect></_> | |||
<_> | |||
<rect> | |||
30 2 3 7</rect></_> | |||
<_> | |||
<rect> | |||
34 1 3 7</rect></_> | |||
<_> | |||
<rect> | |||
34 8 3 2</rect></_> | |||
<_> | |||
<rect> | |||
34 15 3 3</rect></_> | |||
<_> | |||
<rect> | |||
35 3 2 5</rect></_> | |||
<_> | |||
<rect> | |||
35 5 2 5</rect></_> | |||
<_> | |||
<rect> | |||
39 12 1 3</rect></_> | |||
<_> | |||
<rect> | |||
41 0 1 7</rect></_> | |||
<_> | |||
<rect> | |||
41 10 1 4</rect></_> | |||
<_> | |||
<rect> | |||
41 11 1 3</rect></_></features></cascade> | |||
</opencv_storage> |
@@ -0,0 +1,300 @@ | |||
name: "ONet" | |||
input: "data" | |||
input_dim: 1 | |||
input_dim: 3 | |||
input_dim: 48 | |||
input_dim: 120 | |||
################################## | |||
layer { | |||
name: "conv1" | |||
type: "Convolution" | |||
bottom: "data" | |||
top: "conv1" | |||
param { | |||
lr_mult: 1 | |||
decay_mult: 1 | |||
} | |||
param { | |||
lr_mult: 2 | |||
decay_mult: 1 | |||
} | |||
convolution_param { | |||
num_output: 32 | |||
kernel_size: 3 | |||
stride: 1 | |||
weight_filler { | |||
type: "xavier" | |||
} | |||
bias_filler { | |||
type: "constant" | |||
value: 0 | |||
} | |||
} | |||
} | |||
layer { | |||
name: "prelu1" | |||
type: "PReLU" | |||
bottom: "conv1" | |||
top: "conv1" | |||
} | |||
layer { | |||
name: "pool1" | |||
type: "Pooling" | |||
bottom: "conv1" | |||
top: "pool1" | |||
pooling_param { | |||
pool: MAX | |||
kernel_size: 3 | |||
stride: 2 | |||
} | |||
} | |||
layer { | |||
name: "conv2" | |||
type: "Convolution" | |||
bottom: "pool1" | |||
top: "conv2" | |||
param { | |||
lr_mult: 1 | |||
decay_mult: 1 | |||
} | |||
param { | |||
lr_mult: 2 | |||
decay_mult: 1 | |||
} | |||
convolution_param { | |||
num_output: 64 | |||
kernel_size: 3 | |||
stride: 1 | |||
weight_filler { | |||
type: "xavier" | |||
} | |||
bias_filler { | |||
type: "constant" | |||
value: 0 | |||
} | |||
} | |||
} | |||
layer { | |||
name: "prelu2" | |||
type: "PReLU" | |||
bottom: "conv2" | |||
top: "conv2" | |||
} | |||
layer { | |||
name: "pool2" | |||
type: "Pooling" | |||
bottom: "conv2" | |||
top: "pool2" | |||
pooling_param { | |||
pool: MAX | |||
kernel_size: 3 | |||
stride: 2 | |||
} | |||
} | |||
layer { | |||
name: "conv3" | |||
type: "Convolution" | |||
bottom: "pool2" | |||
top: "conv3" | |||
param { | |||
lr_mult: 1 | |||
decay_mult: 1 | |||
} | |||
param { | |||
lr_mult: 2 | |||
decay_mult: 1 | |||
} | |||
convolution_param { | |||
num_output: 64 | |||
kernel_size: 3 | |||
weight_filler { | |||
type: "xavier" | |||
} | |||
bias_filler { | |||
type: "constant" | |||
value: 0 | |||
} | |||
} | |||
} | |||
layer { | |||
name: "prelu3" | |||
type: "PReLU" | |||
bottom: "conv3" | |||
top: "conv3" | |||
} | |||
layer { | |||
name: "pool3" | |||
type: "Pooling" | |||
bottom: "conv3" | |||
top: "pool3" | |||
pooling_param { | |||
pool: MAX | |||
kernel_size: 2 | |||
stride: 2 | |||
} | |||
} | |||
layer { | |||
name: "conv4" | |||
type: "Convolution" | |||
bottom: "pool3" | |||
top: "conv4" | |||
param { | |||
lr_mult: 1 | |||
decay_mult: 1 | |||
} | |||
param { | |||
lr_mult: 2 | |||
decay_mult: 1 | |||
} | |||
convolution_param { | |||
num_output: 128 | |||
kernel_size: 2 | |||
weight_filler { | |||
type: "xavier" | |||
} | |||
bias_filler { | |||
type: "constant" | |||
value: 0 | |||
} | |||
} | |||
} | |||
layer { | |||
name: "prelu4" | |||
type: "PReLU" | |||
bottom: "conv4" | |||
top: "conv4" | |||
} | |||
layer { | |||
name: "conv5i" | |||
type: "InnerProduct" | |||
bottom: "conv4" | |||
top: "conv5" | |||
param { | |||
lr_mult: 1 | |||
decay_mult: 1 | |||
} | |||
param { | |||
lr_mult: 2 | |||
decay_mult: 1 | |||
} | |||
inner_product_param { | |||
#kernel_size: 3 | |||
num_output: 256 | |||
weight_filler { | |||
type: "xavier" | |||
} | |||
bias_filler { | |||
type: "constant" | |||
value: 0 | |||
} | |||
} | |||
} | |||
layer { | |||
name: "drop5i" | |||
type: "Dropout" | |||
bottom: "conv5" | |||
top: "conv5" | |||
dropout_param { | |||
dropout_ratio: 0.25 | |||
} | |||
} | |||
layer { | |||
name: "prelu5" | |||
type: "PReLU" | |||
bottom: "conv5" | |||
top: "conv5" | |||
} | |||
layer { | |||
name: "conv6i-1" | |||
type: "InnerProduct" | |||
bottom: "conv5" | |||
top: "conv6-1" | |||
param { | |||
lr_mult: 1 | |||
decay_mult: 1 | |||
} | |||
param { | |||
lr_mult: 2 | |||
decay_mult: 1 | |||
} | |||
inner_product_param { | |||
#kernel_size: 1 | |||
num_output: 2 | |||
weight_filler { | |||
type: "xavier" | |||
} | |||
bias_filler { | |||
type: "constant" | |||
value: 0 | |||
} | |||
} | |||
} | |||
layer { | |||
name: "conv6i-2" | |||
type: "InnerProduct" | |||
bottom: "conv5" | |||
top: "conv6-2" | |||
param { | |||
lr_mult: 1 | |||
decay_mult: 1 | |||
} | |||
param { | |||
lr_mult: 2 | |||
decay_mult: 1 | |||
} | |||
inner_product_param { | |||
#kernel_size: 1 | |||
num_output: 4 | |||
weight_filler { | |||
type: "xavier" | |||
} | |||
bias_filler { | |||
type: "constant" | |||
value: 0 | |||
} | |||
} | |||
} | |||
layer { | |||
name: "conv6-3" | |||
type: "InnerProduct" | |||
bottom: "conv5" | |||
top: "conv6-3" | |||
param { | |||
lr_mult: 1 | |||
decay_mult: 1 | |||
} | |||
param { | |||
lr_mult: 2 | |||
decay_mult: 1 | |||
} | |||
inner_product_param { | |||
#kernel_size: 1 | |||
num_output: 8 | |||
weight_filler { | |||
type: "xavier" | |||
} | |||
bias_filler { | |||
type: "constant" | |||
value: 0 | |||
} | |||
} | |||
} | |||
layer { | |||
name: "prob1" | |||
type: "Softmax" | |||
bottom: "conv6-1" | |||
top: "prob1" | |||
} |
@@ -1,19 +0,0 @@ | |||
// | |||
// Created by Jack Yu on 21/10/2017. | |||
// | |||
#include "../include/CNNRecognizer.h" | |||
namespace pr{ | |||
CNNRecognizer::CNNRecognizer(std::string prototxt,std::string caffemodel){ | |||
net = cv::dnn::readNetFromCaffe(prototxt, caffemodel); | |||
} | |||
label CNNRecognizer::recognizeCharacter(cv::Mat charImage){ | |||
if(charImage.channels()== 3) | |||
cv::cvtColor(charImage,charImage,cv::COLOR_BGR2GRAY); | |||
cv::Mat inputBlob = cv::dnn::blobFromImage(charImage, 1/255.0, cv::Size(CHAR_INPUT_W,CHAR_INPUT_H), cv::Scalar(0,0,0),false); | |||
net.setInput(inputBlob,"data"); | |||
return net.forward(); | |||
} | |||
} |
@@ -1,108 +0,0 @@ | |||
// | |||
// Created by Jack Yu on 02/10/2017. | |||
// | |||
#include <../include/FastDeskew.h> | |||
namespace pr{ | |||
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; | |||
} | |||
std::vector<float> avgfilter(std::vector<float> angle_list,int windowsSize) { | |||
std::vector<float> angle_list_filtered(angle_list.size() - windowsSize + 1); | |||
for (int i = 0; i < angle_list.size() - windowsSize + 1; i++) { | |||
float avg = 0.00f; | |||
for (int j = 0; j < windowsSize; j++) { | |||
avg += angle_list[i + j]; | |||
} | |||
avg = avg / windowsSize; | |||
angle_list_filtered[i] = avg; | |||
} | |||
return angle_list_filtered; | |||
} | |||
void drawHist(std::vector<float> seq){ | |||
cv::Mat image(300,seq.size(),CV_8U); | |||
image.setTo(0); | |||
for(int i = 0;i<seq.size();i++) | |||
{ | |||
float l = *std::max_element(seq.begin(),seq.end()); | |||
int p = int(float(seq[i])/l*300); | |||
cv::line(image,cv::Point(i,300),cv::Point(i,300-p),cv::Scalar(255,255,255)); | |||
} | |||
cv::imshow("vis",image); | |||
} | |||
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; | |||
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); | |||
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 ) | |||
{ | |||
float x2 = eigen.at<cv::Vec6f>(j, i)[4]; | |||
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; | |||
if(maxPos<ANGLE_MIN) | |||
maxPos-=90; | |||
maxPos=90-maxPos; | |||
cv::Mat deskewed = correctPlateImage(bak, static_cast<float>(maxPos),60.0f); | |||
return deskewed; | |||
} | |||
}//namespace pr |
@@ -1,163 +0,0 @@ | |||
#include "FineMapping.h" | |||
namespace pr{ | |||
const int FINEMAPPING_H = 60 ; | |||
const int FINEMAPPING_W = 140; | |||
const int PADDING_UP_DOWN = 30; | |||
void drawRect(cv::Mat image,cv::Rect rect) | |||
{ | |||
cv::Point p1(rect.x,rect.y); | |||
cv::Point p2(rect.x+rect.width,rect.y+rect.height); | |||
cv::rectangle(image,p1,p2,cv::Scalar(0,255,0),1); | |||
} | |||
FineMapping::FineMapping(std::string prototxt,std::string caffemodel) { | |||
net = cv::dnn::readNetFromCaffe(prototxt, caffemodel); | |||
} | |||
cv::Mat FineMapping::FineMappingHorizon(cv::Mat FinedVertical,int leftPadding,int rightPadding) | |||
{ | |||
cv::Mat inputBlob = cv::dnn::blobFromImage(FinedVertical, 1/255.0, cv::Size(66,16), | |||
cv::Scalar(0,0,0),false); | |||
net.setInput(inputBlob,"data"); | |||
cv::Mat prob = net.forward(); | |||
int front = static_cast<int>(prob.at<float>(0,0)*FinedVertical.cols); | |||
int back = static_cast<int>(prob.at<float>(0,1)*FinedVertical.cols); | |||
front -= leftPadding ; | |||
if(front<0) front = 0; | |||
back +=rightPadding; | |||
if(back>FinedVertical.cols-1) back=FinedVertical.cols - 1; | |||
cv::Mat cropped = FinedVertical.colRange(front,back).clone(); | |||
return cropped; | |||
} | |||
std::pair<int,int> FitLineRansac(std::vector<cv::Point> pts,int zeroadd = 0 ) | |||
{ | |||
std::pair<int,int> res; | |||
if(pts.size()>2) | |||
{ | |||
cv::Vec4f line; | |||
cv::fitLine(pts,line,cv::DIST_HUBER,0,0.01,0.01); | |||
float vx = line[0]; | |||
float vy = line[1]; | |||
float x = line[2]; | |||
float y = line[3]; | |||
int lefty = static_cast<int>((-x * vy / vx) + y); | |||
int righty = static_cast<int>(((136- x) * vy / vx) + y); | |||
res.first = lefty+PADDING_UP_DOWN+zeroadd; | |||
res.second = righty+PADDING_UP_DOWN+zeroadd; | |||
return res; | |||
} | |||
res.first = zeroadd; | |||
res.second = zeroadd; | |||
return res; | |||
} | |||
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); | |||
// this will improve some sen | |||
cv::Mat kernal = cv::getStructuringElement(cv::MORPH_ELLIPSE,cv::Size(1,3)); | |||
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; | |||
float k =lower + i*diff; | |||
cv::adaptiveThreshold(proposal,binary_adaptive,255,cv::ADAPTIVE_THRESH_MEAN_C,cv::THRESH_BINARY,windows_size,k); | |||
cv::Mat draw; | |||
binary_adaptive.copyTo(draw); | |||
cv::findContours(binary_adaptive,contours,cv::RETR_EXTERNAL,cv::CHAIN_APPROX_SIMPLE); | |||
for(auto contour: contours) | |||
{ | |||
cv::Rect bdbox =cv::boundingRect(contour); | |||
float lwRatio = bdbox.height/static_cast<float>(bdbox.width); | |||
int bdboxAera = bdbox.width*bdbox.height; | |||
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); | |||
line_lower.push_back(p2); | |||
contours_nums+=1; | |||
} | |||
} | |||
} | |||
if(contours_nums<41) | |||
{ | |||
cv::bitwise_not(InputProposal,InputProposal); | |||
cv::Mat kernal = cv::getStructuringElement(cv::MORPH_ELLIPSE,cv::Size(1,5)); | |||
cv::Mat bak; | |||
cv::resize(InputProposal,bak,cv::Size(FINEMAPPING_W,FINEMAPPING_H)); | |||
cv::erode(bak,bak,kernal); | |||
if(InputProposal.channels() == 3) | |||
cv::cvtColor(bak,proposal,cv::COLOR_BGR2GRAY); | |||
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::Mat draw; | |||
binary_adaptive.copyTo(draw); | |||
cv::findContours(binary_adaptive,contours,cv::RETR_EXTERNAL,cv::CHAIN_APPROX_SIMPLE); | |||
for(auto contour: contours) | |||
{ | |||
cv::Rect bdbox =cv::boundingRect(contour); | |||
float lwRatio = bdbox.height/static_cast<float>(bdbox.width); | |||
int bdboxAera = bdbox.width*bdbox.height; | |||
if (( lwRatio>0.7&&bdbox.width*bdbox.height>120 && 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); | |||
line_lower.push_back(p2); | |||
contours_nums+=1; | |||
} | |||
} | |||
} | |||
} | |||
cv::Mat rgb; | |||
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, -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; | |||
std::vector<cv::Point2f> corners(4); | |||
corners[0] = cv::Point2f(cols - 1, rightyA); | |||
corners[1] = cv::Point2f(0, leftyA); | |||
corners[2] = cv::Point2f(cols - 1, rightyB); | |||
corners[3] = cv::Point2f(0, leftyB); | |||
std::vector<cv::Point2f> corners_trans(4); | |||
corners_trans[0] = cv::Point2f(136, 36); | |||
corners_trans[1] = cv::Point2f(0, 36); | |||
corners_trans[2] = cv::Point2f(136, 0); | |||
corners_trans[3] = cv::Point2f(0, 0); | |||
cv::Mat transform = cv::getPerspectiveTransform(corners, corners_trans); | |||
cv::Mat quad = cv::Mat::zeros(36, 136, CV_8UC3); | |||
cv::warpPerspective(rgb, quad, transform, quad.size()); | |||
return quad; | |||
} | |||
} | |||
@@ -0,0 +1,67 @@ | |||
#include "../include/Finetune.h" | |||
using namespace std; | |||
using namespace cv; | |||
namespace pr { | |||
FineTune::FineTune(string finetune_prototxt, string finetune_caffemodel) { | |||
FTNet = dnn::readNetFromCaffe(finetune_prototxt, finetune_caffemodel); | |||
} | |||
void FineTune::affine_crop(Mat src, vector<Point> pts, Mat &crop) | |||
{ | |||
Point2f dst[4] = { Point2f(0,0),Point2f(160,0),Point2f(160,40),Point2f(0,40) }; | |||
Point2f srcpt[4] = { Point2f(pts[0]),Point2f(pts[1]) ,Point2f(pts[2]) ,Point2f(pts[3]) }; | |||
Mat _mat = getPerspectiveTransform(srcpt, dst); | |||
warpPerspective(src, crop, _mat, Size(160, 40)); | |||
} | |||
void FineTune::to_refine(Mat src, vector<Point>pts, Mat& crop) | |||
{ | |||
float scale = 3.f; | |||
int cx = 64; int cy = 24; | |||
int cw = 64; int ch = 24; | |||
int tx1 = cx - cw / 2; | |||
int ty1 = cy - ch / 2; | |||
int tx2 = cx + cw / 2; | |||
int ty2 = cy - ch / 2; | |||
int tx3 = cx + cw / 2; | |||
int ty3 = cy + ch / 2; | |||
int tx4 = cx - cw / 2; | |||
int ty4 = cy + ch / 2; | |||
vector<Point2f> dstp(4); | |||
Point2f dst[4] = { (Point2f(tx1*scale, ty1*scale)) ,(Point2f(tx2*scale, ty2*scale)) ,(Point2f(tx3*scale, ty3*scale)) ,(Point2f(tx4*scale, ty4*scale)) }; | |||
Point2f pt[4] = { Point2f(pts[0]),Point2f(pts[1]) ,Point2f(pts[2]) ,Point2f(pts[3]) }; | |||
//estimater | |||
Mat _mat = getPerspectiveTransform(pt, dst); | |||
warpPerspective(src, crop, _mat, Size(120 * scale, 48 * scale)); | |||
} | |||
void FineTune::Finetune(Mat src, Mat& dst) | |||
{ | |||
Mat tof;// = src.clone(); | |||
resize(src, tof, Size(120, 48)); | |||
Mat blob = dnn::blobFromImage(tof, 0.0078125, Size(120, 48), Scalar(127.5, 127.5, 127.5), false, false); | |||
FTNet.setInput(blob); | |||
Mat outblob = FTNet.forward("conv6-3"); | |||
float *data = outblob.ptr<float>(); | |||
vector<Point> pts(4); | |||
Mat fineMat(Size(2, 4), CV_32F, data); | |||
for (int i = 0; i < fineMat.rows; i++) | |||
{ | |||
pts[i].x = fineMat.at<float>(i, 0)*src.cols; | |||
pts[i].y = fineMat.at<float>(i, 1)*src.rows; | |||
} | |||
Mat crop; | |||
to_refine(src, pts, crop); | |||
blob = dnn::blobFromImage(crop, 0.0078128, Size(120, 48), Scalar(127.5, 127.5, 127.5), false, false); | |||
FTNet.setInput(blob); | |||
outblob = FTNet.forward("conv6-3"); | |||
data = outblob.ptr<float>(); | |||
Mat fineMat2(Size(2, 4), CV_32F, data); | |||
for (int i = 0; i < fineMat.rows; i++) | |||
{ | |||
pts[i].x = fineMat2.at<float>(i, 0)*crop.cols; | |||
pts[i].y = fineMat2.at<float>(i, 1)*crop.rows; | |||
} | |||
affine_crop(crop, pts, crop); | |||
dst = crop.clone(); | |||
} | |||
} |
@@ -1,74 +1,70 @@ | |||
// | |||
// Created by Jack Yu on 23/10/2017. | |||
// | |||
#include "../include/Pipeline.h" | |||
namespace pr { | |||
PipelinePR::PipelinePR(std::string detect_prototxt, std::string detect_caffemodel, | |||
std::string finetune_prototxt, std::string finetune_caffemodel, | |||
std::string platerec_prototxt, std::string platerec_caffemodel, | |||
std::string dbstring) | |||
{ | |||
platedetection = new PlateDetection(detect_prototxt, detect_caffemodel); | |||
finetune = new FineTune(finetune_prototxt, finetune_caffemodel); | |||
platerecognation = new PlateRecognation(platerec_prototxt, platerec_caffemodel); | |||
dbdetection = new DBDetection(dbstring); | |||
} | |||
PipelinePR::~PipelinePR() | |||
{ | |||
delete platedetection; | |||
delete finetune; | |||
delete platerecognation; | |||
delete dbdetection; | |||
} | |||
cv::Mat DBcropFromImage(const cv::Mat &image){ | |||
cv::Mat cropped; | |||
image.copyTo(cropped); | |||
int cropped_w = cropped.cols; | |||
int cropped_h = cropped.rows; | |||
cv::Rect up,down; | |||
up.y = cropped_h*0.05;up.x = cropped_w*0.2;up.height = cropped_h*0.35;up.width = cropped_w*0.55; | |||
down.y = cropped_h*0.4;down.x = cropped_w*0.05;down.height = cropped_h*0.6;down.width = cropped_w*0.95; | |||
cv::Mat cropUp,cropDown; | |||
cropped(up).copyTo(cropUp); | |||
cropped(down).copyTo(cropDown); | |||
cv::resize(cropUp,cropUp,cv::Size(64,40)); | |||
cv::resize(cropDown,cropDown,cv::Size(96,40)); | |||
cv::Mat crop = cv::Mat(40,160,CV_8UC3); | |||
cropUp.copyTo(crop(cv::Rect(0,0,64,40))); | |||
cropDown.copyTo(crop(cv::Rect(64,0,96,40))); | |||
return crop; | |||
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 | |||
std::vector<PlateInfo> PipelinePR::RunPiplineAsImage(cv::Mat plateimg,int IsDB) | |||
{ | |||
std::vector<pr::PlateInfo> plates; | |||
std::vector<PlateInfo> plateres; | |||
if(IsDB==1) | |||
{ | |||
dbdetection->DBDetect(plateimg,plates,30,1280); | |||
} | |||
else | |||
{ | |||
platedetection->Detectssd(plateimg, plates); | |||
} | |||
for (pr::PlateInfo plateinfo : plates) { | |||
cv::Mat image = plateinfo.getPlateImage(); | |||
cv::Mat CropImg; | |||
if(IsDB==1) | |||
{ | |||
CropImg = DBcropFromImage(image); | |||
platerecognation->segmentation_free_recognation(CropImg, plateinfo); | |||
} | |||
else | |||
{ | |||
finetune->Finetune(image, CropImg); | |||
platerecognation->segmentation_free_recognation(CropImg, plateinfo); | |||
} | |||
plateres.push_back(plateinfo); | |||
} | |||
return plateres; | |||
} | |||
} |
@@ -1,34 +1,103 @@ | |||
#include "../include/PlateDetection.h" | |||
#include "util.h" | |||
namespace pr{ | |||
PlateDetection::PlateDetection(std::string filename_cascade){ | |||
cascade.load(filename_cascade); | |||
#include "../include/Platedetect.h" | |||
}; | |||
void PlateDetection::plateDetectionRough(cv::Mat InputImage,std::vector<pr::PlateInfo> &plateInfos,int min_w,int max_w){ | |||
cv::Mat processImage; | |||
using namespace cv; | |||
using namespace std; | |||
namespace pr { | |||
PlateDetection::PlateDetection(std::string ssd_prototxt, std::string ssd_caffemodel) | |||
{ | |||
ssdNet = cv::dnn::readNetFromCaffe(ssd_prototxt, ssd_caffemodel); | |||
} | |||
DBDetection::DBDetection(std::string cascadestring) | |||
{ | |||
dbcascade.load(cascadestring); | |||
} | |||
void PlateDetection::Detectssd(cv::Mat img, std::vector<pr::PlateInfo> &plateInfos) | |||
{ | |||
int cols = img.cols; | |||
int rows = img.rows; | |||
Mat in; | |||
img.convertTo(in, CV_32F); | |||
Mat input(img.size(), CV_32FC3); | |||
Mat inputblob1 = input.reshape(1, { 1, 3,rows,cols }); | |||
Mat input_blob = dnn::blobFromImages(in, 0.225, Size(), Scalar(103.53, 116.28, 123.675), false); | |||
float *blobdata = input_blob.ptr<float>(); | |||
float *blobdata2 = inputblob1.ptr<float>(); | |||
{ | |||
for (int i = 0; i < rows; i++) | |||
{ | |||
memcpy(blobdata2 + i * cols, blobdata + 3 * i * cols, cols * sizeof(float)); | |||
memcpy(blobdata2 + i * cols + rows * cols, blobdata + (1 + 3 * i) * cols, cols * sizeof(float)); | |||
memcpy(blobdata2 + i * cols + rows * cols * 2, blobdata + (2 + 3 * i) * cols, cols * sizeof(float)); | |||
} | |||
} | |||
ssdNet.setInput(inputblob1); | |||
Mat outputBlob = ssdNet.forward("detection_out"); | |||
Mat detectmat(outputBlob.size[2], outputBlob.size[3], CV_32F, outputBlob.ptr<float>()); | |||
vector<Rect> recs; | |||
vector<float>scs; | |||
for (int i = 0; i < detectmat.rows; i++) | |||
{ | |||
float confidence = detectmat.at<float>(i, 2); | |||
if (confidence > 0.5) | |||
{ | |||
int x1, x2, y1, y2; | |||
Rect rec; | |||
Mat cimg; | |||
x1 = int(detectmat.at<float>(i, 3) * cols); | |||
y1 = int(detectmat.at<float>(i, 4) * rows); | |||
x2 = int(detectmat.at<float>(i, 5) * cols); | |||
y2 = int(detectmat.at<float>(i, 6) * rows); | |||
x1 = max(x1, 0); | |||
y1 = max(y1, 0); | |||
x2 = min(x2, cols - 1); | |||
y2 = min(y2, rows - 1); | |||
rec.x = x1; rec.y = y1; rec.width = (x2 - x1 + 1); rec.height = (y2 - y1 + 1); | |||
img(rec).copyTo(cimg); | |||
PlateInfo plateInfo(cimg, rec); | |||
plateInfos.push_back(plateInfo); | |||
} | |||
} | |||
} | |||
cv::Mat cropFromImage(const cv::Mat &image,cv::Rect rect){ | |||
int w = image.cols-1; | |||
int h = image.rows-1; | |||
rect.x = std::max(rect.x,0); | |||
rect.y = std::max(rect.y,0); | |||
rect.height = std::min(rect.height,h-rect.y); | |||
rect.width = std::min(rect.width,w-rect.x); | |||
cv::Mat temp(rect.size(), image.type()); | |||
cv::Mat cropped; | |||
temp = image(rect); | |||
temp.copyTo(cropped); | |||
return cropped; | |||
} | |||
void DBDetection::DBDetect(cv::Mat InputImage,std::vector<pr::PlateInfo> &plateInfos,int min_w,int max_w) | |||
{ | |||
cv::Mat processImage; | |||
cv::cvtColor(InputImage,processImage,cv::COLOR_BGR2GRAY); | |||
std::vector<cv::Rect> platesRegions; | |||
cv::Size minSize(min_w,min_w/4); | |||
cv::Size maxSize(max_w,max_w/4); | |||
if (&processImage == NULL) | |||
return; | |||
cascade.detectMultiScale( processImage, platesRegions, | |||
dbcascade.detectMultiScale( processImage, platesRegions, | |||
1.1, 3, cv::CASCADE_SCALE_IMAGE,minSize,maxSize); | |||
for(auto plate:platesRegions) | |||
{ | |||
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); | |||
int zeroadd_w = static_cast<int>(plate.width*0.28); | |||
int zeroadd_h = static_cast<int>(plate.height*0.35); | |||
int zeroadd_x = static_cast<int>(plate.width*0.14); | |||
int zeroadd_y = static_cast<int>(plate.height*0.15); | |||
plate.x-=zeroadd_x; | |||
plate.y-=zeroadd_y; | |||
plate.height += zeroadd_h; | |||
plate.width += zeroadd_w; | |||
cv::Mat plateImage = util::cropFromImage(InputImage,plate); | |||
cv::Mat plateImage = cropFromImage(InputImage,plate); | |||
PlateInfo plateInfo(plateImage,plate); | |||
plateInfos.push_back(plateInfo); | |||
} | |||
} | |||
}//namespace pr | |||
} |
@@ -0,0 +1,61 @@ | |||
#include "../include/PlateRecognation.h" | |||
#include "../include/Pipeline.h" | |||
using namespace std; | |||
using namespace cv; | |||
namespace pr { | |||
PlateRecognation::PlateRecognation(std::string rec_prototxt, std::string rec_caffemodel) | |||
{ | |||
RecNet = cv::dnn::readNetFromCaffe(rec_prototxt, rec_caffemodel); | |||
} | |||
void PlateRecognation::segmentation_free_recognation(cv::Mat src, pr::PlateInfo &plateinfo) | |||
{ | |||
float score = 0; | |||
string text = ""; | |||
Mat src1 = src.clone(); | |||
Mat inputMat(Size(40, 160), CV_8UC3); | |||
for (int j = 0; j < src.rows; j++) | |||
{ | |||
for (int i = 0; i < src.cols; i++) | |||
{ | |||
inputMat.at<Vec3b>(i, j) = src1.at<Vec3b>(j, i); | |||
} | |||
} | |||
Mat blob = dnn::blobFromImage(inputMat, 1 / 255.f, Size(40, 160), Scalar(0, 0, 0), false, false); | |||
RecNet.setInput(blob); | |||
Mat outblob = RecNet.forward(); | |||
int x = outblob.size[2]; | |||
int y = outblob.size[0]; | |||
float *data = outblob.ptr<float>(); | |||
vector<float> scores(84); | |||
vector<int>maxidxs; | |||
vector<float> maxscore; | |||
for (int i = 2; i < 20; i++) | |||
{ | |||
for (int j = 0; j < 84; j++) | |||
{ | |||
scores[j] = data[j * 20 + i]; | |||
} | |||
int idx = max_element(scores.begin(), scores.end()) - scores.begin(); | |||
maxidxs.push_back(idx); | |||
maxscore.push_back(scores[idx]); | |||
} | |||
int charnum = 0; | |||
for (int i = 0; i < maxidxs.size(); i++) | |||
{ | |||
if (maxidxs[i] < pr::CH_PLATE_CODE.size() && (i == 0 || (maxidxs[i - 1] != maxidxs[i]))) | |||
{ | |||
text += pr::CH_PLATE_CODE[maxidxs[i]]; | |||
score += maxscore[i]; | |||
charnum++; | |||
} | |||
} | |||
if (charnum > 0) | |||
{ | |||
score /= charnum; | |||
} | |||
plateinfo.setPlateName(text); | |||
plateinfo.confidence = score; | |||
} | |||
} |
@@ -1,404 +0,0 @@ | |||
// | |||
// Created by Jack Yu on 16/10/2017. | |||
// | |||
#include "../include/PlateSegmentation.h" | |||
#include "../include/niBlackThreshold.h" | |||
//#define DEBUG | |||
namespace pr{ | |||
PlateSegmentation::PlateSegmentation(std::string prototxt,std::string caffemodel) { | |||
net = cv::dnn::readNetFromCaffe(prototxt, caffemodel); | |||
} | |||
cv::Mat PlateSegmentation::classifyResponse(const cv::Mat &cropped){ | |||
cv::Mat inputBlob = cv::dnn::blobFromImage(cropped, 1/255.0, cv::Size(22,22), cv::Scalar(0,0,0),false); | |||
net.setInput(inputBlob,"data"); | |||
return net.forward(); | |||
} | |||
void drawHist(float* seq,int size,const char* name){ | |||
cv::Mat image(300,size,CV_8U); | |||
image.setTo(0); | |||
float* start =seq; | |||
float* end = seq+size; | |||
float l = *std::max_element(start,end); | |||
for(int i = 0;i<size;i++) | |||
{ | |||
int p = int(float(seq[i])/l*300); | |||
cv::line(image,cv::Point(i,300),cv::Point(i,300-p),cv::Scalar(255,255,255)); | |||
} | |||
cv::resize(image,image,cv::Size(600,100)); | |||
cv::imshow(name,image); | |||
} | |||
inline void computeSafeMargin(int &val,const int &rows){ | |||
val = std::min(val,rows); | |||
val = std::max(val,0); | |||
} | |||
cv::Rect boxFromCenter(const cv::Point center,int left,int right,int top,int bottom,cv::Size bdSize) | |||
{ | |||
cv::Point p1(center.x - left ,center.y - top); | |||
cv::Point p2( center.x + right, center.y + bottom); | |||
p1.x = std::max(0,p1.x); | |||
p1.y = std::max(0,p1.y); | |||
p2.x = std::min(p2.x,bdSize.width-1); | |||
p2.y = std::min(p2.y,bdSize.height-1); | |||
cv::Rect rect(p1,p2); | |||
return rect; | |||
} | |||
cv::Rect boxPadding(cv::Rect rect,int left,int right,int top,int bottom,cv::Size bdSize) | |||
{ | |||
cv::Point center(rect.x+(rect.width>>1),rect.y + (rect.height>>1)); | |||
int rebuildLeft = (rect.width>>1 )+ left; | |||
int rebuildRight = (rect.width>>1 )+ right; | |||
int rebuildTop = (rect.height>>1 )+ top; | |||
int rebuildBottom = (rect.height>>1 )+ bottom; | |||
return boxFromCenter(center,rebuildLeft,rebuildRight,rebuildTop,rebuildBottom,bdSize); | |||
} | |||
void PlateSegmentation:: refineRegion(cv::Mat &plateImage,const std::vector<int> &candidatePts,const int padding,std::vector<cv::Rect> &rects){ | |||
int w = candidatePts[5] - candidatePts[4]; | |||
int cols = plateImage.cols; | |||
int rows = plateImage.rows; | |||
for(int i = 0 ; i < candidatePts.size() ; i++) | |||
{ | |||
int left = 0; | |||
int right = 0 ; | |||
if(i == 0 ){ | |||
left= candidatePts[i]; | |||
right = left+w+padding; | |||
} | |||
else { | |||
left = candidatePts[i] - padding; | |||
right = left + w + padding * 2; | |||
} | |||
computeSafeMargin(right,cols); | |||
computeSafeMargin(left,cols); | |||
cv::Rect roi(left,0,right - left,rows-1); | |||
cv::Mat roiImage; | |||
plateImage(roi).copyTo(roiImage); | |||
if (i>=1) | |||
{ | |||
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.27,BINARIZATION_NIBLACK); | |||
std::vector<std::vector<cv::Point>> contours; | |||
cv::findContours(roi_thres,contours,cv::RETR_LIST,cv::CHAIN_APPROX_SIMPLE); | |||
cv::Point boxCenter(roiImage.cols>>1,roiImage.rows>>1); | |||
cv::Rect final_bdbox; | |||
cv::Point final_center; | |||
int final_dist = INT_MAX; | |||
for(auto contour:contours) | |||
{ | |||
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 and bdbox.height > rows>>1) | |||
{ final_dist =dist; | |||
final_center = center; | |||
final_bdbox = bdbox; | |||
} | |||
} | |||
//rebuild box | |||
if(final_bdbox.height/ static_cast<float>(final_bdbox.width) > 3.5 && final_bdbox.width*final_bdbox.height<10) | |||
final_bdbox = boxFromCenter(final_center,8,8,(rows>>1)-3 , (rows>>1) - 2,roiImage.size()); | |||
else { | |||
if(i == candidatePts.size()-1) | |||
final_bdbox = boxPadding(final_bdbox, padding/2, padding, padding/2, padding/2, roiImage.size()); | |||
else | |||
final_bdbox = boxPadding(final_bdbox, padding, padding, padding, padding, roiImage.size()); | |||
// std::cout<<final_bdbox<<std::endl; | |||
// std::cout<<roiImage.size()<<std::endl; | |||
#ifdef DEBUG | |||
cv::imshow("char_thres",roi_thres); | |||
cv::imshow("char",roiImage(final_bdbox)); | |||
cv::waitKey(0); | |||
#endif | |||
} | |||
final_bdbox.x += left; | |||
rects.push_back(final_bdbox); | |||
// | |||
} | |||
else | |||
{ | |||
rects.push_back(roi); | |||
} | |||
// else | |||
// { | |||
// | |||
// } | |||
// cv::GaussianBlur(roiImage,roiImage,cv::Size(7,7),3); | |||
// | |||
// cv::imshow("image",roiImage); | |||
// cv::waitKey(0); | |||
} | |||
} | |||
void avgfilter(float *angle_list,int size,int windowsSize) { | |||
float *filterd = new float[size]; | |||
for(int i = 0 ; i < size ; i++) filterd [i] = angle_list[i]; | |||
// memcpy(filterd,angle_list,size); | |||
cv::Mat kernal_gaussian = cv::getGaussianKernel(windowsSize,3,CV_32F); | |||
float *kernal = (float*)kernal_gaussian.data; | |||
// kernal+=windowsSize; | |||
int r = windowsSize/2; | |||
for (int i = 0; i < size; i++) { | |||
float avg = 0.00f; | |||
for (int j = 0; j < windowsSize; j++) { | |||
if(i+j-r>0&&i+j+r<size-1) | |||
avg += filterd[i + j-r]*kernal[j]; | |||
} | |||
// avg = avg / windowsSize; | |||
angle_list[i] = avg; | |||
} | |||
delete filterd; | |||
} | |||
void PlateSegmentation::templateMatchFinding(const cv::Mat &respones,int windowsWidth,std::pair<float,std::vector<int>> &candidatePts){ | |||
int rows = respones.rows; | |||
int cols = respones.cols; | |||
float *data = (float*)respones.data; | |||
float *engNum_prob = data; | |||
float *false_prob = data+cols; | |||
float *ch_prob = data+cols*2; | |||
avgfilter(engNum_prob,cols,5); | |||
avgfilter(false_prob,cols,5); | |||
// avgfilter(ch_prob,cols,5); | |||
std::vector<int> candidate_pts(7); | |||
#ifdef DEBUG | |||
drawHist(engNum_prob,cols,"engNum_prob"); | |||
drawHist(false_prob,cols,"false_prob"); | |||
drawHist(ch_prob,cols,"ch_prob"); | |||
cv::waitKey(0); | |||
#endif | |||
int cp_list[7]; | |||
float loss_selected = -10; | |||
for(int start = 0 ; start < 20 ; start+=2) | |||
for(int width = windowsWidth-5; width < windowsWidth+5 ; width++ ){ | |||
for(int interval = windowsWidth/2; interval < windowsWidth; interval++) | |||
{ | |||
int cp1_ch = start; | |||
int cp2_p0 = cp1_ch+ width; | |||
int cp3_p1 = cp2_p0+ width + interval; | |||
int cp4_p2 = cp3_p1 + width; | |||
int cp5_p3 = cp4_p2 + width+1; | |||
int cp6_p4 = cp5_p3 + width+2; | |||
int cp7_p5= cp6_p4+ width+2; | |||
int md1 = (cp1_ch+cp2_p0)>>1; | |||
int md2 = (cp2_p0+cp3_p1)>>1; | |||
int md3 = (cp3_p1+cp4_p2)>>1; | |||
int md4 = (cp4_p2+cp5_p3)>>1; | |||
int md5 = (cp5_p3+cp6_p4)>>1; | |||
int md6 = (cp6_p4+cp7_p5)>>1; | |||
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]); | |||
if(loss>loss_selected) | |||
{ | |||
loss_selected = loss; | |||
cp_list[0]= cp1_ch; | |||
cp_list[1]= cp2_p0; | |||
cp_list[2]= cp3_p1; | |||
cp_list[3]= cp4_p2; | |||
cp_list[4]= cp5_p3; | |||
cp_list[5]= cp6_p4; | |||
cp_list[6]= cp7_p5; | |||
} | |||
} | |||
} | |||
candidate_pts[0] = cp_list[0]; | |||
candidate_pts[1] = cp_list[1]; | |||
candidate_pts[2] = cp_list[2]; | |||
candidate_pts[3] = cp_list[3]; | |||
candidate_pts[4] = cp_list[4]; | |||
candidate_pts[5] = cp_list[5]; | |||
candidate_pts[6] = cp_list[6]; | |||
candidatePts.first = loss_selected; | |||
candidatePts.second = candidate_pts; | |||
}; | |||
void PlateSegmentation::segmentPlateBySlidingWindows(cv::Mat &plateImage,int windowsWidth,int stride,cv::Mat &respones){ | |||
// 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 - padding; | |||
for(int i = 0 ; i < width - windowsWidth +1 ; i +=stride) | |||
{ | |||
cv::Rect roi(i,0,windowsWidth,height); | |||
cv::Mat roiImage = plateImageGray(roi); | |||
cv::Mat response = classifyResponse(roiImage); | |||
respones.push_back(response); | |||
} | |||
respones = respones.t(); | |||
// std::pair<float,std::vector<int>> images ; | |||
// | |||
// | |||
// std::cout<<images.first<<" "; | |||
// for(int i = 0 ; i < images.second.size() ; i++) | |||
// { | |||
// std::cout<<images.second[i]<<" "; | |||
//// cv::line(plateImageGray,cv::Point(images.second[i],0),cv::Point(images.second[i],36),cv::Scalar(255,255,255),1); //DEBUG | |||
// } | |||
// int w = images.second[5] - images.second[4]; | |||
// cv::line(plateImageGray,cv::Point(images.second[5]+w,0),cv::Point(images.second[5]+w,36),cv::Scalar(255,255,255),1); //DEBUG | |||
// cv::line(plateImageGray,cv::Point(images.second[5]+2*w,0),cv::Point(images.second[5]+2*w,36),cv::Scalar(255,255,255),1); //DEBUG | |||
// RefineRegion(plateImageGray,images.second,5); | |||
// std::cout<<w<<std::endl; | |||
// std::cout<<<<std::endl; | |||
// cv::resize(plateImageGray,plateImageGray,cv::Size(600,100)); | |||
} | |||
// void filterGaussian(cv::Mat &respones,float sigma){ | |||
// | |||
// } | |||
void PlateSegmentation::segmentPlatePipline(PlateInfo &plateInfo,int stride,std::vector<cv::Rect> &Char_rects){ | |||
cv::Mat plateImage = plateInfo.getPlateImage(); // get src image . | |||
cv::Mat plateImageGray; | |||
cv::cvtColor(plateImage,plateImageGray,cv::COLOR_BGR2GRAY); | |||
//do binarzation | |||
// | |||
std::pair<float,std::vector<int>> sections ; // segment points variables . | |||
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; | |||
refineRegion(plateImageGray,sections.second,5,Char_rects); | |||
#ifdef DEBUG | |||
for(int i = 0 ; i < sections.second.size() ; i++) | |||
{ | |||
std::cout<<sections.second[i]<<" "; | |||
cv::line(plateImageGray,cv::Point(sections.second[i],0),cv::Point(sections.second[i],36),cv::Scalar(255,255,255),1); //DEBUG | |||
} | |||
cv::imshow("plate",plateImageGray); | |||
cv::waitKey(0); | |||
#endif | |||
// cv::waitKey(0); | |||
} | |||
void PlateSegmentation::ExtractRegions(PlateInfo &plateInfo,std::vector<cv::Rect> &rects){ | |||
cv::Mat plateImage = plateInfo.getPlateImage(); | |||
for(int i = 0 ; i < rects.size() ; i++){ | |||
cv::Mat charImage; | |||
plateImage(rects[i]).copyTo(charImage); | |||
if(charImage.channels()) | |||
cv::cvtColor(charImage,charImage,cv::COLOR_BGR2GRAY); | |||
// cv::imshow("image",charImage); | |||
// cv::waitKey(0); | |||
cv::equalizeHist(charImage,charImage); | |||
// | |||
// | |||
std::pair<CharType,cv::Mat> char_instance; | |||
if(i == 0 ){ | |||
char_instance.first = CHINESE; | |||
} else if(i == 1){ | |||
char_instance.first = LETTER; | |||
} | |||
else{ | |||
char_instance.first = LETTER_NUMS; | |||
} | |||
char_instance.second = charImage; | |||
plateInfo.appendPlateChar(char_instance); | |||
} | |||
} | |||
}//namespace pr |
@@ -1,23 +0,0 @@ | |||
// | |||
// 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; | |||
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); | |||
} | |||
} | |||
} | |||
} |
@@ -1,89 +0,0 @@ | |||
// | |||
// 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); | |||
} | |||
} |
@@ -1,67 +0,0 @@ | |||
// | |||
// 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){ | |||
int w = image.cols-1; | |||
int h = image.rows-1; | |||
rect.x = std::max(rect.x,0); | |||
rect.y = std::max(rect.y,0); | |||
rect.height = std::min(rect.height,h-rect.y); | |||
rect.width = std::min(rect.width,w-rect.x); | |||
cv::Mat temp(rect.size(), image.type()); | |||
cv::Mat cropped; | |||
temp = image(rect); | |||
temp.copyTo(cropped); | |||
return cropped; | |||
} | |||
cv::Mat cropBox2dFromImage(const cv::Mat &image,cv::RotatedRect rect) | |||
{ | |||
cv::Mat M, rotated, cropped; | |||
float angle = rect.angle; | |||
cv::Size rect_size(rect.size.width,rect.size.height); | |||
if (rect.angle < -45.) { | |||
angle += 90.0; | |||
swap(rect_size.width, rect_size.height); | |||
} | |||
M = cv::getRotationMatrix2D(rect.center, angle, 1.0); | |||
cv::warpAffine(image, rotated, M, image.size(), cv::INTER_CUBIC); | |||
cv::getRectSubPix(rotated, rect_size, rect.center, cropped); | |||
return cropped; | |||
} | |||
cv::Mat calcHist(const cv::Mat &image) | |||
{ | |||
cv::Mat hsv; | |||
std::vector<cv::Mat> hsv_planes; | |||
cv::cvtColor(image,hsv,cv::COLOR_BGR2HSV); | |||
cv::split(hsv,hsv_planes); | |||
cv::Mat hist; | |||
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); | |||
} | |||
}//namespace util |
@@ -0,0 +1,28 @@ | |||
#include"../include/Pipeline.h" | |||
void TEST_PIPELINE() | |||
{ | |||
pr::PipelinePR prc("../lpr/model/mininet_ssd_v1.prototxt", "../lpr/model/mininet_ssd_v1.caffemodel", | |||
"../lpr/model/refinenet.prototxt", "../lpr/model/refinenet.caffemodel", | |||
"../lpr/model/SegmenationFree-Inception.prototxt", "../lpr/model/SegmenationFree-Inception.caffemodel", | |||
"../lpr/model/cascade_double.xml"); | |||
cv::Mat img = cv::imread("../lpr//res//test.jpg"); | |||
std::vector<pr::PlateInfo> res = prc.RunPiplineAsImage(img,0); | |||
for (auto st : res) { | |||
if (st.confidence > 0.75) { | |||
std::cout << st.getPlateName() << " " << st.confidence << std::endl; | |||
cv::Rect region = st.getPlateRect(); | |||
cv::rectangle(img, 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", img); | |||
//cv::waitKey(0); | |||
} | |||
int main() | |||
{ | |||
TEST_PIPELINE(); | |||
return 0; | |||
} |
@@ -1,32 +0,0 @@ | |||
// | |||
// Created by 庾金科 on 20/09/2017. | |||
// | |||
#include <../include/PlateDetection.h> | |||
void drawRect(cv::Mat image,cv::Rect rect) | |||
{ | |||
cv::Point p1(rect.x,rect.y); | |||
cv::Point p2(rect.x+rect.width,rect.y+rect.height); | |||
cv::rectangle(image,p1,p2,cv::Scalar(0,255,0),1); | |||
} | |||
int main() | |||
{ | |||
cv::Mat image = cv::imread("res/test1.jpg"); | |||
pr::PlateDetection plateDetection("model/cascade.xml"); | |||
std::vector<pr::PlateInfo> plates; | |||
plateDetection.plateDetectionRough(image,plates); | |||
for(pr::PlateInfo platex:plates) | |||
{ | |||
drawRect(image,platex.getPlateRect()); | |||
cv::imwrite("res/cache/test.png",platex.getPlateImage()); | |||
cv::imshow("image",platex.getPlateImage()); | |||
cv::waitKey(0); | |||
} | |||
cv::imshow("image",image); | |||
cv::waitKey(0); | |||
return 0 ; | |||
} |
@@ -1,34 +0,0 @@ | |||
// | |||
// Created by Jack Yu on 02/10/2017. | |||
// | |||
#include <../include/FastDeskew.h> | |||
void drawRect(cv::Mat image,cv::Rect rect) | |||
{ | |||
cv::Point p1(rect.x,rect.y); | |||
cv::Point p2(rect.x+rect.width,rect.y+rect.height); | |||
cv::rectangle(image,p1,p2,cv::Scalar(0,255,0),1); | |||
} | |||
void TEST_DESKEW(){ | |||
cv::Mat image = cv::imread("res/3.png",cv::IMREAD_GRAYSCALE); | |||
// cv::resize(image,image,cv::Size(136*2,36*2)); | |||
cv::Mat deskewed = pr::fastdeskew(image,12); | |||
// cv::imwrite("./res/4.png",deskewed); | |||
// cv::Mat deskewed2 = pr::fastdeskew(deskewed,12); | |||
// | |||
cv::imshow("image",deskewed); | |||
cv::waitKey(0); | |||
} | |||
int main() | |||
{ | |||
TEST_DESKEW(); | |||
return 0 ; | |||
} |
@@ -1,25 +0,0 @@ | |||
// | |||
// Created by Jack Yu on 24/09/2017. | |||
// | |||
#include "FineMapping.h" | |||
int main() | |||
{ | |||
cv::Mat image = cv::imread("res/cache/test.png"); | |||
cv::Mat image_finemapping = pr::FineMapping::FineMappingVertical(image); | |||
pr::FineMapping finemapper = pr::FineMapping("model/HorizonalFinemapping.prototxt","model/HorizonalFinemapping.caffemodel"); | |||
image_finemapping = finemapper.FineMappingHorizon(image_finemapping,0,-3); | |||
cv::imwrite("res/cache/finemappingres.png",image_finemapping); | |||
cv::imshow("image",image_finemapping); | |||
cv::waitKey(0); | |||
return 0 ; | |||
} |
@@ -1,179 +0,0 @@ | |||
// | |||
// Created by Jack Yu on 23/10/2017. | |||
// | |||
#include "../include/Pipeline.h" | |||
using namespace std; | |||
template<class T> | |||
static unsigned int levenshtein_distance(const T &s1, const T &s2) { | |||
const size_t len1 = s1.size(), len2 = s2.size(); | |||
std::vector<unsigned int> 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]; | |||
} | |||
void TEST_ACC(){ | |||
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/SegmenationFree-Inception.prototxt","model/SegmenationFree-Inception.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<pr::PlateInfo> res = prc.RunPiplineAsImage(image,pr::SEGMENTATION_FREE_METHOD); | |||
float conf = 0; | |||
vector<float> con ; | |||
vector<string> 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:"<<max << endl; | |||
cout << "string:" << platestr << endl; | |||
chpr = platestr.substr(0, 2); | |||
ch = imagename.substr(0, 2); | |||
diff = levenshtein_distance(imagename, platestr); | |||
dif = diff - 4; | |||
cout << "差距:" <<dif << endl; | |||
sum += dif; | |||
if (ch != chpr) n++; | |||
if (diff == 0) correct++; | |||
j++; | |||
} | |||
float cha = 1 - float(n) / float(j); | |||
std::cout << "------------------------------------------------" << endl; | |||
cout << "车牌总数:" << j << endl; | |||
cout << "汉字识别准确率:"<<cha << endl; | |||
float chaccuracy = 1 - float(sum - n * 2) /float(j * 8); | |||
cout << "字符识别准确率:" << chaccuracy << endl; | |||
} | |||
void TEST_PIPELINE(){ | |||
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/SegmenationFree-Inception.prototxt","model/SegmenationFree-Inception.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); | |||
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); | |||
} | |||
void TEST_CAM() | |||
{ | |||
cv::VideoCapture capture("test1.mp4"); | |||
cv::Mat frame; | |||
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/SegmenationFree-Inception.prototxt","model/SegmenationFree-Inception.caffemodel" | |||
); | |||
while(1) { | |||
//读取下一帧 | |||
if (!capture.read(frame)) { | |||
std::cout << "读取视频失败" << std::endl; | |||
exit(1); | |||
} | |||
std::vector<pr::PlateInfo> 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 ; | |||
} |
@@ -1,54 +0,0 @@ | |||
// | |||
// Created by Jack Yu on 23/10/2017. | |||
// | |||
#include "../include/CNNRecognizer.h" | |||
std::vector<std::string> chars{"京","沪","津","渝","冀","晋","蒙","辽","吉","黑","苏","浙","皖","闽","赣","鲁","豫","鄂","湘","粤","桂","琼","川","贵","云","藏","陕","甘","青","宁","新","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"}; | |||
#include <opencv2/dnn.hpp> | |||
using namespace cv::dnn; | |||
void getMaxClass(cv::Mat &probBlob, int *classId, double *classProb) | |||
{ | |||
// cv::Mat probMat = probBlob.matRefConst().reshape(1, 1); //reshape the blob to 1x1000 matrix | |||
cv::Point classNumber; | |||
cv::minMaxLoc(probBlob, NULL, classProb, NULL, &classNumber); | |||
*classId = classNumber.x; | |||
} | |||
void TEST_RECOGNIZATION(){ | |||
// pr::CNNRecognizer instance("model/CharacterRecognization.prototxt","model/CharacterRecognization.caffemodel"); | |||
Net net = cv::dnn::readNetFromCaffe("model/CharacterRecognization.prototxt","model/CharacterRecognization.caffemodel"); | |||
cv::Mat image = cv::imread("res/char1.png",cv::IMREAD_GRAYSCALE); | |||
cv::resize(image,image,cv::Size(14,30)); | |||
cv::equalizeHist(image,image); | |||
cv::Mat inputBlob = cv::dnn::blobFromImage(image, 1/255.0, cv::Size(14,30), false); | |||
net.setInput(inputBlob,"data"); | |||
cv::Mat res = net.forward(); | |||
std::cout<<res<<std::endl; | |||
float *p = (float*)res.data; | |||
int maxid= 0; | |||
double prob = 0; | |||
getMaxClass(res,&maxid,&prob); | |||
std::cout<<chars[maxid]<<std::endl; | |||
}; | |||
int main() | |||
{TEST_RECOGNIZATION(); | |||
} |
@@ -1,43 +0,0 @@ | |||
// | |||
// Created by Jack Yu on 16/10/2017. | |||
// | |||
#include "../include/PlateSegmentation.h" | |||
#include "../include/CNNRecognizer.h" | |||
#include "../include/Recognizer.h" | |||
std::vector<std::string> chars{"京","沪","津","渝","冀","晋","蒙","辽","吉","黑","苏","浙","皖","闽","赣","鲁","豫","鄂","湘","粤","桂","琼","川","贵","云","藏","陕","甘","青","宁","新","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"}; | |||
void TEST_SLIDINGWINDOWS_EVAL(){ | |||
cv::Mat demo = cv::imread("res/cache/finemappingres.png"); | |||
cv::resize(demo,demo,cv::Size(136,36)); | |||
cv::Mat respones; | |||
pr::PlateSegmentation plateSegmentation("model/Segmentation.prototxt","model/Segmentation.caffemodel"); | |||
pr::PlateInfo plate; | |||
plate.setPlateImage(demo); | |||
std::vector<cv::Rect> rects; | |||
plateSegmentation.segmentPlatePipline(plate,1,rects); | |||
plateSegmentation.ExtractRegions(plate,rects); | |||
pr::GeneralRecognizer *recognizer = new pr::CNNRecognizer("model/CharacterRecognization.prototxt","model/CharacterRecognization.caffemodel"); | |||
recognizer->SegmentBasedSequenceRecognition(plate); | |||
std::cout<<plate.decodePlateNormal(chars)<<std::endl; | |||
delete(recognizer); | |||
} | |||
int main(){ | |||
TEST_SLIDINGWINDOWS_EVAL(); | |||
return 0; | |||
} |
@@ -1,54 +0,0 @@ | |||
// | |||
// 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<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; | |||
} | |||
int main() | |||
{ | |||
cv::Mat image = cv::imread("res/cache/chars_segment.jpg"); | |||
// cv::transpose(image,image); | |||
// cv::resize(image,image,cv::Size(160,40)); | |||
cv::imshow("xxx",image); | |||
cv::waitKey(0); | |||
pr::SegmentationFreeRecognizer recognizr("model/SegmenationFree-Inception.prototxt","model/ISegmenationFree-Inception.caffemodel"); | |||
std::pair<std::string,float> res = recognizr.SegmentationFreeForSinglePlate(image,pr::CH_PLATE_CODE); | |||
std::cout<<res.first<<" " | |||
<<res.second<<std::endl; | |||
// decodeResults(plate,pr::CH_PLATE_CODE); | |||
cv::imshow("image",image); | |||
cv::waitKey(0); | |||
return 0; | |||
} |
@@ -1,46 +0,0 @@ | |||
cmake_minimum_required(VERSION 3.6) | |||
project(platescan) | |||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") | |||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) | |||
find_package(OpenCV 3.3.0 REQUIRED) | |||
include_directories( ${OpenCV_INCLUDE_DIRS}) | |||
include_directories(include) | |||
add_library( # Sets the name of the library. | |||
platescan | |||
# Sets the library as a shared library. | |||
SHARED | |||
# Provides a relative path to your source file(s). | |||
main.cpp | |||
lpr/CNNRecognizer.cpp | |||
lpr/FastDeskew.cpp | |||
lpr/FineMapping.cpp | |||
lpr/Pipeline.cpp | |||
lpr/PlateDetection.cpp | |||
lpr/PlateSegmentation.cpp | |||
lpr/Recognizer.cpp | |||
lpr/SegmentationFreeRecognizer.cpp | |||
) | |||
target_link_libraries( | |||
platescan | |||
phpcpp | |||
${OpenCV_LIBS} | |||
) | |||
execute_process(COMMAND php-config --extension-dir | |||
OUTPUT_VARIABLE LIBRARY_DIR) | |||
message("PHP_EXTENSIONS_DIR ${LIBRARY_DIR}") | |||
add_custom_command(TARGET platescan | |||
POST_BUILD | |||
COMMAND mv ./libplatescan.so ./platescan.so | |||
COMMAND cp -f ./platescan.so ${LIBRARY_DIR} | |||
COMMAND ${POST_COMPILE_COMMAND} | |||
) |
@@ -1,50 +0,0 @@ | |||
# Prj-PHP | |||
HyperLPR 在PHP扩展程序中的实现,核心代码拷贝了 Prj-Linux 中的代码。 | |||
## CPP 依赖 | |||
+ Opencv 3.3 | |||
+ PHPCPP | |||
## Linux/Mac 编译 | |||
```bash | |||
mkdir build | |||
cd build | |||
cmake ../ | |||
make -j | |||
``` | |||
## DEMO | |||
```php | |||
// 也可编译完后直接在tests目录直接运行 php platescan.php | |||
$path = realpath("demo.png"); // 图片文件所在路径,realpath转为绝对路径 | |||
$model = realpath("model"); // 模型资源所在文件夹 | |||
$res = platescan($path, $model, 0.8); | |||
var_dump($res); // string(9) "苏ED0N19" | |||
``` | |||
最终实现上边这样的PHP调用 | |||
 | |||
## 测试备忘 | |||
经多次测试发现部分图片难以识别或者容易识别错误,经过筛选反推出如下规律: | |||
### 识别精度高的图片 | |||
+ 图片中包含有整个车身 | |||
+ 图片清晰度较高,不模糊 | |||
+ 图片拍摄角度为正面拍摄,车牌在图片中没有较大幅度的倾斜 | |||
+ 图片中的车牌在整个图片中所占位置较小 | |||
### 识别精度低的图片 | |||
+ 图片模糊,程序未能裁切出正确的车牌,或者裁切后因图片太模糊而无法识别(此处应该可以通过训练更多样本解决) | |||
+ 图片中的车牌在整个图片中占了1/3的位置甚至更高 | |||
+ 图片拍摄角度为俯角拍摄,车牌在图片中是倾斜着的 |
@@ -1,24 +0,0 @@ | |||
// | |||
// Created by 庾金科 on 21/10/2017. | |||
// | |||
#ifndef SWIFTPR_CNNRECOGNIZER_H | |||
#define SWIFTPR_CNNRECOGNIZER_H | |||
#include "Recognizer.h" | |||
namespace pr{ | |||
class CNNRecognizer: public GeneralRecognizer{ | |||
public: | |||
const int CHAR_INPUT_W = 14; | |||
const int CHAR_INPUT_H = 30; | |||
CNNRecognizer(std::string prototxt,std::string caffemodel); | |||
label recognizeCharacter(cv::Mat character); | |||
private: | |||
cv::dnn::Net net; | |||
}; | |||
} | |||
#endif //SWIFTPR_CNNRECOGNIZER_H |
@@ -1,18 +0,0 @@ | |||
// | |||
// Created by 庾金科 on 22/09/2017. | |||
// | |||
#ifndef SWIFTPR_FASTDESKEW_H | |||
#define SWIFTPR_FASTDESKEW_H | |||
#include <math.h> | |||
#include <opencv2/opencv.hpp> | |||
namespace pr{ | |||
cv::Mat fastdeskew(cv::Mat skewImage,int blockSize); | |||
// cv::Mat spatialTransformer(cv::Mat skewImage); | |||
}//namepace pr | |||
#endif //SWIFTPR_FASTDESKEW_H |
@@ -1,32 +0,0 @@ | |||
// | |||
// Created by 庾金科 on 22/09/2017. | |||
// | |||
#ifndef SWIFTPR_FINEMAPPING_H | |||
#define SWIFTPR_FINEMAPPING_H | |||
#include <opencv2/opencv.hpp> | |||
#include <opencv2/dnn.hpp> | |||
#include <string> | |||
namespace pr{ | |||
class FineMapping{ | |||
public: | |||
FineMapping(); | |||
FineMapping(std::string prototxt,std::string caffemodel); | |||
static cv::Mat FineMappingVertical(cv::Mat InputProposal,int sliceNum=15,int upper=0,int lower=-50,int windows_size=17); | |||
cv::Mat FineMappingHorizon(cv::Mat FinedVertical,int leftPadding,int rightPadding); | |||
private: | |||
cv::dnn::Net net; | |||
}; | |||
} | |||
#endif //SWIFTPR_FINEMAPPING_H |
@@ -1,60 +0,0 @@ | |||
// | |||
// 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<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 segmentationfree_proto,std::string segmentationfree_caffemodel | |||
); | |||
~PipelinePR(); | |||
std::vector<std::string> plateRes; | |||
std::vector<PlateInfo> RunPiplineAsImage(cv::Mat plateImage,int method); | |||
}; | |||
} | |||
#endif //SWIFTPR_PIPLINE_H |
@@ -1,33 +0,0 @@ | |||
// | |||
// Created by 庾金科 on 20/09/2017. | |||
// | |||
#ifndef SWIFTPR_PLATEDETECTION_H | |||
#define SWIFTPR_PLATEDETECTION_H | |||
#include <opencv2/opencv.hpp> | |||
#include <PlateInfo.h> | |||
#include <vector> | |||
namespace pr{ | |||
class PlateDetection{ | |||
public: | |||
PlateDetection(std::string filename_cascade); | |||
PlateDetection(); | |||
void LoadModel(std::string filename_cascade); | |||
void plateDetectionRough(cv::Mat InputImage,std::vector<pr::PlateInfo> &plateInfos,int min_w=36,int max_w=800); | |||
// std::vector<pr::PlateInfo> plateDetectionRough(cv::Mat InputImage,int min_w= 60,int max_h = 400); | |||
// std::vector<pr::PlateInfo> plateDetectionRoughByMultiScaleEdge(cv::Mat InputImage); | |||
private: | |||
cv::CascadeClassifier cascade; | |||
}; | |||
}// namespace pr | |||
#endif //SWIFTPR_PLATEDETECTION_H |
@@ -1,126 +0,0 @@ | |||
// | |||
// Created by 庾金科 on 20/09/2017. | |||
// | |||
#ifndef SWIFTPR_PLATEINFO_H | |||
#define SWIFTPR_PLATEINFO_H | |||
#include <opencv2/opencv.hpp> | |||
namespace pr { | |||
typedef std::vector<cv::Mat> Character; | |||
enum PlateColor { BLUE, YELLOW, WHITE, GREEN, BLACK,UNKNOWN}; | |||
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>> plateCoding; | |||
float confidence = 0; | |||
PlateInfo(const cv::Mat &plateData, std::string plateName, cv::Rect plateRect, PlateColor plateType) { | |||
licensePlate = plateData; | |||
name = plateName; | |||
ROI = plateRect; | |||
Type = plateType; | |||
} | |||
PlateInfo(const cv::Mat &plateData, cv::Rect plateRect, PlateColor plateType) { | |||
licensePlate = plateData; | |||
ROI = plateRect; | |||
Type = plateType; | |||
} | |||
PlateInfo(const cv::Mat &plateData, cv::Rect plateRect) { | |||
licensePlate = plateData; | |||
ROI = plateRect; | |||
} | |||
PlateInfo() { | |||
} | |||
cv::Mat getPlateImage() { | |||
return licensePlate; | |||
} | |||
void setPlateImage(cv::Mat plateImage){ | |||
licensePlate = plateImage; | |||
} | |||
cv::Rect getPlateRect() { | |||
return ROI; | |||
} | |||
void setPlateRect(cv::Rect plateRect) { | |||
ROI = plateRect; | |||
} | |||
cv::String getPlateName() { | |||
return name; | |||
} | |||
void setPlateName(cv::String plateName) { | |||
name = plateName; | |||
} | |||
int getPlateType() { | |||
return Type; | |||
} | |||
void appendPlateChar(const std::pair<CharType,cv::Mat> &plateChar) | |||
{ | |||
plateChars.push_back(plateChar); | |||
} | |||
void appendPlateCoding(const std::pair<CharType,cv::Mat> &charProb){ | |||
plateCoding.push_back(charProb); | |||
} | |||
// cv::Mat getPlateChars(int id) { | |||
// if(id<PlateChars.size()) | |||
// return PlateChars[id]; | |||
// } | |||
std::string decodePlateNormal(std::vector<std::string> mappingTable) { | |||
std::string decode; | |||
for(auto plate:plateCoding) { | |||
float *prob = (float *)plate.second.data; | |||
if(plate.first == CHINESE) { | |||
decode += mappingTable[std::max_element(prob,prob+31) - prob]; | |||
confidence+=*std::max_element(prob,prob+31); | |||
// std::cout<<*std::max_element(prob,prob+31)<<std::endl; | |||
} | |||
else if(plate.first == LETTER) { | |||
decode += mappingTable[std::max_element(prob+41,prob+65)- prob]; | |||
confidence+=*std::max_element(prob+41,prob+65); | |||
} | |||
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; | |||
confidence/=7; | |||
return decode; | |||
} | |||
private: | |||
cv::Mat licensePlate; | |||
cv::Rect ROI; | |||
std::string name ; | |||
PlateColor Type; | |||
}; | |||
} | |||
#endif //SWIFTPR_PLATEINFO_H |
@@ -1,39 +0,0 @@ | |||
// | |||
// Created by 庾金科 on 16/10/2017. | |||
// | |||
#ifndef SWIFTPR_PLATESEGMENTATION_H | |||
#define SWIFTPR_PLATESEGMENTATION_H | |||
#include "opencv2/opencv.hpp" | |||
#include <opencv2/dnn.hpp> | |||
#include "PlateInfo.h" | |||
namespace pr{ | |||
class PlateSegmentation{ | |||
public: | |||
const int PLATE_NORMAL = 6; | |||
const int PLATE_NORMAL_GREEN = 7; | |||
const int DEFAULT_WIDTH = 20; | |||
PlateSegmentation(std::string phototxt,std::string caffemodel); | |||
PlateSegmentation(){} | |||
void segmentPlatePipline(PlateInfo &plateInfo,int stride,std::vector<cv::Rect> &Char_rects); | |||
void segmentPlateBySlidingWindows(cv::Mat &plateImage,int windowsWidth,int stride,cv::Mat &respones); | |||
void templateMatchFinding(const cv::Mat &respones,int windowsWidth,std::pair<float,std::vector<int>> &candidatePts); | |||
void refineRegion(cv::Mat &plateImage,const std::vector<int> &candidatePts,const int padding,std::vector<cv::Rect> &rects); | |||
void ExtractRegions(PlateInfo &plateInfo,std::vector<cv::Rect> &rects); | |||
cv::Mat classifyResponse(const cv::Mat &cropped); | |||
private: | |||
cv::dnn::Net net; | |||
// RefineRegion() | |||
}; | |||
}//namespace pr | |||
#endif //SWIFTPR_PLATESEGMENTATION_H |
@@ -1,23 +0,0 @@ | |||
// | |||
// Created by 庾金科 on 20/10/2017. | |||
// | |||
#ifndef SWIFTPR_RECOGNIZER_H | |||
#define SWIFTPR_RECOGNIZER_H | |||
#include "PlateInfo.h" | |||
#include "opencv2/dnn.hpp" | |||
namespace pr{ | |||
typedef cv::Mat label; | |||
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); | |||
}; | |||
} | |||
#endif //SWIFTPR_RECOGNIZER_H |
@@ -1,28 +0,0 @@ | |||
// | |||
// 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 |
@@ -1,107 +0,0 @@ | |||
// | |||
// Created by 庾金科 on 26/10/2017. | |||
// | |||
#ifndef SWIFTPR_NIBLACKTHRESHOLD_H | |||
#define SWIFTPR_NIBLACKTHRESHOLD_H | |||
#include <opencv2/opencv.hpp> | |||
using namespace cv; | |||
enum LocalBinarizationMethods{ | |||
BINARIZATION_NIBLACK = 0, //!< Classic Niblack binarization. See @cite Niblack1985 . | |||
BINARIZATION_SAUVOLA = 1, //!< Sauvola's technique. See @cite Sauvola1997 . | |||
BINARIZATION_WOLF = 2, //!< Wolf's technique. See @cite Wolf2004 . | |||
BINARIZATION_NICK = 3 //!< NICK technique. See @cite Khurshid2009 . | |||
}; | |||
void niBlackThreshold( InputArray _src, OutputArray _dst, double maxValue, | |||
int type, int blockSize, double k, int binarizationMethod ) | |||
{ | |||
// Input grayscale image | |||
Mat src = _src.getMat(); | |||
CV_Assert(src.channels() == 1); | |||
CV_Assert(blockSize % 2 == 1 && blockSize > 1); | |||
if (binarizationMethod == BINARIZATION_SAUVOLA) { | |||
CV_Assert(src.depth() == CV_8U); | |||
} | |||
type &= THRESH_MASK; | |||
// Compute local threshold (T = mean + k * stddev) | |||
// using mean and standard deviation in the neighborhood of each pixel | |||
// (intermediate calculations are done with floating-point precision) | |||
Mat test; | |||
Mat thresh; | |||
{ | |||
// note that: Var[X] = E[X^2] - E[X]^2 | |||
Mat mean, sqmean, variance, stddev, sqrtVarianceMeanSum; | |||
double srcMin, stddevMax; | |||
boxFilter(src, mean, CV_32F, Size(blockSize, blockSize), | |||
Point(-1,-1), true, BORDER_REPLICATE); | |||
sqrBoxFilter(src, sqmean, CV_32F, Size(blockSize, blockSize), | |||
Point(-1,-1), true, BORDER_REPLICATE); | |||
variance = sqmean - mean.mul(mean); | |||
sqrt(variance, stddev); | |||
switch (binarizationMethod) | |||
{ | |||
case BINARIZATION_NIBLACK: | |||
thresh = mean + stddev * static_cast<float>(k); | |||
break; | |||
case BINARIZATION_SAUVOLA: | |||
thresh = mean.mul(1. + static_cast<float>(k) * (stddev / 128.0 - 1.)); | |||
break; | |||
case BINARIZATION_WOLF: | |||
minMaxIdx(src, &srcMin,NULL); | |||
minMaxIdx(stddev, NULL, &stddevMax); | |||
thresh = mean - static_cast<float>(k) * (mean - srcMin - stddev.mul(mean - srcMin) / stddevMax); | |||
break; | |||
case BINARIZATION_NICK: | |||
sqrt(variance + sqmean, sqrtVarianceMeanSum); | |||
thresh = mean + static_cast<float>(k) * sqrtVarianceMeanSum; | |||
break; | |||
default: | |||
CV_Error( CV_StsBadArg, "Unknown binarization method" ); | |||
break; | |||
} | |||
thresh.convertTo(thresh, src.depth()); | |||
thresh.convertTo(test, src.depth()); | |||
// | |||
// cv::imshow("imagex",test); | |||
// cv::waitKey(0); | |||
} | |||
// Prepare output image | |||
_dst.create(src.size(), src.type()); | |||
Mat dst = _dst.getMat(); | |||
CV_Assert(src.data != dst.data); // no inplace processing | |||
// Apply thresholding: ( pixel > threshold ) ? foreground : background | |||
Mat mask; | |||
switch (type) | |||
{ | |||
case THRESH_BINARY: // dst = (src > thresh) ? maxval : 0 | |||
case THRESH_BINARY_INV: // dst = (src > thresh) ? 0 : maxval | |||
compare(src, thresh, mask, (type == THRESH_BINARY ? CMP_GT : CMP_LE)); | |||
dst.setTo(0); | |||
dst.setTo(maxValue, mask); | |||
break; | |||
case THRESH_TRUNC: // dst = (src > thresh) ? thresh : src | |||
compare(src, thresh, mask, CMP_GT); | |||
src.copyTo(dst); | |||
thresh.copyTo(dst, mask); | |||
break; | |||
case THRESH_TOZERO: // dst = (src > thresh) ? src : 0 | |||
case THRESH_TOZERO_INV: // dst = (src > thresh) ? 0 : src | |||
compare(src, thresh, mask, (type == THRESH_TOZERO ? CMP_GT : CMP_LE)); | |||
dst.setTo(0); | |||
src.copyTo(dst, mask); | |||
break; | |||
default: | |||
CV_Error( CV_StsBadArg, "Unknown threshold type" ); | |||
break; | |||
} | |||
} | |||
#endif //SWIFTPR_NIBLACKTHRESHOLD_H |
@@ -1,19 +0,0 @@ | |||
// | |||
// Created by 庾金科 on 21/10/2017. | |||
// | |||
#include "CNNRecognizer.h" | |||
namespace pr{ | |||
CNNRecognizer::CNNRecognizer(std::string prototxt,std::string caffemodel){ | |||
net = cv::dnn::readNetFromCaffe(prototxt, caffemodel); | |||
} | |||
label CNNRecognizer::recognizeCharacter(cv::Mat charImage){ | |||
if(charImage.channels()== 3) | |||
cv::cvtColor(charImage,charImage,cv::COLOR_BGR2GRAY); | |||
cv::Mat inputBlob = cv::dnn::blobFromImage(charImage, 1/255.0, cv::Size(CHAR_INPUT_W,CHAR_INPUT_H), cv::Scalar(0,0,0),false); | |||
net.setInput(inputBlob,"data"); | |||
return net.forward(); | |||
} | |||
} |
@@ -1,108 +0,0 @@ | |||
// | |||
// Created by Jack Yu on 02/10/2017. | |||
// | |||
#include "FastDeskew.h" | |||
namespace pr{ | |||
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; | |||
} | |||
std::vector<float> avgfilter(std::vector<float> angle_list,int windowsSize) { | |||
std::vector<float> angle_list_filtered(angle_list.size() - windowsSize + 1); | |||
for (int i = 0; i < angle_list.size() - windowsSize + 1; i++) { | |||
float avg = 0.00f; | |||
for (int j = 0; j < windowsSize; j++) { | |||
avg += angle_list[i + j]; | |||
} | |||
avg = avg / windowsSize; | |||
angle_list_filtered[i] = avg; | |||
} | |||
return angle_list_filtered; | |||
} | |||
void drawHist(std::vector<float> seq){ | |||
cv::Mat image(300,seq.size(),CV_8U); | |||
image.setTo(0); | |||
for(int i = 0;i<seq.size();i++) | |||
{ | |||
float l = *std::max_element(seq.begin(),seq.end()); | |||
int p = int(float(seq[i])/l*300); | |||
cv::line(image,cv::Point(i,300),cv::Point(i,300-p),cv::Scalar(255,255,255)); | |||
} | |||
cv::imshow("vis",image); | |||
} | |||
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; | |||
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); | |||
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 ) | |||
{ | |||
float x2 = eigen.at<cv::Vec6f>(j, i)[4]; | |||
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; | |||
if(maxPos<ANGLE_MIN) | |||
maxPos-=90; | |||
maxPos=90-maxPos; | |||
cv::Mat deskewed = correctPlateImage(bak, static_cast<float>(maxPos),60.0f); | |||
return deskewed; | |||
} | |||
}//namespace pr |
@@ -1,170 +0,0 @@ | |||
#include "FineMapping.h" | |||
namespace pr{ | |||
const int FINEMAPPING_H = 60 ; | |||
const int FINEMAPPING_W = 140; | |||
const int PADDING_UP_DOWN = 30; | |||
void drawRect(cv::Mat image,cv::Rect rect) | |||
{ | |||
cv::Point p1(rect.x,rect.y); | |||
cv::Point p2(rect.x+rect.width,rect.y+rect.height); | |||
cv::rectangle(image,p1,p2,cv::Scalar(0,255,0),1); | |||
} | |||
FineMapping::FineMapping(std::string prototxt,std::string caffemodel) { | |||
net = cv::dnn::readNetFromCaffe(prototxt, caffemodel); | |||
} | |||
cv::Mat FineMapping::FineMappingHorizon(cv::Mat FinedVertical,int leftPadding,int rightPadding) | |||
{ | |||
// if(FinedVertical.channels()==1) | |||
// cv::cvtColor(FinedVertical,FinedVertical,cv::COLOR_GRAY2BGR); | |||
cv::Mat inputBlob = cv::dnn::blobFromImage(FinedVertical, 1/255.0, cv::Size(66,16), | |||
cv::Scalar(0,0,0),false); | |||
net.setInput(inputBlob,"data"); | |||
cv::Mat prob = net.forward(); | |||
int front = static_cast<int>(prob.at<float>(0,0)*FinedVertical.cols); | |||
int back = static_cast<int>(prob.at<float>(0,1)*FinedVertical.cols); | |||
front -= leftPadding ; | |||
if(front<0) front = 0; | |||
back +=rightPadding; | |||
if(back>FinedVertical.cols-1) back=FinedVertical.cols - 1; | |||
cv::Mat cropped = FinedVertical.colRange(front,back).clone(); | |||
return cropped; | |||
} | |||
std::pair<int,int> FitLineRansac(std::vector<cv::Point> pts,int zeroadd = 0 ) | |||
{ | |||
std::pair<int,int> res; | |||
if(pts.size()>2) | |||
{ | |||
cv::Vec4f line; | |||
cv::fitLine(pts,line,cv::DIST_HUBER,0,0.01,0.01); | |||
float vx = line[0]; | |||
float vy = line[1]; | |||
float x = line[2]; | |||
float y = line[3]; | |||
int lefty = static_cast<int>((-x * vy / vx) + y); | |||
int righty = static_cast<int>(((136- x) * vy / vx) + y); | |||
res.first = lefty+PADDING_UP_DOWN+zeroadd; | |||
res.second = righty+PADDING_UP_DOWN+zeroadd; | |||
return res; | |||
} | |||
res.first = zeroadd; | |||
res.second = zeroadd; | |||
return res; | |||
} | |||
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); | |||
// this will improve some sen | |||
cv::Mat kernal = cv::getStructuringElement(cv::MORPH_ELLIPSE,cv::Size(1,3)); | |||
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; | |||
float k =lower + i*diff; | |||
cv::adaptiveThreshold(proposal,binary_adaptive,255,cv::ADAPTIVE_THRESH_MEAN_C,cv::THRESH_BINARY,windows_size,k); | |||
cv::Mat draw; | |||
binary_adaptive.copyTo(draw); | |||
cv::findContours(binary_adaptive,contours,cv::RETR_EXTERNAL,cv::CHAIN_APPROX_SIMPLE); | |||
for(auto contour: contours) | |||
{ | |||
cv::Rect bdbox =cv::boundingRect(contour); | |||
float lwRatio = bdbox.height/static_cast<float>(bdbox.width); | |||
int bdboxAera = bdbox.width*bdbox.height; | |||
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); | |||
line_lower.push_back(p2); | |||
contours_nums+=1; | |||
} | |||
} | |||
} | |||
if(contours_nums<41) | |||
{ | |||
cv::bitwise_not(InputProposal,InputProposal); | |||
cv::Mat kernal = cv::getStructuringElement(cv::MORPH_ELLIPSE,cv::Size(1,5)); | |||
cv::Mat bak; | |||
cv::resize(InputProposal,bak,cv::Size(FINEMAPPING_W,FINEMAPPING_H)); | |||
cv::erode(bak,bak,kernal); | |||
if(InputProposal.channels() == 3) | |||
cv::cvtColor(bak,proposal,cv::COLOR_BGR2GRAY); | |||
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::Mat draw; | |||
binary_adaptive.copyTo(draw); | |||
cv::findContours(binary_adaptive,contours,cv::RETR_EXTERNAL,cv::CHAIN_APPROX_SIMPLE); | |||
for(auto contour: contours) | |||
{ | |||
cv::Rect bdbox =cv::boundingRect(contour); | |||
float lwRatio = bdbox.height/static_cast<float>(bdbox.width); | |||
int bdboxAera = bdbox.width*bdbox.height; | |||
if (( lwRatio>0.7&&bdbox.width*bdbox.height>120 && 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); | |||
line_lower.push_back(p2); | |||
contours_nums+=1; | |||
} | |||
} | |||
} | |||
} | |||
cv::Mat rgb; | |||
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, -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; | |||
std::vector<cv::Point2f> corners(4); | |||
corners[0] = cv::Point2f(cols - 1, rightyA); | |||
corners[1] = cv::Point2f(0, leftyA); | |||
corners[2] = cv::Point2f(cols - 1, rightyB); | |||
corners[3] = cv::Point2f(0, leftyB); | |||
std::vector<cv::Point2f> corners_trans(4); | |||
corners_trans[0] = cv::Point2f(136, 36); | |||
corners_trans[1] = cv::Point2f(0, 36); | |||
corners_trans[2] = cv::Point2f(136, 0); | |||
corners_trans[3] = cv::Point2f(0, 0); | |||
cv::Mat transform = cv::getPerspectiveTransform(corners, corners_trans); | |||
cv::Mat quad = cv::Mat::zeros(36, 136, CV_8UC3); | |||
cv::warpPerspective(rgb, quad, transform, quad.size()); | |||
return quad; | |||
} | |||
} | |||
@@ -1,101 +0,0 @@ | |||
// | |||
// Created by 庾金科 on 23/10/2017. | |||
// | |||
#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)); | |||
// cv::imshow("image_finemapping",image_finemapping); | |||
// cv::waitKey(0); | |||
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)); | |||
// 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); | |||
} | |||
results.push_back(plateinfo); | |||
} | |||
// for (auto str:results) { | |||
// std::cout << str << std::endl; | |||
// } | |||
return results; | |||
}//namespace pr | |||
} |
@@ -1,32 +0,0 @@ | |||
#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); | |||
std::vector<cv::Rect> platesRegions; | |||
cv::Size minSize(min_w,min_w/4); | |||
cv::Size maxSize(max_w,max_w/4); | |||
cascade.detectMultiScale( processImage, platesRegions, | |||
1.1, 3, cv::CASCADE_SCALE_IMAGE,minSize,maxSize); | |||
for(auto plate:platesRegions) | |||
{ | |||
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; | |||
plate.width += zeroadd_w; | |||
cv::Mat plateImage = util::cropFromImage(InputImage,plate); | |||
PlateInfo plateInfo(plateImage,plate); | |||
plateInfos.push_back(plateInfo); | |||
} | |||
} | |||
}//namespace pr |
@@ -1,404 +0,0 @@ | |||
// | |||
// Created by 庾金科 on 16/10/2017. | |||
// | |||
#include "PlateSegmentation.h" | |||
#include "niBlackThreshold.h" | |||
//#define DEBUG | |||
namespace pr{ | |||
PlateSegmentation::PlateSegmentation(std::string prototxt,std::string caffemodel) { | |||
net = cv::dnn::readNetFromCaffe(prototxt, caffemodel); | |||
} | |||
cv::Mat PlateSegmentation::classifyResponse(const cv::Mat &cropped){ | |||
cv::Mat inputBlob = cv::dnn::blobFromImage(cropped, 1/255.0, cv::Size(22,22), cv::Scalar(0,0,0),false); | |||
net.setInput(inputBlob,"data"); | |||
return net.forward(); | |||
} | |||
void drawHist(float* seq,int size,const char* name){ | |||
cv::Mat image(300,size,CV_8U); | |||
image.setTo(0); | |||
float* start =seq; | |||
float* end = seq+size; | |||
float l = *std::max_element(start,end); | |||
for(int i = 0;i<size;i++) | |||
{ | |||
int p = int(float(seq[i])/l*300); | |||
cv::line(image,cv::Point(i,300),cv::Point(i,300-p),cv::Scalar(255,255,255)); | |||
} | |||
cv::resize(image,image,cv::Size(600,100)); | |||
cv::imshow(name,image); | |||
} | |||
inline void computeSafeMargin(int &val,const int &rows){ | |||
val = std::min(val,rows); | |||
val = std::max(val,0); | |||
} | |||
cv::Rect boxFromCenter(const cv::Point center,int left,int right,int top,int bottom,cv::Size bdSize) | |||
{ | |||
cv::Point p1(center.x - left ,center.y - top); | |||
cv::Point p2( center.x + right, center.y + bottom); | |||
p1.x = std::max(0,p1.x); | |||
p1.y = std::max(0,p1.y); | |||
p2.x = std::min(p2.x,bdSize.width-1); | |||
p2.y = std::min(p2.y,bdSize.height-1); | |||
cv::Rect rect(p1,p2); | |||
return rect; | |||
} | |||
cv::Rect boxPadding(cv::Rect rect,int left,int right,int top,int bottom,cv::Size bdSize) | |||
{ | |||
cv::Point center(rect.x+(rect.width>>1),rect.y + (rect.height>>1)); | |||
int rebuildLeft = (rect.width>>1 )+ left; | |||
int rebuildRight = (rect.width>>1 )+ right; | |||
int rebuildTop = (rect.height>>1 )+ top; | |||
int rebuildBottom = (rect.height>>1 )+ bottom; | |||
return boxFromCenter(center,rebuildLeft,rebuildRight,rebuildTop,rebuildBottom,bdSize); | |||
} | |||
void PlateSegmentation:: refineRegion(cv::Mat &plateImage,const std::vector<int> &candidatePts,const int padding,std::vector<cv::Rect> &rects){ | |||
int w = candidatePts[5] - candidatePts[4]; | |||
int cols = plateImage.cols; | |||
int rows = plateImage.rows; | |||
for(int i = 0 ; i < candidatePts.size() ; i++) | |||
{ | |||
int left = 0; | |||
int right = 0 ; | |||
if(i == 0 ){ | |||
left= candidatePts[i]; | |||
right = left+w+padding; | |||
} | |||
else { | |||
left = candidatePts[i] - padding; | |||
right = left + w + padding * 2; | |||
} | |||
computeSafeMargin(right,cols); | |||
computeSafeMargin(left,cols); | |||
cv::Rect roi(left,0,right - left,rows-1); | |||
cv::Mat roiImage; | |||
plateImage(roi).copyTo(roiImage); | |||
if (i>=1) | |||
{ | |||
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.27,BINARIZATION_NIBLACK); | |||
std::vector<std::vector<cv::Point>> contours; | |||
cv::findContours(roi_thres,contours,cv::RETR_LIST,cv::CHAIN_APPROX_SIMPLE); | |||
cv::Point boxCenter(roiImage.cols>>1,roiImage.rows>>1); | |||
cv::Rect final_bdbox; | |||
cv::Point final_center; | |||
int final_dist = INT_MAX; | |||
for(auto contour:contours) | |||
{ | |||
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 and bdbox.height > rows>>1) | |||
{ final_dist =dist; | |||
final_center = center; | |||
final_bdbox = bdbox; | |||
} | |||
} | |||
//rebuild box | |||
if(final_bdbox.height/ static_cast<float>(final_bdbox.width) > 3.5 && final_bdbox.width*final_bdbox.height<10) | |||
final_bdbox = boxFromCenter(final_center,8,8,(rows>>1)-3 , (rows>>1) - 2,roiImage.size()); | |||
else { | |||
if(i == candidatePts.size()-1) | |||
final_bdbox = boxPadding(final_bdbox, padding/2, padding, padding/2, padding/2, roiImage.size()); | |||
else | |||
final_bdbox = boxPadding(final_bdbox, padding, padding, padding, padding, roiImage.size()); | |||
// std::cout<<final_bdbox<<std::endl; | |||
// std::cout<<roiImage.size()<<std::endl; | |||
#ifdef DEBUG | |||
cv::imshow("char_thres",roi_thres); | |||
cv::imshow("char",roiImage(final_bdbox)); | |||
cv::waitKey(0); | |||
#endif | |||
} | |||
final_bdbox.x += left; | |||
rects.push_back(final_bdbox); | |||
// | |||
} | |||
else | |||
{ | |||
rects.push_back(roi); | |||
} | |||
// else | |||
// { | |||
// | |||
// } | |||
// cv::GaussianBlur(roiImage,roiImage,cv::Size(7,7),3); | |||
// | |||
// cv::imshow("image",roiImage); | |||
// cv::waitKey(0); | |||
} | |||
} | |||
void avgfilter(float *angle_list,int size,int windowsSize) { | |||
float *filterd = new float[size]; | |||
for(int i = 0 ; i < size ; i++) filterd [i] = angle_list[i]; | |||
// memcpy(filterd,angle_list,size); | |||
cv::Mat kernal_gaussian = cv::getGaussianKernel(windowsSize,3,CV_32F); | |||
float *kernal = (float*)kernal_gaussian.data; | |||
// kernal+=windowsSize; | |||
int r = windowsSize/2; | |||
for (int i = 0; i < size; i++) { | |||
float avg = 0.00f; | |||
for (int j = 0; j < windowsSize; j++) { | |||
if(i+j-r>0&&i+j+r<size-1) | |||
avg += filterd[i + j-r]*kernal[j]; | |||
} | |||
// avg = avg / windowsSize; | |||
angle_list[i] = avg; | |||
} | |||
delete filterd; | |||
} | |||
void PlateSegmentation::templateMatchFinding(const cv::Mat &respones,int windowsWidth,std::pair<float,std::vector<int>> &candidatePts){ | |||
int rows = respones.rows; | |||
int cols = respones.cols; | |||
float *data = (float*)respones.data; | |||
float *engNum_prob = data; | |||
float *false_prob = data+cols; | |||
float *ch_prob = data+cols*2; | |||
avgfilter(engNum_prob,cols,5); | |||
avgfilter(false_prob,cols,5); | |||
// avgfilter(ch_prob,cols,5); | |||
std::vector<int> candidate_pts(7); | |||
#ifdef DEBUG | |||
drawHist(engNum_prob,cols,"engNum_prob"); | |||
drawHist(false_prob,cols,"false_prob"); | |||
drawHist(ch_prob,cols,"ch_prob"); | |||
cv::waitKey(0); | |||
#endif | |||
int cp_list[7]; | |||
float loss_selected = -10; | |||
for(int start = 0 ; start < 20 ; start+=2) | |||
for(int width = windowsWidth-5; width < windowsWidth+5 ; width++ ){ | |||
for(int interval = windowsWidth/2; interval < windowsWidth; interval++) | |||
{ | |||
int cp1_ch = start; | |||
int cp2_p0 = cp1_ch+ width; | |||
int cp3_p1 = cp2_p0+ width + interval; | |||
int cp4_p2 = cp3_p1 + width; | |||
int cp5_p3 = cp4_p2 + width+1; | |||
int cp6_p4 = cp5_p3 + width+2; | |||
int cp7_p5= cp6_p4+ width+2; | |||
int md1 = (cp1_ch+cp2_p0)>>1; | |||
int md2 = (cp2_p0+cp3_p1)>>1; | |||
int md3 = (cp3_p1+cp4_p2)>>1; | |||
int md4 = (cp4_p2+cp5_p3)>>1; | |||
int md5 = (cp5_p3+cp6_p4)>>1; | |||
int md6 = (cp6_p4+cp7_p5)>>1; | |||
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]); | |||
if(loss>loss_selected) | |||
{ | |||
loss_selected = loss; | |||
cp_list[0]= cp1_ch; | |||
cp_list[1]= cp2_p0; | |||
cp_list[2]= cp3_p1; | |||
cp_list[3]= cp4_p2; | |||
cp_list[4]= cp5_p3; | |||
cp_list[5]= cp6_p4; | |||
cp_list[6]= cp7_p5; | |||
} | |||
} | |||
} | |||
candidate_pts[0] = cp_list[0]; | |||
candidate_pts[1] = cp_list[1]; | |||
candidate_pts[2] = cp_list[2]; | |||
candidate_pts[3] = cp_list[3]; | |||
candidate_pts[4] = cp_list[4]; | |||
candidate_pts[5] = cp_list[5]; | |||
candidate_pts[6] = cp_list[6]; | |||
candidatePts.first = loss_selected; | |||
candidatePts.second = candidate_pts; | |||
}; | |||
void PlateSegmentation::segmentPlateBySlidingWindows(cv::Mat &plateImage,int windowsWidth,int stride,cv::Mat &respones){ | |||
// 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 - padding; | |||
for(int i = 0 ; i < width - windowsWidth +1 ; i +=stride) | |||
{ | |||
cv::Rect roi(i,0,windowsWidth,height); | |||
cv::Mat roiImage = plateImageGray(roi); | |||
cv::Mat response = classifyResponse(roiImage); | |||
respones.push_back(response); | |||
} | |||
respones = respones.t(); | |||
// std::pair<float,std::vector<int>> images ; | |||
// | |||
// | |||
// std::cout<<images.first<<" "; | |||
// for(int i = 0 ; i < images.second.size() ; i++) | |||
// { | |||
// std::cout<<images.second[i]<<" "; | |||
//// cv::line(plateImageGray,cv::Point(images.second[i],0),cv::Point(images.second[i],36),cv::Scalar(255,255,255),1); //DEBUG | |||
// } | |||
// int w = images.second[5] - images.second[4]; | |||
// cv::line(plateImageGray,cv::Point(images.second[5]+w,0),cv::Point(images.second[5]+w,36),cv::Scalar(255,255,255),1); //DEBUG | |||
// cv::line(plateImageGray,cv::Point(images.second[5]+2*w,0),cv::Point(images.second[5]+2*w,36),cv::Scalar(255,255,255),1); //DEBUG | |||
// RefineRegion(plateImageGray,images.second,5); | |||
// std::cout<<w<<std::endl; | |||
// std::cout<<<<std::endl; | |||
// cv::resize(plateImageGray,plateImageGray,cv::Size(600,100)); | |||
} | |||
// void filterGaussian(cv::Mat &respones,float sigma){ | |||
// | |||
// } | |||
void PlateSegmentation::segmentPlatePipline(PlateInfo &plateInfo,int stride,std::vector<cv::Rect> &Char_rects){ | |||
cv::Mat plateImage = plateInfo.getPlateImage(); // get src image . | |||
cv::Mat plateImageGray; | |||
cv::cvtColor(plateImage,plateImageGray,cv::COLOR_BGR2GRAY); | |||
//do binarzation | |||
// | |||
std::pair<float,std::vector<int>> sections ; // segment points variables . | |||
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; | |||
refineRegion(plateImageGray,sections.second,5,Char_rects); | |||
#ifdef DEBUG | |||
for(int i = 0 ; i < sections.second.size() ; i++) | |||
{ | |||
std::cout<<sections.second[i]<<" "; | |||
cv::line(plateImageGray,cv::Point(sections.second[i],0),cv::Point(sections.second[i],36),cv::Scalar(255,255,255),1); //DEBUG | |||
} | |||
cv::imshow("plate",plateImageGray); | |||
cv::waitKey(0); | |||
#endif | |||
// cv::waitKey(0); | |||
} | |||
void PlateSegmentation::ExtractRegions(PlateInfo &plateInfo,std::vector<cv::Rect> &rects){ | |||
cv::Mat plateImage = plateInfo.getPlateImage(); | |||
for(int i = 0 ; i < rects.size() ; i++){ | |||
cv::Mat charImage; | |||
plateImage(rects[i]).copyTo(charImage); | |||
if(charImage.channels()) | |||
cv::cvtColor(charImage,charImage,cv::COLOR_BGR2GRAY); | |||
// cv::imshow("image",charImage); | |||
// cv::waitKey(0); | |||
cv::equalizeHist(charImage,charImage); | |||
// | |||
// | |||
std::pair<CharType,cv::Mat> char_instance; | |||
if(i == 0 ){ | |||
char_instance.first = CHINESE; | |||
} else if(i == 1){ | |||
char_instance.first = LETTER; | |||
} | |||
else{ | |||
char_instance.first = LETTER_NUMS; | |||
} | |||
char_instance.second = charImage; | |||
plateInfo.appendPlateChar(char_instance); | |||
} | |||
} | |||
}//namespace pr |
@@ -1,23 +0,0 @@ | |||
// | |||
// Created by Jack Yu on 22/10/2017. | |||
// | |||
#include "Recognizer.h" | |||
namespace pr{ | |||
void GeneralRecognizer::SegmentBasedSequenceRecognition(PlateInfo &plateinfo){ | |||
for(auto char_instance:plateinfo.plateChars) | |||
{ | |||
std::pair<CharType,cv::Mat> 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); | |||
} | |||
} | |||
} | |||
} |
@@ -1,89 +0,0 @@ | |||
// | |||
// Created by Jack Yu on 28/11/2017. | |||
// | |||
#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); | |||
} | |||
} |
@@ -1,67 +0,0 @@ | |||
// | |||
// 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){ | |||
int w = image.cols-1; | |||
int h = image.rows-1; | |||
rect.x = std::max(rect.x,0); | |||
rect.y = std::max(rect.y,0); | |||
rect.height = std::min(rect.height,h-rect.y); | |||
rect.width = std::min(rect.width,w-rect.x); | |||
cv::Mat temp(rect.size(), image.type()); | |||
cv::Mat cropped; | |||
temp = image(rect); | |||
temp.copyTo(cropped); | |||
return cropped; | |||
} | |||
cv::Mat cropBox2dFromImage(const cv::Mat &image,cv::RotatedRect rect) | |||
{ | |||
cv::Mat M, rotated, cropped; | |||
float angle = rect.angle; | |||
cv::Size rect_size(rect.size.width,rect.size.height); | |||
if (rect.angle < -45.) { | |||
angle += 90.0; | |||
swap(rect_size.width, rect_size.height); | |||
} | |||
M = cv::getRotationMatrix2D(rect.center, angle, 1.0); | |||
cv::warpAffine(image, rotated, M, image.size(), cv::INTER_CUBIC); | |||
cv::getRectSubPix(rotated, rect_size, rect.center, cropped); | |||
return cropped; | |||
} | |||
cv::Mat calcHist(const cv::Mat &image) | |||
{ | |||
cv::Mat hsv; | |||
std::vector<cv::Mat> hsv_planes; | |||
cv::cvtColor(image,hsv,cv::COLOR_BGR2HSV); | |||
cv::split(hsv,hsv_planes); | |||
cv::Mat hist; | |||
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); | |||
} | |||
}//namespace util |
@@ -1,107 +0,0 @@ | |||
// | |||
// Created by Coleflowers on 20/06/2018. | |||
// Updated by Justid on 02/07/2018. | |||
// | |||
#include <phpcpp.h> | |||
#include <iostream> | |||
#include "PlateSegmentation.h" | |||
#include "CNNRecognizer.h" | |||
#include "Recognizer.h" | |||
#include "PlateDetection.h" | |||
#include "FastDeskew.h" | |||
#include "FineMapping.h" | |||
#include "Pipeline.h" | |||
/* 关闭原opencv报错输出 */ | |||
int handleError( int status, const char* func_name, | |||
const char* err_msg, const char* file_name, | |||
int line, void* userdata ) | |||
{ | |||
//Do nothing -- will suppress console output | |||
return 0; //Return value is not used | |||
} | |||
/** | |||
* 车牌图片识别 | |||
* @params imgpath 图片的绝对路径 | |||
* @params modelpath 识别模型所在文件夹路径 | |||
* @params confidence 可信度要求,可选参数,默认值0.75 | |||
* @return 车牌号 图片路径的图片不存在的话 返回空值 | |||
*/ | |||
cv::String scan(std::string imgpath, std::string modelpath, double confidence){ | |||
cv::redirectError(handleError); | |||
try { | |||
pr::PipelinePR prc(modelpath+"/cascade.xml", | |||
modelpath+"/HorizonalFinemapping.prototxt",modelpath+"/HorizonalFinemapping.caffemodel", | |||
modelpath+"/Segmentation.prototxt",modelpath+"/Segmentation.caffemodel", | |||
modelpath+"/CharacterRecognization.prototxt",modelpath+"/CharacterRecognization.caffemodel", | |||
modelpath+"/SegmenationFree-Inception.prototxt",modelpath+"/SegmenationFree-Inception.caffemodel" | |||
); | |||
cv::Mat image = cv::imread(imgpath); | |||
std::vector<pr::PlateInfo> res = prc.RunPiplineAsImage(image,pr::SEGMENTATION_FREE_METHOD); | |||
cv::String platenum = ""; | |||
for(auto st:res) { | |||
if(st.confidence>confidence) { | |||
platenum = st.getPlateName(); | |||
break; | |||
} | |||
} | |||
return platenum; | |||
} | |||
catch( cv::Exception& e ) | |||
{ | |||
const char* err_msg = e.what(); | |||
throw Php::Exception(err_msg); | |||
} | |||
} | |||
Php::Value funcWrapper(Php::Parameters ¶ms) { | |||
// 图片路径 | |||
std::string img = params[0]; | |||
// 模型路径(文件夹) | |||
std::string model = params[1]; | |||
// 可信度要求 | |||
double confidence = 0.75; | |||
if (params.size() == 3){ | |||
confidence = (double)params[2]; | |||
} | |||
cv::String res = scan(img, model, confidence); | |||
return res.c_str(); | |||
} | |||
/** | |||
* tell the compiler that the get_module is a pure C function | |||
*/ | |||
extern "C" { | |||
/** | |||
* Function that is called by PHP right after the PHP process | |||
* has started, and that returns an address of an internal PHP | |||
* strucure with all the details and features of your extension | |||
* | |||
* @return void* a pointer to an address that is understood by PHP | |||
*/ | |||
PHPCPP_EXPORT void *get_module() { | |||
// static(!) Php::Extension object that should stay in memory | |||
// for the entire duration of the process (that's why it's static) | |||
static Php::Extension extension("platescan", "1.0"); | |||
// @todo add your own functions, classes, namespaces to the extension | |||
extension.add<funcWrapper>("platescan", { | |||
Php::ByVal("imgpath", Php::Type::String, true), | |||
Php::ByVal("modelpath", Php::Type::String, true), | |||
Php::ByVal("confidence", Php::Type::Float, false) | |||
}); | |||
// return the extension | |||
return extension; | |||
} | |||
} |
@@ -1,2 +0,0 @@ | |||
extension=platescan.so | |||
@@ -1,21 +0,0 @@ | |||
将/Prj-Linux/lpr/model目录下的 | |||
cascade.xml | |||
CharacterRecognization.caffemodel | |||
CharacterRecognization.prototxt | |||
HorizonalFinemapping.caffemodel | |||
HorizonalFinemapping.prototxt | |||
SegmenationFree-Inception.caffemodel | |||
SegmenationFree-Inception.prototxt | |||
Segmentation.caffemodel | |||
Segmentation.prototxt | |||
放置在该目录 |
@@ -1,13 +0,0 @@ | |||
<?php | |||
// | |||
// Created by Coleflowers on 20/06/2018. | |||
// Updated by JustID on 03/07/2018. | |||
// | |||
/** | |||
* 车牌识别PHP扩展程序测试 | |||
*/ | |||
$res = platescan(realpath("demo.png"),realpath("model"),0.8); | |||
var_dump($res); | |||
?> |
@@ -22,18 +22,18 @@ namespace pr | |||
PlateDetection *platedetection; | |||
FineTune *finetune; | |||
PlateRecognation *platerecognation; | |||
//PlateColorClass *platecolorclass; | |||
DBDetection *dbdetection; | |||
PipelinePR(std::string detect_prototxt, std::string detect_caffemodel, | |||
std::string finetune_prototxt, std::string finetune_caffemodel, | |||
std::string platerec_prototxt, std::string platerec_caffemodel/*, | |||
std::string platecolor_mnn*/); | |||
std::string platerec_prototxt, std::string platerec_caffemodel, | |||
std::string dbstring); | |||
~PipelinePR(); | |||
std::vector<std::string> plateRes; | |||
std::vector<PlateInfo> RunPiplineAsImage(cv::Mat srcImage); | |||
std::vector<PlateInfo> RunPiplineAsImage(cv::Mat srcImage,int IsDB); | |||
}; | |||
} |
@@ -12,5 +12,12 @@ namespace pr | |||
private: | |||
cv::dnn::Net ssdNet; | |||
}; | |||
class DBDetection{ | |||
public: | |||
DBDetection(std::string cascadestring); | |||
void DBDetect(cv::Mat inputImg,std::vector<pr::PlateInfo> &plateInfos,int min_w,int max_w); | |||
private: | |||
cv::CascadeClassifier dbcascade; | |||
}; | |||
}//namespace pr | |||
#endif // !_PLATEDETECT_H_ |
@@ -0,0 +1,504 @@ | |||
<?xml version="1.0"?> | |||
<opencv_storage> | |||
<cascade> | |||
<stageType>BOOST</stageType> | |||
<featureType>LBP</featureType> | |||
<height>24</height> | |||
<width>44</width> | |||
<stageParams> | |||
<boostType>GAB</boostType> | |||
<minHitRate>9.9599999189376831e-01</minHitRate> | |||
<maxFalseAlarm>5.0000000000000000e-01</maxFalseAlarm> | |||
<weightTrimRate>9.4999999999999996e-01</weightTrimRate> | |||
<maxDepth>1</maxDepth> | |||
<maxWeakCount>28</maxWeakCount></stageParams> | |||
<featureParams> | |||
<maxCatCount>256</maxCatCount> | |||
<featSize>1</featSize></featureParams> | |||
<stageNum>11</stageNum> | |||
<stages> | |||
<!-- stage 0 --> | |||
<_> | |||
<maxWeakCount>3</maxWeakCount> | |||
<stageThreshold>-1.1049392223358154e+00</stageThreshold> | |||
<weakClassifiers> | |||
<_> | |||
<internalNodes> | |||
0 -1 17 -3334 -513 -573452048 -1057 -1 -267777 -1 -1025</internalNodes> | |||
<leafValues> | |||
-9.4297146797180176e-01 7.8370976448059082e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 36 -262198 -12062208 -169869377 -674954752 -7602177 | |||
-16781941 -67109937 -1073</internalNodes> | |||
<leafValues> | |||
-8.8537323474884033e-01 7.2940820455551147e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 9 1431697887 1431687647 -545270049 -262145 1413609965 | |||
1364250775 -1065985 -67108865</internalNodes> | |||
<leafValues> | |||
-8.3008646965026855e-01 7.2340542078018188e-01</leafValues></_></weakClassifiers></_> | |||
<!-- stage 1 --> | |||
<_> | |||
<maxWeakCount>3</maxWeakCount> | |||
<stageThreshold>-1.0404651165008545e+00</stageThreshold> | |||
<weakClassifiers> | |||
<_> | |||
<internalNodes> | |||
0 -1 19 -524289 -136314913 1360393719 -2097153 -134219777 | |||
-4194817 274068735 -1</internalNodes> | |||
<leafValues> | |||
-8.5476654767990112e-01 8.4671354293823242e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 29 -16515073 -150929664 -1 -8650881 -8388609 -11403265 | |||
-1 -2097153</internalNodes> | |||
<leafValues> | |||
-7.7620923519134521e-01 7.8929436206817627e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 1 2013233135 2147450879 -45760593 2147474943 2146959359 | |||
2104754047 2080374783 2147417087</internalNodes> | |||
<leafValues> | |||
-8.9144438505172729e-01 5.9051072597503662e-01</leafValues></_></weakClassifiers></_> | |||
<!-- stage 2 --> | |||
<_> | |||
<maxWeakCount>3</maxWeakCount> | |||
<stageThreshold>-1.1397969722747803e+00</stageThreshold> | |||
<weakClassifiers> | |||
<_> | |||
<internalNodes> | |||
0 -1 15 -1041 -8225 -546308113 -1 -33554433 -394753 -2359297 | |||
-1</internalNodes> | |||
<leafValues> | |||
-8.5447394847869873e-01 7.4388968944549561e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 27 -1053970 -17 -35651601 -1048625 -345331574 -5247030 | |||
-74453009 -1</internalNodes> | |||
<leafValues> | |||
-8.6756819486618042e-01 6.3549250364303589e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 43 -1050897 -1025 -71304209 -134219793 -1033 -559948801 | |||
-67110929 1996976642</internalNodes> | |||
<leafValues> | |||
-8.6068797111511230e-01 5.8224511146545410e-01</leafValues></_></weakClassifiers></_> | |||
<!-- stage 3 --> | |||
<_> | |||
<maxWeakCount>3</maxWeakCount> | |||
<stageThreshold>-9.8026764392852783e-01</stageThreshold> | |||
<weakClassifiers> | |||
<_> | |||
<internalNodes> | |||
0 -1 12 -1077953601 -1 -1073758273 -16387 -147457 -1 | |||
-1073758209 -1</internalNodes> | |||
<leafValues> | |||
-8.2477015256881714e-01 7.1671992540359497e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 47 -4345 -989855745 -271062524 -319815697 -134742265 | |||
1423962843 -134218173 -1</internalNodes> | |||
<leafValues> | |||
-7.4230498075485229e-01 7.3275351524353027e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 37 -22347778 -3477554 -33554433 -2066 -9438209 -65537 | |||
-1 -1048577</internalNodes> | |||
<leafValues> | |||
-8.3125960826873779e-01 5.8680748939514160e-01</leafValues></_></weakClassifiers></_> | |||
<!-- stage 4 --> | |||
<_> | |||
<maxWeakCount>5</maxWeakCount> | |||
<stageThreshold>-1.2986627817153931e+00</stageThreshold> | |||
<weakClassifiers> | |||
<_> | |||
<internalNodes> | |||
0 -1 4 -8388737 -262273 -10485761 -137 -8388745 -129 -262273 | |||
-1</internalNodes> | |||
<leafValues> | |||
-8.7727063894271851e-01 6.1173391342163086e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 20 -1 -10241 1431688703 -1 -1 -1042 1163263999 | |||
2002780159</internalNodes> | |||
<leafValues> | |||
-8.2954949140548706e-01 5.9151750802993774e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 3 -44786212 -33726467 -268509185 -17409 -657175332 | |||
-2270500 -1198986500 -1148450934</internalNodes> | |||
<leafValues> | |||
-7.6026451587677002e-01 5.8319890499114990e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 28 -15794258 -78643282 -821817846 -552742962 -653344834 | |||
-91750417 -1622147105 -7340065</internalNodes> | |||
<leafValues> | |||
-7.6077878475189209e-01 5.5891805887222290e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 30 1427232247 357954767 1971310559 2012602108 | |||
-202375953 -44049 -4456789 -18</internalNodes> | |||
<leafValues> | |||
-6.7643576860427856e-01 6.0950380563735962e-01</leafValues></_></weakClassifiers></_> | |||
<!-- stage 5 --> | |||
<_> | |||
<maxWeakCount>5</maxWeakCount> | |||
<stageThreshold>-1.3029408454895020e+00</stageThreshold> | |||
<weakClassifiers> | |||
<_> | |||
<internalNodes> | |||
0 -1 39 -134218753 -1 -1 -202899593 -1 -4194305 -67108865 | |||
-527497</internalNodes> | |||
<leafValues> | |||
-7.5626724958419800e-01 7.5137990713119507e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 6 -8388737 -8388737 -1 -1 -8421505 -129 -8388737 -1</internalNodes> | |||
<leafValues> | |||
-7.7118909358978271e-01 6.3570922613143921e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 45 -825233914 -654313761 -589830738 -35651585 -16778427 | |||
-83886281 -151000316 -1056964737</internalNodes> | |||
<leafValues> | |||
-7.2490030527114868e-01 5.7298541069030762e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 18 2002780159 2136866815 -67109377 -19969 2147344383 | |||
2101472763 2108680957 2147450607</internalNodes> | |||
<leafValues> | |||
-8.5162043571472168e-01 4.5608481764793396e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 16 -7472470 -3505654 -29841 -65536 -1166086177 | |||
-67109121 -288690177 -32085</internalNodes> | |||
<leafValues> | |||
-7.9073858261108398e-01 5.0315058231353760e-01</leafValues></_></weakClassifiers></_> | |||
<!-- stage 6 --> | |||
<_> | |||
<maxWeakCount>5</maxWeakCount> | |||
<stageThreshold>-1.3164747953414917e+00</stageThreshold> | |||
<weakClassifiers> | |||
<_> | |||
<internalNodes> | |||
0 -1 41 -1 -1025 -1 -2228225 -8432299 -571189899 -139265 -1</internalNodes> | |||
<leafValues> | |||
-7.8127676248550415e-01 6.5899217128753662e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 2 -34275329 -198665 -2113 -12289 -573243396 -590292744 | |||
-1049857 -277</internalNodes> | |||
<leafValues> | |||
-7.3563832044601440e-01 6.3897633552551270e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 14 -1565523969 -1347420193 -277086209 -1342177313 | |||
-134217729 -263169 -285212673 -1459618305</internalNodes> | |||
<leafValues> | |||
-8.1234931945800781e-01 4.9628043174743652e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 33 -1079312417 -83826176 -33686017 -570426508 | |||
-1627464961 -5377 -277761 -17</internalNodes> | |||
<leafValues> | |||
-7.0463657379150391e-01 5.2093976736068726e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 25 -66 -4116 1607291240 -5298489 -9847160 2011036101 | |||
357852669 1476259327</internalNodes> | |||
<leafValues> | |||
-8.2066470384597778e-01 4.9184983968734741e-01</leafValues></_></weakClassifiers></_> | |||
<!-- stage 7 --> | |||
<_> | |||
<maxWeakCount>5</maxWeakCount> | |||
<stageThreshold>-1.1098697185516357e+00</stageThreshold> | |||
<weakClassifiers> | |||
<_> | |||
<internalNodes> | |||
0 -1 44 -134217949 -167773185 -404750589 -1 -134744525 | |||
-1846018321 -2097357 -1</internalNodes> | |||
<leafValues> | |||
-7.6240319013595581e-01 6.8946647644042969e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 7 -12633797 -524321 1058880319 -129 -50790401 -262405 | |||
-1075052545 -5</internalNodes> | |||
<leafValues> | |||
-7.1431988477706909e-01 6.2125796079635620e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 24 -144703501 -10486797 -134217729 -136317057 | |||
-271646721 -174069583 -168952849 -1072726014</internalNodes> | |||
<leafValues> | |||
-6.5710061788558960e-01 6.1531358957290649e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 38 -134218774 -149487872 -33554433 -537927872 -69209089 | |||
-145228029 -2360849 -524449</internalNodes> | |||
<leafValues> | |||
-7.3570650815963745e-01 4.9681660532951355e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 5 -136380419 -8390657 -2228225 -196707 1565810157 | |||
2147048386 -268702725 2080373485</internalNodes> | |||
<leafValues> | |||
-7.2735637426376343e-01 5.2713739871978760e-01</leafValues></_></weakClassifiers></_> | |||
<!-- stage 8 --> | |||
<_> | |||
<maxWeakCount>5</maxWeakCount> | |||
<stageThreshold>-2.0547957420349121e+00</stageThreshold> | |||
<weakClassifiers> | |||
<_> | |||
<internalNodes> | |||
0 -1 13 -11141121 -44695553 -1 -11144193 -9217 -321 | |||
-335811841 -4216577</internalNodes> | |||
<leafValues> | |||
-7.3916637897491455e-01 6.7595410346984863e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 26 -369104657 -4194321 -1061429013 -67114529 -251662085 | |||
-138412033 3334395 -234882305</internalNodes> | |||
<leafValues> | |||
-6.9217604398727417e-01 5.4744583368301392e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 11 1373590751 1373632511 -262169 -33859589 -572533249 | |||
-572524625 -135266305 -32833</internalNodes> | |||
<leafValues> | |||
-7.1100026369094849e-01 5.3469187021255493e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 23 -3148053 -1054802 -1 -5 -7340125 -3689942 -74448917 | |||
-687087094</internalNodes> | |||
<leafValues> | |||
-5.6383520364761353e-01 6.3540917634963989e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 8 245501180 -1615197700 -46219265 -1075925028 | |||
-307580929 -373826 -1076187139 -1343746644</internalNodes> | |||
<leafValues> | |||
-5.8823972940444946e-01 6.1824375391006470e-01</leafValues></_></weakClassifiers></_> | |||
<!-- stage 9 --> | |||
<_> | |||
<maxWeakCount>6</maxWeakCount> | |||
<stageThreshold>-1.6300759315490723e+00</stageThreshold> | |||
<weakClassifiers> | |||
<_> | |||
<internalNodes> | |||
0 -1 42 -1 -4129 -8193 -135795737 -1 -6417 -1 -137887866</internalNodes> | |||
<leafValues> | |||
-7.7990013360977173e-01 6.1912822723388672e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 31 -12845643 -1934361103 -581837313 -1644167171 | |||
-1175537153 -1392516625 -1681655299 -1358963807</internalNodes> | |||
<leafValues> | |||
-7.1357387304306030e-01 5.6909996271133423e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 34 288428543 -34262659 1976906747 -42117703 858797567 | |||
-4965441 2008290292 -1146080848</internalNodes> | |||
<leafValues> | |||
-6.7784935235977173e-01 5.4983222484588623e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 22 -25297611 -100663553 -9830515 -570556417 -53741251 | |||
-36570627 -67437302 -12583252</internalNodes> | |||
<leafValues> | |||
-6.3567954301834106e-01 5.9044981002807617e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 46 -403706354 82769839 -446830048 -989858098 -8921600 | |||
1087893408 -100663520 -134217729</internalNodes> | |||
<leafValues> | |||
-7.0569902658462524e-01 5.4874616861343384e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 0 -965744853 -420544541 -8392718 -1569784218 -192940313 | |||
1744830335 -9 -1003227661</internalNodes> | |||
<leafValues> | |||
-5.7118493318557739e-01 6.4167028665542603e-01</leafValues></_></weakClassifiers></_> | |||
<!-- stage 10 --> | |||
<_> | |||
<maxWeakCount>5</maxWeakCount> | |||
<stageThreshold>-2.1370947360992432e+00</stageThreshold> | |||
<weakClassifiers> | |||
<_> | |||
<internalNodes> | |||
0 -1 40 -673196033 -2144789 287251423 -538968593 -1399068449 | |||
-73535505 -13631489 -526857</internalNodes> | |||
<leafValues> | |||
-7.2344118356704712e-01 6.8316829204559326e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 32 -214216429 -2112561 -445819937 1964790555 -17185861 | |||
-303183720 -357832229 -3148837</internalNodes> | |||
<leafValues> | |||
-7.1031409502029419e-01 5.4083776473999023e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 10 -9043969 -36118539 2147450623 -4194305 -2246657 | |||
-102721404 1073685759 -1366622208</internalNodes> | |||
<leafValues> | |||
-5.8772116899490356e-01 6.4753490686416626e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 35 1167938037 16237049 -1120535169 1029034397 9567155 | |||
-2001626128 -1146622977 -1142248004</internalNodes> | |||
<leafValues> | |||
-6.4004391431808472e-01 5.6415843963623047e-01</leafValues></_> | |||
<_> | |||
<internalNodes> | |||
0 -1 21 -70126622 -134227061 -536243648 188013035 | |||
-1234960385 1416625375 -486868997 62913535</internalNodes> | |||
<leafValues> | |||
-8.8218396902084351e-01 4.1129270195960999e-01</leafValues></_></weakClassifiers></_></stages> | |||
<features> | |||
<_> | |||
<rect> | |||
0 1 1 6</rect></_> | |||
<_> | |||
<rect> | |||
1 0 8 3</rect></_> | |||
<_> | |||
<rect> | |||
1 4 8 3</rect></_> | |||
<_> | |||
<rect> | |||
1 6 13 2</rect></_> | |||
<_> | |||
<rect> | |||
2 1 5 2</rect></_> | |||
<_> | |||
<rect> | |||
2 4 9 2</rect></_> | |||
<_> | |||
<rect> | |||
3 2 5 2</rect></_> | |||
<_> | |||
<rect> | |||
4 0 11 3</rect></_> | |||
<_> | |||
<rect> | |||
4 21 9 1</rect></_> | |||
<_> | |||
<rect> | |||
7 1 5 5</rect></_> | |||
<_> | |||
<rect> | |||
7 7 6 2</rect></_> | |||
<_> | |||
<rect> | |||
10 0 3 5</rect></_> | |||
<_> | |||
<rect> | |||
11 1 9 3</rect></_> | |||
<_> | |||
<rect> | |||
11 2 11 4</rect></_> | |||
<_> | |||
<rect> | |||
12 0 4 3</rect></_> | |||
<_> | |||
<rect> | |||
14 2 5 2</rect></_> | |||
<_> | |||
<rect> | |||
14 6 3 3</rect></_> | |||
<_> | |||
<rect> | |||
15 1 5 4</rect></_> | |||
<_> | |||
<rect> | |||
16 0 9 4</rect></_> | |||
<_> | |||
<rect> | |||
17 3 4 5</rect></_> | |||
<_> | |||
<rect> | |||
17 6 4 3</rect></_> | |||
<_> | |||
<rect> | |||
18 12 3 2</rect></_> | |||
<_> | |||
<rect> | |||
19 0 3 3</rect></_> | |||
<_> | |||
<rect> | |||
19 3 2 6</rect></_> | |||
<_> | |||
<rect> | |||
19 4 2 4</rect></_> | |||
<_> | |||
<rect> | |||
19 12 2 4</rect></_> | |||
<_> | |||
<rect> | |||
21 2 2 5</rect></_> | |||
<_> | |||
<rect> | |||
22 5 3 4</rect></_> | |||
<_> | |||
<rect> | |||
22 14 3 3</rect></_> | |||
<_> | |||
<rect> | |||
24 1 6 5</rect></_> | |||
<_> | |||
<rect> | |||
25 3 4 5</rect></_> | |||
<_> | |||
<rect> | |||
25 6 6 1</rect></_> | |||
<_> | |||
<rect> | |||
26 1 2 5</rect></_> | |||
<_> | |||
<rect> | |||
26 3 5 4</rect></_> | |||
<_> | |||
<rect> | |||
26 21 6 1</rect></_> | |||
<_> | |||
<rect> | |||
27 1 5 1</rect></_> | |||
<_> | |||
<rect> | |||
29 3 4 6</rect></_> | |||
<_> | |||
<rect> | |||
30 0 4 5</rect></_> | |||
<_> | |||
<rect> | |||
30 2 3 7</rect></_> | |||
<_> | |||
<rect> | |||
34 1 3 7</rect></_> | |||
<_> | |||
<rect> | |||
34 8 3 2</rect></_> | |||
<_> | |||
<rect> | |||
34 15 3 3</rect></_> | |||
<_> | |||
<rect> | |||
35 3 2 5</rect></_> | |||
<_> | |||
<rect> | |||
35 5 2 5</rect></_> | |||
<_> | |||
<rect> | |||
39 12 1 3</rect></_> | |||
<_> | |||
<rect> | |||
41 0 1 7</rect></_> | |||
<_> | |||
<rect> | |||
41 10 1 4</rect></_> | |||
<_> | |||
<rect> | |||
41 11 1 3</rect></_></features></cascade> | |||
</opencv_storage> |
@@ -3,35 +3,68 @@ | |||
namespace pr { | |||
PipelinePR::PipelinePR(std::string detect_prototxt, std::string detect_caffemodel, | |||
std::string finetune_prototxt, std::string finetune_caffemodel, | |||
std::string platerec_prototxt, std::string platerec_caffemodel/*, | |||
std::string platecolor_color*/) | |||
std::string platerec_prototxt, std::string platerec_caffemodel, | |||
std::string dbstring) | |||
{ | |||
platedetection = new PlateDetection(detect_prototxt, detect_caffemodel); | |||
finetune = new FineTune(finetune_prototxt, finetune_caffemodel); | |||
platerecognation = new PlateRecognation(platerec_prototxt, platerec_caffemodel); | |||
//platecolorclass = new PlateColorClass(platecolor_color); | |||
dbdetection = new DBDetection(dbstring); | |||
} | |||
PipelinePR::~PipelinePR() | |||
{ | |||
delete platedetection; | |||
delete finetune; | |||
delete platerecognation; | |||
//delete platecolorclass; | |||
delete dbdetection; | |||
} | |||
std::vector<PlateInfo> PipelinePR::RunPiplineAsImage(cv::Mat plateimg) | |||
cv::Mat DBcropFromImage(const cv::Mat &image){ | |||
cv::Mat cropped; | |||
image.copyTo(cropped); | |||
int cropped_w = cropped.cols; | |||
int cropped_h = cropped.rows; | |||
cv::Rect up,down; | |||
up.y = cropped_h*0.05;up.x = cropped_w*0.2;up.height = cropped_h*0.35;up.width = cropped_w*0.55; | |||
down.y = cropped_h*0.4;down.x = cropped_w*0.05;down.height = cropped_h*0.6;down.width = cropped_w*0.95; | |||
cv::Mat cropUp,cropDown; | |||
cropped(up).copyTo(cropUp); | |||
cropped(down).copyTo(cropDown); | |||
cv::resize(cropUp,cropUp,cv::Size(64,40)); | |||
cv::resize(cropDown,cropDown,cv::Size(96,40)); | |||
cv::Mat crop = cv::Mat(40,160,CV_8UC3); | |||
cropUp.copyTo(crop(cv::Rect(0,0,64,40))); | |||
cropDown.copyTo(crop(cv::Rect(64,0,96,40))); | |||
return crop; | |||
} | |||
std::vector<PlateInfo> PipelinePR::RunPiplineAsImage(cv::Mat plateimg,int IsDB) | |||
{ | |||
std::vector<pr::PlateInfo> plates; | |||
std::vector<PlateInfo> plateres; | |||
platedetection->Detectssd(plateimg, plates); | |||
if(IsDB==1) | |||
{ | |||
dbdetection->DBDetect(plateimg,plates,30,1280); | |||
} | |||
else | |||
{ | |||
platedetection->Detectssd(plateimg, plates); | |||
} | |||
for (pr::PlateInfo plateinfo : plates) { | |||
cv::Mat image = plateinfo.getPlateImage(); | |||
cv::Mat CropImg; | |||
finetune->Finetune(image, CropImg); | |||
platerecognation->segmentation_free_recognation(CropImg, plateinfo); | |||
//platecolorclass->plateColor(CropImg, plateinfo); | |||
if(IsDB==1) | |||
{ | |||
CropImg = DBcropFromImage(image); | |||
platerecognation->segmentation_free_recognation(CropImg, plateinfo); | |||
} | |||
else | |||
{ | |||
finetune->Finetune(image, CropImg); | |||
platerecognation->segmentation_free_recognation(CropImg, plateinfo); | |||
} | |||
plateres.push_back(plateinfo); | |||
} | |||
return plateres; | |||
} | |||
} | |||
} |
@@ -8,6 +8,10 @@ namespace pr { | |||
{ | |||
ssdNet = cv::dnn::readNetFromCaffe(ssd_prototxt, ssd_caffemodel); | |||
} | |||
DBDetection::DBDetection(std::string cascadestring) | |||
{ | |||
dbcascade.load(cascadestring); | |||
} | |||
void PlateDetection::Detectssd(cv::Mat img, std::vector<pr::PlateInfo> &plateInfos) | |||
{ | |||
int cols = img.cols; | |||
@@ -57,4 +61,43 @@ namespace pr { | |||
} | |||
} | |||
} | |||
cv::Mat cropFromImage(const cv::Mat &image,cv::Rect rect){ | |||
int w = image.cols-1; | |||
int h = image.rows-1; | |||
rect.x = std::max(rect.x,0); | |||
rect.y = std::max(rect.y,0); | |||
rect.height = std::min(rect.height,h-rect.y); | |||
rect.width = std::min(rect.width,w-rect.x); | |||
cv::Mat temp(rect.size(), image.type()); | |||
cv::Mat cropped; | |||
temp = image(rect); | |||
temp.copyTo(cropped); | |||
return cropped; | |||
} | |||
void DBDetection::DBDetect(cv::Mat InputImage,std::vector<pr::PlateInfo> &plateInfos,int min_w,int max_w) | |||
{ | |||
cv::Mat processImage; | |||
cv::cvtColor(InputImage,processImage,cv::COLOR_BGR2GRAY); | |||
std::vector<cv::Rect> platesRegions; | |||
cv::Size minSize(min_w,min_w/4); | |||
cv::Size maxSize(max_w,max_w/4); | |||
if (&processImage == NULL) | |||
return; | |||
dbcascade.detectMultiScale( processImage, platesRegions, | |||
1.1, 3, cv::CASCADE_SCALE_IMAGE,minSize,maxSize); | |||
for(auto plate:platesRegions) | |||
{ | |||
int zeroadd_w = static_cast<int>(plate.width*0.28); | |||
int zeroadd_h = static_cast<int>(plate.height*0.35); | |||
int zeroadd_x = static_cast<int>(plate.width*0.14); | |||
int zeroadd_y = static_cast<int>(plate.height*0.15); | |||
plate.x-=zeroadd_x; | |||
plate.y-=zeroadd_y; | |||
plate.height += zeroadd_h; | |||
plate.width += zeroadd_w; | |||
cv::Mat plateImage = cropFromImage(InputImage,plate); | |||
PlateInfo plateInfo(plateImage,plate); | |||
plateInfos.push_back(plateInfo); | |||
} | |||
} | |||
} |
@@ -4,9 +4,10 @@ void TEST_PIPELINE() | |||
{ | |||
pr::PipelinePR prc("../lpr\\model\\mininet_ssd_v1.prototxt", "../lpr\\model\\mininet_ssd_v1.caffemodel", | |||
"../lpr\\model\\refinenet.prototxt", "../lpr\\model\\refinenet.caffemodel", | |||
"../lpr\\model\\SegmenationFree-Inception.prototxt", "../lpr\\model\\SegmenationFree-Inception.caffemodel"); | |||
"../lpr\\model\\SegmenationFree-Inception.prototxt", "../lpr\\model\\SegmenationFree-Inception.caffemodel", | |||
"../lpr\\model\\cascade_double.xml"); | |||
cv::Mat img = cv::imread("../lpr\\res\\test.jpg"); | |||
std::vector<pr::PlateInfo> res = prc.RunPiplineAsImage(img); | |||
std::vector<pr::PlateInfo> res = prc.RunPiplineAsImage(img,0); | |||
for (auto st : res) { | |||
if (st.confidence > 0.75) { | |||
std::cout << st.getPlateName() << " " << st.confidence << std::endl; | |||
@@ -16,12 +17,12 @@ void TEST_PIPELINE() | |||
} | |||
} | |||
cv::imshow("image", img); | |||
cv::waitKey(0); | |||
//cv::imshow("image", img); | |||
//cv::waitKey(0); | |||
} | |||
int main() | |||
{ | |||
TEST_PIPELINE(); | |||
return 0; | |||
} | |||
} |
@@ -1,8 +0,0 @@ | |||
platform :ios, '10.1' | |||
target "lpr" do | |||
pod 'OpenCV', '~> 3.4.2' | |||
pod 'Masonry' | |||
end |
@@ -1,20 +0,0 @@ | |||
PODS: | |||
- Masonry (1.1.0) | |||
- OpenCV (3.4.2) | |||
DEPENDENCIES: | |||
- Masonry | |||
- OpenCV (~> 3.4.2) | |||
SPEC REPOS: | |||
https://github.com/cocoapods/specs.git: | |||
- Masonry | |||
- OpenCV | |||
SPEC CHECKSUMS: | |||
Masonry: 678fab65091a9290e40e2832a55e7ab731aad201 | |||
OpenCV: 452909747854c92e0f59670961ed5131f5286cb5 | |||
PODFILE CHECKSUM: 94db02cda76a5ac6371a03e6e2ca4e9035fc0da6 | |||
COCOAPODS: 1.5.3 |
@@ -1,4 +0,0 @@ | |||
Depency Library: | |||
- Masonry, 1.1.0 | |||
- OpenCV, 3.4.2 |
@@ -1,17 +0,0 @@ | |||
将/Prj-Linux/lpr/model目录下的 | |||
cascade.xml | |||
CharacterRecognization.caffemodel | |||
CharacterRecognization.prototxt | |||
HorizonalFinemapping.caffemodel | |||
HorizonalFinemapping.prototxt | |||
Segmentation.caffemodel | |||
Segmentation.prototxt | |||
放置在该目录 |
@@ -1,530 +0,0 @@ | |||
// !$*UTF8*$! | |||
{ | |||
archiveVersion = 1; | |||
classes = { | |||
}; | |||
objectVersion = 50; | |||
objects = { | |||
/* Begin PBXBuildFile section */ | |||
34ECFDD12182DD9300B162D4 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 34ECFDD02182DD9300B162D4 /* AppDelegate.m */; }; | |||
34ECFDD92182DD9400B162D4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 34ECFDD82182DD9400B162D4 /* Assets.xcassets */; }; | |||
34ECFDDC2182DD9400B162D4 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 34ECFDDA2182DD9400B162D4 /* LaunchScreen.storyboard */; }; | |||
34ECFDDF2182DD9400B162D4 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 34ECFDDE2182DD9400B162D4 /* main.m */; }; | |||
34ECFE152182DEF500B162D4 /* PlateSegmentation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 34ECFE0D2182DEF500B162D4 /* PlateSegmentation.cpp */; }; | |||
34ECFE162182DEF500B162D4 /* PlateDetection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 34ECFE0E2182DEF500B162D4 /* PlateDetection.cpp */; }; | |||
34ECFE172182DEF500B162D4 /* Pipeline.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 34ECFE0F2182DEF500B162D4 /* Pipeline.cpp */; }; | |||
34ECFE182182DEF500B162D4 /* FastDeskew.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 34ECFE102182DEF500B162D4 /* FastDeskew.cpp */; }; | |||
34ECFE192182DEF500B162D4 /* Recognizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 34ECFE112182DEF500B162D4 /* Recognizer.cpp */; }; | |||
34ECFE1A2182DEF500B162D4 /* FineMapping.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 34ECFE122182DEF500B162D4 /* FineMapping.cpp */; }; | |||
34ECFE1B2182DEF500B162D4 /* CNNRecognizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 34ECFE142182DEF500B162D4 /* CNNRecognizer.cpp */; }; | |||
34ECFE242182DF2F00B162D4 /* HorizonalFinemapping.caffemodel in Resources */ = {isa = PBXBuildFile; fileRef = 34ECFE1D2182DF2E00B162D4 /* HorizonalFinemapping.caffemodel */; }; | |||
34ECFE252182DF2F00B162D4 /* CharacterRecognization.caffemodel in Resources */ = {isa = PBXBuildFile; fileRef = 34ECFE1E2182DF2E00B162D4 /* CharacterRecognization.caffemodel */; }; | |||
34ECFE262182DF2F00B162D4 /* cascade.xml in Resources */ = {isa = PBXBuildFile; fileRef = 34ECFE1F2182DF2E00B162D4 /* cascade.xml */; }; | |||
34ECFE272182DF2F00B162D4 /* Segmentation.prototxt in Resources */ = {isa = PBXBuildFile; fileRef = 34ECFE202182DF2E00B162D4 /* Segmentation.prototxt */; }; | |||
34ECFE282182DF2F00B162D4 /* HorizonalFinemapping.prototxt in Resources */ = {isa = PBXBuildFile; fileRef = 34ECFE212182DF2E00B162D4 /* HorizonalFinemapping.prototxt */; }; | |||
34ECFE292182DF2F00B162D4 /* Segmentation.caffemodel in Resources */ = {isa = PBXBuildFile; fileRef = 34ECFE222182DF2E00B162D4 /* Segmentation.caffemodel */; }; | |||
34ECFE2A2182DF2F00B162D4 /* CharacterRecognization.prototxt in Resources */ = {isa = PBXBuildFile; fileRef = 34ECFE232182DF2E00B162D4 /* CharacterRecognization.prototxt */; }; | |||
34ECFE2D2182E10700B162D4 /* RootViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 34ECFE2C2182E10700B162D4 /* RootViewController.mm */; }; | |||
34ECFE332182E51200B162D4 /* CameraViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 34ECFE322182E51100B162D4 /* CameraViewController.mm */; }; | |||
34ECFE352182E56900B162D4 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34ECFE342182E56900B162D4 /* AVFoundation.framework */; }; | |||
34ECFE382182E5F100B162D4 /* Utility.mm in Sources */ = {isa = PBXBuildFile; fileRef = 34ECFE372182E5F100B162D4 /* Utility.mm */; }; | |||
34ECFE3A2182FAB700B162D4 /* CoreImage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34ECFE392182FAB700B162D4 /* CoreImage.framework */; }; | |||
A396A338993421DC89845E63 /* libPods-lpr.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A33861A99BC945120023AC25 /* libPods-lpr.a */; }; | |||
/* End PBXBuildFile section */ | |||
/* Begin PBXFileReference section */ | |||
34ECFDCC2182DD9300B162D4 /* lpr.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = lpr.app; sourceTree = BUILT_PRODUCTS_DIR; }; | |||
34ECFDCF2182DD9300B162D4 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; }; | |||
34ECFDD02182DD9300B162D4 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; }; | |||
34ECFDD82182DD9400B162D4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; }; | |||
34ECFDDB2182DD9400B162D4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; }; | |||
34ECFDDD2182DD9400B162D4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; | |||
34ECFDDE2182DD9400B162D4 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; }; | |||
34ECFE032182DEF500B162D4 /* PlateSegmentation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlateSegmentation.h; sourceTree = "<group>"; }; | |||
34ECFE042182DEF500B162D4 /* Recognizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Recognizer.h; sourceTree = "<group>"; }; | |||
34ECFE052182DEF500B162D4 /* PlateDetection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlateDetection.h; sourceTree = "<group>"; }; | |||
34ECFE062182DEF500B162D4 /* PlateInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlateInfo.h; sourceTree = "<group>"; }; | |||
34ECFE072182DEF500B162D4 /* FineMapping.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FineMapping.h; sourceTree = "<group>"; }; | |||
34ECFE082182DEF500B162D4 /* niBlackThreshold.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = niBlackThreshold.h; sourceTree = "<group>"; }; | |||
34ECFE092182DEF500B162D4 /* FastDeskew.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FastDeskew.h; sourceTree = "<group>"; }; | |||
34ECFE0A2182DEF500B162D4 /* Pipeline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Pipeline.h; sourceTree = "<group>"; }; | |||
34ECFE0B2182DEF500B162D4 /* CNNRecognizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CNNRecognizer.h; sourceTree = "<group>"; }; | |||
34ECFE0D2182DEF500B162D4 /* PlateSegmentation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PlateSegmentation.cpp; sourceTree = "<group>"; }; | |||
34ECFE0E2182DEF500B162D4 /* PlateDetection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PlateDetection.cpp; sourceTree = "<group>"; }; | |||
34ECFE0F2182DEF500B162D4 /* Pipeline.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Pipeline.cpp; sourceTree = "<group>"; }; | |||
34ECFE102182DEF500B162D4 /* FastDeskew.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FastDeskew.cpp; sourceTree = "<group>"; }; | |||
34ECFE112182DEF500B162D4 /* Recognizer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Recognizer.cpp; sourceTree = "<group>"; }; | |||
34ECFE122182DEF500B162D4 /* FineMapping.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FineMapping.cpp; sourceTree = "<group>"; }; | |||
34ECFE132182DEF500B162D4 /* util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = util.h; sourceTree = "<group>"; }; | |||
34ECFE142182DEF500B162D4 /* CNNRecognizer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CNNRecognizer.cpp; sourceTree = "<group>"; }; | |||
34ECFE1D2182DF2E00B162D4 /* HorizonalFinemapping.caffemodel */ = {isa = PBXFileReference; lastKnownFileType = file; path = HorizonalFinemapping.caffemodel; sourceTree = "<group>"; }; | |||
34ECFE1E2182DF2E00B162D4 /* CharacterRecognization.caffemodel */ = {isa = PBXFileReference; lastKnownFileType = file; path = CharacterRecognization.caffemodel; sourceTree = "<group>"; }; | |||
34ECFE1F2182DF2E00B162D4 /* cascade.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = cascade.xml; sourceTree = "<group>"; }; | |||
34ECFE202182DF2E00B162D4 /* Segmentation.prototxt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Segmentation.prototxt; sourceTree = "<group>"; }; | |||
34ECFE212182DF2E00B162D4 /* HorizonalFinemapping.prototxt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = HorizonalFinemapping.prototxt; sourceTree = "<group>"; }; | |||
34ECFE222182DF2E00B162D4 /* Segmentation.caffemodel */ = {isa = PBXFileReference; lastKnownFileType = file; path = Segmentation.caffemodel; sourceTree = "<group>"; }; | |||
34ECFE232182DF2E00B162D4 /* CharacterRecognization.prototxt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CharacterRecognization.prototxt; sourceTree = "<group>"; }; | |||
34ECFE2B2182E10700B162D4 /* RootViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RootViewController.h; sourceTree = "<group>"; }; | |||
34ECFE2C2182E10700B162D4 /* RootViewController.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = RootViewController.mm; sourceTree = "<group>"; }; | |||
34ECFE312182E51100B162D4 /* CameraViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CameraViewController.h; sourceTree = "<group>"; }; | |||
34ECFE322182E51100B162D4 /* CameraViewController.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = CameraViewController.mm; sourceTree = "<group>"; }; | |||
34ECFE342182E56900B162D4 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; }; | |||
34ECFE362182E5F100B162D4 /* Utility.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Utility.h; sourceTree = "<group>"; }; | |||
34ECFE372182E5F100B162D4 /* Utility.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = Utility.mm; sourceTree = "<group>"; }; | |||
34ECFE392182FAB700B162D4 /* CoreImage.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreImage.framework; path = System/Library/Frameworks/CoreImage.framework; sourceTree = SDKROOT; }; | |||
66BAD4CEFABD6705C5100968 /* Pods-lpr.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-lpr.release.xcconfig"; path = "Pods/Target Support Files/Pods-lpr/Pods-lpr.release.xcconfig"; sourceTree = "<group>"; }; | |||
A33861A99BC945120023AC25 /* libPods-lpr.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-lpr.a"; sourceTree = BUILT_PRODUCTS_DIR; }; | |||
E169020B9373AF28E9C472DD /* Pods-lpr.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-lpr.debug.xcconfig"; path = "Pods/Target Support Files/Pods-lpr/Pods-lpr.debug.xcconfig"; sourceTree = "<group>"; }; | |||
/* End PBXFileReference section */ | |||
/* Begin PBXFrameworksBuildPhase section */ | |||
34ECFDC92182DD9300B162D4 /* Frameworks */ = { | |||
isa = PBXFrameworksBuildPhase; | |||
buildActionMask = 2147483647; | |||
files = ( | |||
34ECFE3A2182FAB700B162D4 /* CoreImage.framework in Frameworks */, | |||
34ECFE352182E56900B162D4 /* AVFoundation.framework in Frameworks */, | |||
A396A338993421DC89845E63 /* libPods-lpr.a in Frameworks */, | |||
); | |||
runOnlyForDeploymentPostprocessing = 0; | |||
}; | |||
/* End PBXFrameworksBuildPhase section */ | |||
/* Begin PBXGroup section */ | |||
34ECFDC32182DD9300B162D4 = { | |||
isa = PBXGroup; | |||
children = ( | |||
34ECFDCE2182DD9300B162D4 /* lpr */, | |||
34ECFE1C2182DF2E00B162D4 /* Resource */, | |||
34ECFDCD2182DD9300B162D4 /* Products */, | |||
DE72138A4B42368326688C6A /* Pods */, | |||
97C4CF37B3E356C8641CE105 /* Frameworks */, | |||
); | |||
sourceTree = "<group>"; | |||
}; | |||
34ECFDCD2182DD9300B162D4 /* Products */ = { | |||
isa = PBXGroup; | |||
children = ( | |||
34ECFDCC2182DD9300B162D4 /* lpr.app */, | |||
); | |||
name = Products; | |||
sourceTree = "<group>"; | |||
}; | |||
34ECFDCE2182DD9300B162D4 /* lpr */ = { | |||
isa = PBXGroup; | |||
children = ( | |||
34ECFE012182DEF500B162D4 /* Source */, | |||
34ECFDCF2182DD9300B162D4 /* AppDelegate.h */, | |||
34ECFDD02182DD9300B162D4 /* AppDelegate.m */, | |||
34ECFDD82182DD9400B162D4 /* Assets.xcassets */, | |||
34ECFDDA2182DD9400B162D4 /* LaunchScreen.storyboard */, | |||
34ECFDDD2182DD9400B162D4 /* Info.plist */, | |||
34ECFDDE2182DD9400B162D4 /* main.m */, | |||
34ECFE2B2182E10700B162D4 /* RootViewController.h */, | |||
34ECFE2C2182E10700B162D4 /* RootViewController.mm */, | |||
34ECFE312182E51100B162D4 /* CameraViewController.h */, | |||
34ECFE322182E51100B162D4 /* CameraViewController.mm */, | |||
34ECFE362182E5F100B162D4 /* Utility.h */, | |||
34ECFE372182E5F100B162D4 /* Utility.mm */, | |||
); | |||
path = lpr; | |||
sourceTree = "<group>"; | |||
}; | |||
34ECFE012182DEF500B162D4 /* Source */ = { | |||
isa = PBXGroup; | |||
children = ( | |||
34ECFE022182DEF500B162D4 /* include */, | |||
34ECFE0C2182DEF500B162D4 /* src */, | |||
); | |||
path = Source; | |||
sourceTree = "<group>"; | |||
}; | |||
34ECFE022182DEF500B162D4 /* include */ = { | |||
isa = PBXGroup; | |||
children = ( | |||
34ECFE032182DEF500B162D4 /* PlateSegmentation.h */, | |||
34ECFE042182DEF500B162D4 /* Recognizer.h */, | |||
34ECFE052182DEF500B162D4 /* PlateDetection.h */, | |||
34ECFE062182DEF500B162D4 /* PlateInfo.h */, | |||
34ECFE072182DEF500B162D4 /* FineMapping.h */, | |||
34ECFE082182DEF500B162D4 /* niBlackThreshold.h */, | |||
34ECFE092182DEF500B162D4 /* FastDeskew.h */, | |||
34ECFE0A2182DEF500B162D4 /* Pipeline.h */, | |||
34ECFE0B2182DEF500B162D4 /* CNNRecognizer.h */, | |||
); | |||
path = include; | |||
sourceTree = "<group>"; | |||
}; | |||
34ECFE0C2182DEF500B162D4 /* src */ = { | |||
isa = PBXGroup; | |||
children = ( | |||
34ECFE0D2182DEF500B162D4 /* PlateSegmentation.cpp */, | |||
34ECFE0E2182DEF500B162D4 /* PlateDetection.cpp */, | |||
34ECFE0F2182DEF500B162D4 /* Pipeline.cpp */, | |||
34ECFE102182DEF500B162D4 /* FastDeskew.cpp */, | |||
34ECFE112182DEF500B162D4 /* Recognizer.cpp */, | |||
34ECFE122182DEF500B162D4 /* FineMapping.cpp */, | |||
34ECFE132182DEF500B162D4 /* util.h */, | |||
34ECFE142182DEF500B162D4 /* CNNRecognizer.cpp */, | |||
); | |||
path = src; | |||
sourceTree = "<group>"; | |||
}; | |||
34ECFE1C2182DF2E00B162D4 /* Resource */ = { | |||
isa = PBXGroup; | |||
children = ( | |||
34ECFE1D2182DF2E00B162D4 /* HorizonalFinemapping.caffemodel */, | |||
34ECFE1E2182DF2E00B162D4 /* CharacterRecognization.caffemodel */, | |||
34ECFE1F2182DF2E00B162D4 /* cascade.xml */, | |||
34ECFE202182DF2E00B162D4 /* Segmentation.prototxt */, | |||
34ECFE212182DF2E00B162D4 /* HorizonalFinemapping.prototxt */, | |||
34ECFE222182DF2E00B162D4 /* Segmentation.caffemodel */, | |||
34ECFE232182DF2E00B162D4 /* CharacterRecognization.prototxt */, | |||
); | |||
path = Resource; | |||
sourceTree = "<group>"; | |||
}; | |||
97C4CF37B3E356C8641CE105 /* Frameworks */ = { | |||
isa = PBXGroup; | |||
children = ( | |||
34ECFE392182FAB700B162D4 /* CoreImage.framework */, | |||
34ECFE342182E56900B162D4 /* AVFoundation.framework */, | |||
A33861A99BC945120023AC25 /* libPods-lpr.a */, | |||
); | |||
name = Frameworks; | |||
sourceTree = "<group>"; | |||
}; | |||
DE72138A4B42368326688C6A /* Pods */ = { | |||
isa = PBXGroup; | |||
children = ( | |||
E169020B9373AF28E9C472DD /* Pods-lpr.debug.xcconfig */, | |||
66BAD4CEFABD6705C5100968 /* Pods-lpr.release.xcconfig */, | |||
); | |||
name = Pods; | |||
sourceTree = "<group>"; | |||
}; | |||
/* End PBXGroup section */ | |||
/* Begin PBXNativeTarget section */ | |||
34ECFDCB2182DD9300B162D4 /* lpr */ = { | |||
isa = PBXNativeTarget; | |||
buildConfigurationList = 34ECFDE22182DD9400B162D4 /* Build configuration list for PBXNativeTarget "lpr" */; | |||
buildPhases = ( | |||
12CCA15FA936D51F737FDEDF /* [CP] Check Pods Manifest.lock */, | |||
34ECFDC82182DD9300B162D4 /* Sources */, | |||
34ECFDC92182DD9300B162D4 /* Frameworks */, | |||
34ECFDCA2182DD9300B162D4 /* Resources */, | |||
); | |||
buildRules = ( | |||
); | |||
dependencies = ( | |||
); | |||
name = lpr; | |||
productName = lpr; | |||
productReference = 34ECFDCC2182DD9300B162D4 /* lpr.app */; | |||
productType = "com.apple.product-type.application"; | |||
}; | |||
/* End PBXNativeTarget section */ | |||
/* Begin PBXProject section */ | |||
34ECFDC42182DD9300B162D4 /* Project object */ = { | |||
isa = PBXProject; | |||
attributes = { | |||
LastUpgradeCheck = 1000; | |||
ORGANIZATIONNAME = lprSample; | |||
TargetAttributes = { | |||
34ECFDCB2182DD9300B162D4 = { | |||
CreatedOnToolsVersion = 10.0; | |||
}; | |||
}; | |||
}; | |||
buildConfigurationList = 34ECFDC72182DD9300B162D4 /* Build configuration list for PBXProject "lpr" */; | |||
compatibilityVersion = "Xcode 9.3"; | |||
developmentRegion = en; | |||
hasScannedForEncodings = 0; | |||
knownRegions = ( | |||
en, | |||
Base, | |||
); | |||
mainGroup = 34ECFDC32182DD9300B162D4; | |||
productRefGroup = 34ECFDCD2182DD9300B162D4 /* Products */; | |||
projectDirPath = ""; | |||
projectRoot = ""; | |||
targets = ( | |||
34ECFDCB2182DD9300B162D4 /* lpr */, | |||
); | |||
}; | |||
/* End PBXProject section */ | |||
/* Begin PBXResourcesBuildPhase section */ | |||
34ECFDCA2182DD9300B162D4 /* Resources */ = { | |||
isa = PBXResourcesBuildPhase; | |||
buildActionMask = 2147483647; | |||
files = ( | |||
34ECFE2A2182DF2F00B162D4 /* CharacterRecognization.prototxt in Resources */, | |||
34ECFDDC2182DD9400B162D4 /* LaunchScreen.storyboard in Resources */, | |||
34ECFDD92182DD9400B162D4 /* Assets.xcassets in Resources */, | |||
34ECFE282182DF2F00B162D4 /* HorizonalFinemapping.prototxt in Resources */, | |||
34ECFE242182DF2F00B162D4 /* HorizonalFinemapping.caffemodel in Resources */, | |||
34ECFE272182DF2F00B162D4 /* Segmentation.prototxt in Resources */, | |||
34ECFE262182DF2F00B162D4 /* cascade.xml in Resources */, | |||
34ECFE292182DF2F00B162D4 /* Segmentation.caffemodel in Resources */, | |||
34ECFE252182DF2F00B162D4 /* CharacterRecognization.caffemodel in Resources */, | |||
); | |||
runOnlyForDeploymentPostprocessing = 0; | |||
}; | |||
/* End PBXResourcesBuildPhase section */ | |||
/* Begin PBXShellScriptBuildPhase section */ | |||
12CCA15FA936D51F737FDEDF /* [CP] Check Pods Manifest.lock */ = { | |||
isa = PBXShellScriptBuildPhase; | |||
buildActionMask = 2147483647; | |||
files = ( | |||
); | |||
inputPaths = ( | |||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock", | |||
"${PODS_ROOT}/Manifest.lock", | |||
); | |||
name = "[CP] Check Pods Manifest.lock"; | |||
outputPaths = ( | |||
"$(DERIVED_FILE_DIR)/Pods-lpr-checkManifestLockResult.txt", | |||
); | |||
runOnlyForDeploymentPostprocessing = 0; | |||
shellPath = /bin/sh; | |||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; | |||
showEnvVarsInLog = 0; | |||
}; | |||
/* End PBXShellScriptBuildPhase section */ | |||
/* Begin PBXSourcesBuildPhase section */ | |||
34ECFDC82182DD9300B162D4 /* Sources */ = { | |||
isa = PBXSourcesBuildPhase; | |||
buildActionMask = 2147483647; | |||
files = ( | |||
34ECFE1A2182DEF500B162D4 /* FineMapping.cpp in Sources */, | |||
34ECFE182182DEF500B162D4 /* FastDeskew.cpp in Sources */, | |||
34ECFE162182DEF500B162D4 /* PlateDetection.cpp in Sources */, | |||
34ECFDDF2182DD9400B162D4 /* main.m in Sources */, | |||
34ECFE382182E5F100B162D4 /* Utility.mm in Sources */, | |||
34ECFE2D2182E10700B162D4 /* RootViewController.mm in Sources */, | |||
34ECFE172182DEF500B162D4 /* Pipeline.cpp in Sources */, | |||
34ECFE332182E51200B162D4 /* CameraViewController.mm in Sources */, | |||
34ECFE152182DEF500B162D4 /* PlateSegmentation.cpp in Sources */, | |||
34ECFE1B2182DEF500B162D4 /* CNNRecognizer.cpp in Sources */, | |||
34ECFDD12182DD9300B162D4 /* AppDelegate.m in Sources */, | |||
34ECFE192182DEF500B162D4 /* Recognizer.cpp in Sources */, | |||
); | |||
runOnlyForDeploymentPostprocessing = 0; | |||
}; | |||
/* End PBXSourcesBuildPhase section */ | |||
/* Begin PBXVariantGroup section */ | |||
34ECFDDA2182DD9400B162D4 /* LaunchScreen.storyboard */ = { | |||
isa = PBXVariantGroup; | |||
children = ( | |||
34ECFDDB2182DD9400B162D4 /* Base */, | |||
); | |||
name = LaunchScreen.storyboard; | |||
sourceTree = "<group>"; | |||
}; | |||
/* End PBXVariantGroup section */ | |||
/* Begin XCBuildConfiguration section */ | |||
34ECFDE02182DD9400B162D4 /* Debug */ = { | |||
isa = XCBuildConfiguration; | |||
buildSettings = { | |||
ALWAYS_SEARCH_USER_PATHS = NO; | |||
CLANG_ANALYZER_NONNULL = YES; | |||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; | |||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; | |||
CLANG_CXX_LIBRARY = "libc++"; | |||
CLANG_ENABLE_MODULES = YES; | |||
CLANG_ENABLE_OBJC_ARC = YES; | |||
CLANG_ENABLE_OBJC_WEAK = YES; | |||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; | |||
CLANG_WARN_BOOL_CONVERSION = YES; | |||
CLANG_WARN_COMMA = YES; | |||
CLANG_WARN_CONSTANT_CONVERSION = YES; | |||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; | |||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; | |||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES; | |||
CLANG_WARN_EMPTY_BODY = YES; | |||
CLANG_WARN_ENUM_CONVERSION = YES; | |||
CLANG_WARN_INFINITE_RECURSION = YES; | |||
CLANG_WARN_INT_CONVERSION = YES; | |||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; | |||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; | |||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; | |||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; | |||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; | |||
CLANG_WARN_STRICT_PROTOTYPES = YES; | |||
CLANG_WARN_SUSPICIOUS_MOVE = YES; | |||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; | |||
CLANG_WARN_UNREACHABLE_CODE = YES; | |||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; | |||
CODE_SIGN_IDENTITY = "iPhone Developer"; | |||
COPY_PHASE_STRIP = NO; | |||
DEBUG_INFORMATION_FORMAT = dwarf; | |||
ENABLE_STRICT_OBJC_MSGSEND = YES; | |||
ENABLE_TESTABILITY = YES; | |||
GCC_C_LANGUAGE_STANDARD = gnu11; | |||
GCC_DYNAMIC_NO_PIC = NO; | |||
GCC_NO_COMMON_BLOCKS = YES; | |||
GCC_OPTIMIZATION_LEVEL = 0; | |||
GCC_PREPROCESSOR_DEFINITIONS = ( | |||
"DEBUG=1", | |||
"$(inherited)", | |||
); | |||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES; | |||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; | |||
GCC_WARN_UNDECLARED_SELECTOR = YES; | |||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; | |||
GCC_WARN_UNUSED_FUNCTION = YES; | |||
GCC_WARN_UNUSED_VARIABLE = YES; | |||
HEADER_SEARCH_PATHS = ( | |||
"\"$(SRCROOT)/lpr/Source/incllude\"", | |||
"\"$(SRCROOT)\"", | |||
); | |||
IPHONEOS_DEPLOYMENT_TARGET = 10.1; | |||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; | |||
MTL_FAST_MATH = YES; | |||
ONLY_ACTIVE_ARCH = YES; | |||
SDKROOT = iphoneos; | |||
}; | |||
name = Debug; | |||
}; | |||
34ECFDE12182DD9400B162D4 /* Release */ = { | |||
isa = XCBuildConfiguration; | |||
buildSettings = { | |||
ALWAYS_SEARCH_USER_PATHS = NO; | |||
CLANG_ANALYZER_NONNULL = YES; | |||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; | |||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; | |||
CLANG_CXX_LIBRARY = "libc++"; | |||
CLANG_ENABLE_MODULES = YES; | |||
CLANG_ENABLE_OBJC_ARC = YES; | |||
CLANG_ENABLE_OBJC_WEAK = YES; | |||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; | |||
CLANG_WARN_BOOL_CONVERSION = YES; | |||
CLANG_WARN_COMMA = YES; | |||
CLANG_WARN_CONSTANT_CONVERSION = YES; | |||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; | |||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; | |||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES; | |||
CLANG_WARN_EMPTY_BODY = YES; | |||
CLANG_WARN_ENUM_CONVERSION = YES; | |||
CLANG_WARN_INFINITE_RECURSION = YES; | |||
CLANG_WARN_INT_CONVERSION = YES; | |||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; | |||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; | |||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; | |||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; | |||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; | |||
CLANG_WARN_STRICT_PROTOTYPES = YES; | |||
CLANG_WARN_SUSPICIOUS_MOVE = YES; | |||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; | |||
CLANG_WARN_UNREACHABLE_CODE = YES; | |||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; | |||
CODE_SIGN_IDENTITY = "iPhone Developer"; | |||
COPY_PHASE_STRIP = NO; | |||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; | |||
ENABLE_NS_ASSERTIONS = NO; | |||
ENABLE_STRICT_OBJC_MSGSEND = YES; | |||
GCC_C_LANGUAGE_STANDARD = gnu11; | |||
GCC_NO_COMMON_BLOCKS = YES; | |||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES; | |||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; | |||
GCC_WARN_UNDECLARED_SELECTOR = YES; | |||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; | |||
GCC_WARN_UNUSED_FUNCTION = YES; | |||
GCC_WARN_UNUSED_VARIABLE = YES; | |||
HEADER_SEARCH_PATHS = ( | |||
"\"$(SRCROOT)/lpr/Source/incllude\"", | |||
"\"$(SRCROOT)\"", | |||
); | |||
IPHONEOS_DEPLOYMENT_TARGET = 10.1; | |||
MTL_ENABLE_DEBUG_INFO = NO; | |||
MTL_FAST_MATH = YES; | |||
SDKROOT = iphoneos; | |||
VALIDATE_PRODUCT = YES; | |||
}; | |||
name = Release; | |||
}; | |||
34ECFDE32182DD9400B162D4 /* Debug */ = { | |||
isa = XCBuildConfiguration; | |||
baseConfigurationReference = E169020B9373AF28E9C472DD /* Pods-lpr.debug.xcconfig */; | |||
buildSettings = { | |||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; | |||
CLANG_CXX_LANGUAGE_STANDARD = "compiler-default"; | |||
CODE_SIGN_IDENTITY = "iPhone Developer"; | |||
CODE_SIGN_STYLE = Automatic; | |||
DEVELOPMENT_TEAM = YZGMTHK294; | |||
HEADER_SEARCH_PATHS = ( | |||
"$(inherited)", | |||
"\"${PODS_ROOT}/Headers/Public\"", | |||
"\"${PODS_ROOT}/Headers/Public/OpenCV\"", | |||
); | |||
INFOPLIST_FILE = lpr/Info.plist; | |||
LD_RUNPATH_SEARCH_PATHS = ( | |||
"$(inherited)", | |||
"@executable_path/Frameworks", | |||
); | |||
PRODUCT_BUNDLE_IDENTIFIER = com.TongxingPay.IDCardRecognizeDemo; | |||
PRODUCT_NAME = "$(TARGET_NAME)"; | |||
PROVISIONING_PROFILE_SPECIFIER = ""; | |||
TARGETED_DEVICE_FAMILY = "1,2"; | |||
}; | |||
name = Debug; | |||
}; | |||
34ECFDE42182DD9400B162D4 /* Release */ = { | |||
isa = XCBuildConfiguration; | |||
baseConfigurationReference = 66BAD4CEFABD6705C5100968 /* Pods-lpr.release.xcconfig */; | |||
buildSettings = { | |||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; | |||
CLANG_CXX_LANGUAGE_STANDARD = "compiler-default"; | |||
CODE_SIGN_IDENTITY = "iPhone Developer"; | |||
CODE_SIGN_STYLE = Automatic; | |||
DEVELOPMENT_TEAM = YZGMTHK294; | |||
HEADER_SEARCH_PATHS = ( | |||
"$(inherited)", | |||
"\"${PODS_ROOT}/Headers/Public\"", | |||
"\"${PODS_ROOT}/Headers/Public/OpenCV\"", | |||
); | |||
INFOPLIST_FILE = lpr/Info.plist; | |||
LD_RUNPATH_SEARCH_PATHS = ( | |||
"$(inherited)", | |||
"@executable_path/Frameworks", | |||
); | |||
PRODUCT_BUNDLE_IDENTIFIER = com.TongxingPay.IDCardRecognizeDemo; | |||
PRODUCT_NAME = "$(TARGET_NAME)"; | |||
PROVISIONING_PROFILE_SPECIFIER = ""; | |||
TARGETED_DEVICE_FAMILY = "1,2"; | |||
}; | |||
name = Release; | |||
}; | |||
/* End XCBuildConfiguration section */ | |||
/* Begin XCConfigurationList section */ | |||
34ECFDC72182DD9300B162D4 /* Build configuration list for PBXProject "lpr" */ = { | |||
isa = XCConfigurationList; | |||
buildConfigurations = ( | |||
34ECFDE02182DD9400B162D4 /* Debug */, | |||
34ECFDE12182DD9400B162D4 /* Release */, | |||
); | |||
defaultConfigurationIsVisible = 0; | |||
defaultConfigurationName = Release; | |||
}; | |||
34ECFDE22182DD9400B162D4 /* Build configuration list for PBXNativeTarget "lpr" */ = { | |||
isa = XCConfigurationList; | |||
buildConfigurations = ( | |||
34ECFDE32182DD9400B162D4 /* Debug */, | |||
34ECFDE42182DD9400B162D4 /* Release */, | |||
); | |||
defaultConfigurationIsVisible = 0; | |||
defaultConfigurationName = Release; | |||
}; | |||
/* End XCConfigurationList section */ | |||
}; | |||
rootObject = 34ECFDC42182DD9300B162D4 /* Project object */; | |||
} |
@@ -1,7 +0,0 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<Workspace | |||
version = "1.0"> | |||
<FileRef | |||
location = "self:lpr.xcodeproj"> | |||
</FileRef> | |||
</Workspace> |
@@ -1,8 +0,0 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |||
<plist version="1.0"> | |||
<dict> | |||
<key>IDEDidComputeMac32BitWarning</key> | |||
<true/> | |||
</dict> | |||
</plist> |
@@ -1,14 +0,0 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |||
<plist version="1.0"> | |||
<dict> | |||
<key>SchemeUserState</key> | |||
<dict> | |||
<key>lpr.xcscheme</key> | |||
<dict> | |||
<key>orderHint</key> | |||
<integer>2</integer> | |||
</dict> | |||
</dict> | |||
</dict> | |||
</plist> |
@@ -1,10 +0,0 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<Workspace | |||
version = "1.0"> | |||
<FileRef | |||
location = "group:lpr.xcodeproj"> | |||
</FileRef> | |||
<FileRef | |||
location = "group:Pods/Pods.xcodeproj"> | |||
</FileRef> | |||
</Workspace> |
@@ -1,8 +0,0 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |||
<plist version="1.0"> | |||
<dict> | |||
<key>IDEDidComputeMac32BitWarning</key> | |||
<true/> | |||
</dict> | |||
</plist> |
@@ -1,37 +0,0 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<Bucket | |||
type = "0" | |||
version = "2.0"> | |||
<Breakpoints> | |||
<BreakpointProxy | |||
BreakpointExtensionID = "Xcode.Breakpoint.ExceptionBreakpoint"> | |||
<BreakpointContent | |||
shouldBeEnabled = "Yes" | |||
ignoreCount = "0" | |||
continueAfterRunningActions = "No" | |||
scope = "0" | |||
stopOnStyle = "0"> | |||
</BreakpointContent> | |||
</BreakpointProxy> | |||
<BreakpointProxy | |||
BreakpointExtensionID = "Xcode.Breakpoint.OpenGLErrorBreakpoint"> | |||
<BreakpointContent | |||
shouldBeEnabled = "Yes" | |||
ignoreCount = "0" | |||
continueAfterRunningActions = "No" | |||
breakpointStackSelectionBehavior = "1" | |||
symbolName = "__GPUTOOLS_HAS_DETECTED_AN_OPENGL_ERROR__" | |||
moduleName = "libglInterpose.dylib"> | |||
<Actions> | |||
<BreakpointActionProxy | |||
ActionExtensionID = "Xcode.BreakpointAction.OpenGLError"> | |||
<ActionContent> | |||
</ActionContent> | |||
</BreakpointActionProxy> | |||
</Actions> | |||
<Locations> | |||
</Locations> | |||
</BreakpointContent> | |||
</BreakpointProxy> | |||
</Breakpoints> | |||
</Bucket> |
@@ -1,3 +0,0 @@ | |||
.DS_Store | |||
Pods/ | |||
.clang-format |
@@ -1,17 +0,0 @@ | |||
// | |||
// AppDelegate.h | |||
// lpr | |||
// | |||
// Created by baotim on 2018/10/26. | |||
// Copyright © 2018 lprSample. All rights reserved. | |||
// | |||
#import <UIKit/UIKit.h> | |||
@interface AppDelegate : UIResponder <UIApplicationDelegate> | |||
@property (strong, nonatomic) UIWindow *window; | |||
@end | |||
@@ -1,55 +0,0 @@ | |||
// | |||
// AppDelegate.m | |||
// lpr | |||
// | |||
// Created by baotim on 2018/10/26. | |||
// Copyright © 2018 lprSample. All rights reserved. | |||
// | |||
#import "AppDelegate.h" | |||
#import "RootViewController.h" | |||
@interface AppDelegate () | |||
@end | |||
@implementation AppDelegate | |||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { | |||
// Override point for customization after application launch. | |||
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; | |||
self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:[RootViewController new]]; | |||
[self.window makeKeyAndVisible]; | |||
return YES; | |||
} | |||
- (void)applicationWillResignActive:(UIApplication *)application { | |||
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. | |||
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. | |||
} | |||
- (void)applicationDidEnterBackground:(UIApplication *)application { | |||
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. | |||
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. | |||
} | |||
- (void)applicationWillEnterForeground:(UIApplication *)application { | |||
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. | |||
} | |||
- (void)applicationDidBecomeActive:(UIApplication *)application { | |||
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. | |||
} | |||
- (void)applicationWillTerminate:(UIApplication *)application { | |||
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. | |||
} | |||
@end |