虹軟人臉識別——官方 Qt Demo 移植到 Linux

1、前言

最近須要在 Linux 平臺下開發一我的臉識別相關的應用,用到了虹軟的人臉識別 SDK。以前在 Windows 平臺用過,感受不錯,SDK 裏面還帶了 Demo 能夠快速看到效果。打開 Linux 版本的 SDK 裏面沒有發現 Demo,因而想着把 Windows 的 Demo 移植到 Linux。這篇文章記錄了移植的過程,Linux 用的是 Ubuntu 20.04(使用虛擬機 VMware Workstation 15 Player)。html

2、配置依賴

2.1 ArcFace SDK

到虹軟官網下載人臉識別 SDK 3.1 Linux 增值版本 解壓到合適的目錄,並從官網獲取 APP_ID、SDK_KEY 和 ACTIVE_KEY,用於寫到配置文件用來激活 SDK。linux

2.2 OpenCV

到 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

2.3 Qt

Qt 使用的是 5.14.2 版本。github

3、項目文件

3.1 .pro 文件

原 Windows Demo 使用的是 Visual Studio 2015,在 Linux 下我這裏用到了 Qt Creator 進行開發,所以須要編寫 .pro 文件,包括如下幾個方面:windows

  • 用到的 Qt 模塊
  • 編譯出來的程序名
  • 用到的頭文件、源文件和資源文件
  • 依賴庫的頭文件及庫名

更具體的內容查看文末提供的源碼。安全

3.2 文件編碼

原源碼文件使用的是 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

4、代碼修改

到這裏已經能夠用 Qt Creator 打開項目了,但在代碼中還存在一些問題,一方面是原代碼使用了一些 Windows 平臺特有的 API,一方面是有些代碼在 Linux 有兼容性問題。先去除 Windows 特有的依賴到編譯經過,再補充必要的依賴,最後解決兼容性問題。函數

4.1 修改報錯直至編譯經過

直接進行編譯,逐步解決編譯錯誤,經過下面的方式能夠解決編譯錯誤:ui

  • 刪除 Utils.cpp 中報錯的頭文件、GUID 宏、listDevices 函數的主體、UTF8_To_string 和 string_To_UTF8 函數。
  • 將全部包含的 qDebug 改成 QDebug
  • Sleep(milli) 改成 std::this_thread::sleep_for(std::chrono::milliseconds(milli))
  • 刪除 MSVC 的連接庫的編譯指令 #pragma comment ...
  • 將原來使用 OpenCV 2 的接口遷移到目前的 OpenCV 3。
    • IplImage 到 cv::Mat 的轉換由 cv::Mat mat(ipl, false) 改爲 cv::Mat mat = cv::cvarrToMat(ipl)
    • cv::Mat 到 IplImage 的轉換由 IplImage(mat) 改爲 cvIplImage(mat),在原來的代碼裏 cv::Mat 轉爲 IplImage 後有個取地址,對右值取地址是不安全的,須要用一個變量保存轉換後的值再對這個變量取地址。
    • 在調用 cvRectangle 時將 CV_RGB 改爲 cvScalar
    • 使用 cv::cvtColor 須要額外包含頭文件 opencv2/imgproc.hpp
    • 使用 cv::VideoCapture 須要額外包含頭文件 opencv2/videoio.hpp
  • strcpy_s 改爲 strncpy,僅有參數位置上的改變。
  • TRUE 改成 true,將 FALSE 改成 false

改了編譯錯誤後,忽略警告已經能夠編譯經過了,接下來是補充剛纔刪除的一些必要依賴及解決兼容性問題。

由於環境差別,可能出現錯誤的順序不一致,但基本上是上面提到的錯誤之一。

4.2 從新實現獲取攝像頭列表的函數

原 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 時會有更多的說明。

4.3 修復彈出文件選擇框失敗的兼容性問題

在 Ubuntu 20.04 下,Qt 的 QFileDialog::getOpenFileName 和 QFileDialog::getExistingDirectory 存在一些問題,在打開時會卡死界面,經過將最後一個參數設置爲 QFileDialog::DontUseNativeDialog 能夠解決這個問題。

5、運行 Demo

5.1 界面預覽

5.2 配置

  1. 配置文件已經隨源碼打包好了,在運行時須要移動到可執行程序所在的同級目錄下。
  2. 在配置文件中填入官網獲取的 APP_ID、SDK_KEY 和 ACTIVE_KEY。
  3. 編譯並運行。

6、源碼下載

基於官方windows Qt Demo修改後的源碼

相關文章
相關標籤/搜索