最近須要在 Linux 平臺下開發一我的臉識別相關的應用,用到了虹軟的人臉識別 SDK。以前在 Windows 平臺用過,感受不錯,SDK 裏面還帶了 Demo 能夠快速看到效果。打開 Linux 版本的 SDK 裏面沒有發現 Demo,因而想着把 Windows 的 Demo 移植到 Linux。這篇文章記錄了移植的過程,Linux 用的是 Ubuntu 20.04(使用虛擬機 VMware Workstation 15 Player)。html
到虹軟官網下載人臉識別 SDK 3.1 Linux 增值版本 解壓到合適的目錄,並從官網獲取 APP_ID、SDK_KEY 和 ACTIVE_KEY,用於寫到配置文件用來激活 SDK。linux
到 OpenCV 官網下載源碼,我用的版本是 3.4.9。能夠按照官網的教程 Installation in Linux 自行編譯,我參考官網教程使用下面的這些命令在 GCC 9.3.0(Ubuntu 20.04 自帶的編譯器) 上編譯成功。git
sudo apt update sudo apt install build-essential sudo apt install cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev cd <OpenCV 源碼目錄> mkdir build cd build cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=<自定義目錄> .. make -j3 # 能夠使用核心數 - 1 個線程來編譯 sudo make install
Qt 使用的是 5.14.2 版本。github
原 Windows Demo 使用的是 Visual Studio 2015,在 Linux 下我這裏用到了 Qt Creator 進行開發,所以須要編寫 .pro 文件,包括如下幾個方面:windows
更具體的內容查看文末提供的源碼。安全
原源碼文件使用的是 GBK 編碼,須要轉換爲 UTF-8 編碼。將下面的命令保存到 convert.sh
文件中並用 chmod u+x convert.sh
賦予可執行權限。bash
#!/bin/bash for i in "$@"; do desc=$(file "$i") if $(echo $desc | grep -i "UTF-8 Unicode" > /dev/null); then if $(echo $desc | grep -i "(with BOM)" > /dev/null); then echo "Remove UTF-8 BOM: " $i sed -i "1s/^\xef\xbb\xbf//" "$i" fi elif $(echo $desc | grep -i "ISO-8859" > /dev/null); then echo "GBK --> UTF-8 : " $i temp=temp.txt iconv -f gbk -t utf-8 -o "$temp" "$i" mv "$temp" "$i" fi done
在源碼根目錄下運行 find . -type f \( -name "*.h" -o -name "*.cpp" \) | xargs -I{} ./convert.sh "{}"
將全部的文件的編碼從 GBK 轉爲 UTF-8,並去除現有 UTF-8 文件的 BOM 頭。ide
到這裏已經能夠用 Qt Creator 打開項目了,但在代碼中還存在一些問題,一方面是原代碼使用了一些 Windows 平臺特有的 API,一方面是有些代碼在 Linux 有兼容性問題。先去除 Windows 特有的依賴到編譯經過,再補充必要的依賴,最後解決兼容性問題。函數
直接進行編譯,逐步解決編譯錯誤,經過下面的方式能夠解決編譯錯誤:ui
qDebug
改成 QDebug
。Sleep(milli)
改成 std::this_thread::sleep_for(std::chrono::milliseconds(milli))
。#pragma comment ...
。cv::Mat mat(ipl, false)
改爲 cv::Mat mat = cv::cvarrToMat(ipl)
。IplImage(mat)
改爲 cvIplImage(mat)
,在原來的代碼裏 cv::Mat 轉爲 IplImage 後有個取地址,對右值取地址是不安全的,須要用一個變量保存轉換後的值再對這個變量取地址。CV_RGB
改爲 cvScalar
。cv::cvtColor
須要額外包含頭文件 opencv2/imgproc.hpp
。cv::VideoCapture
須要額外包含頭文件 opencv2/videoio.hpp
strcpy_s
改爲 strncpy
,僅有參數位置上的改變。TRUE
改成 true
,將 FALSE
改成 false
。改了編譯錯誤後,忽略警告已經能夠編譯經過了,接下來是補充剛纔刪除的一些必要依賴及解決兼容性問題。
由於環境差別,可能出現錯誤的順序不一致,但基本上是上面提到的錯誤之一。
原 Windows Demo 使用了 Windows 特有的 dshow 來查找攝像頭,在這裏直接用 cv::VideoCapture 嘗試打開來獲取攝像頭的索引:
auto list = std::vector<int>(); for (auto i = 0; i != 10; ++i) { auto cap = cv::VideoCapture(i); if (cap.isOpened()) { list.emplace_back(i); } cap.release(); }
Demo 能夠只打開一個RGB攝像頭,也能夠同時打開一個RGB攝像頭和一個IR攝像頭。原代碼保存獲取攝像頭的名稱,僅用來統計數量,具體打開哪一個攝像頭是經過settings.ini
文件來配置的。在改變探測攝像頭存在的數量的方式後,順帶改變了打開攝像頭的邏輯,僅一個攝像頭就認爲是僅打開普通攝像頭。在settings.ini
文件中配置兩種攝像頭的索引,若是索引爲 -1,則自動把小的索引認爲是普通攝像頭,大的索引認爲是紅外攝像頭,若是和真實狀況不一致可手動指定攝像頭索引。
settings.ini
文件在後面運行 Demo 時會有更多的說明。
在 Ubuntu 20.04 下,Qt 的 QFileDialog::getOpenFileName 和 QFileDialog::getExistingDirectory 存在一些問題,在打開時會卡死界面,經過將最後一個參數設置爲 QFileDialog::DontUseNativeDialog
能夠解決這個問題。