基于QML的简易车牌识别客户端实现

前言

最近看了一些车牌识别的相关项目的代码。有基于Python的,也有C++的,他们都利用了一些开源的库,所以在了解了那些图像处理的库的基础上再看他们的项目还是可以看懂的。EasyPR是基于OpenCV做的一个开源项目。项目已经比较完善,接口也做的很好,所以我就利用项目提供的接口做了一个linux下的桌面客户端。

主要目的有:

1,复习Qt做界面的流程
2,掌握Qt和C++融合的相关技巧
3, 了解界面逻辑和业务逻辑的分工

所以这里不会太多介绍车牌识别的相关知识,感兴趣的童鞋可以参考大牛的博客源代码

目录

项目预览

QML设计

业务逻辑实现

结束语

项目预览

这里是最后的效果图,做的有点丑哈,如果你觉得还可以可以继续往下看哦。

这里写图片描述

这里写图片描述

项目目录:

├── main   (qml主目录)
├── top     (qml标题栏目录)
├── mid     (qml中间目录)
├── button  (qml底部目录)
├── easyprsource (easypr源文件)
├── main.cpp     (主文件)
├── getplatelicense.cpp (获取车牌字符文件)
├── getplatelicense.h
├── ico           (图标文件夹)
├── lib            (编译打包文件夹)
├── fonts          (字体文件夹)
├── fonts.qrc
├── qml.qrc
├── ico.qrc
└── MyEasyPr.pro

QML设计

QML是Qt Quick 中的一种语言,有点类似于js和css,当然这两种语法它都支持,与Qt的ui设计相比,QML更强调了设计本身适合扁平化的风格,而不是把所有的控件都进行封装,这样设计的灵活性更高,但有时候也会让人一头雾水,熟悉的控件都找不到了,还有用过Qt的都知道,它自带的可视化设计界面很好用,省去了不少代码,但是qml输入也有可视化的设计功能,但是用起来真的不爽,反正我是没有用。因为QML自己本身也是一种语言,所以完全可以不用任何C++代码就能设计出一些界面来,这对于数量了js和css的童鞋来说是一种福音。

标题栏设计

标题栏主要是logo和窗口缩放按钮和一个设置按钮原来响应弹出层,
最外层是Item。然后依次将这些控件从左到右排列即可,主要相邻之间的间隔。代码中大多是关于属性,全部贴出了看起来也很费力,所以下面贴出的代码都会省掉不重要的属性设置,并在里面加入注释说明。

import QtQuick 2.1
import QtQuick.Window 2.2
import QtQuick.Controls 2.3
import QtQuick.Controls.Styles 1.4
import QtGraphicalEffects 1.0
import "../button/" as Btn

Item
{
    id:toprow
    FontLoader { id: localFont; source: "qrc:/fonts/迷你简瘦金书.ttf" //设置标题栏中文字的字体}

    Rectangle {
        id: idrec
        color: "#3FE295"
        //标题栏背景
    }
    Image
    {
        id:logo
        //左侧logo
    }
    Text
    {
        id:textId
        font.family: localFont.name
        text: "EasyPr  [车牌识别系统]"
    }
    Btn.Basebtn
    {
        id: closebtn
        //关闭窗口按钮
        onButtonClicked: Qt.quit()
    }
    Btn.Basebtn
    {
        id: maxbtn
        //窗口最大化按钮
        //双击标题栏实现最大化和窗口还原
        onButtonClicked:
        {
            if (mainRoot.visibility ==Window.Maximized)
            {
                mainRoot.visibility = Window.AutomaticVisibility
                console.log("恢复")
            }
            else{
                mainRoot.visibility = Window.Maximized
                console.log("最大化")
            }

        }
    }
    Btn.Basebtn
    {
        id: minbtn
        //最小化按钮
        onButtonClicked:
        {
            if (mainRoot.visibility !=Window.Minimized)
            {
                mainRoot.visibility = Window.Minimized
                console.log("最小化")
            }
        }
    }
    Btn.Basebtn
    {
        id: setbtn
        //设置按钮
        //弹出层
        Pop
        {
        id:settingpop
        }
        onButtonClicked:
        {
            //settingpage.visible=!settingpage.visible
            settingpop.open()
        }
   }
}

<span id="左侧菜单栏"></span>

左侧菜单栏

左侧的菜单栏也是继承了按钮类,然后做了一些属性美化

import QtQuick.Dialogs 1.0
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.3
import QtQuick.Controls.Styles 1.4
import QtGraphicalEffects 1.0
import QtQml.Models 2.1
import "../button" as Btn
import com.mxq.easypr 1.0
Item
{
    property string getstring: ""
// 列布局
Row{
    spacing: 0
    Column
    {
        id:leftopt
        spacing: 15*heightbili
        FileDialog
        {
        id:fds
        title: "选择文件"
        folder: shortcuts.desktop
        selectExisting: true
        selectFolder: false
        selectMultiple: false
        nameFilters: ["图片 (*.jpg|*.jpeg|*.png|*.svg)"]
        onAccepted: {
            //选择成功之后的响应
        }
        onRejected: {
            if(getstring == "")
            imgshow.imgborderopa = 0.5
        }

        }
        Btn.Baseopt
        {
            labelstr: "打开车牌图"
        }

        Btn.Baseopt
        {
            labelstr: "开启摄像头"
        }
        Btn.Baseopt
        {
            labelstr: "新车牌识别 "
        }
        Item
        {
             //原来充当分割空间
             width: 90*widthbili
             height: 20*heightbili
        }
        //下面的小菜单使用了Listview
        ListView
        {
            spacing: 20*heightbili
            width: 90*widthbili
            height: 150
            //anchors.fill: parent
            model: Listdelegate
            {
            }
            delegate: Reslistview{}
        }
    }
    Item {
        width: 5*widthbili
        height: 20*heightbili
    }

图片显示区域

图片显示区域主要是原来显示选择的链接的文件夹,并且获得url传给easypr相关函数。

Showimage
    {
    id:imgshow
    imgurl: getstring
    width:  mainRoot.width - 300*widthbili;
    height: mainRoot.height - 100*heightbili
    onDoubleClicked:
    {
       fds.open()
    }
    }


    Item
    {
        height: 100
        width: 10*widthbili
    }
    }

车牌显示区域

Rightlist
    {
        width: 120*widthbili
        height: 100*heightbili
        ListView
        {
            id:showplates
            width: 200*widthbili; height: 200*heightbili
            model:platelist
            delegate: Btn.Basegrid{}
        }
    }
}
PlateLicense
{
    id:easypr
}

其他设计

业务逻辑实现

这里的业务逻辑时指车牌识别的相关函数。前面我们已经实现了整个界面,包括很多按钮,其中一些比如打开文件夹和显示图片的逻辑是可以用qml自身去实现。但是车牌识别算法我们是在easypr源代码中的,所以我们需要将easypr的源代码加入qt中,然后在qml中调用相关函数。这里就包括了两个主要部分:环境配置和c++与qml的相互交互。

环境配置

如何在将c++的源文件加入到qt中,这里的主要工作是在qt的工程配置文件中进行操作,包括导入源文件,导入相关库…
直接上代码。

QT += quick
CONFIG += c++11
DEFINES += QT_DEPRECATED_WARNINGS
RESOURCES += qml.qrc \
    ico.qrc \
    fonts.qrc
QML_IMPORT_PATH =
QML_DESIGNER_IMPORT_PATH =
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

INCLUDEPATH += $$PWD/easyprsource/include

SOURCES += \
    main.cpp \
    getplatelicense.cpp \

HEADERS += \

    getplatelicense.h
# 导入opencv相关库
INCLUDEPATH += /usr/local/opencv3.2.0/include \
               /usr/local/opencv3.2.0/opencv\
               /usr/local/opencv3.2.0/opencv2\
# 添加静态文件库
LIBS += -L$$PWD/easyprsource/lib -leasypr
LIBS += -L$$PWD/easyprsource/lib -lthirdparty
# opencv动态库
LIBS += /usr/local/opencv3.2.0/lib/libopencv*

QML,C++交互

QML和C++是两种不同的语言,而且各种有各种的专长。qt提供了将两者融合的方案。项目中是用c++注册的方式实现。

结束语


如果堆这个博客的内容有什么疑问或感兴趣,愿意就此进一步交流的,欢迎加QQ:1529806383。共同学习,一起进步!

代码完整下载地址

猜你喜欢

转载自blog.csdn.net/hust_a/article/details/82463816