计算机视觉
图像处理

人脸识别系统开发(4) — 图片列表功能

文章目录

在该人脸识别系统中,每次识别过程都会从摄像头实时捕获N(暂定为3)张人脸图片,用这N张图片来和证件上面的人脸进行比对。系统会将每次捕获的人脸图片显示在右侧的列表中,我们可以通过QML中的ListView来实现列表功能。

MVC

在说ListView功能前,就不得不提MVC设计模式了,因为ListView是采用这个模式来实现的。

Model-View—Controller(MVC)是源自SmallTalk的一个设计模式,在构建用户界面或前端网页时经常用到。作为一种经典的设计模式,MVC通过将系统分解为模型、视图、控制器三部分,每一部分相互独立,职责单一,在实现过程中只用专注于自身的核心逻辑。模型代表数据,视图代表呈现给用户看的界面部分,而控制器就是一个中间人,从模型拿数据给视图来呈现。

Qt中MVC框架对Controller部分进行了改动,引入了delegate的概念,合起来就是Model-View-Delegate。模型还是负责提供数据,View负责提供舞台进行呈现,Delegate负责控制以什么方式来显示。

Model

ListView的Model(也就是数据)可以在QML中定义,如:

import QtQuick 2.2
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.1

Rectangle {
    width: 360;
    height: 300;
    color: "#EEEEEE";

    Component {
        id: phoneDelegate;
        Item {
            id: wrapper;
            width: parent.width;
            height: 30;

            MouseArea {
                anchors.fill: parent;
                onClicked: wrapper.ListView.view.currentIndex = index;
            }

            RowLayout {
                anchors.left: parent.left;
                anchors.verticalCenter: parent.verticalCenter;
                spacing: 8;
                Text { 
                    id: col1;
                    text: name; 
                    color: wrapper.ListView.isCurrentItem ? "red" : "black";
                    font.pixelSize: wrapper.ListView.isCurrentItem ? 22 : 18;
                    Layout.preferredWidth: 120;
                }

                Text { 
                    text: cost; 
                    color: wrapper.ListView.isCurrentItem ? "red" : "black";
                    font.pixelSize: wrapper.ListView.isCurrentItem ? 22 : 18;
                    Layout.preferredWidth: 80;
                }

                Text { 
                    text: manufacturer; 
                    color: wrapper.ListView.isCurrentItem ? "red" : "black";
                    font.pixelSize: wrapper.ListView.isCurrentItem ? 22 : 18;
                    Layout.fillWidth: true;
                }                
            }
        }
    }

    ListView {
        id: listView;
        anchors.fill: parent;

        delegate: phoneDelegate;

        model: ListModel {
            id: phoneModel;
            ListElement{
                name: "iPhone 3GS";
                cost: "1000";
                manufacturer: "Apple";
            }
            ListElement{
                name: "iPhone 4";
                cost: "1800";
                manufacturer: "Apple";
            }            
            ListElement{
                name: "iPhone 4S";
                cost: "2300";
                manufacturer: "Apple";
            } 
            ListElement{
                name: "iPhone 5";
                cost: "4900";
                manufacturer: "Apple";
            }    
            ListElement{
                name: "B199";
                cost: "1590";
                manufacturer: "HuaWei";
            }  
            ListElement{
                name: "MI 2S";
                cost: "1999";
                manufacturer: "XiaoMi";
            }         
            ListElement{
                name: "GALAXY S5";
                cost: "4699";
                manufacturer: "Samsung";
            }                                                  
        }

        focus: true;

        highlight: Rectangle{
            color: "lightblue";
        }
    }
}

有时候ListView中的Model数据可能是通过某种复杂的方式获取到的(如网络接收、文件读取、硬件解码等),这个就需要通过C++构造Model提供到QML中。我们的人脸识别系统的Model数据就是实时从摄像头捕获的图片数据,所以也是在C++中定义Model。

在Qt中QAbstractItemModel是大部分模型(Model)类的基类,比如QAbstractListModel, QAbstractProxyModel, QAbstractTableModel, QFileSystemModel等。
QAbstractItemView是多部分视图(View)类的基类,如QListView, QTableView, QTreeView等。
QAbstractItemDelegate是所有delegate的基类,它又衍生出了QStyledItemDelegate和QItemDelegate两个分支。如果需要实现自己的delegate,可以从这2个类中选择一个作为基类。

C++中Model类GrapImageListModel定义:

#pragma once

#include <QAbstractListModel>
#include <QImage>
#include "GrapImageData.h"

class GrapImageListModelPrivate;

// http://doc.qt.io/qt-5/qabstractlistmodel.html
//
class GrapImageListModel : public QAbstractListModel {
    Q_OBJECT
public:
    GrapImageListModel(QObject* parent = NULL);
    virtual ~GrapImageListModel();

    // virtual function.
    int rowCount(const QModelIndex &parent = QModelIndex() ) const;
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole ) const;
    QHash<int, QByteArray> roleNames() const;
public slots:
    void addGrapImage(const GrapImageData& data);
    void clearGrapImage();
signals:
    void newImage(const QImage &img) const; // 连接ImageDisplay::setImage槽
protected:
    GrapImageListModelPrivate* m_pPrivate;
private:
    mutable int m_iIndex;
};

 

该类的关键在重载的三个虚函数rowCount,data,roleNames,Delegate在需要数据时会调用这3个函数来获取数据。
delegate定义在QML中(因为篇幅有删减):

Component {
    id: grapImageDelegate;

    Rectangle {
        id: wrapper;
        width: 140;
        height: 90;
        color: "transparent";

        Image {
            id: imgGrap;
            anchors.fill: parent;
            smooth: true;
            fillMode: Image.PreserveAspectFit;
            source: imgUri;
            visible: false;
        }
    }
}

delegate的定义比较简单,在Component中定义一个Image即可。注意,Image的source设置的不是图片实际地址,而是imgUri。
Delegate通过rowCount函数获取数据的总行数;通过roleNames来获取到QHash<int, QByteArray>,QHash<int, QByteArray>可以理解为”int – string”的对应集合,比如我们设置0 – imgUri将0对应到imgUri上,在Delegate需要数据,调用data时就会在role参数传0,我们就可以知道这时是需要什么类型的数据了,并且可以根据index参数知道Delegate要获取哪一行的数据。

转载注明来源:CV视觉网 » 人脸识别系统开发(4) — 图片列表功能

分享到:更多 ()
扫描二维码,给作者 打赏
pay_weixinpay_weixin

请选择你看完该文章的感受:

0不错 0超赞 0无聊 0扯淡 0不解 0路过

评论 抢沙发

评论前必须登录!