@@ -6,3 +6,4 @@ | |||
Prj-Linux/lpr/TEST_* | |||
Prj-Linux/*build*/ | |||
*.pyc | |||
/Prj-PHP/build |
@@ -1,21 +1,12 @@ | |||
cmake_minimum_required(VERSION 3.6) | |||
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) | |||
include_directories( ${OpenCV_INCLUDE_DIRS}) | |||
include_directories(include) | |||
add_library( # Sets the name of the library. | |||
platescan | |||
@@ -42,10 +33,10 @@ target_link_libraries( | |||
${OpenCV_LIBS} | |||
) | |||
execute_process(COMMAND ${PHP_CONFIG} --extension-dir | |||
execute_process(COMMAND php-config --extension-dir | |||
OUTPUT_VARIABLE LIBRARY_DIR) | |||
message("Test ${LIBRARY_DIR} failed.") | |||
message("PHP_EXTENSIONS_DIR ${LIBRARY_DIR}") | |||
add_custom_command(TARGET platescan | |||
POST_BUILD | |||
@@ -1,9 +1,29 @@ | |||
# Prj-PHP | |||
HyperLPR 在PHP扩展程序中的实现,核心代码拷贝了 Prj-Linux 中庾金科大牛的代码。我做的这部分工作主要是配置编译成PHP扩展程序。 | |||
## CPP 依赖 | |||
+ Opencv 3.3 | |||
+ PHPCPP | |||
## Linux/Mac 编译 | |||
```bash | |||
mkdir build | |||
cd build | |||
cmake ../ | |||
make -j | |||
``` | |||
## DEMO | |||
```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" | |||
``` | |||
@@ -12,5 +32,19 @@ var_dump($res); // string(9) "苏ED0N19" | |||
![image](./tests/demo.png) | |||
## 测试备忘 | |||
经多次测试发现部分图片难以识别或者容易识别错误,经过筛选反推出如下规律: | |||
### 识别精度高的图片 | |||
+ 图片中包含有整个车身 | |||
+ 图片清晰度较高,不模糊 | |||
+ 图片拍摄角度为正面拍摄,车牌在图片中没有较大幅度的倾斜 | |||
+ 图片中的车牌在整个图片中所占位置较小 | |||
### 识别精度低的图片 | |||
#### 感谢各位大牛! | |||
+ 图片模糊,程序未能裁切出正确的车牌,或者裁切后因图片太模糊而无法识别(此处应该可以通过训练更多样本解决) | |||
+ 图片中的车牌在整个图片中占了1/3的位置甚至更高 | |||
+ 图片拍摄角度为俯角拍摄,车牌在图片中是倾斜着的 |
@@ -1,5 +1,6 @@ | |||
// | |||
// Created by Coleflowers on 20/06/2018. | |||
// Updated by Justid on 02/07/2018. | |||
// | |||
#include <phpcpp.h> | |||
#include <iostream> | |||
@@ -10,88 +11,69 @@ | |||
#include "PlateDetection.h" | |||
#include "FastDeskew.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 车牌号 图片路径的图片不存在的话 返回空值 | |||
*/ | |||
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"); | |||
// @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 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 | |||
// | |||
// Created by Coleflowers on 20/06/2018. | |||
// Updated by JustID on 03/07/2018. | |||
// | |||
/** | |||
* 车牌识别PHP扩展程序测试 | |||
*/ | |||
$path = realpath("demo.png"); | |||
$res = platescan($path); | |||
$res = platescan(realpath("demo.png"),realpath("model"),0.8); | |||
var_dump($res); | |||
?> |