数据可视化 Final Project

目录
数据可视化 Final Project 1

  1. 项目介绍 1
    1.1. 人脸互换(face swap) 2
    1.2 人脸融合(face morph) 2
    1.3 本征脸(eigen face) 2
  2. 算法结构与处理过程 2
    2.1 人脸变换 2
    2.1.1 人脸关键点检测 2
    2.1.2 计算凸包 3
    2.1.3 德劳内(Delaunay)三角划分 3
    2.1.4 进行仿射变换 3
    2.1.5 无缝融合 3
    2.2 人脸融合 3
    2.2.1 人脸关键点检测 3
    2.2.2 定义融合度 4
    2.2.3 采样点加权 4
    2.2.4 德劳内三角划分 4
    2.2.5 图像融合 4
    2.3 本征脸 5
    2.3.1 数据预处理 5
    2.3.2 主成分分析 5
    2.3.3 获得本征脸 5
  3. 代码结构 5
    3.1 人脸互换 5
    3.2 人脸融合 6
    3.3 本征脸人脸 6
    3.4 GUI 部分 6
  4. 开发环境 6
  5. 可执行文件及使用的数据集 7
    5.1 数据集 7
    5.2 可执行文件及运行方式 7
  6. 项目成果与反思 8
    6.1 项目成果 8
    6.1.1 人脸互换 8
    6.1.2 人脸融合 8
    6.1.3 本征脸 9
    6.2 项目思考与改进 10
    6.1.1 人脸互换 10
    6.1.1 人脸融合 10
    6.2.3 本征脸 10
  7. 小组成员工作内容 10

4.开发环境
在本次项目中,算法几接口 API 都是由 pyhton3.5(python3.6)完成的,其中还使用了
openCV 库。GUI 使用 pyqt 完成。API 使用 face++人脸关键点接口。
1.1.人脸互换(face swap)
人脸互换部分主要实现的功能是,给定任意两张人脸图片,通过一系列操作,使两个人的脸部交换,这部分需要的问题有:
1.不同的人的脸部结构千差万别,同一个人也会因为角度、面部表情的不同而导致差别,即如何实现不同图片的人脸对齐;
2.不同人脸的肤色、光照不同,即不同图片的面部亮度不同,在换脸后如何与整体亮度统一;
3.不同人脸的纹理不同,比如老人的皱纹等,如何实现换脸后纹理的统一。
1.2人脸融合(face morph)
在人脸融合部分,我们需要实现给定任意两张人脸图片和融合度α,通过一系列操作,实现两个人脸的融合。这一部分的困难在于:
1.人脸结构的检测与分割。对于给定的人脸图片,人脸的结构差异很大。
2.人脸融合度的构建。对于给定的融合度 α,如何对两张图片的人脸取样与映射。
1.3本征脸(eigen face)
在这一部分,需要对较大的数据集(几百张,几千张人脸图片)进行处理,通过主成分分析的方法,得到一定数量的人脸主成分。这一部分的主要困难在于数据集的预处理, 我们需要将不同图片中的人脸对齐,才能进行后续的处理。
2.算法结构与处理过程
2.1人脸变换
2.1.1人脸关键点检测
实现人脸变换的第一步,便是人脸关键点的检测,得到图片中的人脸的结构。在这里,我们利用旷视face++的API 来定位人脸关键的集合{V1,V2,…,Vn},其中关键点的数量可以选择 83 或者 106.
2.1.2计算凸包
在获取人脸关键点集合后,我们需要计算这些关键点的凸包(convex hull)(凸包是一个计算几何(图形学)中的概念:在一个实数向量空间 V 中,对于给定集合 X,所有包含X 的凸集的交集 S 被称为 X 的凸包。X 的凸包可以用 X 内所有点(X1,…Xn)的凸组合来构造.)在这里,我们计算凸包是为了获取这些人脸关键点组成的一个人脸区域。
2.1.3德劳内(Delaunay)三角划分
在获得凸包以后,我们对凸包内的人脸关键点进行德劳内三角的划分。德劳内三角划分能将我们的凸包区域进行分割,本文转载自http://www.biyezuopin.vip/onews.asp?id=14906并且更易于保留人脸的细节部分,并且因为获取仿射变换需要原图片和目标图片的各三个点,正好对应于原图和目标图的对应的德劳内三角。
2.1.4进行仿射变换
在获得原图片和目标图图片的德劳内三角以后,我们需要寻找两张图对应的三角形对,对这样的每一对三角形,我们可以计算得到一个仿射函数。这个仿射函数将被用于三角形对之间的仿射变换。重复这个操作,直到所有区域都操作完毕,我们得到了人脸的位置变换。
2.1.5无缝融合
在上述人脸仿射变换后,我们得到人脸结构和位置的变换,但我们没有对人脸区域亮度进行调整,这样会造成人脸区域和其他区域的颜色协调的问题。所以最后我们用 opencv 的无缝融合函数seamlessClone()来实现无缝融合操作。

# -*- coding: utf-8 -*-# Form implementation generated from reading ui file 'mainPage.ui'## Created by: PyQt5 UI code generator 5.10.1## WARNING! All changes made in this file will be lost!from morphGUI import *from swapGUI import *from eigenGUI import *class Ui_MainPage(object):    #打开融合脸界面的函数    def startMorph(self):        self.morph=Ui_Morph()        self.morph.show()    #打开换脸界面的函数    def startSwap(self):        self.Swap=Ui_Swap()        self.Swap.show()    #打开生成特征脸的函数    def startEigen(self):        self.Eigen=Ui_Eigen()        self.Eigen.show()    #打开主界面的函数    def setupUi(self, MainWindow):        MainWindow.setObjectName("MainWindow")        MainWindow.resize(718, 493)        MainWindow.setStyleSheet("background-color: rgb(2, 136, 209);")        self.centralwidget = QtWidgets.QWidget(MainWindow)        self.centralwidget.setObjectName("centralwidget")        self.label = QtWidgets.QLabel(self.centralwidget)        self.label.setGeometry(QtCore.QRect(40, 180, 231, 91))        self.label.setStyleSheet("font: 75 40pt \"Microsoft YaHei UI\";\n""color: rgb(255, 255, 255);")        self.label.setObjectName("label")        self.graphicsView = QtWidgets.QGraphicsView(self.centralwidget)        self.graphicsView.setGeometry(QtCore.QRect(0, 450, 731, 41))        self.graphicsView.setStyleSheet("background-color: rgb(255, 255, 255);")        self.graphicsView.setObjectName("graphicsView")        self.label_2 = QtWidgets.QLabel(self.centralwidget)        self.label_2.setGeometry(QtCore.QRect(40, 260, 401, 61))        self.label_2.setStyleSheet("font: 25 12pt \"Microsoft YaHei UI\";\n""text-decoration: underline;\n""color: rgb(255, 255, 255);\n""color: rgb(225, 225, 225);")        self.label_2.setObjectName("label_2")        self.pushButton = QtWidgets.QPushButton(self.centralwidget)        self.pushButton.setGeometry(QtCore.QRect(470, 170, 141, 34))        self.pushButton.setStyleSheet("QPushButton{background-color:#16A085;border:none;color:#ffffff;font: 25 9pt \"Microsoft YaHei UI\";}"                               "QPushButton:hover{background-color:#333333;}")        self.pushButton.clicked.connect(self.startMorph)        self.pushButton.setObjectName("pushButton")        self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget)        self.pushButton_2.setGeometry(QtCore.QRect(470, 250, 141, 34))        self.pushButton_2.setStyleSheet("QPushButton{background-color:#16A085;border:none;color:#ffffff;font: 25 9pt \"Microsoft YaHei UI\";}"                               "QPushButton:hover{background-color:#333333;}")        self.pushButton_2.clicked.connect(self.startSwap)        self.pushButton_2.setObjectName("pushButton_2")        self.pushButton_3 = QtWidgets.QPushButton(self.centralwidget)        self.pushButton_3.setGeometry(QtCore.QRect(470, 320, 141, 34))        self.pushButton_3.setStyleSheet("QPushButton{background-color:#16A085;border:none;color:#ffffff;font: 25 9pt \"Microsoft YaHei UI\";}"                               "QPushButton:hover{background-color:#333333;}")        self.pushButton_3.setObjectName("pushButton_3")        self.pushButton_3.clicked.connect(self.startEigen)        self.graphicsView_2 = QtWidgets.QGraphicsView(self.centralwidget)        self.graphicsView_2.setGeometry(QtCore.QRect(0, 0, 731, 41))        self.graphicsView_2.setStyleSheet("background-color: rgb(2, 136, 209);\n""border:none")        self.graphicsView_2.setObjectName("graphicsView_2")        MainWindow.setCentralWidget(self.centralwidget)        self.retranslateUi(MainWindow)        QtCore.QMetaObject.connectSlotsByName(MainWindow)    #对主界面部件加上文字    def retranslateUi(self, MainWindow):        _translate = QtCore.QCoreApplication.translate        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))        self.label.setText(_translate("MainWindow", "Face#"))        self.label_2.setText(_translate("MainWindow", "Better Codes. Better Faces"))        self.pushButton.setText(_translate("MainWindow", "Face Morphing"))        self.pushButton_2.setText(_translate("MainWindow", "Face Swap"))        self.pushButton_3.setText(_translate("MainWindow", "EigenFace"))class MyWindow(QtWidgets.QWidget, Ui_MainPage):    def __init__(self):        super(MyWindow, self).__init__()        self.setupUi(self)#启动该文件,会启动GUI画面if __name__=="__main__":    import sys    app=QtWidgets.QApplication(sys.argv)    widget = QtWidgets.QMainWindow()    login = Ui_MainPage()    login.setupUi(widget)    widget.show()    sys.exit(app.exec_())