@@ -6,3 +6,4 @@ | |||||
Prj-Linux/lpr/TEST_* | Prj-Linux/lpr/TEST_* | ||||
Prj-Linux/*build*/ | Prj-Linux/*build*/ | ||||
*.pyc | *.pyc | ||||
/Prj-PHP/build |
@@ -1,21 +1,12 @@ | |||||
cmake_minimum_required(VERSION 3.6) | cmake_minimum_required(VERSION 3.6) | ||||
project(platescan) | project(platescan) | ||||
set(OpenCV_DIR /usr/platescan/opencv-3.3.0/release/) | |||||
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -g -O2 -std=c++11 -fpic -o") | |||||
#set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) | |||||
set(CMAKE_CXX_STANDARD 11) | |||||
set(PHP_CONFIG_DIR /etc/php.d/) | |||||
set(PHP_CONFIG php-config) | |||||
set(POST_COMPILE_COMMAND systemctl restart php-fpm) | |||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") | |||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) | |||||
find_package(OpenCV 3.3.0 REQUIRED) | find_package(OpenCV 3.3.0 REQUIRED) | ||||
include_directories( ${OpenCV_INCLUDE_DIRS}) | include_directories( ${OpenCV_INCLUDE_DIRS}) | ||||
include_directories(include) | include_directories(include) | ||||
add_library( # Sets the name of the library. | add_library( # Sets the name of the library. | ||||
platescan | platescan | ||||
@@ -42,10 +33,10 @@ target_link_libraries( | |||||
${OpenCV_LIBS} | ${OpenCV_LIBS} | ||||
) | ) | ||||
execute_process(COMMAND ${PHP_CONFIG} --extension-dir | |||||
execute_process(COMMAND php-config --extension-dir | |||||
OUTPUT_VARIABLE LIBRARY_DIR) | OUTPUT_VARIABLE LIBRARY_DIR) | ||||
message("Test ${LIBRARY_DIR} failed.") | |||||
message("PHP_EXTENSIONS_DIR ${LIBRARY_DIR}") | |||||
add_custom_command(TARGET platescan | add_custom_command(TARGET platescan | ||||
POST_BUILD | POST_BUILD | ||||
@@ -1,9 +1,29 @@ | |||||
# Prj-PHP | # Prj-PHP | ||||
HyperLPR 在PHP扩展程序中的实现,核心代码拷贝了 Prj-Linux 中庾金科大牛的代码。我做的这部分工作主要是配置编译成PHP扩展程序。 | HyperLPR 在PHP扩展程序中的实现,核心代码拷贝了 Prj-Linux 中庾金科大牛的代码。我做的这部分工作主要是配置编译成PHP扩展程序。 | ||||
## CPP 依赖 | |||||
+ Opencv 3.3 | |||||
+ PHPCPP | |||||
## Linux/Mac 编译 | |||||
```bash | |||||
mkdir build | |||||
cd build | |||||
cmake ../ | |||||
make -j | |||||
``` | |||||
## DEMO | |||||
```php | ```php | ||||
$path = realpath("demo.png"); | |||||
$res = platescan($path); | |||||
// 也可编译完后直接在tests目录直接运行 php platescan.php | |||||
$path = realpath("demo.png"); // 图片文件所在路径,realpath转为绝对路径 | |||||
$model = realpath("model"); // 模型资源所在文件夹 | |||||
$res = platescan($path, $model, 0.8); | |||||
var_dump($res); // string(9) "苏ED0N19" | var_dump($res); // string(9) "苏ED0N19" | ||||
``` | ``` | ||||
@@ -12,5 +32,19 @@ var_dump($res); // string(9) "苏ED0N19" | |||||
![image](./tests/demo.png) | ![image](./tests/demo.png) | ||||
## 测试备忘 | |||||
经多次测试发现部分图片难以识别或者容易识别错误,经过筛选反推出如下规律: | |||||
### 识别精度高的图片 | |||||
+ 图片中包含有整个车身 | |||||
+ 图片清晰度较高,不模糊 | |||||
+ 图片拍摄角度为正面拍摄,车牌在图片中没有较大幅度的倾斜 | |||||
+ 图片中的车牌在整个图片中所占位置较小 | |||||
### 识别精度低的图片 | |||||
#### 感谢各位大牛! | |||||
+ 图片模糊,程序未能裁切出正确的车牌,或者裁切后因图片太模糊而无法识别(此处应该可以通过训练更多样本解决) | |||||
+ 图片中的车牌在整个图片中占了1/3的位置甚至更高 | |||||
+ 图片拍摄角度为俯角拍摄,车牌在图片中是倾斜着的 |
@@ -1,5 +1,6 @@ | |||||
// | // | ||||
// Created by Coleflowers on 20/06/2018. | // Created by Coleflowers on 20/06/2018. | ||||
// Updated by Justid on 02/07/2018. | |||||
// | // | ||||
#include <phpcpp.h> | #include <phpcpp.h> | ||||
#include <iostream> | #include <iostream> | ||||
@@ -10,88 +11,69 @@ | |||||
#include "PlateDetection.h" | #include "PlateDetection.h" | ||||
#include "FastDeskew.h" | #include "FastDeskew.h" | ||||
#include "FineMapping.h" | #include "FineMapping.h" | ||||
#include "Pipeline.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"}; | |||||
/* 关闭原opencv报错输出 */ | |||||
int handleError( int status, const char* func_name, | |||||
const char* err_msg, const char* file_name, | |||||
int line, void* userdata ) | |||||
{ | |||||
//Do nothing -- will suppress console output | |||||
return 0; //Return value is not used | |||||
} | |||||
/** | /** | ||||
* 车牌图片识别 | * 车牌图片识别 | ||||
* @param imgpath 图片的绝对路径 | |||||
* @params imgpath 图片的绝对路径 | |||||
* @params modelpath 识别模型所在文件夹路径 | |||||
* @params confidence 可信度要求,可选参数,默认值0.75 | |||||
* @return 车牌号 图片路径的图片不存在的话 返回空值 | * @return 车牌号 图片路径的图片不存在的话 返回空值 | ||||
*/ | */ | ||||
cv::String scan(const char *imgpath){ | |||||
// 读取图片获取车牌的粗略部分 | |||||
cv::Mat image = cv::imread(imgpath); | |||||
if(!image.data) { | |||||
printf("No img data!\n"); | |||||
return ""; | |||||
} | |||||
pr::PlateDetection plateDetection("/usr/platescan/src/lpr/model/cascade.xml"); | |||||
std::vector<pr::PlateInfo> plates; | |||||
plateDetection.plateDetectionRough(image,plates); | |||||
// todo 处理发现的每一个车牌信息 | |||||
// 目前只处理了一组 | |||||
cv::Mat img; | |||||
for(pr::PlateInfo platex:plates) { | |||||
// 暂时不保存了 | |||||
//cv::imwrite("res/mmm.png",platex.getPlateImage()); | |||||
img = platex.getPlateImage(); | |||||
} | |||||
// 车牌部分 | |||||
cv::Mat image_finemapping = pr::FineMapping::FineMappingVertical(img); | |||||
pr::FineMapping finemapper = pr::FineMapping("/usr/platescan/src/lpr/model/HorizonalFinemapping.prototxt","/usr/platescan/src/lpr/model/HorizonalFinemapping.caffemodel"); | |||||
// | |||||
image_finemapping = pr::fastdeskew(image_finemapping, 5); | |||||
// image_finemapping = finemapper.FineMappingHorizon(image_finemapping,0,-3); | |||||
// Android 代码里这个是 | |||||
// 改了之后部分图片数据精度发生变化 ,比如 字母精度有了,但是汉字又错了 | |||||
image_finemapping = finemapper.FineMappingHorizon(image_finemapping,2,5); | |||||
// 暂时不保存了 | |||||
//cv::imwrite("res/m222222222.png",image_finemapping); | |||||
// 设置尺寸 识别 | |||||
cv::Mat demo = image_finemapping; | |||||
cv::resize(demo,demo,cv::Size(136,36)); | |||||
//cv::imwrite("res/m333333.png",demo); | |||||
cv::String scan(std::string imgpath, std::string modelpath, double confidence){ | |||||
cv::redirectError(handleError); | |||||
try { | |||||
pr::PipelinePR prc(modelpath+"/cascade.xml", | |||||
modelpath+"/HorizonalFinemapping.prototxt",modelpath+"/HorizonalFinemapping.caffemodel", | |||||
modelpath+"/Segmentation.prototxt",modelpath+"/Segmentation.caffemodel", | |||||
modelpath+"/CharacterRecognization.prototxt",modelpath+"/CharacterRecognization.caffemodel", | |||||
modelpath+"/SegmentationFree.prototxt",modelpath+"/SegmentationFree.caffemodel" | |||||
); | |||||
cv::Mat image = cv::imread(imgpath); | |||||
std::vector<pr::PlateInfo> res = prc.RunPiplineAsImage(image,pr::SEGMENTATION_FREE_METHOD); | |||||
cv::Mat respones; | |||||
pr::PlateSegmentation plateSegmentation("/usr/platescan/src/lpr/model/Segmentation.prototxt","/usr/platescan/src/lpr/model/Segmentation.caffemodel"); | |||||
pr::PlateInfo plate; | |||||
plate.setPlateImage(demo); | |||||
std::vector<cv::Rect> rects; | |||||
plateSegmentation.segmentPlatePipline(plate,1,rects); | |||||
plateSegmentation.ExtractRegions(plate,rects); | |||||
cv::String platenum = ""; | |||||
for(auto st:res) { | |||||
if(st.confidence>confidence) { | |||||
platenum = st.getPlateName(); | |||||
break; | |||||
} | |||||
} | |||||
pr::GeneralRecognizer *recognizer = new pr::CNNRecognizer("/usr/platescan/src/lpr/model/CharacterRecognization.prototxt","/usr/platescan/src/lpr/model/CharacterRecognization.caffemodel"); | |||||
recognizer->SegmentBasedSequenceRecognition(plate); | |||||
//std::cout<<plate.decodePlateNormal(chars)<<std::endl; | |||||
plate.decodePlateNormal(chars); | |||||
cv::String txt = plate.getPlateName(); | |||||
// printf("res:%s\n", txt.c_str()); | |||||
return platenum; | |||||
} | |||||
catch( cv::Exception& e ) | |||||
{ | |||||
const char* err_msg = e.what(); | |||||
throw Php::Exception(err_msg); | |||||
} | |||||
// | |||||
// 写入结果到文件 | |||||
// FILE *fp; | |||||
// fp = fopen(resSaveFile, "wb+"); | |||||
// fprintf(fp, "%s", txt.c_str()); | |||||
// fclose(fp); | |||||
// | |||||
delete(recognizer); | |||||
return txt; | |||||
} | } | ||||
Php::Value myFunction(Php::Parameters ¶ms) { | |||||
std::string str = params[0]; | |||||
const char *str_c = str.c_str(); | |||||
Php::Value funcWrapper(Php::Parameters ¶ms) { | |||||
// 图片路径 | |||||
std::string img = params[0]; | |||||
// 模型路径(文件夹) | |||||
std::string model = params[1]; | |||||
// 可信度要求 | |||||
double confidence = 0.75; | |||||
if (params.size() == 3){ | |||||
confidence = (double)params[2]; | |||||
} | |||||
cv::String res = scan(str_c); | |||||
return res.c_str(); | |||||
cv::String res = scan(img, model, confidence); | |||||
return res.c_str(); | |||||
} | } | ||||
@@ -113,7 +95,11 @@ extern "C" { | |||||
static Php::Extension extension("platescan", "1.0"); | static Php::Extension extension("platescan", "1.0"); | ||||
// @todo add your own functions, classes, namespaces to the extension | // @todo add your own functions, classes, namespaces to the extension | ||||
extension.add<myFunction>("platescan", {Php::ByRef("string", Php::Type::String)}); | |||||
extension.add<funcWrapper>("platescan", { | |||||
Php::ByVal("imgpath", Php::Type::String, true), | |||||
Php::ByVal("modelpath", Php::Type::String, true), | |||||
Php::ByVal("confidence", Php::Type::Float, false) | |||||
}); | |||||
// return the extension | // return the extension | ||||
return extension; | return extension; | ||||
@@ -0,0 +1,123 @@ | |||||
input: "data" | |||||
input_dim: 1 | |||||
input_dim: 1 | |||||
input_dim: 30 | |||||
input_dim: 14 | |||||
layer { | |||||
name: "conv2d_1" | |||||
type: "Convolution" | |||||
bottom: "data" | |||||
top: "conv2d_1" | |||||
convolution_param { | |||||
num_output: 32 | |||||
bias_term: true | |||||
pad: 0 | |||||
kernel_size: 3 | |||||
stride: 1 | |||||
} | |||||
} | |||||
layer { | |||||
name: "activation_1" | |||||
type: "ReLU" | |||||
bottom: "conv2d_1" | |||||
top: "activation_1" | |||||
} | |||||
layer { | |||||
name: "max_pooling2d_1" | |||||
type: "Pooling" | |||||
bottom: "activation_1" | |||||
top: "max_pooling2d_1" | |||||
pooling_param { | |||||
pool: MAX | |||||
kernel_size: 2 | |||||
stride: 2 | |||||
pad: 0 | |||||
} | |||||
} | |||||
layer { | |||||
name: "conv2d_2" | |||||
type: "Convolution" | |||||
bottom: "max_pooling2d_1" | |||||
top: "conv2d_2" | |||||
convolution_param { | |||||
num_output: 64 | |||||
bias_term: true | |||||
pad: 0 | |||||
kernel_size: 3 | |||||
stride: 1 | |||||
} | |||||
} | |||||
layer { | |||||
name: "activation_2" | |||||
type: "ReLU" | |||||
bottom: "conv2d_2" | |||||
top: "activation_2" | |||||
} | |||||
layer { | |||||
name: "max_pooling2d_2" | |||||
type: "Pooling" | |||||
bottom: "activation_2" | |||||
top: "max_pooling2d_2" | |||||
pooling_param { | |||||
pool: MAX | |||||
kernel_size: 2 | |||||
stride: 2 | |||||
pad: 0 | |||||
} | |||||
} | |||||
layer { | |||||
name: "conv2d_3" | |||||
type: "Convolution" | |||||
bottom: "max_pooling2d_2" | |||||
top: "conv2d_3" | |||||
convolution_param { | |||||
num_output: 128 | |||||
bias_term: true | |||||
pad: 0 | |||||
kernel_size: 2 | |||||
stride: 1 | |||||
} | |||||
} | |||||
layer { | |||||
name: "activation_3" | |||||
type: "ReLU" | |||||
bottom: "conv2d_3" | |||||
top: "activation_3" | |||||
} | |||||
layer { | |||||
name: "flatten_1" | |||||
type: "Flatten" | |||||
bottom: "activation_3" | |||||
top: "flatten_1" | |||||
} | |||||
layer { | |||||
name: "dense_1" | |||||
type: "InnerProduct" | |||||
bottom: "flatten_1" | |||||
top: "dense_1" | |||||
inner_product_param { | |||||
num_output: 256 | |||||
} | |||||
} | |||||
layer { | |||||
name: "relu2" | |||||
type: "ReLU" | |||||
bottom: "dense_1" | |||||
top: "relu2" | |||||
} | |||||
layer { | |||||
name: "dense2" | |||||
type: "InnerProduct" | |||||
bottom: "relu2" | |||||
top: "dense2" | |||||
inner_product_param { | |||||
num_output: 65 | |||||
} | |||||
} | |||||
layer { | |||||
name: "prob" | |||||
type: "Softmax" | |||||
bottom: "dense2" | |||||
top: "prob" | |||||
} |
@@ -0,0 +1,95 @@ | |||||
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" | |||||
} |
@@ -0,0 +1,114 @@ | |||||
input: "data" | |||||
input_dim: 1 | |||||
input_dim: 1 | |||||
input_dim: 22 | |||||
input_dim: 22 | |||||
layer { | |||||
name: "conv2d_12" | |||||
type: "Convolution" | |||||
bottom: "data" | |||||
top: "conv2d_12" | |||||
convolution_param { | |||||
num_output: 16 | |||||
bias_term: true | |||||
pad: 0 | |||||
kernel_size: 3 | |||||
stride: 1 | |||||
} | |||||
} | |||||
layer { | |||||
name: "activation_18" | |||||
type: "ReLU" | |||||
bottom: "conv2d_12" | |||||
top: "activation_18" | |||||
} | |||||
layer { | |||||
name: "max_pooling2d_10" | |||||
type: "Pooling" | |||||
bottom: "activation_18" | |||||
top: "max_pooling2d_10" | |||||
pooling_param { | |||||
pool: MAX | |||||
kernel_size: 2 | |||||
stride: 2 | |||||
pad: 0 | |||||
} | |||||
} | |||||
layer { | |||||
name: "conv2d_13" | |||||
type: "Convolution" | |||||
bottom: "max_pooling2d_10" | |||||
top: "conv2d_13" | |||||
convolution_param { | |||||
num_output: 16 | |||||
bias_term: true | |||||
pad: 0 | |||||
kernel_size: 3 | |||||
stride: 1 | |||||
} | |||||
} | |||||
layer { | |||||
name: "activation_19" | |||||
type: "ReLU" | |||||
bottom: "conv2d_13" | |||||
top: "activation_19" | |||||
} | |||||
layer { | |||||
name: "max_pooling2d_11" | |||||
type: "Pooling" | |||||
bottom: "activation_19" | |||||
top: "max_pooling2d_11" | |||||
pooling_param { | |||||
pool: MAX | |||||
kernel_size: 2 | |||||
stride: 2 | |||||
pad: 0 | |||||
} | |||||
} | |||||
layer { | |||||
name: "flatten_6" | |||||
type: "Flatten" | |||||
bottom: "max_pooling2d_11" | |||||
top: "flatten_6" | |||||
} | |||||
layer { | |||||
name: "dense_9" | |||||
type: "InnerProduct" | |||||
bottom: "flatten_6" | |||||
top: "dense_9" | |||||
inner_product_param { | |||||
num_output: 256 | |||||
} | |||||
} | |||||
layer { | |||||
name: "dropout_9" | |||||
type: "Dropout" | |||||
bottom: "dense_9" | |||||
top: "dropout_9" | |||||
dropout_param { | |||||
dropout_ratio: 0.5 | |||||
} | |||||
} | |||||
layer { | |||||
name: "activation_20" | |||||
type: "ReLU" | |||||
bottom: "dropout_9" | |||||
top: "activation_20" | |||||
} | |||||
layer { | |||||
name: "dense_10" | |||||
type: "InnerProduct" | |||||
bottom: "activation_20" | |||||
top: "dense_10" | |||||
inner_product_param { | |||||
num_output: 3 | |||||
} | |||||
} | |||||
layer { | |||||
name: "prob" | |||||
type: "Softmax" | |||||
bottom: "dense_10" | |||||
top: "prob" | |||||
} |
@@ -0,0 +1,318 @@ | |||||
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: "conv_512_15" | |||||
type: "Convolution" | |||||
bottom: "pool2" | |||||
top: "conv_512_15" | |||||
convolution_param { | |||||
num_output: 512 | |||||
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: "conv_512_15" | |||||
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: "conv_512_51" | |||||
type: "Convolution" | |||||
bottom: "batch_normalization_1" | |||||
top: "conv_512_51" | |||||
convolution_param { | |||||
num_output: 512 | |||||
bias_term: true | |||||
pad_h: 0 | |||||
pad_w: 0 | |||||
kernel_h: 5 | |||||
kernel_w: 1 | |||||
stride_h: 1 | |||||
stride_w: 1 | |||||
} | |||||
} | |||||
layer { | |||||
name: "batch_normalization_2" | |||||
type: "BatchNorm" | |||||
bottom: "conv_512_51" | |||||
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: "activation_2" | |||||
type: "ReLU" | |||||
bottom: "batch_normalization_2" | |||||
top: "batch_normalization_2" | |||||
} | |||||
layer { | |||||
name: "conv_1024_11" | |||||
type: "Convolution" | |||||
bottom: "batch_normalization_2" | |||||
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_3" | |||||
type: "BatchNorm" | |||||
bottom: "conv_1024_11" | |||||
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: "activation_3" | |||||
type: "ReLU" | |||||
bottom: "batch_normalization_3" | |||||
top: "batch_normalization_3" | |||||
} | |||||
layer { | |||||
name: "conv_class_11" | |||||
type: "Convolution" | |||||
bottom: "batch_normalization_3" | |||||
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" | |||||
} |
@@ -1,13 +1,13 @@ | |||||
<?php | <?php | ||||
// | // | ||||
// Created by Coleflowers on 20/06/2018. | // Created by Coleflowers on 20/06/2018. | ||||
// Updated by JustID on 03/07/2018. | |||||
// | // | ||||
/** | /** | ||||
* 车牌识别PHP扩展程序测试 | * 车牌识别PHP扩展程序测试 | ||||
*/ | */ | ||||
$path = realpath("demo.png"); | |||||
$res = platescan($path); | |||||
$res = platescan(realpath("demo.png"),realpath("model"),0.8); | |||||
var_dump($res); | var_dump($res); | ||||
?> | ?> |