基于iTop4412的车牌识别系统
买了讯为的开发板,视频看的也差不多了,打算做个东西练练手,想来想去,打算做一个车牌识别系统,也没有打算弄算法那块,就想用调用百度云AI的车牌识别来实现功能。
百度云AI车牌识别SDK开发文档地址:http://ai.baidu.com/docs#/OCR-Cpp-SDK/top
所有资料下载地址:链接:https://pan.baidu.com/s/16d7IS-jm9bqYYHuM8u3ccA
提取码:e01u
复制这段内容后打开百度网盘手机App,操作更方便哦
要使用百度云的SDK,有一些依赖库需要安装下
首先是必须要支持C++11,而我又想做个简单的GUI,所以选择了Qt5.7作为开发环境,注意Q4.7是不支持C++11的,讯为已经提供了Qt5的开发环境,我就直接使用了。
交叉编译开发环境:Ubuntu16.04
编译器版本:arm-none-linux-gnueabi-gcc version 4.8.3
一、依赖库安装
1、交叉编译openssl
注意先装openssl 再装libcurl,因为开发手册说了需要libcurl支持https,要想让openssl 支持libcurl就必须支持openssl,当然参数里面也要加上一项 。
openssl介绍:https://baike.baidu.com/item/openssl/5454803?fr=aladdin
1)首先解压压缩包
tar -vxf openssl-1.0.2s.tar.gz
2)进入解压后的目录
cd openssl-1.0.2s/
3)配置编译
setarch i386 ./config no-asm shared --prefix=/usr/local/openssl/
no-asm: 是在交叉编译过程中不使用汇编代码代码加速编译过程,原因是它的汇编代码是对arm格式不支持的。
shared :生成动态连接库。
–prefix :指定make install后生成目录的路径,不修改此项则默认为OPENSSLDIR目录(/usr/local/ssl)。
4)修改Makefile
CC= arm-none-linux-gnueabi-gcc
AR= arm-none-linux-gnueabi-ar $(ARFLAGS) r
RANLIB= arm-none-linux-gnueabi-ranlib
NM= arm-none-linux-gnueabi-nm
如果Makefile中有 -m32和-m64 就删掉 -m32和-m64,但是我的Makefile中没有,就没管这个。
5)执行make命令编译openssl
make
6)执行make install命令安装openssl
make install
7)最后我们可以看到在 /usr/local/openssl/ 目录下已经安装好了 openssl 可执行文件、头文件和库文件
8)进入 /usr/local/ 目录下 打包整个 openssl目录
cd /usr/local/
tar -vcf openssl.tar openssl
9)将打包后的 openssl.tar 用U盘拷贝到开发板的 /usr/local/ 目录下,然后解压(注意以下操作均在开发板上完成)
注意:我的开发板镜像有自动挂载U盘的功能,你的可以没有,需要手动挂载,关于怎样挂载U盘和从U盘里复制文件到开发板,请自行百度,这里每个人的命令可能都不一样,不做过多阐述。
-
将 openssl.tar 拷贝到 /usr/local/ 目录下
cp u盘上的openssl.tar文件所在的路径 /usr/local/
-
解压 openssl.tar
tar -vxf openssl.tar
-
改变环境变量(修改/etc/inid.d/rcS)
vi /etc/init.d/rcS
-
在文件中找到 PATH 变量,在后面加上 :/usr/local/openssl/bin ,或者直接在最后一行加上一句话
PATH=$PATH:/usr/local/openssl/bin
-
更新环境变量
source /etc/init.d/rcS
-
拷贝 /usr/local/openssl/lib 下的所有文件到 /lib 目录下
cp /usr/local/openssl/lib/* /lib
这样openssl就算是移植完成了
2、移植libcurl
上一步已经移植好了openssl,一会在配置libcurl的Makefile时加上 --with-ssl=/usr/local/openssl 选项就可以让curl支持https了。
libcurl简介:https://baike.baidu.com/item/libcurl/5256898?fr=aladdin
1)首先解压压缩包
tar -vxf curl-7.65.0.tar.gz
2)进入解压后的目录
cd curl-7.65.0/
3)配置编译
./configure --prefix=/usr/local/curl/ --host=arm-none-linux-gnueabi CC=arm-none-linux-gnueabi-gcc CXX=arm-none-linux-gnueabi-g++ --with-ssl=/usr/local/openssl
–prefix :指定make install后生成目录的路径,不修改此项则默认为OPENSSLDIR目录(/usr/local/ssl)。
–host :该软件将运行的平台
CC和CXX是对应使用的交叉编译器
–with-ssl :使curllib支持https
配置完了看看SSL这一项是不是开启了
4)执行make命令编译libcurl
make
5)执行make install命令安装libcurl
make install
6)最后我们可以看到在 /usr/local/libcurl/ 目录下已经安装好了 libcurl可执行文件、头文件和库文件
7)进入 /usr/local/ 目录下 打包整个 libcurl目录
cd /usr/local/
tar -vcf libcurl.tar libcurl
8)后面的操作和上一步移植openssl基本差不多,就不再赘述了,基本上就是以下几步
- 将打包后的 libcurl.tar 用U盘拷贝到开发板的 /usr/local/ 目录下,然后解压
- 改变环境变量
- 更新环境变量
- 拷贝 /usr/local/libcurl/lib 下的所有文件到 /lib 目录下
这样libcurl就算是移植完成了
3、移植jsoncpp
jsoncpp简介:https://www.cnblogs.com/tocy/p/json-intro_jsoncpp-lib.html
1)首先解压压缩包
tar -vxf jsoncpp-1.6.5.tar.gz
2)进入解压后的目录
cd jsoncpp-1.6.5/
3)新建一个arm_jsoncpp文件夹
mkdir arm_jsoncpp
4)复制编译需要用到的库文件到arm_jsoncpp文件夹
cp src/lib_json/* arm_jsoncpp/
5)复制编译需要用到的头文件到arm_jsoncpp文件夹
cp include/ arm_jsoncpp/ -r
6)进入arm_jsoncpp文件夹
cd arm_jsoncpp/
7)编译静态库
arm-none-linux-gnueabi-g++ -c *.cpp -I./include -fPIC
mkdir lib
ar cr ./lib/libjsoncpp.a *.o
8)编译动态库
arm-none-linux-gnueabi-g++ -shared -fPIC *.cpp -I./include -o ./lib/libjsoncpp.so
注意以下操作均在开发板上完成
9)将 arm_jsoncpp 目录下的 include 文件夹和lib文件夹打包 复制到开发板的 /usr/local/json/ 目录(没有json文件夹就新建一个 mkdir /usr/local/json)
10)拷贝 /usr/local/json/lib 下的所有文件到 /lib 目录下
这样jsoncpp就算是移植完成了
4、移植opencv
请参考文件
iTOP-4412-QtE-opencv-UVC摄像头测试文档_V1.0.zip
这里我只是用opencv读取摄像头的数据,如果你有其他办法,也可以不安装opencv。
5、移植tinyplay和ffmpeg
移植tinyplay请参考文件
iTOP-4412-linux系统-声卡测试tinyplay.zip
移植ffmpeg请参考链接
https://blog.csdn.net/qq_15718789/article/details/72637659
https://blog.csdn.net/horotororensu/article/details/78499709
我用tinyplay和ffmpeg只是为了播放音频文件,因为我想识别出车牌后,再通过声卡播放出车牌号,用的是百度云的语音合成,因为百度云合成的音频文件是单声道的,而在我的板子上tinyplay只能播放双声道的wav文件,所以我用到了ffmpeg对音频文件进行转码。
如果你有更好的办法播放百度云合成的音频文件,这两个也是不用安装的。
-
tinyplay播放音乐
tinyplay test.wav
-
ffmpeg mp3转wav双声道
ffmpeg -i test.mp3 -ac 2 -ar 16000 test.wav
二、使用Qt creator编写应用程序
Qt小白,大佬手下留情 —_—
1、新建一个Qt工程,我用的是 Widget
2、将百度云的SDK添加到工程
├── base
│ ├── base.h // 请求客户端基类
│ ├── base64.h // base64加密相关类
│ ├── http.h // http请求封装类
│ └── utils.h // 工具类
├── ocr.h // 文字识别 交互类
└──speech.h // 语音合成 交互类
3、添加资源文件
用一张图片作为背景图片
4、修改工程文件(*.pro),添加头文件和库文件路径车牌识别
5、*.ui设计
6、系统框图
7、程序流程图
8、核心代码(识别按钮按下的槽函数)
//按键按下事件
void Widget::on_picture_clicked()
{
std::string PlateNumber ;
int Ret;
//保存图片到本地
imag.save("./PlateNumber.jpg", "JPG", 100);
//获取车牌号
PlateNumber = GetPlateNumber("./PlateNumber.jpg");
ui->plateNumber->setText(QString::fromStdString(PlateNumber));
//删除上一次合成的音频文件
remove("./PlateNumber.wav");
remove("./PlateNumber.mp3");
//获取语音合成的音频文件
Ret = GetSpeech(PlateNumber, "./PlateNumber.mp3");
//播放
if(0 == Ret)
{
//转码
system("ffmpeg -i PlateNumber.mp3 -ac 2 -ar 16000 PlateNumber.wav");
//播放
system("tinyplay PlateNumber.wav &");
}
}
//获取图片中的车牌号
std::string GetPlateNumber(std::string ImagePath)
{
Json::Value result;
std::string image;
//加载需要识别的图片
aip::get_file_content(ImagePath.c_str(), &image);
//调用车牌识别
//result = client1.license_plate(image, aip::null);
//如果有可选参数
std::map<std::string, std::string> options;
options["multi_detect"] = "true";
//带参数调用车牌识别
result = client1.license_plate(image, options);
if(result["error_code"].isNull())
{
//识别成功
//std::cout <<result["words_result"][0]["number"]<<std::endl;
return (result["words_result"][0]["number"].asString() + ",欢迎光临.");
}
else
{
//识别失败
//std::cout << result <<std::endl;
return ("识别失败");
}
return ("识别失败");
}
//获取语音合成的音频文件
int GetSpeech(std::string text, std::string FileName)
{
std::ofstream ofile;
std::string file_ret;
std::map<std::string, std::string> options;
options["spd"] = "3"; //语速
//options["aue"] = "6"; //输出格式
//合成成功的二进制数据写入文件中
ofile.open(FileName, std::ios::out | std::ios::binary);
//不带可选参数调用
//std::cout << text << std::endl;
//Json::Value result = client2.text2audio(text, aip::null, file_ret);
// 带可选参数调用, 参数参考参数列表中的可选参数
Json::Value result = client2.text2audio(text, options, file_ret);
// 如果file_ret为不为空则说明合成成功,返回mp3文件内容回结果
if (!file_ret.empty())
{
//输出音频文件
ofile << file_ret;
return 0;
}
else
{
//服务端合成错误
//std::cout << result.toStyledString();
return 1;
}
return 2;
}
9、使用qmake将程序移植到开发板
1)进入的工程目录下,有baiduyun.pro文件的才是工程目录
2)使用qmake命令,生成交叉编译的Makefile。讯为搭建好Ubuntu中,qmake在 /opt/qt5.7.0/bin/ 目录下