直接從github上克隆項目倉庫。c++
git clone https://github.com/ShiqiYu/libfacedetection.git
這個項目使用了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
這裏和上面也是同樣的。先使用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
由於就這麼幾個文件,生成一個龐大的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日)。
/***************************************************** * 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(); }