Browse Source

format

pull/4/head
jackyu1127 4 years ago
parent
commit
24ecdd93ad
79 changed files with 902 additions and 16634 deletions
  1. +0
    -3
      Prj-Linux/CMakeLists.txt
  2. +9
    -11
      Prj-Linux/hyperlpr/CMakeLists.txt
  3. +0
    -0
      Prj-Linux/hyperlpr/demos/test_detection.cpp
  4. +0
    -0
      Prj-Linux/hyperlpr/demos/test_fastdeskew.cpp
  5. +0
    -0
      Prj-Linux/hyperlpr/demos/test_finemapping.cpp
  6. +0
    -0
      Prj-Linux/hyperlpr/demos/test_pipeline.cpp
  7. +0
    -0
      Prj-Linux/hyperlpr/demos/test_recognization.cpp
  8. +0
    -0
      Prj-Linux/hyperlpr/demos/test_segmentation.cpp
  9. +0
    -0
      Prj-Linux/hyperlpr/demos/test_segmentationFree.cpp
  10. +21
    -0
      Prj-Linux/hyperlpr/src/CNNRecognizer.cpp
  11. +104
    -0
      Prj-Linux/hyperlpr/src/FastDeskew.cpp
  12. +165
    -0
      Prj-Linux/hyperlpr/src/FineMapping.cpp
  13. +82
    -0
      Prj-Linux/hyperlpr/src/Pipeline.cpp
  14. +31
    -0
      Prj-Linux/hyperlpr/src/PlateDetection.cpp
  15. +305
    -0
      Prj-Linux/hyperlpr/src/PlateSegmentation.cpp
  16. +22
    -0
      Prj-Linux/hyperlpr/src/Recognizer.cpp
  17. +87
    -0
      Prj-Linux/hyperlpr/src/SegmentationFreeRecognizer.cpp
  18. +62
    -0
      Prj-Linux/hyperlpr/src/util.h
  19. +0
    -24
      Prj-Linux/lpr/include/CNNRecognizer.h
  20. +0
    -18
      Prj-Linux/lpr/include/FastDeskew.h
  21. +0
    -32
      Prj-Linux/lpr/include/FineMapping.h
  22. +0
    -60
      Prj-Linux/lpr/include/Pipeline.h
  23. +0
    -33
      Prj-Linux/lpr/include/PlateDetection.h
  24. +0
    -126
      Prj-Linux/lpr/include/PlateInfo.h
  25. +0
    -35
      Prj-Linux/lpr/include/PlateSegmentation.h
  26. +0
    -23
      Prj-Linux/lpr/include/Recognizer.h
  27. +0
    -28
      Prj-Linux/lpr/include/SegmentationFreeRecognizer.h
  28. +0
    -107
      Prj-Linux/lpr/include/niBlackThreshold.h
  29. BIN
      Prj-Linux/lpr/model/CharacterRecognization.caffemodel
  30. +0
    -123
      Prj-Linux/lpr/model/CharacterRecognization.prototxt
  31. BIN
      Prj-Linux/lpr/model/HorizonalFinemapping.caffemodel
  32. +0
    -95
      Prj-Linux/lpr/model/HorizonalFinemapping.prototxt
  33. BIN
      Prj-Linux/lpr/model/SegmenationFree-Inception.caffemodel
  34. +0
    -454
      Prj-Linux/lpr/model/SegmenationFree-Inception.prototxt
  35. BIN
      Prj-Linux/lpr/model/Segmentation.caffemodel
  36. +0
    -114
      Prj-Linux/lpr/model/Segmentation.prototxt
  37. +0
    -12117
      Prj-Linux/lpr/model/cascade.xml
  38. +0
    -19
      Prj-Linux/lpr/src/CNNRecognizer.cpp
  39. +0
    -108
      Prj-Linux/lpr/src/FastDeskew.cpp
  40. +0
    -170
      Prj-Linux/lpr/src/FineMapping.cpp
  41. +0
    -85
      Prj-Linux/lpr/src/Pipeline.cpp
  42. +0
    -32
      Prj-Linux/lpr/src/PlateDetection.cpp
  43. +0
    -404
      Prj-Linux/lpr/src/PlateSegmentation.cpp
  44. +0
    -23
      Prj-Linux/lpr/src/Recognizer.cpp
  45. +0
    -89
      Prj-Linux/lpr/src/SegmentationFreeRecognizer.cpp
  46. +0
    -67
      Prj-Linux/lpr/src/util.h
  47. +0
    -28
      Prj-Win/Prj-Win.sln
  48. +0
    -181
      Prj-Win/Prj-Win/Prj-Win.vcxproj
  49. +0
    -84
      Prj-Win/Prj-Win/Prj-Win.vcxproj.filters
  50. +0
    -4
      Prj-Win/Prj-Win/Prj-Win.vcxproj.user
  51. +0
    -24
      Prj-Win/lpr/include/CNNRecognizer.h
  52. +0
    -18
      Prj-Win/lpr/include/FastDeskew.h
  53. +0
    -32
      Prj-Win/lpr/include/FineMapping.h
  54. +0
    -60
      Prj-Win/lpr/include/Pipeline.h
  55. +0
    -33
      Prj-Win/lpr/include/PlateDetection.h
  56. +0
    -126
      Prj-Win/lpr/include/PlateInfo.h
  57. +0
    -35
      Prj-Win/lpr/include/PlateSegmentation.h
  58. +0
    -23
      Prj-Win/lpr/include/Recognizer.h
  59. +0
    -28
      Prj-Win/lpr/include/SegmentationFreeRecognizer.h
  60. +0
    -109
      Prj-Win/lpr/include/niBlackThreshold.h
  61. +0
    -17
      Prj-Win/lpr/model/README.md
  62. BIN
      Prj-Win/lpr/res/test.jpg
  63. +0
    -19
      Prj-Win/lpr/src/CNNRecognizer.cpp
  64. +0
    -108
      Prj-Win/lpr/src/FastDeskew.cpp
  65. +0
    -170
      Prj-Win/lpr/src/FineMapping.cpp
  66. +0
    -85
      Prj-Win/lpr/src/Pipeline.cpp
  67. +0
    -32
      Prj-Win/lpr/src/PlateDetection.cpp
  68. +0
    -404
      Prj-Win/lpr/src/PlateSegmentation.cpp
  69. +0
    -23
      Prj-Win/lpr/src/Recognizer.cpp
  70. +0
    -89
      Prj-Win/lpr/src/SegmentationFreeRecognizer.cpp
  71. +0
    -68
      Prj-Win/lpr/src/util.h
  72. +0
    -34
      Prj-Win/lpr/tests/test_detection.cpp
  73. +0
    -34
      Prj-Win/lpr/tests/test_fastdeskew.cpp
  74. +0
    -25
      Prj-Win/lpr/tests/test_finemapping.cpp
  75. +0
    -184
      Prj-Win/lpr/tests/test_pipeline.cpp
  76. +0
    -54
      Prj-Win/lpr/tests/test_recognization.cpp
  77. +0
    -43
      Prj-Win/lpr/tests/test_segmentation.cpp
  78. +0
    -54
      Prj-Win/lpr/tests/test_segmentationFree.cpp
  79. +14
    -6
      README.md

+ 0
- 3
Prj-Linux/CMakeLists.txt View File

@@ -1,3 +0,0 @@
cmake_minimum_required(VERSION 3.6)
project(SwiftPR)
add_subdirectory(lpr)

Prj-Linux/lpr/CMakeLists.txt → Prj-Linux/hyperlpr/CMakeLists.txt View File

@@ -3,7 +3,8 @@ 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 REQUIRED)

include_directories( ${OpenCV_INCLUDE_DIRS})
include_directories(include)

@@ -21,37 +22,34 @@ 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)
add_executable(TEST_Detection ${SRC_DETECTION} demos/test_detection.cpp)
target_link_libraries(TEST_Detection ${OpenCV_LIBS})

#TEST_FINEMAPPING
add_executable(TEST_FINEMAPPING ${SRC_FINEMAPPING} tests/test_finemapping.cpp)
add_executable(TEST_FINEMAPPING ${SRC_FINEMAPPING} demos/test_finemapping.cpp)
target_link_libraries(TEST_FINEMAPPING ${OpenCV_LIBS})

#TEST_DESKEW

add_executable(TEST_FASTDESKEW ${SRC_FASTDESKEW} tests/test_fastdeskew.cpp)
add_executable(TEST_FASTDESKEW ${SRC_FASTDESKEW} demos/test_fastdeskew.cpp)
target_link_libraries(TEST_FASTDESKEW ${OpenCV_LIBS})

#TEST_SEGMENTATION

add_executable(TEST_SEGMENTATION ${SRC_SEGMENTATION} ${SRC_RECOGNIZE} tests/test_segmentation.cpp)
add_executable(TEST_SEGMENTATION ${SRC_SEGMENTATION} ${SRC_RECOGNIZE} demos/test_segmentation.cpp)
target_link_libraries(TEST_SEGMENTATION ${OpenCV_LIBS})

#TEST_RECOGNIZATION

add_executable(TEST_RECOGNIZATION ${SRC_RECOGNIZE} tests/test_recognization.cpp)
add_executable(TEST_RECOGNIZATION ${SRC_RECOGNIZE} demos/test_recognization.cpp)
target_link_libraries(TEST_RECOGNIZATION ${OpenCV_LIBS})

#TEST_SEGMENTATIONFREE
add_executable(TEST_SEGMENTATIONFREE ${SRC_SEGMENTATIONFREE} tests/test_segmentationFree.cpp)
add_executable(TEST_SEGMENTATIONFREE ${SRC_SEGMENTATIONFREE} demos/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_FINEMAPPING} ${SRC_FASTDESKEW} ${SRC_SEGMENTATION} ${SRC_RECOGNIZE} ${SRC_PIPLINE} ${SRC_SEGMENTATIONFREE} demos/test_pipeline.cpp)
target_link_libraries(TEST_PIPLINE ${OpenCV_LIBS})

Prj-Linux/lpr/tests/test_detection.cpp → Prj-Linux/hyperlpr/demos/test_detection.cpp View File


Prj-Linux/lpr/tests/test_fastdeskew.cpp → Prj-Linux/hyperlpr/demos/test_fastdeskew.cpp View File


Prj-Linux/lpr/tests/test_finemapping.cpp → Prj-Linux/hyperlpr/demos/test_finemapping.cpp View File


Prj-Linux/lpr/tests/test_pipeline.cpp → Prj-Linux/hyperlpr/demos/test_pipeline.cpp View File


Prj-Linux/lpr/tests/test_recognization.cpp → Prj-Linux/hyperlpr/demos/test_recognization.cpp View File


Prj-Linux/lpr/tests/test_segmentation.cpp → Prj-Linux/hyperlpr/demos/test_segmentation.cpp View File


Prj-Linux/lpr/tests/test_segmentationFree.cpp → Prj-Linux/hyperlpr/demos/test_segmentationFree.cpp View File


+ 21
- 0
Prj-Linux/hyperlpr/src/CNNRecognizer.cpp View File

@@ -0,0 +1,21 @@
//
// 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();
}
} // namespace pr

+ 104
- 0
Prj-Linux/hyperlpr/src/FastDeskew.cpp View File

@@ -0,0 +1,104 @@
//
// 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

+ 165
- 0
Prj-Linux/hyperlpr/src/FineMapping.cpp View File

@@ -0,0 +1,165 @@
#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;
}
} // namespace pr

+ 82
- 0
Prj-Linux/hyperlpr/src/Pipeline.cpp View File

@@ -0,0 +1,82 @@
//
// Created by Jack Yu on 23/10/2017.
//

#include "../include/Pipeline.h"
namespace pr {

const int HorizontalPadding = 4;
PipelinePR::PipelinePR(std::string detector_filename,
std::string finemapping_prototxt,
std::string finemapping_caffemodel,
std::string segmentation_prototxt,
std::string segmentation_caffemodel,
std::string charRecognization_proto,
std::string charRecognization_caffemodel,
std::string segmentationfree_proto,
std::string segmentationfree_caffemodel) {
plateDetection = new PlateDetection(detector_filename);
fineMapping = new FineMapping(finemapping_prototxt, finemapping_caffemodel);
plateSegmentation =
new PlateSegmentation(segmentation_prototxt, segmentation_caffemodel);
generalRecognizer =
new CNNRecognizer(charRecognization_proto, charRecognization_caffemodel);
segmentationFreeRecognizer = new SegmentationFreeRecognizer(
segmentationfree_proto, segmentationfree_caffemodel);
}

PipelinePR::~PipelinePR() {

delete plateDetection;
delete fineMapping;
delete plateSegmentation;
delete generalRecognizer;
delete segmentationFreeRecognizer;
}

std::vector<PlateInfo> PipelinePR::RunPiplineAsImage(cv::Mat plateImage,
int method) {
std::vector<PlateInfo> results;
std::vector<pr::PlateInfo> plates;
plateDetection->plateDetectionRough(plateImage, plates, 36, 700);

for (pr::PlateInfo plateinfo : plates) {

cv::Mat image_finemapping = plateinfo.getPlateImage();
image_finemapping = fineMapping->FineMappingVertical(image_finemapping);
image_finemapping = pr::fastdeskew(image_finemapping, 5);
// Segmentation-based
if (method == SEGMENTATION_BASED_METHOD) {
image_finemapping = fineMapping->FineMappingHorizon(image_finemapping, 2,
HorizontalPadding);
cv::resize(image_finemapping, image_finemapping,
cv::Size(136 + HorizontalPadding, 36));
plateinfo.setPlateImage(image_finemapping);
std::vector<cv::Rect> rects;
plateSegmentation->segmentPlatePipline(plateinfo, 1, rects);
plateSegmentation->ExtractRegions(plateinfo, rects);
cv::copyMakeBorder(image_finemapping, image_finemapping, 0, 0, 0, 20,
cv::BORDER_REPLICATE);
plateinfo.setPlateImage(image_finemapping);
generalRecognizer->SegmentBasedSequenceRecognition(plateinfo);
plateinfo.decodePlateNormal(pr::CH_PLATE_CODE);

}
// Segmentation-free
else if (method == SEGMENTATION_FREE_METHOD) {
image_finemapping = fineMapping->FineMappingHorizon(
image_finemapping, 4, HorizontalPadding + 3);
cv::resize(image_finemapping, image_finemapping,
cv::Size(136 + HorizontalPadding, 36));
plateinfo.setPlateImage(image_finemapping);
std::pair<std::string, float> res =
segmentationFreeRecognizer->SegmentationFreeForSinglePlate(
plateinfo.getPlateImage(), pr::CH_PLATE_CODE);
plateinfo.confidence = res.second;
plateinfo.setPlateName(res.first);
}
results.push_back(plateinfo);
}
return results;
}
} // namespace pr

+ 31
- 0
Prj-Linux/hyperlpr/src/PlateDetection.cpp View File

@@ -0,0 +1,31 @@
#include "../include/PlateDetection.h"
#include "util.h"
namespace pr {
PlateDetection::PlateDetection(std::string filename_cascade) {
cascade.load(filename_cascade);
};
void PlateDetection::plateDetectionRough(cv::Mat InputImage,
std::vector<pr::PlateInfo> &plateInfos,
int min_w, int max_w) {
cv::Mat processImage;
cv::cvtColor(InputImage, processImage, cv::COLOR_BGR2GRAY);
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

+ 305
- 0
Prj-Linux/hyperlpr/src/PlateSegmentation.cpp View File

@@ -0,0 +1,305 @@
//
// Created by Jack Yu on 16/10/2017.
//

#include "../include/PlateSegmentation.h"
#include "../include/niBlackThreshold.h"

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);
std::vector<int> candidate_pts(7);
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] * 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::Mat plateImageGray;
cv::cvtColor(plateImage, plateImageGray, cv::COLOR_BGR2GRAY);
int padding = plateImage.cols - 136;
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();
}

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;
}
refineRegion(plateImageGray, sections.second, 5, Char_rects);
}

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::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

+ 22
- 0
Prj-Linux/hyperlpr/src/Recognizer.cpp View File

@@ -0,0 +1,22 @@
//
// 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);
}
}
}
} // namespace pr

+ 87
- 0
Prj-Linux/hyperlpr/src/SegmentationFreeRecognizer.cpp View File

@@ -0,0 +1,87 @@
//
// 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);
}
} // namespace pr

+ 62
- 0
Prj-Linux/hyperlpr/src/util.h View File

@@ -0,0 +1,62 @@
//
// 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
- 24
Prj-Linux/lpr/include/CNNRecognizer.h View File

@@ -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

+ 0
- 18
Prj-Linux/lpr/include/FastDeskew.h View File

@@ -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

+ 0
- 32
Prj-Linux/lpr/include/FineMapping.h View File

@@ -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
- 60
Prj-Linux/lpr/include/Pipeline.h View File

@@ -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

+ 0
- 33
Prj-Linux/lpr/include/PlateDetection.h View File

@@ -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

+ 0
- 126
Prj-Linux/lpr/include/PlateInfo.h View File

@@ -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

+ 0
- 35
Prj-Linux/lpr/include/PlateSegmentation.h View File

@@ -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
- 23
Prj-Linux/lpr/include/Recognizer.h View File

@@ -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

+ 0
- 28
Prj-Linux/lpr/include/SegmentationFreeRecognizer.h View File

@@ -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

+ 0
- 107
Prj-Linux/lpr/include/niBlackThreshold.h View File

@@ -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

BIN
Prj-Linux/lpr/model/CharacterRecognization.caffemodel View File


+ 0
- 123
Prj-Linux/lpr/model/CharacterRecognization.prototxt View File

@@ -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"
}

BIN
Prj-Linux/lpr/model/HorizonalFinemapping.caffemodel View File


+ 0
- 95
Prj-Linux/lpr/model/HorizonalFinemapping.prototxt View File

@@ -1,95 +0,0 @@
input: "data"
input_dim: 1
input_dim: 3
input_dim: 16
input_dim: 66
layer {
name: "conv1"
type: "Convolution"
bottom: "data"
top: "conv1"
convolution_param {
num_output: 10
bias_term: true
pad: 0
kernel_size: 3
stride: 1
}
}
layer {
name: "relu1"
type: "ReLU"
bottom: "conv1"
top: "conv1"
}
layer {
name: "max_pooling2d_3"
type: "Pooling"
bottom: "conv1"
top: "max_pooling2d_3"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
pad: 0
}
}
layer {
name: "conv2"
type: "Convolution"
bottom: "max_pooling2d_3"
top: "conv2"
convolution_param {
num_output: 16
bias_term: true
pad: 0
kernel_size: 3
stride: 1
}
}
layer {
name: "relu2"
type: "ReLU"
bottom: "conv2"
top: "conv2"
}
layer {
name: "conv3"
type: "Convolution"
bottom: "conv2"
top: "conv3"
convolution_param {
num_output: 32
bias_term: true
pad: 0
kernel_size: 3
stride: 1
}
}
layer {
name: "relu3"
type: "ReLU"
bottom: "conv3"
top: "conv3"
}
layer {
name: "flatten_2"
type: "Flatten"
bottom: "conv3"
top: "flatten_2"
}
layer {
name: "dense"
type: "InnerProduct"
bottom: "flatten_2"
top: "dense"
inner_product_param {
num_output: 2
}
}
layer {
name: "relu4"
type: "ReLU"
bottom: "dense"
top: "dense"
}

BIN
Prj-Linux/lpr/model/SegmenationFree-Inception.caffemodel View File


+ 0
- 454
Prj-Linux/lpr/model/SegmenationFree-Inception.prototxt View File

@@ -1,454 +0,0 @@
input: "data"
input_dim: 1
input_dim: 3
input_dim: 160
input_dim: 40
layer {
name: "conv0"
type: "Convolution"
bottom: "data"
top: "conv0"
convolution_param {
num_output: 32
bias_term: true
pad_h: 1
pad_w: 1
kernel_h: 3
kernel_w: 3
stride_h: 1
stride_w: 1
}
}
layer {
name: "bn0"
type: "BatchNorm"
bottom: "conv0"
top: "bn0"
batch_norm_param {
moving_average_fraction: 0.99
eps: 0.001
}
}
layer {
name: "bn0_scale"
type: "Scale"
bottom: "bn0"
top: "bn0"
scale_param {
bias_term: true
}
}
layer {
name: "relu0"
type: "ReLU"
bottom: "bn0"
top: "bn0"
}
layer {
name: "pool0"
type: "Pooling"
bottom: "bn0"
top: "pool0"
pooling_param {
pool: MAX
kernel_h: 2
kernel_w: 2
stride_h: 2
stride_w: 2
pad_h: 0
pad_w: 0
}
}
layer {
name: "conv1"
type: "Convolution"
bottom: "pool0"
top: "conv1"
convolution_param {
num_output: 64
bias_term: true
pad_h: 1
pad_w: 1
kernel_h: 3
kernel_w: 3
stride_h: 1
stride_w: 1
}
}
layer {
name: "bn1"
type: "BatchNorm"
bottom: "conv1"
top: "bn1"
batch_norm_param {
moving_average_fraction: 0.99
eps: 0.001
}
}
layer {
name: "bn1_scale"
type: "Scale"
bottom: "bn1"
top: "bn1"
scale_param {
bias_term: true
}
}
layer {
name: "relu1"
type: "ReLU"
bottom: "bn1"
top: "bn1"
}
layer {
name: "pool1"
type: "Pooling"
bottom: "bn1"
top: "pool1"
pooling_param {
pool: MAX
kernel_h: 2
kernel_w: 2
stride_h: 2
stride_w: 2
pad_h: 0
pad_w: 0
}
}
layer {
name: "conv2"
type: "Convolution"
bottom: "pool1"
top: "conv2"
convolution_param {
num_output: 128
bias_term: true
pad_h: 1
pad_w: 1
kernel_h: 3
kernel_w: 3
stride_h: 1
stride_w: 1
}
}
layer {
name: "bn2"
type: "BatchNorm"
bottom: "conv2"
top: "bn2"
batch_norm_param {
moving_average_fraction: 0.99
eps: 0.001
}
}
layer {
name: "bn2_scale"
type: "Scale"
bottom: "bn2"
top: "bn2"
scale_param {
bias_term: true
}
}
layer {
name: "relu2"
type: "ReLU"
bottom: "bn2"
top: "bn2"
}
layer {
name: "pool2"
type: "Pooling"
bottom: "bn2"
top: "pool2"
pooling_param {
pool: MAX
kernel_h: 2
kernel_w: 2
stride_h: 2
stride_w: 2
pad_h: 0
pad_w: 0
}
}
layer {
name: "conv2d_1"
type: "Convolution"
bottom: "pool2"
top: "conv2d_1"
convolution_param {
num_output: 256
bias_term: true
pad_h: 0
pad_w: 0
kernel_h: 1
kernel_w: 5
stride_h: 1
stride_w: 1
}
}
layer {
name: "batch_normalization_1"
type: "BatchNorm"
bottom: "conv2d_1"
top: "batch_normalization_1"
batch_norm_param {
moving_average_fraction: 0.99
eps: 0.001
}
}
layer {
name: "batch_normalization_1_scale"
type: "Scale"
bottom: "batch_normalization_1"
top: "batch_normalization_1"
scale_param {
bias_term: true
}
}
layer {
name: "activation_1"
type: "ReLU"
bottom: "batch_normalization_1"
top: "batch_normalization_1"
}
layer {
name: "conv2d_2"
type: "Convolution"
bottom: "batch_normalization_1"
top: "conv2d_2"
convolution_param {
num_output: 256
bias_term: true
pad_h: 3
pad_w: 0
kernel_h: 7
kernel_w: 1
stride_h: 1
stride_w: 1
}
}
layer {
name: "conv2d_3"
type: "Convolution"
bottom: "batch_normalization_1"
top: "conv2d_3"
convolution_param {
num_output: 256
bias_term: true
pad_h: 2
pad_w: 0
kernel_h: 5
kernel_w: 1
stride_h: 1
stride_w: 1
}
}
layer {
name: "conv2d_4"
type: "Convolution"
bottom: "batch_normalization_1"
top: "conv2d_4"
convolution_param {
num_output: 256
bias_term: true
pad_h: 1
pad_w: 0
kernel_h: 3
kernel_w: 1
stride_h: 1
stride_w: 1
}
}
layer {
name: "conv2d_5"
type: "Convolution"
bottom: "batch_normalization_1"
top: "conv2d_5"
convolution_param {
num_output: 256
bias_term: true
pad_h: 0
pad_w: 0
kernel_h: 1
kernel_w: 1
stride_h: 1
stride_w: 1
}
}
layer {
name: "batch_normalization_2"
type: "BatchNorm"
bottom: "conv2d_2"
top: "batch_normalization_2"
batch_norm_param {
moving_average_fraction: 0.99
eps: 0.001
}
}
layer {
name: "batch_normalization_2_scale"
type: "Scale"
bottom: "batch_normalization_2"
top: "batch_normalization_2"
scale_param {
bias_term: true
}
}
layer {
name: "batch_normalization_3"
type: "BatchNorm"
bottom: "conv2d_3"
top: "batch_normalization_3"
batch_norm_param {
moving_average_fraction: 0.99
eps: 0.001
}
}
layer {
name: "batch_normalization_3_scale"
type: "Scale"
bottom: "batch_normalization_3"
top: "batch_normalization_3"
scale_param {
bias_term: true
}
}
layer {
name: "batch_normalization_4"
type: "BatchNorm"
bottom: "conv2d_4"
top: "batch_normalization_4"
batch_norm_param {
moving_average_fraction: 0.99
eps: 0.001
}
}
layer {
name: "batch_normalization_4_scale"
type: "Scale"
bottom: "batch_normalization_4"
top: "batch_normalization_4"
scale_param {
bias_term: true
}
}
layer {
name: "batch_normalization_5"
type: "BatchNorm"
bottom: "conv2d_5"
top: "batch_normalization_5"
batch_norm_param {
moving_average_fraction: 0.99
eps: 0.001
}
}
layer {
name: "batch_normalization_5_scale"
type: "Scale"
bottom: "batch_normalization_5"
top: "batch_normalization_5"
scale_param {
bias_term: true
}
}
layer {
name: "activation_2"
type: "ReLU"
bottom: "batch_normalization_2"
top: "batch_normalization_2"
}
layer {
name: "activation_3"
type: "ReLU"
bottom: "batch_normalization_3"
top: "batch_normalization_3"
}
layer {
name: "activation_4"
type: "ReLU"
bottom: "batch_normalization_4"
top: "batch_normalization_4"
}
layer {
name: "activation_5"
type: "ReLU"
bottom: "batch_normalization_5"
top: "batch_normalization_5"
}
layer {
name: "concatenate_1"
type: "Concat"
bottom: "batch_normalization_2"
bottom: "batch_normalization_3"
bottom: "batch_normalization_4"
bottom: "batch_normalization_5"
top: "concatenate_1"
concat_param {
axis: 1
}
}
layer {
name: "conv_1024_11"
type: "Convolution"
bottom: "concatenate_1"
top: "conv_1024_11"
convolution_param {
num_output: 1024
bias_term: true
pad_h: 0
pad_w: 0
kernel_h: 1
kernel_w: 1
stride_h: 1
stride_w: 1
}
}
layer {
name: "batch_normalization_6"
type: "BatchNorm"
bottom: "conv_1024_11"
top: "batch_normalization_6"
batch_norm_param {
moving_average_fraction: 0.99
eps: 0.001
}
}
layer {
name: "batch_normalization_6_scale"
type: "Scale"
bottom: "batch_normalization_6"
top: "batch_normalization_6"
scale_param {
bias_term: true
}
}
layer {
name: "activation_6"
type: "ReLU"
bottom: "batch_normalization_6"
top: "batch_normalization_6"
}
layer {
name: "conv_class_11"
type: "Convolution"
bottom: "batch_normalization_6"
top: "conv_class_11"
convolution_param {
num_output: 84
bias_term: true
pad_h: 0
pad_w: 0
kernel_h: 1
kernel_w: 1
stride_h: 1
stride_w: 1
}
}
layer {
name: "prob"
type: "Softmax"
bottom: "conv_class_11"
top: "prob"
}


BIN
Prj-Linux/lpr/model/Segmentation.caffemodel View File


+ 0
- 114
Prj-Linux/lpr/model/Segmentation.prototxt View File

@@ -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
- 12117
Prj-Linux/lpr/model/cascade.xml
File diff suppressed because it is too large
View File


+ 0
- 19
Prj-Linux/lpr/src/CNNRecognizer.cpp View File

@@ -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();
}
}

+ 0
- 108
Prj-Linux/lpr/src/FastDeskew.cpp View File

@@ -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

+ 0
- 170
Prj-Linux/lpr/src/FineMapping.cpp View File

@@ -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;
}
}



+ 0
- 85
Prj-Linux/lpr/src/Pipeline.cpp View File

@@ -1,85 +0,0 @@
//
// Created by Jack Yu on 23/10/2017.
//

#include "../include/Pipeline.h"


namespace pr {



const int HorizontalPadding = 4;
PipelinePR::PipelinePR(std::string detector_filename,
std::string finemapping_prototxt, std::string finemapping_caffemodel,
std::string segmentation_prototxt, std::string segmentation_caffemodel,
std::string charRecognization_proto, std::string charRecognization_caffemodel,
std::string segmentationfree_proto,std::string segmentationfree_caffemodel) {
plateDetection = new PlateDetection(detector_filename);
fineMapping = new FineMapping(finemapping_prototxt, finemapping_caffemodel);
plateSegmentation = new PlateSegmentation(segmentation_prototxt, segmentation_caffemodel);
generalRecognizer = new CNNRecognizer(charRecognization_proto, charRecognization_caffemodel);
segmentationFreeRecognizer = new SegmentationFreeRecognizer(segmentationfree_proto,segmentationfree_caffemodel);

}

PipelinePR::~PipelinePR() {

delete plateDetection;
delete fineMapping;
delete plateSegmentation;
delete generalRecognizer;
delete segmentationFreeRecognizer;


}

std::vector<PlateInfo> PipelinePR:: RunPiplineAsImage(cv::Mat plateImage,int method) {
std::vector<PlateInfo> results;
std::vector<pr::PlateInfo> plates;
plateDetection->plateDetectionRough(plateImage,plates,36,700);

for (pr::PlateInfo plateinfo:plates) {

cv::Mat image_finemapping = plateinfo.getPlateImage();
image_finemapping = fineMapping->FineMappingVertical(image_finemapping);
image_finemapping = pr::fastdeskew(image_finemapping, 5);



//Segmentation-based

if(method==SEGMENTATION_BASED_METHOD)
{
image_finemapping = fineMapping->FineMappingHorizon(image_finemapping, 2, HorizontalPadding);
cv::resize(image_finemapping, image_finemapping, cv::Size(136+HorizontalPadding, 36));
plateinfo.setPlateImage(image_finemapping);
std::vector<cv::Rect> rects;
plateSegmentation->segmentPlatePipline(plateinfo, 1, rects);
plateSegmentation->ExtractRegions(plateinfo, rects);
cv::copyMakeBorder(image_finemapping, image_finemapping, 0, 0, 0, 20, cv::BORDER_REPLICATE);
plateinfo.setPlateImage(image_finemapping);
generalRecognizer->SegmentBasedSequenceRecognition(plateinfo);
plateinfo.decodePlateNormal(pr::CH_PLATE_CODE);

}
//Segmentation-free
else if(method==SEGMENTATION_FREE_METHOD)
{
image_finemapping = fineMapping->FineMappingHorizon(image_finemapping, 4, HorizontalPadding+3);
cv::resize(image_finemapping, image_finemapping, cv::Size(136+HorizontalPadding, 36));
plateinfo.setPlateImage(image_finemapping);
std::pair<std::string,float> res = segmentationFreeRecognizer->SegmentationFreeForSinglePlate(plateinfo.getPlateImage(),pr::CH_PLATE_CODE);
plateinfo.confidence = res.second;
plateinfo.setPlateName(res.first);
}
results.push_back(plateinfo);
}

return results;

}//namespace pr



}

+ 0
- 32
Prj-Linux/lpr/src/PlateDetection.cpp View File

@@ -1,32 +0,0 @@
#include "../include/PlateDetection.h"
#include "util.h"
namespace pr{
PlateDetection::PlateDetection(std::string filename_cascade){
cascade.load(filename_cascade);

};
void PlateDetection::plateDetectionRough(cv::Mat InputImage,std::vector<pr::PlateInfo> &plateInfos,int min_w,int max_w){
cv::Mat processImage;
cv::cvtColor(InputImage,processImage,cv::COLOR_BGR2GRAY);
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

+ 0
- 404
Prj-Linux/lpr/src/PlateSegmentation.cpp View File

@@ -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

+ 0
- 23
Prj-Linux/lpr/src/Recognizer.cpp View File

@@ -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);
}
}
}
}

+ 0
- 89
Prj-Linux/lpr/src/SegmentationFreeRecognizer.cpp View File

@@ -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);
}
}

+ 0
- 67
Prj-Linux/lpr/src/util.h View File

@@ -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
- 28
Prj-Win/Prj-Win.sln View File

@@ -1,28 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Prj-Win", "Prj-Win\Prj-Win.vcxproj", "{69FAD143-D7C9-4804-A186-90254BD80549}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{69FAD143-D7C9-4804-A186-90254BD80549}.Debug|x64.ActiveCfg = Debug|x64
{69FAD143-D7C9-4804-A186-90254BD80549}.Debug|x64.Build.0 = Debug|x64
{69FAD143-D7C9-4804-A186-90254BD80549}.Debug|x86.ActiveCfg = Debug|Win32
{69FAD143-D7C9-4804-A186-90254BD80549}.Debug|x86.Build.0 = Debug|Win32
{69FAD143-D7C9-4804-A186-90254BD80549}.Release|x64.ActiveCfg = Release|x64
{69FAD143-D7C9-4804-A186-90254BD80549}.Release|x64.Build.0 = Release|x64
{69FAD143-D7C9-4804-A186-90254BD80549}.Release|x86.ActiveCfg = Release|Win32
{69FAD143-D7C9-4804-A186-90254BD80549}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

+ 0
- 181
Prj-Win/Prj-Win/Prj-Win.vcxproj View File

@@ -1,181 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{69FAD143-D7C9-4804-A186-90254BD80549}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>PrjWin</RootNamespace>
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>D:\opencv\build\include\opencv2;D:\opencv\build\include\opencv;D:\opencv\build\include;$(IncludePath)</IncludePath>
<LibraryPath>D:\opencv\build\x64\vc14\lib;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>D:\Prj-Win\lpr\include;D:\opencv\build\include;D:\opencv\build\include\opencv2;$(IncludePath)</IncludePath>
<LibraryPath>D:\opencv\build\x64\vc15\lib;$(LibraryPath)</LibraryPath>
<OutDir>$(SolutionDir)Build\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>opencv_world400d.lib;opencv_world400.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\lpr\include\CNNRecognizer.h" />
<ClInclude Include="..\lpr\include\FastDeskew.h" />
<ClInclude Include="..\lpr\include\FineMapping.h" />
<ClInclude Include="..\lpr\include\niBlackThreshold.h" />
<ClInclude Include="..\lpr\include\Pipeline.h" />
<ClInclude Include="..\lpr\include\PlateDetection.h" />
<ClInclude Include="..\lpr\include\PlateInfo.h" />
<ClInclude Include="..\lpr\include\PlateSegmentation.h" />
<ClInclude Include="..\lpr\include\Recognizer.h" />
<ClInclude Include="..\lpr\include\SegmentationFreeRecognizer.h" />
<ClInclude Include="..\lpr\src\util.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\lpr\src\CNNRecognizer.cpp" />
<ClCompile Include="..\lpr\src\FastDeskew.cpp" />
<ClCompile Include="..\lpr\src\FineMapping.cpp" />
<ClCompile Include="..\lpr\src\Pipeline.cpp" />
<ClCompile Include="..\lpr\src\PlateDetection.cpp" />
<ClCompile Include="..\lpr\src\PlateSegmentation.cpp" />
<ClCompile Include="..\lpr\src\Recognizer.cpp" />
<ClCompile Include="..\lpr\src\SegmentationFreeRecognizer.cpp" />
<ClCompile Include="..\lpr\tests\test_pipeline.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

+ 0
- 84
Prj-Win/Prj-Win/Prj-Win.vcxproj.filters View File

@@ -1,84 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="源文件">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="头文件">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="资源文件">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="源文件\test">
<UniqueIdentifier>{40ff6658-4f52-40c1-8658-4ae399661603}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\lpr\include\CNNRecognizer.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="..\lpr\include\FastDeskew.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="..\lpr\include\FineMapping.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="..\lpr\include\niBlackThreshold.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="..\lpr\include\Pipeline.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="..\lpr\include\PlateDetection.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="..\lpr\include\PlateInfo.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="..\lpr\include\PlateSegmentation.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="..\lpr\include\Recognizer.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="..\lpr\src\util.h">
<Filter>源文件</Filter>
</ClInclude>
<ClInclude Include="..\lpr\include\SegmentationFreeRecognizer.h">
<Filter>头文件</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\lpr\src\CNNRecognizer.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="..\lpr\src\FastDeskew.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="..\lpr\src\FineMapping.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="..\lpr\src\PlateDetection.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="..\lpr\src\PlateSegmentation.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="..\lpr\src\Recognizer.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="..\lpr\tests\test_pipeline.cpp">
<Filter>源文件\test</Filter>
</ClCompile>
<ClCompile Include="..\lpr\src\Pipeline.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="..\lpr\src\SegmentationFreeRecognizer.cpp">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
</Project>

+ 0
- 4
Prj-Win/Prj-Win/Prj-Win.vcxproj.user View File

@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>

+ 0
- 24
Prj-Win/lpr/include/CNNRecognizer.h View File

@@ -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

+ 0
- 18
Prj-Win/lpr/include/FastDeskew.h View File

@@ -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

+ 0
- 32
Prj-Win/lpr/include/FineMapping.h View File

@@ -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
- 60
Prj-Win/lpr/include/Pipeline.h View File

@@ -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

+ 0
- 33
Prj-Win/lpr/include/PlateDetection.h View File

@@ -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

+ 0
- 126
Prj-Win/lpr/include/PlateInfo.h View File

@@ -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

+ 0
- 35
Prj-Win/lpr/include/PlateSegmentation.h View File

@@ -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
- 23
Prj-Win/lpr/include/Recognizer.h View File

@@ -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

+ 0
- 28
Prj-Win/lpr/include/SegmentationFreeRecognizer.h View File

@@ -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

+ 0
- 109
Prj-Win/lpr/include/niBlackThreshold.h View File

@@ -1,109 +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" );
CV_Error(-5, "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" );
CV_Error(-5, "Unknown threshold type");
break;
}
}

#endif //SWIFTPR_NIBLACKTHRESHOLD_H

+ 0
- 17
Prj-Win/lpr/model/README.md View File

@@ -1,17 +0,0 @@
将/Prj-Linux/lpr/model目录下的

cascade.xml

CharacterRecognization.caffemodel

CharacterRecognization.prototxt

HorizonalFinemapping.caffemodel

HorizonalFinemapping.prototxt

SegmentationFree.caffemodel

SegmentationFree.prototxt

放置在该目录

BIN
Prj-Win/lpr/res/test.jpg View File

Before After
Width: 500  |  Height: 375  |  Size: 32 kB

+ 0
- 19
Prj-Win/lpr/src/CNNRecognizer.cpp View File

@@ -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();
}
}

+ 0
- 108
Prj-Win/lpr/src/FastDeskew.cpp View File

@@ -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

+ 0
- 170
Prj-Win/lpr/src/FineMapping.cpp View File

@@ -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;
}
}



+ 0
- 85
Prj-Win/lpr/src/Pipeline.cpp View File

@@ -1,85 +0,0 @@
//
// Created by Jack Yu on 23/10/2017.
//

#include "../include/Pipeline.h"


namespace pr {



const int HorizontalPadding = 4;
PipelinePR::PipelinePR(std::string detector_filename,
std::string finemapping_prototxt, std::string finemapping_caffemodel,
std::string segmentation_prototxt, std::string segmentation_caffemodel,
std::string charRecognization_proto, std::string charRecognization_caffemodel,
std::string segmentationfree_proto,std::string segmentationfree_caffemodel) {
plateDetection = new PlateDetection(detector_filename);
fineMapping = new FineMapping(finemapping_prototxt, finemapping_caffemodel);
plateSegmentation = new PlateSegmentation(segmentation_prototxt, segmentation_caffemodel);
generalRecognizer = new CNNRecognizer(charRecognization_proto, charRecognization_caffemodel);
segmentationFreeRecognizer = new SegmentationFreeRecognizer(segmentationfree_proto,segmentationfree_caffemodel);

}

PipelinePR::~PipelinePR() {

delete plateDetection;
delete fineMapping;
delete plateSegmentation;
delete generalRecognizer;
delete segmentationFreeRecognizer;


}

std::vector<PlateInfo> PipelinePR:: RunPiplineAsImage(cv::Mat plateImage,int method) {
std::vector<PlateInfo> results;
std::vector<pr::PlateInfo> plates;
plateDetection->plateDetectionRough(plateImage,plates,36,700);

for (pr::PlateInfo plateinfo:plates) {

cv::Mat image_finemapping = plateinfo.getPlateImage();
image_finemapping = fineMapping->FineMappingVertical(image_finemapping);
image_finemapping = pr::fastdeskew(image_finemapping, 5);



//Segmentation-based

if(method==SEGMENTATION_BASED_METHOD)
{
image_finemapping = fineMapping->FineMappingHorizon(image_finemapping, 2, HorizontalPadding);
cv::resize(image_finemapping, image_finemapping, cv::Size(136+HorizontalPadding, 36));
plateinfo.setPlateImage(image_finemapping);
std::vector<cv::Rect> rects;
plateSegmentation->segmentPlatePipline(plateinfo, 1, rects);
plateSegmentation->ExtractRegions(plateinfo, rects);
cv::copyMakeBorder(image_finemapping, image_finemapping, 0, 0, 0, 20, cv::BORDER_REPLICATE);
plateinfo.setPlateImage(image_finemapping);
generalRecognizer->SegmentBasedSequenceRecognition(plateinfo);
plateinfo.decodePlateNormal(pr::CH_PLATE_CODE);

}
//Segmentation-free
else if(method==SEGMENTATION_FREE_METHOD)
{
image_finemapping = fineMapping->FineMappingHorizon(image_finemapping, 4, HorizontalPadding+3);
cv::resize(image_finemapping, image_finemapping, cv::Size(136+HorizontalPadding, 36));
plateinfo.setPlateImage(image_finemapping);
std::pair<std::string,float> res = segmentationFreeRecognizer->SegmentationFreeForSinglePlate(plateinfo.getPlateImage(),pr::CH_PLATE_CODE);
plateinfo.confidence = res.second;
plateinfo.setPlateName(res.first);
}
results.push_back(plateinfo);
}

return results;

}//namespace pr



}

+ 0
- 32
Prj-Win/lpr/src/PlateDetection.cpp View File

@@ -1,32 +0,0 @@
#include "../include/PlateDetection.h"
#include "util.h"
namespace pr{
PlateDetection::PlateDetection(std::string filename_cascade){
cascade.load(filename_cascade);

};
void PlateDetection::plateDetectionRough(cv::Mat InputImage,std::vector<pr::PlateInfo> &plateInfos,int min_w,int max_w){
cv::Mat processImage;
cv::cvtColor(InputImage,processImage,cv::COLOR_BGR2GRAY);
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

+ 0
- 404
Prj-Win/lpr/src/PlateSegmentation.cpp View File

@@ -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 && 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

+ 0
- 23
Prj-Win/lpr/src/Recognizer.cpp View File

@@ -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);
}
}
}
}

+ 0
- 89
Prj-Win/lpr/src/SegmentationFreeRecognizer.cpp View File

@@ -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);
}
}

+ 0
- 68
Prj-Win/lpr/src/util.h View File

@@ -1,68 +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);
return cv::compareHist(histA, histB, 0);
}
}//namespace util

+ 0
- 34
Prj-Win/lpr/tests/test_detection.cpp View File

@@ -1,34 +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 ;


}

+ 0
- 34
Prj-Win/lpr/tests/test_fastdeskew.cpp View File

@@ -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 ;


}

+ 0
- 25
Prj-Win/lpr/tests/test_finemapping.cpp View File

@@ -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 ;

}

+ 0
- 184
Prj-Win/lpr/tests/test_pipeline.cpp View File

@@ -1,184 +0,0 @@
//
// Created by Jack Yu on 23/10/2017.
//

#include "../include/Pipeline.h"
#include<fstream>
#include<vector>



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_CAM()
{
cv::VideoCapture capture("test1.mp4");
cv::Mat frame;
pr::PipelinePR prc("../lpr/model/cascade.xml",
"../lpr/model/HorizonalFinemapping.prototxt", "../lpr/model/HorizonalFinemapping.caffemodel",
"../lpr/model/Segmentation.prototxt", "../lpr/model/Segmentation.caffemodel",
"../lpr/model/CharacterRecognization.prototxt", "../lpr/model/CharacterRecognization.caffemodel",
"../lpr/model/SegmenationFree-Inception.prototxt", "../lpr/model/SegmenationFree-Inception.caffemodel"
);
while (1) {
//读取下一帧
if (!capture.read(frame)) {
std::cout << "读取视频失败" << std::endl;
exit(1);
}
//
// cv::transpose(frame,frame);
// cv::flip(frame,frame,2);

// cv::resize(frame,frame,cv::Size(frame.cols/2,frame.rows/2));


std::vector<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);
}
}


void TEST_ACC() {

pr::PipelinePR prc("../lpr/model/cascade.xml",
"../lpr/model/HorizonalFinemapping.prototxt", "../lpr/model/HorizonalFinemapping.caffemodel",
"../lpr/model/Segmentation.prototxt", "../lpr/model/Segmentation.caffemodel",
"../lpr/model/CharacterRecognization.prototxt", "../lpr/model/CharacterRecognization.caffemodel",
"../lpr/model/SegmenationFree-Inception.prototxt", "../lpr/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("../lpr/model/cascade.xml",
"../lpr/model/HorizonalFinemapping.prototxt", "../lpr/model/HorizonalFinemapping.caffemodel",
"../lpr/model/Segmentation.prototxt", "../lpr/model/Segmentation.caffemodel",
"../lpr/model/CharacterRecognization.prototxt", "../lpr/model/CharacterRecognization.caffemodel",
"../lpr/model/SegmenationFree-Inception.prototxt", "../lpr/model/SegmenationFree-Inception.caffemodel"
);

cv::Mat image = cv::imread("../lpr/res/test.jpg");


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);

}


int main()
{
// TEST_ACC();

// TEST_CAM();
TEST_PIPELINE();
return 0;
}

+ 0
- 54
Prj-Win/lpr/tests/test_recognization.cpp View File

@@ -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();


}

+ 0
- 43
Prj-Win/lpr/tests/test_segmentation.cpp View File

@@ -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;
}

+ 0
- 54
Prj-Win/lpr/tests/test_segmentationFree.cpp View File

@@ -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;

}

+ 14
- 6
README.md View File

@@ -196,9 +196,17 @@ int main(){

- HyperLPR讨论QQ群1: 673071218(已满,邀请可进), 群2: 746123554 ,加前请备注HyperLPR交流。

#### 联系方式:

- JackYu (jackyu@zeusee.com)

- Zeusee (contact@zeusee.com)

### 作者和贡献者信息:

##### 作者昵称不分前后

- Jack Yu 作者(jack-yu-business@foxmail.com / https://github.com/szad670401)
- AlanNewImage v2版win工程、python双层完善 (https://github.com/AlanNewImage)
- lsy17096535 整理(https://github.com/lsy17096535)
- xiaojun123456 IOS贡献(https://github.com/xiaojun123456)
- sundyCoder Android第三方贡献(https://github.com/sundyCoder)
- coleflowers php贡献(@coleflowers)
- Free&Easy 资源贡献
- 海豚嘎嘎 LBP cascade检测器训练
- Windows工程端到端模型 (https://github.com/SalamanderEyes)
- Android实时扫描实现 (https://github.com/lxhAndSmh)

Loading…
Cancel
Save