libfacedetection簡單使用記錄

一、源碼下載

直接從github上克隆項目倉庫。c++

git clone https://github.com/ShiqiYu/libfacedetection.git

二、編譯

2.一、linux

這個項目使用了cmake腳本,先生成makefile。(我這裏是在ArchLinux x86_64環境下測試的)git

cmake -DENABLE_NEON=OFF -DCMAKE_BUILD_TYPE=RELEASE .

執行上面的命令成功後,執行下面語句進行編譯github

make -j4

編譯完成後會同時生成動態庫和靜態庫小程序

[ 90%] Linking CXX static library libfacedetection.a
[100%] Linking CXX shared library libfacedetection.so

2.二、Windows MINGW64

這裏和上面也是同樣的。先使用cmake生產Makefile文件,而後執行編譯便可。這裏我指定了使用g++做爲C++的編譯器,由於若是不指定會使用gcc去連接,致使生成動態庫的時候找不到c++標準庫的一些定義。windows

cmake -DENABLE_NEON=OFF -DCMAKE_BUILD_TYPE=RELEASE  -DCMAKE_CXX_COMPILER=g++ .

其它的與上面linux的一致。bash

備註:我這裏使用的是MSYS2環境,直接使用pacman命令安裝的gcc/g++。ide

2.三、VS2017 NMake編譯

由於就這麼幾個文件,生成一個龐大的VS工程實在有點多餘,因此我簡單寫了一個Makefile.vc文件,使用nmake腳原本生成靜態庫(由於源碼中並無對函數接口進行export,因此只生成靜態庫)。函數

Makefile.vc 文件內容以下:工具

# 編譯參數設置
CXX           = cl
DEFINES       = -DWIN32 -DWIN64 -DNDEBUG -D_WINDLL
CXXFLAGS      = -nologo -Zc:wchar_t -FS -Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -O2 -MD -W3 -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 -wd4577 -wd4467 -EHsc $(DEFINES)
INCPATH       = -I.
LIBEXE        = lib
LIBFLAGS      = /NOLOGO 
LIBS          =  kernel32.lib

# 源文件
SOURCES       = facedetectcnn.cpp           \
                facedetectcnn-floatdata.cpp \
                facedetectcnn-int8data.cpp  \
                facedetectcnn-model.cpp
OBJECTS       = facedetectcnn.obj           \
                facedetectcnn-floatdata.obj \
                facedetectcnn-int8data.obj  \
                facedetectcnn-model.obj

# 輸出目標文件
DESTDIR_TARGET = libfacedetection.lib

# 編譯規則
.cpp.obj::
    $(CXX) @<< -c $(CXXFLAGS) $(INCPATH) $<
<<

all:    $(DESTDIR_TARGET)

$(DESTDIR_TARGET):  $(OBJECTS)
    $(LIBEXE) $(LIBFLAGS) /OUT:$(DESTDIR_TARGET) $(LIBS) $(OBJECTS)

facedetectcnn.obj: facedetectcnn.cpp facedetectcnn.h
facedetectcnn-floatdata.obj: facedetectcnn-floatdata.cpp facedetectcnn.h
facedetectcnn-int8data.obj: facedetectcnn-int8data.cpp facedetectcnn.h
facedetectcnn-model.obj: facedetectcnn-model.cpp facedetectcnn.h

clean:
    del /Q $(OBJECTS)

VS2017開發者命令行工具中直接使用nmake命令來生成靜態庫

nmake -f Makefile.vc

三、簡單測試程序

使用Qt寫了一個小程序,簡單的測試了一下。

測試的時候發現年齡始終是0,而後就看了一下源碼,發現其並未對年齡和麪部特徵點進行輸出,實際在代碼中也沒有進行檢測,年齡和麪部特徵點相關的代碼我沒有找到(2019年4月16日)。

3.一、測試截圖

3.二、測試代碼以下

/*****************************************************
 *       project:libfacedetection 測試代碼            *
 *       anchor:ymwh@foxmail.com/solym@sohu.com      *
 *       date:2019-4-16                              *
 *****************************************************/

#include <facedetectcnn.h>

#include <QApplication>
#include <QWidget>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QFileDialog>
#include <QPainter>
#include <QGraphicsView>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QImage srcImage;
    // 建立窗口
    QWidget widget;
    // 添加控件
    QGraphicsScene* gsViewScene = new QGraphicsScene();
    gsViewScene->setItemIndexMethod(QGraphicsScene::NoIndex);
    QGraphicsView* gvImageView = new QGraphicsView(&widget);
    gvImageView->setScene(gsViewScene);

    QLineEdit* leImagePath = new QLineEdit(&widget);
    QPushButton* pbSelectFile = new QPushButton(QStringLiteral("選擇文件"),&widget);
    QPushButton* pbRunDetect = new QPushButton(QStringLiteral("執行檢測"),&widget);
    pbRunDetect->setEnabled(false);
    QHBoxLayout* hbLayout = new QHBoxLayout;
    // 設置佈局
    hbLayout->addWidget(leImagePath);
    hbLayout->addWidget(pbSelectFile);
    hbLayout->addWidget(pbRunDetect);
    QVBoxLayout* vbLayout = new QVBoxLayout(&widget);
    vbLayout->addLayout(hbLayout);
    vbLayout->addWidget(gvImageView);
    // 添加處理操做
    QObject::connect(pbSelectFile,&QPushButton::clicked,
                     [leImagePath,gvImageView,gsViewScene,pbRunDetect,&srcImage,&widget]()
    {
        static QString path;
        path = QFileDialog::getOpenFileName(&widget,
                                            QStringLiteral("選擇人像圖"),
                                            path,
                                            QString("Images (*.png *.jpg *.jpeg *.jfif)"));
        if(path.isEmpty()){return;}
        QImage image;
        if(!image.load(path)){return;}
        // 圖像太大的時候,執行太慢,先縮小一點
        if(image.width() > 2048){ image = image.scaledToWidth(2048); }
        if(image.width() > 1536){ image = image.scaledToWidth(1536); }

        srcImage.swap(image);
        leImagePath->setText(path);

        gsViewScene->clear();
        gsViewScene->setSceneRect(srcImage.rect());
        gsViewScene->addPixmap(QPixmap::fromImage(srcImage));
        gvImageView->fitInView(gvImageView->sceneRect());

        pbRunDetect->setEnabled(true);
    });

    QObject::connect(pbRunDetect,&QPushButton::clicked,
                     [gvImageView,gsViewScene,&srcImage]
    {
        // 轉換爲RGB24
        QImage image = srcImage.convertToFormat(QImage::Format_RGB888);
        int rows = image.height();
        int cols = image.width();
        int rowbytes = image.bytesPerLine();

        uchar* pImgData = image.bits();
        // RGB -> BGR 由於facedetect_cnn函數要求傳入圖像爲BGR三波段圖像
        for( int r = 0; r < rows; ++r ){
            uchar* pRow = pImgData + (r * rowbytes);
            for(int c = 0; c < cols; ++c ){
                qSwap(pRow[c*3],pRow[c*3+2]);
            }
        }
        // 進行檢測
        QByteArray buffer(0x20000,0);
        int* pResults = facedetect_cnn((uchar*)buffer.data(),pImgData,cols,rows,rowbytes);
        // 將檢測結果畫到圖像上
        QPixmap pixmap = QPixmap::fromImage(srcImage);
        if(pResults != NULL) {
            for(int i=0; i< *pResults; ++i) {
                short * p = ((short*)(pResults+1))+142*i;
                int x = p[0];
                int y = p[1];
                int w = p[2];
                int h = p[3];
                int confidence = p[4];
                // 查看源碼可知,其並未進行人像框範圍和置信率之外的數據賦值
                int angle = p[5];
                QPainter painter(&pixmap);
                // painter.setBrush(QBrush(QColor(255,0,0),));
                painter.setPen(Qt::green);
                // painter.drawEllipse(x,y,w,h);
                painter.drawRect(x,y,w,h);
                painter.drawText(x,y,w,h,Qt::AlignCenter,
                                 QStringLiteral("置信:%1%\n年齡:%2").arg(confidence).arg(angle));
            }
        }

        gsViewScene->clear();
        gsViewScene->setSceneRect(pixmap.rect());
        gsViewScene->addPixmap(pixmap);
        gvImageView->fitInView(gvImageView->sceneRect());
    });

    widget.resize(1024,768);
    widget.show();
    return a.exec();
}
相關文章
相關標籤/搜索