HTML5技术

一个简单粗暴的人脸认证标注工具的实现 - 喵耳朵

字号+ 作者:H5之家 来源:H5之家 2017-01-05 11:01 我要评论( )

小喵的唠叨话:话说最近小喵也要开始写论文了,想了两周还是没有头绪,不知道该写些什么。恰好又被分配了一点标注数据的工作,于是乎想写点代码,休闲一下。结果也就是这篇博客。对了,小喵对GUI编程一窍不通,只知道Windows有MFC,Mac上的不知道。。。恰好

小喵的唠叨话:话说最近小喵也要开始写论文了,想了两周还是没有头绪,不知道该写些什么。恰好又被分配了一点标注数据的工作,于是乎想写点代码,休闲一下。结果也就是这篇博客。对了,小喵对GUI编程一窍不通,只知道Windows有MFC,Mac上的不知道。。。恰好听说过QT,而且知道这个界面库是跨平台的,也就选用了这个工具了。

 

本文系原创,转载请注明出处~

小喵的博客:

博客原文:一个简单粗暴的人脸认证标注工具的实现.html

 

那么现在开始和小喵一起瞎猫似的捯饬QT吧~

先看一眼效果图:

是不是乍一看还挺炫酷。功能上也还好,至少简单的标注工作都能完成了。那么让我们来一步一步的完成这个工具吧。

一、功能需求

这个程序主要的功能是完成一个人脸认证的标注工具。

具体来说,就是给定很多对人脸的图片,要标注一下这一对是不是同一个人。同时,每一对的图片的人脸一张是生活照,一张是证件照,需要同时标注出哪张是证件照,那张是生活照。照片都是经过检测和对齐的,这个工具只需要完成简单的显示、标注、保存记录的工作就可以。

当然考虑到有时候需要标注的list可能很大,可以加入跳转的功能。标注结果都保存在内存,用户可以随时更改,点击保存,则写入硬盘。

二、数据结构

那么是不是现在就可以动手写代码了呢?当然不是!

小喵写这个软件一共用了3天的时间,第一天完成了一个超简单demo程序,熟悉了一下QT的事件添加,路径选择和显示图片的几个功能。之后又仔细的思考了一下各种数据的结构,才动手做了这一版工具。没有一个清晰的数据的概念,会造成许多的无用功。所以,大家在写程序的时候,要在准备阶段多花一点时间来思考,毕竟写代码才是最简单的事情不是吗?

三、界面制作

GUI程序的界面一直是个很让人头疼的问题,记得在本科学习Java的时候,需要自己手写一个控件,使用new JButton()类似的方式创建按钮,然后添加到主界面上,位置什么的都得调用这个对象来设置,十分的繁琐。那么QT能不能简化这个过程呢?答案是肯定的。

创建项目->选择Application->Qt Widgets Application。然后项目名改成Anno Pro,其他全部默认设置,就创建好了一个项目了。这个初始的项目里面有3个文件夹:头文件,源文件和界面文件,以及一个.pro结尾的项目配置文件。

既然需要编辑界面,我们自然会想查看一下界面文件了,双击MainWindow.ui(我这里全部都是默认的名字)。出现的是一个充满各种控件的可视化界面编辑器。

按照我们之前的界面样式,拖动左边的控件,就可以完成界面的编写了。小喵这里只用到了几种控件:

QPushButton:各种按钮

QLabel:所以显示文字和图像的区域都是这这个控件

QFrame:一个容器,小喵用它只是为了结构上更清晰

QSlider:滑动条,小喵用的是水平滑动条

QStatusBar:状态栏, 这应该是自带的,如果删掉的话,在MainWindow控件点击右键就可以创建了

拖动完成后,双击空间,就可以给空间设置文本,同时注意给每个控件起一个好听的名字(起名字很重要的!《代码大全》中甚至用一章,好几十页的篇幅介绍如何命名)。

至于其他的控件,大家可以自行研究。反正小喵现在的道行应该才是筑基。

那么我们就愉快的完成了界面的编写了~点击左右下的运行图标(三角形的那个),就可以看到自己的运行程序了!

四、数据定义与初始化

我们先前已经分析了我们需要的数据了,这部分开始使用代码的定义这些结构。

打开我们/*唯一的*/头文件mianwindow.h,添加需要的变量,小喵就直接把自己的头文件复制下来了:

1 #ifndef MAINWINDOW_H 2 #define MAINWINDOW_H 3 4 #include <QMainWindow> 5 #include <vector> 6 #include <string> 7 namespace Ui { MainWindow; 10 } MainWindow : public QMainWindow 13 { 14 enum AnnoState { YES = NO = UNSURE = }; : 22 explicit MainWindow(QWidget *parent = 0); 23 ~MainWindow(); : std::vector<std::std::vector<std::current_idx; total_pair_num; std::vector< AnnoState > annotation_list; };

可以看出,小喵添加了一个enum的类型,用来表示标注结果的类型。虽然只有4个状态,我们甚至可以直接约定几个int值来表示,但相信我,为这么4个状态定义一个枚举类型是完全有必要的。

之后我们所有的成员变量都是private的。具体含义,注释中也有写明。

下一步就是初始化了。初始化的过程当然得写在构造函数里,这里,小喵在初始化的时候强迫用户选择一个标注的list,如果不这么做,会有很多的意外情况。请原谅小喵的怠惰。。。

1 MainWindow::MainWindow(QWidget *parent) : 2 QMainWindow(parent), 3 ui(new Ui::MainWindow) 4 { 5 ui->setupUi(this); (1) { , ); 10 if (file_name.isEmpty()) { , , QMessageBox::Ok | QMessageBox::Cancel); 12 if (ok == QMessageBox::Ok) { 13 exit(0); 14 } 15 continue; 16 } 17 std::ifstream is(file_name.toStdString()); 18 std::string image_name; 19 bool is_odd = true; 20 while (is >> image_name) { 21 if (is_odd) { 22 this->image_list_1.push_back(image_name); 23 } else { 24 this->image_list_2.push_back(image_name); 25 } 26 is_odd = !is_odd; 27 } 28 is.close(); (image_list_1.size() != image_list_2.size()) { , , QMessageBox::Ok); 32 continue; 33 } 34 if (0 == image_list_1.size()) { , , QMessageBox::Ok); 36 continue; 37 } 38 break; 39 } 40 41 assert(image_list_1.size() == image_list_2.size()); ->total_pair_num = image_list_1.size(); 44 this->current_idx = 0; 45 std::vector<AnnoState> annotation_list(this->total_pair_num, AnnoState::UNKNOWN); 46 this->annotation_list.swap(annotation_list); 47 48 display(); 49 }

这里用了两个QT的组件:

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • 简单酷炫的canvas动画 - 魔洁

    简单酷炫的canvas动画 - 魔洁

    2017-01-01 11:02

  • iosselect:一个js picker项目,在H5中实现IOS的select下拉框效果 - mufc-go

    iosselect:一个js picker项目,在H5中实现IOS的select下拉框效果 -

    2017-01-01 10:02

  • 如何一步一步用DDD设计一个电商网站(九)—— 小心陷入值对象持久化的坑 - Zachary_Fan

    如何一步一步用DDD设计一个电商网站(九)—— 小心陷入值对象持久化

    2016-12-27 13:06

  • Html5 简单选择排序演示 - 飞翔的月亮

    Html5 简单选择排序演示 - 飞翔的月亮

    2016-12-27 10:00

网友点评