# Imx6ULL_QT_Camera **Repository Path**: abigpad/Imx6ULL_QT_Camera ## Basic Information - **Project Name**: Imx6ULL_QT_Camera - **Description**: 野火imx6ull的摄像头车牌识别项目 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 8 - **Created**: 2023-01-15 - **Last Updated**: 2023-01-15 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## Imx6ULL填坑计划 此次用到的所有资料我都放到了奶牛快传里,下载的话速度极快! [https://c-t.work/s/fe0b4a22171342](https://c-t.work/s/fe0b4a22171342) > 我买这个板子已经很久了,跟着野火正点原子的教程踉踉跄跄学了一段儿,对很多基础知识也是一知半解,最终也算是搞了下字符驱动开发,并且做了自己的第一次尝试: [video(video-jQtXvHFH-1594732387928)(type-bilibili)(url-https://player.bilibili.com/player.html?aid=968211607)(image-https://ss.csdn.net/p?http://i2.hdslb.com/bfs/archive/5bb3d4c819a2ef5afce4466f58d8128bfcee1651.jpg)(title-【linux学习vlog】周末两天爆肝入门linux嵌入式)] > 然后呢最近终于费了九牛二虎之力搞成了自己第一个最完善的应用:基于百度图像与语音的一个小作品: [video(video-BZfFjKtn-1594733187960)(type-bilibili)(url-https://player.bilibili.com/player.html?aid=286290368)(image-https://ss.csdn.net/p?http://i2.hdslb.com/bfs/archive/9848ab5dbf050c09832985f49a35708ef19a5562.jpg)(title-【野火linux】我的第一个linux+QT应用)] --- > 接下来就总结一下我的制作过程,由于我没有该视频的文档,所以我都是跟着视频敲代码,一点一点撸出来的!! > 参考讯为的图像识别项目教程: [https://www.bilibili.com/video/BV157411c7sc/](https://www.bilibili.com/video/BV157411c7sc/) ## 制作总结 > 我的做法与讯为的不同点: > 讯为使用的摄像头带驱动,我买的免驱的USB摄像头,这样更简单。 > 讯为调用摄像头采用的是Opencv,我感觉没必要,我直接用的QT的camera组件。 > 然后讯为在同步板子和电脑上交叉编译库的时候,用的是设计根文件系统,而我直接通过NFS怼进去的,这样更简单(野火构建根本文件系统的教程一言难尽,依赖文件太多,下载太慢。) 1. linux板环境准备 > QT交叉编译环境的搭建 (按照野火的文档手册39.1节来就可以,前提是你要把野火需要下载的东西都搞定,且编译通过) > PC端QT环境的搭建,最终完成的效果是生成一个最基本的QT程序,能在PC上编译运行,然后交叉编译以后能板子上正常运行,这时候最基本的准备就完成了。 这里的坑就是: ``` *安装 arm-linux-gnueabihf-gcc v8.3.0* 野火文档上面的编译脚本是有问题的,一是他的排版问题,导致你sh命令总会出错,你可以自己拷贝下来以后自己排查一下修改一下,我编译高版本的8.3的GCC的时候就已经出问题了,一是sh脚本根本无法运行,二是下载失败。其实这个还是比较简单的,因为sh脚本并不复杂可以看得懂,就是把编译器下载下来,然后放到/opt目录下即可。 我已经准备好了在网盘里:arm-linux-gnueabihf-gcc v8.3.0 然后按照野火的教程走,导出环境变量,并验证版本。 剩下的交叉编译触摸驱动tslib以及声卡alsa(这两个是交叉编译进QT工程里面的) 交叉编译QT也是一样的,使用我检验过的即可。 可以按照我做好的sh脚本来执行,直接就OK了。(野火的排版有问题,复制下来是不行的) 然后就按照野火教程安装QT Creator 这里是没问题的 然后把交叉编译的第一个APP nfs扔到板子里,能正常跑,OK到这里基本的准备条件就完成了,就可以在QT的海洋里遨游了。 ``` 2. 百度应用的创建与准备 接下来是百度端的应用创建,这个我比较熟悉,因为之前就玩过树莓派的图像识别、人脸识别、以及语音识别。 如图:创建语音应用和图像识别应用 ![在这里插入图片描述](https://images.gitee.com/uploads/images/2020/0715/213433_8c8e1d6e_2051063.png) ``` 主要是用到百度的三元组 AppID API Key Secret Key ``` 3. 依赖库的交叉编译 ``` 接下来其他的就暂时脱离QT了,这是对 整个图像识别和百度语音识别做准备的: 编译openssl cd openssl-1.0.2f/ setarch i386 ./config no-asm shared --prefix=/usr/local/openssl/ CC= arm-linux-gnueabihf-gcc AR= arm-linux-gnueabihf-ar $(ARFLAGS) r RANLIB= arm-linux-gnueabihf-ranlib NM= arm-linux-gnueabihf-nm make sudo make install 编译curl ./configure --prefix=/usr/local/curl/ --host=arm-linux-gnueabihf CC=arm-linux-gnueabihf-gcc CXX=arm-linux-gnueabihf-g++ --with-ssl=/usr/local/openssl make sudo make install 编译jsoncpp (我这里虽然编译成功了,但是在QT里总是调用失败,解决方法见下文) mkdir arm_jsoncpp cp -r include/ arm_jsoncpp/ cp src/lib_json/* arm_jsoncpp/ arm-linux-gnueabihf-g++ -c *.cpp -I./include -fPIC mkdir lib ar cr ./lib/libjsoncpp.a *.o 编译动态库 arm-linux-gnueabihf-g++ -shared -fPIC *.cpp -I./include -o ./lib/libjsoncpp.so ××解决jsoncpp问题×× 我百度查了查 jsoncpp即使不进行动态编译,一样可以调用,直接把cjson需要用到的文件扔QT工程里面就行了。直接在QT里引用外部文件把整个json文件夹饮用即可! 参考链接: https://www.cnblogs.com/zengjfgit/p/4959965.html ``` 4. 根文件系统的整理与拷贝 ``` 然后就是以上依赖库的环境变量引导,把上面的文件在PC上放到指定位置进行交叉编译生成QT可执行文件,nfs扔到板子上运行,会提示找不到依赖库。 此时把依赖库文件,放到imx6ull板子的指定路径,并且编辑环境变量。再次运行就不报错了。 vi ./etc/init.d/rcS 讯为的教程使用的是 设计根文件系统,而我是直接NFS传进去,其实原理是一样的,无论怎么样,只要能让QT应用在板子的指定位置找到指定的依赖文件即可。 ``` ![在这里插入图片描述](https://images.gitee.com/uploads/images/2020/0715/213433_1dc3476a_2051063.png) 5. QTAPP的编写 百度APP初始化部分: ``` #include "json/include/json/json.h" //由于我没编译成功jsoncpp的依赖库,所以用这种本地依赖的方法来作 #include "ocr.h" #include "speech.h" // 设置语音合成 APPID/AK/SK std::string speech_app_id = "21275374"; std::string speech_api_key = "5ZGKQxLfmVamG2GnP9zsXGKX"; std::string speech_secret_key = "ZW5Aoopu2K88DOQtgcZBQGjmTnDH8ncQ"; aip::Speech client_speech(speech_app_id, speech_api_key, speech_secret_key); // 设置文字识别APPID/AK/SK std::string app_id = "21267850"; std::string api_key = "mXTgSiRIQ07OYFGqB3aSlY2t"; std::string secret_key = "LWoGPMUaqKzLfUPihDUnphEMNX148uR2"; aip::Ocr client(app_id, api_key, secret_key); ``` 车牌识别部分: ``` std::string GetPlateNumber(std::string PicturePath) { Json::Value result; std::string image; aip::get_file_content(PicturePath.c_str(), &image); // 调用车牌识别 result = client.license_plate(image, aip::null); // 如果有可选参数 std::map options; options["multi_detect"] = "true"; // 带参数调用车牌识别 result = client.license_plate(image, options); if(result["error_code"].isNull()) //无报错 { return ("车牌号"+result["words_result"][0]["number"].asString()+"欢迎光临"); }else { return ("error"); } } ``` 语音合成(文字转语音部分): ``` int tts(std::string text,std::string FileName) { std::ofstream ofile; std::string file_ret; std::map options; options["spd"] = "4"; options["per"] = "5"; // 合成成功的二进制数据写入文件中 ofile.open(FileName, std::ios::out | std::ios::binary); // 不带可选参数调用 //Json::Value result = client_speech.text2audio("百度语音合成测试", aip::null, file_ret); // 带可选参数调用, 参数参考参数列表中的可选参数 Json::Value result = client_speech.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; } ``` 拍照按钮事件的执行: ``` void Camera::processCapturedImage(int requestId, const QImage& img) { Q_UNUSED(requestId); QImage scaledImage = img.scaled(ui->viewfinder->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation); ui->lastImagePreviewLabel->setPixmap(QPixmap::fromImage(scaledImage)); const QPixmap *pixmap=ui->lastImagePreviewLabel->pixmap(); pixmap->save("./a.jpg"); //存储到指定位置 std::string out; std::int8_t sp_out; out = GetPlateNumber("./a.jpg"); ui->statusbar->showMessage(out.c_str()); //语音合成 sp_out = tts(out,"./a.mp3"); if(sp_out == 0) { //播放 开启新线程执行系统命令 QProcess *process = new QProcess(); process->start("gplay-1.0 a.mp3"); // system("gplay-1.0 a.mp3"); }else { ui->statusbar->showMessage("语音合成失败"); } QMessageBox::warning(this, tr("OK"), out.c_str()); // Display captured image for 4 seconds. 这里会在linux板子上面卡住 // displayCapturedImage(); // QTimer::singleShot(4000, this, &Camera::displayViewfinder); } ``` > 这一切搞完,就OK了,完美运行!我太难了!四处碰壁。 > 总之,最终完成了,还是很开心的。好好学习、天天向上!