src change
parent
24ecdd93ad
commit
632c7de2ed
@ -0,0 +1,24 @@
|
|||||||
|
//
|
||||||
|
// Created by Jack Yu on 21/10/2017.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef HYPERPR_CNNRECOGNIZER_H
|
||||||
|
#define HYPERPR_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;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace pr
|
||||||
|
|
||||||
|
#endif // HYPERPR_CNNRECOGNIZER_H
|
@ -0,0 +1,17 @@
|
|||||||
|
//
|
||||||
|
// Created by Jack Yu on 22/09/2017.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef HYPERPR_FASTDESKEW_H
|
||||||
|
#define HYPERPR_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);
|
||||||
|
|
||||||
|
} // namespace pr
|
||||||
|
|
||||||
|
#endif // HYPERPR_FASTDESKEW_H
|
@ -0,0 +1,29 @@
|
|||||||
|
//
|
||||||
|
// Created by Jack Yu on 22/09/2017.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef HYPERPR_FINEMAPPING_H
|
||||||
|
#define HYPERPR_FINEMAPPING_H
|
||||||
|
|
||||||
|
#include <opencv2/dnn.hpp>
|
||||||
|
#include <opencv2/opencv.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;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace pr
|
||||||
|
#endif // HYPERPR_FINEMAPPING_H
|
@ -0,0 +1,54 @@
|
|||||||
|
//
|
||||||
|
// Created by Jack Yu on 22/10/2017.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef HYPERPR_PIPLINE_H
|
||||||
|
#define HYPERPR_PIPLINE_H
|
||||||
|
|
||||||
|
#include "CNNRecognizer.h"
|
||||||
|
#include "FastDeskew.h"
|
||||||
|
#include "FineMapping.h"
|
||||||
|
#include "PlateDetection.h"
|
||||||
|
#include "PlateInfo.h"
|
||||||
|
#include "PlateSegmentation.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);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace pr
|
||||||
|
#endif // HYPERPR_PIPLINE_H
|
@ -0,0 +1,32 @@
|
|||||||
|
//
|
||||||
|
// Created by Jack Yu on 20/09/2017.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef HYPERPR_PLATEDETECTION_H
|
||||||
|
#define HYPERPR_PLATEDETECTION_H
|
||||||
|
|
||||||
|
#include <PlateInfo.h>
|
||||||
|
#include <opencv2/opencv.hpp>
|
||||||
|
#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 // HYPERPR_PLATEDETECTION_H
|
@ -0,0 +1,94 @@
|
|||||||
|
//
|
||||||
|
// Created by Jack Yu on 20/09/2017.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef HYPERPR_PLATEINFO_H
|
||||||
|
#define HYPERPR_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);
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
} else if (plate.first == INVALID) {
|
||||||
|
decode += '*';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
name = decode;
|
||||||
|
|
||||||
|
confidence /= 7;
|
||||||
|
|
||||||
|
return decode;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
cv::Mat licensePlate;
|
||||||
|
cv::Rect ROI;
|
||||||
|
std::string name;
|
||||||
|
PlateColor Type;
|
||||||
|
};
|
||||||
|
} // namespace pr
|
||||||
|
|
||||||
|
#endif // HYPERPR_PLATEINFO_H
|
@ -0,0 +1,35 @@
|
|||||||
|
#ifndef HYPERPR_PLATESEGMENTATION_H
|
||||||
|
#define HYPERPR_PLATESEGMENTATION_H
|
||||||
|
|
||||||
|
#include "PlateInfo.h"
|
||||||
|
#include "opencv2/opencv.hpp"
|
||||||
|
#include <opencv2/dnn.hpp>
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace pr
|
||||||
|
|
||||||
|
#endif // HYPERPR_PLATESEGMENTATION_H
|
@ -0,0 +1,22 @@
|
|||||||
|
//
|
||||||
|
// Created by Jack Yu on 20/10/2017.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef HYPERPR_RECOGNIZER_H
|
||||||
|
#define HYPERPR_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);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace pr
|
||||||
|
#endif // HYPERPR_RECOGNIZER_H
|
@ -0,0 +1,27 @@
|
|||||||
|
//
|
||||||
|
// Created by Jack Yu on 28/11/2017.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef HYPERPR_SEGMENTATIONFREERECOGNIZER_H
|
||||||
|
#define HYPERPR_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;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace pr
|
||||||
|
#endif // HYPERPR_SEGMENTATIONFREERECOGNIZER_H
|
@ -0,0 +1,105 @@
|
|||||||
|
//
|
||||||
|
// Created by Jack Yu on 26/10/2017.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef HYPERPR_NIBLACKTHRESHOLD_H
|
||||||
|
#define HYPERPR_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 // HYPERPR_NIBLACKTHRESHOLD_H
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue