libfacedetection简单使用记录
1、源码下载
直接从github上克隆项目仓库。
git clone https://github.com/ShiqiYu/libfacedetection.git
2、编译
2.1、linux
这个项目使用了cmake脚本,先生成makefile。(我这里是在ArchLinux x86_64环境下测试的)
cmake -DENABLE_NEON=OFF -DCMAKE_BUILD_TYPE=RELEASE .
执行上面的命令成功后,执行下面语句进行编译
make -j4
编译完成后会同时生成动态库和静态库
[ 90%] Linking CXX static library libfacedetection.a
[100%] Linking CXX shared library libfacedetection.so
2.2、Windows MINGW64
这里和上面也是一样的。先使用cmake生产Makefile文件,然后执行编译即可。这里我指定了使用g++作为C++的编译器,因为如果不指定会使用gcc去链接,导致生成动态库的时候找不到c++标准库的一些定义。
cmake -DENABLE_NEON=OFF -DCMAKE_BUILD_TYPE=RELEASE -DCMAKE_CXX_COMPILER=g++ .
其它的与上面linux的一致。
备注:我这里使用的是MSYS2环境,直接使用pacman命令安装的gcc/g++。
2.3、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

3、简单测试程序
使用Qt写了一个小程序,简单的测试了一下。
测试的时候发现年龄始终是0,然后就看了一下源码,发现其并未对年龄和面部特征点进行输出,实际在代码中也没有进行检测,年龄和面部特征点相关的代码我没有找到(2019年4月16日)。
3.1、测试截图


3.2、测试代码如下
/*****************************************************
* 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();
}
libfacedetection简单使用记录的更多相关文章
- 如果简单的记录,就可以为这个世界创造更多的财富,那么还有什么理由不去写博客呢? — 读<<黑客与画家>> 有感
上一次博文发文时间是2016.1.15,7个月已经过去了.最近读了一本<>的书,对我触动挺大的!里面有关于技术趋势的探讨,也有关于人生和财富的思考! 开始更新iOS122的文章的初衷是,聚 ...
- Python简单爬虫记录
为了避免自己忘了Python的爬虫相关知识和流程,下面简单的记录一下爬虫的基本要求和编程问题!! 简单了解了一下,爬虫的方法很多,我简单的使用了已经做好的库requests来获取网页信息和Beauti ...
- redis5.0.3单实例简单安装记录
redis5.0.3单实例简单安装记录 日常需要测试使用,索性记录下来,免得临时又麻烦的找资料. yum -y install make gcc-c++ cmake bison-devel ncurs ...
- Oracle触发器简单入门记录
写在前面: 最近,老项目新增了日报优化的需求,丽姐让我用触发器去实现当数据插入或者更新的时候,实现对日报表数据更新操作.嗯嗯嗯呢,之前学习数据库的时候,有碰到过触发器,但都是一跳而过,也没怎么去真正的 ...
- 27:简单错误记录SimpleErrorLog
题目描述 开发一个简单错误记录功能小模块,能够记录出错的代码所在的文件名称和行号. 处理: 1. 记录最多8条错误记录,循环记录,对相同的错误记录(净文件名称和行号完全匹配)只记录一条,错误计数增加: ...
- percona-toolkit 3.0.13 简单安装记录
percona-toolkit 3.0.13 简单安装记录 环境:centos6.x mysql:8.0.17 yum -y install perl-DBIyum -y install perl-D ...
- .Net写txt文件-简单的记录执行日志信息代码
在执行一些批量操作时,想记录一些执行日志信息,越简单方便越好啊.提供一个常用的简单方法,将信息记录在txt文件里: public static void log(string content, str ...
- 测试与开发如何有效沟通,QC11(HP ALM 11)的简单使用记录
笔者所在的项目组使用的缺陷管理工具是HP的QC11,作为测试人员,为了与开发一起跟随Bug的一生,简单的写了使用流程,这里记录一下,主要是让开发人员熟悉一下. 首先使用账户登录QC,如地址: http ...
- 从壹开始前后端分离【 .NET Core2.0 +Vue2.0 】框架之十 || AOP面向切面编程浅解析:简单日志记录 + 服务切面缓存
代码已上传Github+Gitee,文末有地址 上回<从壹开始前后端分离[ .NET Core2.0 Api + Vue 2.0 + AOP + 分布式]框架之九 || 依赖注入IoC学习 + ...
随机推荐
- Codeforces 948D Perfect Security 【01字典树】
<题目链接> 题目大意: 给定两个长度为n的序列,可以改变第二个序列中数的顺序,使得两个序列相同位置的数异或之后得到的新序列的字典序最小. 解题分析: 用01字典树来解决异或最值问题.因为 ...
- Django之setting文件
Django之setting文件 转载:https://www.jb51.net/article/128678.htm 目录 设置语言.时区 app路径 数据库配置 静态文件配置 中间件 sessio ...
- 实现DataGridView控件中CheckBox列的使用
最近做WindowsForms程序,使用DataGridView控件时,加了一列做选择用,发现CheckBox不能选中.搜索后,要实现DataGridView的CellContentClick事件,将 ...
- C#相关FTP操作
C# 相关 FTP(File Transfer Protocol) 操作 1.获取文件目录 UsePassive:需要设置为false. 使用被动模式,因为客户端防火墙的存在,所以为了确保数据可以正常 ...
- Windows上搭建安卓的Java开发环境
下载安装JDK path的系统变量增加值(示例): D:\Program Files\Java\jdk1.8.0_25\bin同理为名为classpath的系统变量增加值(示例:没有的话可以新建)D: ...
- input输入框限制20个字符,十个汉字
英文和数字为一个字符,汉字为两个字符 在 Web 开发中,经常要对表单元素的输入进行限制,比如说不允许输入特殊字符,标点.通常我们会监听 input 事件: inputElement.addEvent ...
- VMware5.5-高可用性和动态资源调度(DRS)
高可用性 故障分类:ESX主机---虚拟机(主机通过vmtools监控)---应用程序(基本不用6.0新增了这一功能) 高可用的信号检测目前可分为两种 一.网络信号 二.存储信号 新建群集 上图的自定 ...
- python2和python3比较好的共存方法
文章根据网络资料编写,只为个人学习使用.青山... ---------------------------------------------------- 由于工作学习的需求,大家都想同时安装pyt ...
- 第2讲——wiz
PC端信息收集 网页剪藏 win+s 屏幕截图:win+printscreen微博收集:@mywiz @我的印象笔记 按ESC隐藏/恢复左边导航栏 F11全屏阅读 打标签:解决文件夹重叠问题 搜索 ...
- python系统编程(八)
进程VS线程 功能 进程,能够完成多任务,比如 在一台电脑上能够同时运行多个QQ 线程,能够完成多任务,比如 一个QQ中的多个聊天窗口 定义的不同 进程是系统进行资源分配和调度的一个独立单位. 线程是 ...