精华内容
下载资源
问答
  • 考勤打卡系统

    2018-07-25 12:43:16
    之前为公司编写使用多年的IC卡考勤系统。100%原创。100%可以使用。以前是用Delphi5及SQL 2000编写的. 在Delphi7下需要将MS Comm控件升级一下就可以. 非常适合小型生产工厂使用。MS Comm控件是用于读取考勤机的数据.
  • 考勤 打卡系统
  • Python人脸识别考勤打卡系统

    千次阅读 多人点赞 2021-07-14 15:42:40
    Python人脸识别考勤打卡系统 如需安装运行环境或远程调试,可加QQ905733049,或QQ2945218359由专业技术人员远程协助! 运行结果如下: 主要代码: import random import cv2 import numpy import datetime ...

    Python人脸识别考勤打卡系统

    如需安装运行环境或远程调试,可加QQ905733049, 或QQ2945218359由专业技术人员远程协助!

    运行结果如下:

     主要代码:

    import random
    import cv2
    import numpy
    import datetime
    import os
    import time
    import cv2 as cv
    import numpy as np
    import threading
    from PIL import Image, ImageFont, ImageDraw
    
    database_file_path = './resources/data.db'
    picture_dir_path = "./resources/pictures"
    trainer_file_path = './resources/Trainer/trainer.yml'
    font_file_path = './resources/simsun.ttc'
    zsc_circle_file_path = './resources/zsc.jpg'
    zsc_rectangle_file_path = './resources/zsc.png'
    haarcascade_frontalface_file_path = './resources/haarcascade_frontalface_default.xml'
    capture_opt = 0  # 摄像头参数,0,1为本机摄像头
    
    # 继承wx库里面的Frame类来使用
    class MainFrame(wx.Frame):
        def __init__(self):
            # 初始化窗体数据
            wx.Frame.__init__(self, None, -1, '人脸识别考勤系统', pos=(100, 100), size=(1337, 600))
            panel = wx.Panel(self, -1)
            sizer = wx.BoxSizer(wx.HORIZONTAL)
            sizer1 = wx.BoxSizer(wx.VERTICAL)
            sizer2 = wx.BoxSizer(wx.VERTICAL)
            font = wx.Font(15, wx.ROMAN, wx.NORMAL, wx.BOLD)
    
            # 设置窗口以及托盘图标
            icon = wx.Icon()
            icon.CopyFromBitmap(wx.Bitmap(wx.Image((zsc_circle_file_path), wx.BITMAP_TYPE_JPEG)))
            self.SetIcon(icon)
    
            # 设置左边背景学院logo
            image = wx.Image(zsc_rectangle_file_path, wx.BITMAP_TYPE_PNG).ConvertToBitmap()
            self.background = wx.StaticBitmap(panel, -1, bitmap=image, style=wx.ALIGN_CENTER)
            sizer1.Add(self.background, proportion=10, flag=wx.ALIGN_CENTER, border=10)
    
            # 设置采集人脸按钮
            self.command1 = wx.Button(panel, -1, '采集人脸')
            self.command1.SetFont(font)
            self.command1.SetBackgroundColour('#3299CC')
            sizer1.Add(self.command1, proportion=5, flag=wx.ALL | wx.EXPAND, border=10)
    
            # 设置训练数据按钮
            self.command2 = wx.Button(panel, -1, '训练数据')
            self.command2.SetFont(font)
            self.command2.SetBackgroundColour('#DBDB70')
            sizer1.Add(self.command2, proportion=5, flag=wx.ALL | wx.EXPAND, border=10)
    
            # 设置人脸识别按钮
            self.command3 = wx.Button(panel, -1, '识别打卡')
            self.command3.SetFont(font)
            self.command3.SetBackgroundColour('#32CC32')
            sizer1.Add(self.command3, proportion=5, flag=wx.ALL | wx.EXPAND, border=10)
    
            # 设置退出系统按钮
            self.command4 = wx.Button(panel, -1, '关闭摄像头')
            self.command4.SetFont(font)
            self.command4.SetBackgroundColour((random.randint(1, 255), random.randint(0, 255), random.randint(0, 255)))
            sizer1.Add(self.command4, proportion=5, flag=wx.ALL | wx.EXPAND, border=10)
    
            # 设置消息提示文本
            self.text5 = wx.StaticText(panel, -1, '\n\n', style=wx.ALIGN_CENTER)
            self.text5.SetFont(font)
            self.text5.SetForegroundColour('Red')
            sizer1.Add(self.text5, proportion=15, flag=wx.ALL | wx.EXPAND, border=10)
    
            # 设置个人信息文本
            self.text6 = wx.StaticText(panel, -1, '姓名:')
            self.text7 = wx.StaticText(panel, -1, '学号:')
            self.text8 = wx.StaticText(panel, -1, '学院:')
            sizer1.Add(self.text6, proportion=3, flag=wx.LEFT, border=0)
            sizer1.Add(self.text7, proportion=3, flag=wx.LEFT, border=0)
            sizer1.Add(self.text8, proportion=3, flag=wx.LEFT, border=0)
    
            # 把分布局全部加入整体顶级布局
            sizer.Add(sizer1, flag=wx.EXPAND | wx.ALL, border=20)
    
    
            # 设置右上边消息提示文本
            sizer3 = wx.BoxSizer(wx.HORIZONTAL)
            font = wx.Font(12, wx.ROMAN, wx.NORMAL, wx.BOLD)
            self.text9 = wx.StaticText(panel, -1, '', style=wx.ALIGN_LEFT)
            self.text9.SetFont(font)
            self.text9.SetForegroundColour('brown')
            self.text9.SetLabel(u''+'您好,欢迎使用人脸考勤系统!')
    
            self.text10 = wx.StaticText(panel, -1, '', style=wx.ALIGN_RIGHT)
            self.text10.SetFont(font)
            self.text10.SetForegroundColour('Blue')
            self.data_num = 0
            self.updateSumData()
            sizer3.Add(self.text9, proportion=1, flag= wx.ALL|wx.EXPAND, border=10)
            sizer3.Add(self.text10, proportion=1, flag= wx.ALL|wx.EXPAND, border=10)
    
            sizer2.Add(sizer3, proportion=1, flag=wx.EXPAND | wx.ALL, border=0)
    
            # 封面图片
            self.image_cover = wx.Image(zsc_circle_file_path, wx.BITMAP_TYPE_ANY).Scale(575, 460)
            self.bmp = wx.StaticBitmap(panel, -1, wx.Bitmap(self.image_cover))
            sizer2.Add(self.bmp, proportion=1, flag=wx.ALL|wx.EXPAND ,border=0)
    
    
            # 加入顶级布局
            sizer.Add(sizer2, flag=wx.EXPAND | wx.ALL, border=10)
    
            # 实例化数据库操作对象
            self.mySqlDao = MySQLDao(self)
            self.grid = MyGrid(panel, self.mySqlDao)
            self.grid.updateGrid()
            # 打卡记录表
            sizer.Add(self.grid, proportion=1, flag=wx.EXPAND | wx.ALL, border=10)
    
    
            panel.SetSizer(sizer)
    
            # 四个按钮对应的事件
            self.command1.Bind(wx.EVT_BUTTON, self.command1_event)
            self.command4.Bind(wx.EVT_BUTTON, self.command4_event)
            self.command3.Bind(wx.EVT_BUTTON, self.command3_event)
            self.command2.Bind(wx.EVT_BUTTON, self.command2_event)
    
            # 关闭事件
            self.Bind(wx.EVT_CLOSE,self.onClose)
    
            # 窗口居中,显示
            self.Center()
            self.Show()
    
            # 控制摄像头的开启与关闭
            self.recognition = False
            self.collected = False
    
        '''
            主窗体关闭事件
        '''
        def onClose(self,event):
            self.command4_event(event)
            # 等待子线程完成 再关闭,防止不正常退出
            time.sleep(1)
            self.Destroy()
    
        '''
            采集数据按钮的响应事件
        '''
        def command1_event(self, event):
            self.text6.SetLabel('姓名:')
            self.text7.SetLabel('学号:')
            self.text8.SetLabel('学院:')
            self.text5.SetLabel(u'\n温馨提示:\n' + '⚪正在进学生信息录入...')
            self.text5.Update()
    
            collectFrame = CollectFrame(self,self.mySqlDao)
            collectFrame.Show()
    
        '''
            训练数据按钮的响应事件
        '''
        def command2_event(self, event):
            self.trainData()
    
        '''
            识别打卡按钮的响应事件
        '''
        def command3_event(self, event):
            self.text5.SetLabel(u'')
            self.recognition = False
            t1 = threading.Thread(target=self.recognitionFace)
            t1.start()
    
        '''
            关闭摄像头按钮的响应事件
        '''
        def command4_event(self, event):
            if self.collected == False:
                self.collected = True
            if self.recognition == False:
                self.recognition = True
    
    
    
    
        def updateSumData(self):
            self.data_num = 0
            for list in os.listdir(picture_dir_path):
                if len(os.listdir(picture_dir_path + '/' + list)) >= 200:
                    self.data_num += 1
            self.text10.SetLabel(u'当前已采集人脸数据的人数:' + str(self.data_num))
            self.text10.Update()
    
    
        '''
            @Author:Himit_ZH
            @Function:处理收集人脸每一帧生成图片存入对应文件夹
        '''
        def collect(self,face_id):
    
            self.text5.SetLabel(u'\n温馨提示:\n' + '请看向摄像头\n准备采集200张人脸图片...')
    
            count = 0  # 统计照片数量
            path = picture_dir_path+"/Stu_" + str(face_id)  # 人脸图片数据的储存路径
            # 读取视频
            cap = cv.VideoCapture(capture_opt)
            print(cap.isOpened())
            if cap.isOpened() == False:
                self.text5.SetLabel(u'\n错误提示:\n' + '×采集人脸数据失败!\n原因:未能成功打开摄像头')
                return
    
            # 加载特征数据
            face_detector = cv.CascadeClassifier(haarcascade_frontalface_file_path)
            if not os.path.exists(path):  # 如果没有对应文件夹,自动生成
                os.makedirs(path)
            while self.collected == False:
                flag, frame = cap.read()
                # print('flag:',flag,'frame.shape:',frame.shape)
                if not flag:
                    break
                # 将图片灰度
                gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
                faces = face_detector.detectMultiScale(gray, 1.1, 3)
                if len(faces) > 1:  # 一帧出现两张照片丢弃,原因:有人乱入,也有可能人脸识别出现差错
                    continue
                # 框选人脸,for循环保证一个能检测的实时动态视频流
                for x, y, w, h in faces:
                    cv.rectangle(frame, (x, y), (x + w, y + h), color=(0, 255, 0), thickness=2)
                    count += 1
                    cv.imwrite(path + '/' + str(count) + '.png', gray[y:y + h, x:x + w])
                    # # 显示图片
                    # cv.imshow('Camera', frame)
                    # 将一帧帧图片显示在UI中
                    image1 = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
                    image2 = cv2.resize(image1, (575, 460))
                    height, width = image2.shape[:2]
                    pic = wx.Bitmap.FromBuffer(width, height, image2)
                    # 显示图片在panel上
                    self.bmp.SetBitmap(pic)
                    self.bmp.Update()
    
                self.text9.SetLabel(u'温馨提示:\n' + '已采集'+ str(count)+'张人脸照片')
                if count >= 200:  #默认采集200张照片
                    break
            # 关闭资源
            if count >=200:
                self.text5.SetLabel(u'\n温馨提示:\n' + '✔已成功采集到人脸数据!')
                self.updateSumData()
            else:
                self.text5.SetLabel(u'\n错误提示:\n' + '×采集人脸数据失败!\n未能收集到200张人脸数据!')
                # 删除该文件夹下的所有数据
                ls = os.listdir(path)
                for file_path in ls:
                    f_path = os.path.join(path, file_path)
                    os.remove(f_path)
                os.rmdir(path)
    
            cv.destroyAllWindows()
            cap.release()
            self.bmp.SetBitmap(wx.Bitmap(self.image_cover))
    
        '''
            @Author:Himit_ZH
            @Function:遍历指定文件夹里面的人脸数据,根据文件夹名字,训练对应数据
        '''
        def trainData(self):
            self.text5.SetLabel(u'\n温馨提示:\n' + '⚪正在整合训练的人脸数据\n请稍后...')
            # 图片路径
            path = picture_dir_path
            facesSamples = []
            imageFiles = []
            ids = []
            for root, dirs, files in os.walk(path):
                # root 表示当前正在访问的文件夹路径
                # dirs 表示该文件夹下的子目录名list
                # files 表示该文件夹下的文件list
                # 遍历文件
                for file in files:
                    imageFiles.append(os.path.join(root, file))
            # 检测人脸的模型数据
            face_detector = cv2.CascadeClassifier(haarcascade_frontalface_file_path)
            # 遍历列表中的图片
            stu_map =  self.mySqlDao.getIdfromSql()
            for imagefile in imageFiles:  # 获得所有文件名字
                imagefile = imagefile.replace('\\', '/')
                sno = imagefile.split('/')[3].split('_')[1]
                if stu_map.get(sno):
                    PIL_img = Image.open(imagefile).convert('L')  # 打开图片并且转为灰度图片
                    # 将图像转换为数组
                    img_numpy = np.array(PIL_img, 'uint8')
                    faces = face_detector.detectMultiScale(img_numpy)
                    for x, y, w, h in faces:
                        facesSamples.append(img_numpy[y:y + h, x:x + w])
                        ids.append(int(stu_map.get(sno)))
    
    
    
    
    if __name__ == '__main__':
        app = wx.App()
        app.locale = wx.Locale(wx.LANGUAGE_CHINESE_SIMPLIFIED)
        frame = MainFrame()
        app.MainLoop()
    

     运行结果如下:

     

    Python, C++, PHP语言学习参考实例连接

    C++学习参考实例

    C++实现图形界面五子棋游戏源码:

    https://blog.csdn.net/alicema1111/article/details/90035420

    C++实现图形界面五子棋游戏源码2:

    https://blog.csdn.net/alicema1111/article/details/106479579

    C++ OpenCV相片视频人脸识别统计人数:

    https://blog.csdn.net/alicema1111/article/details/105833928

    VS2017+PCL开发环境配置:

    https://blog.csdn.net/alicema1111/article/details/106877145

    VS2017+Qt+PCL点云开发环境配置:

    https://blog.csdn.net/alicema1111/article/details/105433636

    C++ OpenCV汽车检测障碍物与测距:

    https://blog.csdn.net/alicema1111/article/details/105833449

    Windows VS2017安装配置PCL点云库:

    https://blog.csdn.net/alicema1111/article/details/105111110

    VS+VTK+Dicom(dcm)+CT影像切片窗体界面显示源码

    https://blog.csdn.net/alicema1111/article/details/106994839

    Python学习参考实例

    Python相片更换背景颜色qt窗体程序:

    https://blog.csdn.net/alicema1111/article/details/106919140

    OpenCV汽车识别检测数量统计:

    https://blog.csdn.net/alicema1111/article/details/106597260

    OpenCV视频识别检测人数跟踪统计:

    https://blog.csdn.net/alicema1111/article/details/106113042

    OpenCV米粒检测数量统计:

    https://blog.csdn.net/alicema1111/article/details/106089697

    opencv人脸识别与变形哈哈镜:

    https://blog.csdn.net/alicema1111/article/details/105833123

    OpenCV人脸检测打卡系统:

    https://blog.csdn.net/alicema1111/article/details/105315066

    Python+OpenCV摄像头人脸识别:

    https://blog.csdn.net/alicema1111/article/details/105107286

    Python+Opencv识别视频统计人数:

    https://blog.csdn.net/alicema1111/article/details/103804032

    Python+OpenCV图像人脸识别人数统计

    https://blog.csdn.net/alicema1111/article/details/105378639

    python人脸头发身体部位识别人数统计

    https://blog.csdn.net/alicema1111/article/details/116424942

    VS+QT+VTK三维网格图像显示GUI

    https://blog.csdn.net/alicema1111/article/details/117060734

    PHP网页框架

    PHP Laravel框架安装与配置后台管理前台页面显示:

    https://blog.csdn.net/alicema1111/article/details/106686523

    展开全文
  • 基于QT的人脸识别考勤打卡系统(移植到ARM板)

    千次阅读 热门讨论 2019-08-20 23:33:35
    前两篇已经实现了基于QT的人脸识别考勤打卡系统 ,当时我把这个系统分为用户考勤打卡和管理员管理员系统,并且都在window上运行,但是如果要运用到实际当中,还是存在很多问题,虽然我们自己做的系统几乎是很难运用...

           前两篇已经实现了基于QT的人脸识别考勤打卡系统 ,当时我把这个系统分为用户考勤打卡和管理员管理员系统,并且都在window上运行,但是如果要运用到实际当中,还是存在很多问题,虽然我们自己做的系统几乎是很难运用在实际当中,但是我们做的系统要努力贴近实际。

            基于QT的人脸识别考勤管理系统【一】 https://blog.csdn.net/qq_42449351/article/details/99716413

            基于QT的人脸识别考勤管理系统【二】 https://blog.csdn.net/qq_42449351/article/details/99753675

            前面实现的系统,最大的问题就是用户考勤打卡这一块,当用户打卡时,必须打开电脑运行用户考勤打卡系统,很明显这样是不可取的,所以我想着将用户考勤系统移植到Arm gec6818板上,这样打卡只需要在门前安装一个arn板就可以。

    一、移植主要的问题

            1、在Arm板上无法用opencv打开摄像头 (只是个人运行会这样)。所以我采用的是专门为 linux 设备设计的一套视频框架V4L2。

            2、需要将pro文件的opencv路径改成linux下opencv的路径。

            3、Arm板的处理速度肯定没有电脑快,所以要减少运算量。

    二、移植前期准备

    1、交叉编译QT程序

     如果在linux下没有通过交叉编译让QT程序生成可执行文件,那么一切都是空谈。下面我就跟大家分享如何交叉编译QT程序。 首先准备好使用到的工具     

          1、ubuntu16.04 --64

          2、arm-linux-gnueabi-5.4.0.tar.xz --交叉编译工具

          3、Qt-Embedded-5.7.0.tar.xz ---arm版本Qt

    一、安装交叉编译的工具的步骤:

         1、将arm-linux-gnueabi-5.4.0.tar.xz 拷贝到linux系统 /usr/local/arm目录下(如果没有这个目录就创建)解压

         2、解压命令为:sudo tar -xf arm-linux-gnueabi-5.4.0.tar.xz ,解压成功后会得到arm-linux-gnueabi-5.4.0.tar.xz  , usr

         3、为了方便操作把usr下面的路径移到当前目录    执行:sudo mv usr/local/arm/5.4.0 ./

         4、设置环境变量,打开 ~/.bashrc  在最后面添加 export PATH=/usr/local/arm/5.4.0/usr/bin:$PATH

    二、安装arm版本Qt

         1、 Qt-Embedded-5.7.0.tar.xz拷贝到/usr/local目录下(必须是这个目录)解压,这个过程解压完成即可

    三、交叉编译Qt程序

         1、 进入到qt程序工程目录下

         2、 执行/usr/local/Qt-Embedded-5.7.0/bin/qmake --makefile文件

         3、 make ---编译  把生成的可执行文件下载到arm开发板运行

    如果ARM板能运行该可执行文件,那么恭喜你成功交叉编译QT程序

    2、将运行时需要使用的文件拷贝到Arm板

         1、opencv官方训练好的人脸检测分类器(haarcascade_frontalface_alt2.xml)。

         2、自己训练成功的人脸识别文件(MyFaceFisherModel.xml)。

         3、 数据库文件(stuface.db)

    三、源代码改写

    配置文件  (将window的opencv的路径改成linux的路径)

    INCLUDEPATH +=/opt/opencv/include
    INCLUDEPATH +=/opt/opencv/include/opencv
    INCLUDEPATH +=/opt/opencv/include/opencv2
    LIBS += -L/opt/opencv/lib/ -lopencv_core -lopencv_highgui -lopencv_imgcodecs \
    -lopencv_calib3d     -lopencv_highgui    -lopencv_shape\
    -lopencv_core        -lopencv_imgcodecs  -lopencv_stitching\
    -lopencv_dnn         -lopencv_imgproc    -lopencv_superres\
    -lopencv_face        -lopencv_ml         -lopencv_videoio\
    -lopencv_features2d  -lopencv_objdetect  -lopencv_video\
    -lopencv_flann       -lopencv_photo      -lopencv_videostab\

    1、V4L2打开摄像头和采集图片的程序

    将V4L2的程序设计为一个线程类,通过信号将Mat型的图片传给主线程,V4L2采集图片的步骤有:1、打开设备 2、配置设备(采集的频率,图像宽高, 图像格式(jpeg, yuv--422,420))3、在内核空间申请缓冲区队列(2-4个)4、把申请好的缓冲区对象一一映射到用户空间  5、开始采集

    1、打开设备(摄像头)

    //1.打开设备
    this->vfd = ::open(deviceName.c_str(), O_RDWR);
    if(this->vfd < 0)
    {
        perror("open fail");
        VideoException vexp("open fail");//创建异常对象
        //抛异常
        throw vexp;
    }

    2、配置设备

    //2.配置采集属性
    struct v4l2_format vfmt;
    vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; //
    vfmt.fmt.pix.width = WIDTH;
    vfmt.fmt.pix.height = HEIGHT;
    vfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;//(设置视频输出格式,但是要摄像头支持4:2:2)
    //通过ioctl把属性写入设备
    int ret  = ioctl(this->vfd, VIDIOC_S_FMT, &vfmt);
    if(ret < 0)
    {
       VideoException vexp("set fail");//创建异常对象
       throw vexp;
    }

    3、申请缓冲区队列

    //1申请缓冲区队列
    struct v4l2_requestbuffers reqbuffer;
    reqbuffer.count = this->count;//申请缓冲区队列长度
    reqbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    reqbuffer.memory = V4L2_MEMORY_MMAP;
    int ret = ioctl(this->vfd, VIDIOC_REQBUFS, &reqbuffer);
    if(ret < 0)
    {
       VideoException vexp("req buffer fail");//创建异常对象
       throw vexp;
    }

    4、申请好的缓冲区对象一一映射到用户空间

    for(int i=0; i<this->count; i++)
    {
       struct VideoFrame frame;
       struct v4l2_buffer mapbuffer;
       mapbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
       mapbuffer.index = i;
       mapbuffer.memory = V4L2_MEMORY_MMAP;
       //从队列中拿到内核空间
       ret  = ioctl(this->vfd, VIDIOC_QUERYBUF, &mapbuffer);
       if(ret < 0)
       {
           perror("query fail");
       }
       //映射
       frame.length = mapbuffer.length;
       frame.start = (char *)mmap(NULL, mapbuffer.length, PROT_READ|PROT_WRITE, MAP_SHARED, this->vfd, mapbuffer.m.offset);
    
       //空间放回队列中(内核空间)
       ret = ioctl(this->vfd, VIDIOC_QBUF, &mapbuffer);
    
       //把frame添加到容器framebuffers
       framebuffers.push_back(frame);
    }

    5、开始采集图片

    void V4l2Api::grapImage(char *imageBuffer, int *length)
    {
    
        //select (rfds, wfds, efds, time)
    
        struct v4l2_buffer readbuf;
        readbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        readbuf.memory = V4L2_MEMORY_MMAP;
        //perror("read");
        if(ioctl(this->vfd, VIDIOC_DQBUF, &readbuf)<0)//取一针数据
        {
            perror("read image fail");
        }
        //printf("%ld\n", readbuf.length);
        *length = readbuf.length;
        memcpy(imageBuffer,framebuffers[readbuf.index].start, framebuffers[readbuf.index].length);
    
        //把用完的队列空间放回队列中重复使用
        if(ioctl(vfd, VIDIOC_QBUF, &readbuf)<0)
        {
            perror("destroy fail");
            exit(1);
        }
    }

    现在V4L2的采集工作已做完,现在我们在这个类的run函数里一直采集图片,并通过opencv将采集的数据变成RGB型,每采集一次,就通过信号发送给主线程

    void V4l2Api::run()
    {
        Mat yuvImage(HEIGHT,WIDTH,CV_8UC2);
        uchar *buffer = yuvImage.data;
    
        int len;
        while(1)
        {
            grapImage((char *)buffer, &len);  //采集图片
            //把yuv转rgb
            Mat rgbImage;
            cvtColor(yuvImage, rgbImage, CV_YUV2RGB_YUYV);
            emit sendImage(rgbImage);
        
    
            msleep(50);
    }
    

    2、人脸识别的程序

    以前的程序,是通过opencv进行打开摄像头,现在只需要改成用V4L2线程类打开即可,创建V4L2线程类对象,当点击按钮时,启动线程,这样就会去执行run函数,再将人脸识别的函数与线程类的发送信号相连接,如果有信号来,就会调用人脸识别函数

    1、启动线程,绑定信号

    //在构造函数绑定信号
    connect(&vapi, &V4l2Api::sendImage, this, &ArmFace::recvMat);
    
    
    void ArmFace::on_openbt_clicked()
    {
       /* if(capture.open(1)<0)  // 以前的写法
        {
            qDebug()<<"open fail";
            return ;
        }*/
     
        //训练好的文件名称,放置在可执行文件同目录下
        cascade.load("haarcascade_frontalface_alt2.xml");
        model = face::FisherFaceRecognizer::create();
        //1.加载训练好的分类器
        model->read("MyFaceFisherModel.xml");
        ui->openbt->setStyleSheet("border-image:url(:/open.png)");
        vapi.start();     //开启线程
    
        //mtimer.start(20);
    
    }

    2、人脸识别函数

    因为要考虑Arm板的处理速度,所以这里将接收到的图片变小,并且在进行人脸检测的时候,改变检测次数,以减少运算量

    void ArmFace::recvMat(Mat cap)
    {
    
       //capture>>cap;
       std::vector<Rect> faces(0);
       cv::resize(cap, cap, Size(460, 340));       /*原图片为640*480 变成460*340  */
       cvtColor(cap, gray, CV_RGB2GRAY);
       equalizeHist(gray, gray); 
       //检测人脸
       cascade.detectMultiScale(gray, faces,   /*减少匹配次数*/
          1.1, 3,
          //|CV_HAAR_FIND_BIGGEST_OBJECT,    /*只检测最大的物体*/
          CV_HAAR_DO_ROUGH_SEARCH,         /*初略的检测*/
          //CV_HAAR_SCALE_IMAGE,           /*正常比例检测*/
          Size(200, 200));  
        Mat* pImage_roi = new Mat[faces.size()];    
        Mat face;
        .......
        下面的操作不变
    }

    至此我们的代码就已经改好了,现在只需要将程序进行交叉编译,再将可执行文件下载到Arm板运行即可,效果如下

    总结:这次移植虽然能将用户打卡系统运行,但是还是存在着很问题。还记得当时我是把数据库文件拷贝到开发板里,然后用户打卡系统直接操作Arm板的数据库文件,然而我的管理员系统在window上运行。所以这两个系统的数据是不能相通的。

    解决方案:将数据库放到服务器上,在服务器上创建一个用C++写的服务端,用户打卡系统和管理员管理系统作为客户端,服务端的功能:接收客户端发送的命令,并通过接收到的命令去执行相应的操作(操作数据库),再将操作的结果返回给客户端,这样两个系统的数据就相通了。这样做的话,程序要改很多,现在没时间,以后有时间再进行完善。

    问题咨询及项目源码请加群:

    QQ群

    名称:IT项目交流群

    群号:245022761

    展开全文
  • 采用USB摄像头,ARM GEC6818来实现用户考勤打卡,博客链接为:https://mp.csdn.net/postedit?not_checkout=1
  • MATLAB人脸考勤打卡签到系统[摄像头界面GUI]_GUI_matlab人脸_MATLAB教室考勤打卡签到_MATLAB人脸考
  • java在线职工考勤管理系统,通过JAVA语言编写,软件用于打卡,查询,请假等日常功能。
  • 设计考勤打卡的心得体会

    千次阅读 2019-01-01 13:23:22
    &amp;nbsp;&amp;nbsp;...考勤打卡每个企业个性化比较强,我的这个项目是促销人员使用的考勤打卡系统,模式:班次–排版-考勤。 每个人各不相同,不具备使用考勤组的。 一个促销人员一天...

        在今年8-10份,独自一个人担任促销管理系统的考勤系统的开发。从需求理解、到表设计、到API接口的输出,bug的修复到最后的完工。今天停下脚步总结一下。


    在整个过程中,给我最深刻的时最开始的表设计。考勤打卡每个企业个性化比较强,我的这个项目是促销人员使用的考勤打卡系统,模式:班次–排版-考勤。 每个人各不相同,不具备使用考勤组。(其他考勤系统,常常用考勤组,便于管理)。

    需求场景

    • 一个促销人员一天可以有多个班次,每个班次都有一个考勤,考勤和班次强关联
    • 每个班次必须要有签到和签退、签到签退可以打卡多次,但有效签到只取第一次,签退只取最后一次,
    • 每个班次可以设置限制最早打卡时间、最晚打卡时间;
    • 每个班次可以设置晚到多少时间不算迟到、同时保证考勤时长、签退时间应该顺延时间差值、
    • 每个班次可以设置一个时间段做为不计工时时间段。
    • 考虑到复杂性,将跨天情况进行排除;
    • 多班次,班次与客户,排版问题等、会涉及到大量一对多关系。

    最后需要按月抽取一张报表,统计每个人员,应出勤天数、实际出勤天数、应出勤工时、实际出勤工时、迟到次数、早退次数、缺口次数、迟到总时长、早退总时长、且按月按请假类型汇总该有请假时长(请假类型固定)。


    面临的问题:

    1. 如果一个人有多个岗位(角色)、使用不同的岗位打卡、如何统计这个人的考勤、;不管是多少岗位,都是一个人;即计表时;应该用人员id
    2. 如果冗余的字段会设计大量被更新的可能性、这样的冗余是不合适的。如果主表的时间被修改、则冗余字段是否应该修改,需要考虑两个问题:一、是历史数据;二、是未发生的记录。冗余字段适合 查询多、修改少)
    3. 报表的抽取问题、是按月抽取还是按日抽取;抽取的时间点很重要。如果按月抽取、这个月发生的数据不能形成报表;如果按照天抽取,是增量抽取,还是该月发生的数据抽取;同时考虑,人员变更情况(入职和离职)
    4. 如果存在跨月份审批问题;会修改过去月份;这个时候会设涉及更新历史报表汇总数据问题
    5. 数据校验问题、牵扯对象过多,校验变得越发复杂;
    6. 进度 vs 质量。 这个是一个需要权衡的点。领导更关注结果;但质量是我们对自己的要求。当然先完成任务可能偏重要一点

    后记

    在设计阶段应该将问题搞清楚、后面的工作才会更轻松一些。考勤系统多种多样;个性化强、没有所谓的通用版本。满足了客户要求;让客户用着安心才是软件开发目的。

    展开全文
  • 钉钉企业内部应用 - 获取考勤打卡结果
  • WIFI 考勤打卡 浅析

    万次阅读 2017-07-21 22:47:48
    WIFI 考勤打卡 浅析一、背景最近产品部提出了wifi考勤打卡新需求,根据管理员设置的wifi相关信息(主要是WIFI名称和MAC地址),员工用户利用移动端相连接的wifi进行wifi考勤打卡。二、名词术语解释下面的理解全是...

    WIFI 考勤打卡 浅析

    一、背景

    最近产品部提出了在WEB端设置wifi考勤打卡新需求,根据管理员设置的wifi相关信息(主要是WIFI名称和MAC地址),员工用户利用移动端相连接的wifi进行wifi考勤打卡。

    二、名词术语解释

    下面的理解全是建立在无线路由器的基础上。如有错误请指出。

    1、SS

    SS(Service set)即服务集,是无线局域网中的一个术语,用以描述802.11无线网络的构成单位(一组互相有联系的无线设备),使用服务集标识符(SSID)作为识别。

    可以分为独立基本服务集(IBSS)、基本服务集(BSS)和扩展服务集(ESS)三类。其中IBSS属于对等拓扑模式(又称Ad-Hoc模式、无线随意网络),而BSS和ESS属于基础架构模式。这些拓扑是原始的802.11规范中定义的,其他的如网桥、中继器等则是属于特定厂商的扩展或者WDS的拓扑模式。

    2、SSID

    SSID(Service Set Identifier)即服务集标识符,是一个或一组基础架构模式无线网络的标识,依照标识方式又可细分为两种:
    基本服务集标识符(BSSID),表示的是AP的数据链路层的MAC地址。
    扩展服务集标识符(ESSID),一个最长32字节区分大小写的字符串,ESSID标识与SSID相同的网络。术语SSID最常用。
    在此可以理解为无线路由器发射的某个wifi的名称。(SSID=name of network)

    3、BSS

    BSS(Basic Service Set)即基本服务集,是一组能在PHY层相互通信的所有站。每个BSS都有一个称为BSSID的标识(ID),它是服务于BSS的接入点的MAC地址。
    用在无线路由器发射出的wifi上可以这样理解:某一个无线路由器发射出的wifi信号所覆盖的范围可视为BSS。

    BSS

    4、BSSID

    BSSID(Basic Service Set Identifier)即基本服务集标识符。

    在上面的基础上可以这样理解:对某一个BSS基本服务集的唯一标识。例如,某无线路由器发射了一个名称为A的wifi热点,同一区域另一个无线路由器也发出了一个名称为A的wifi热点,当手机连接A热点时,如何辨别连接的是由哪一个路由器发射的wifi呢?

    这时候就要用到BSSID了。一般情况下BSSID可以理解为无线路由器的MAC地址,通过查看手机连接wifi的MAC地址即可知道连接的是哪一个路由。(BSSID=AP MAC address)
    其实准确来说手机得到的BSSID并不是路由器的基准(出厂)MAC地址。

    例如,笔者公司的某款无线路由器B的出厂MAC地址为 XX:XX:XX:XX:XX:F1,当手机连接此wifi查看mac地址时发现是XX:XX:XX:XX:XX:F2,或者是XX:XX:XX:XX:XX:F3。

    5、ESS ESSID

    ESS(Extended Service Set )即扩展的基本服务集。
    ESSID(Extended Service Set Identifier)即扩展的基本服务集标识符。
    BSS+BSS+BSS+BSS+…=ESS。ESS为多个BSS的集合。ESS使用指定的ESSID作识别。

    通过将多个BSS比邻安置,可以扩展网络的范围,如果这些BSS通过各种分布系统互联(无论是有线的还是无线的),拥有一致的ESSID,并且对于逻辑链路控制层来说可以认为是一个BSS的话,那么这些BSS可以被统一为一个ESS。

    在同一个ESS中的不同BSS之间切换的过程称为漫游。一般而言,一个ESS中的BSS都会使用相同的SSID和安全机制以提供接近于无缝漫游的可能。两个BSS之间通常有15%左右的重叠范围来保证漫游时信号不会长时间丢失,并且设置在不同频段来防止相互干扰。

    ESS

    6、MAC

    MAC地址采用十六进制数表示,共六个字节(48位)。(XX:XX:XX:XX:XX:XX )其中,前三个字节是由IEEE的注册管理机构RA负责给不同厂家分配的代码(高位24位),也称为“编制上唯一的标识符”(Organizationally Unique Identifier),后三个字节(低位24位)由各厂家自行指派给生产的适配器接口,称为扩展标识符(唯一性)。

    三、历程

    当产品部提出wifi考勤打卡需求时,普遍认为一个路由器有一个mac地址,手机连接wifi可以根据mac地址等信息进行打卡。当我们用多个手机连接公司名称为A(SSID)的wifi时,发现手机上展示的mac地址并不是一致的,这个就尴尬了,打翻了原有理念。
    然后发现我们公司共有五个无线路由器,wifi名称都是A。哦,这时候才感觉到原来以前的知识还是靠谱的,可能是多个手机具体连接的路由器不是同一个。

    然后把五个路由器wifi热点名称改为A、B、C、D、E,多个手机连接A热点时,发现手机得到的mac地址是一致的,到这里可以得出的结论是手机连接同一个wifi热点得到的mac地址是一致的。但是…..又尴尬了。

    当多款手机连接B热点时,发现又出现了不一致的mac地址,查找原因发现,原来B无线路由器中可以设置2.4G Hz和5G Hz两个不同频段的wifi热点。B路由器中默认是开启2.4G Hz和5G Hz频段的wifi热点,并且wifi名称(SSID)是同一个。经过检查还有个问题是B路由器的出厂mac地址和手机连接得到的mac地址不一致。

    例如上面举得例子:笔者公司的某款无线路由器B的出厂MAC地址为 XX:XX:XX:XX:XX:F1,当手机连接此wifi查看mac地址时发现是XX:XX:XX:XX:XX:F2,另一款手机连接时是XX:XX:XX:XX:XX:F3。由此可得出的结论是,路由器有一个基准(出厂)mac地址,然后发射出wifi的mac在基准mac地址上按照一定的算法进行变动,具体的变动算法不清楚,有清楚的请告知我,非常感谢。

    另外还有一个问题是,C路由器设备后面所写的出厂说明mac地址是XX:XX:XX:XX:XX:56,但是通过路由器后台看到的出厂mac地址是XX:XX:XX:XX:XX:57,手机连接后得到的mac地址是XX:XX:XX:XX:XX:56。这就尴尬了,是厂家写错了还是根据特定的算法算的?

    除了根据wifi设备分析外,我们也对具有wifi考勤打卡功能的软件进行了分析。比如现在比较火爆的由阿里团队研发的钉钉,以及纷享销客APP,在Android端,他们的处理都是获取周围wifi信息(并不是当前手机连接的wifi)进行打卡。在iOS端,他们的处理都是根据当前手机连接的wifi信息进行打卡。据iOS同事说,iOS获取周围wifi信息需要申请此功能,并最低支持版本是iOS 9。另外据可靠消息,分享逍客对mac地址的处理也是通过忽略低4位进行匹配。

    四、结论

    经过上述分析,手机获取的无线路由器MAC地址的低4位是变化的。那我们实现这个需求时,除了匹配虚拟位置、手机信息、wifi相关等其他信息外,只针对mac地址,我们可以忽略mac地址的低4位来做匹配。

    上述分析难免有错误,如有发现,或者wifi考勤有更好的解决方案,请联系我,非常感谢。

    五、参考资料

    http://www.juniper.net/documentation/en_US/junos-space-apps12.3/network-director/topics/concept/wireless-ssid-bssid-essid.html

    原创文章,来自于Vitamio,转载请注明出处。

    展开全文
  • 这样公司任何人,只要打开网页就可以查询自己的考勤记录,有分上午,中午,晚上打卡时间。 注意修改PHP的max_execution_time 时间,查询全部内容时,会出现超时,可能我的算法有问题,但还是能得出结果。
  • 人脸识别考勤打卡.zip

    2020-04-23 23:19:43
    人脸识别考勤管理系统,既能有效提高企业的考勤管理方式,规范员工考勤管理操作,还可以防止出现代打卡、弄虚作假的行为。目前,云脉人脸识别考勤广泛应用于企事业单位、校园等场景。此代码使用Python实现,含UI界面...
  • 考勤打卡:用户id,上班打卡时间,下班打卡时间 审批:用户id,日期,类型 现在要把一些没有审批的条目查出来 两个问题: 1.表设计的好像不好,不知道怎么设计 2.遇到的查询问题,就是一天要是有多个单子,...
  • 行业分类-电信-通过WIFI探针实现考勤打卡或统计人流量的方法与系统.rar
  • 1. 掌握医院考勤系统的应用背景、功能与特点,系统功能模块划分(用流程图分析),系统运行环境。 2. 登陆界面。实现用户的登陆。 输入用户名,密码和验证码,点击登陆按钮进入考勤系统。 3. 人员管理功能。包括 ...
  • 这是一个基于Java开发的纯原创的、简单的员工打卡系统,里面涉及了文件的存取,所以提交了整个项目工程。 注释均为英文注释,是自己写的,如果有不足还望海涵。 第二次提交,原先的就不要了吧!求审核通过!
  • 由于项目需求需要在项目中实现手机端(基于网页)考勤打卡功能,最初考虑使用H5自身定位功能,但尝试过后,效果很不稳定。然后尝试使用百度地图JsAPI,百度家的稳定倒是很稳定,没想到的是定位位置和实际位置居然...
  • 怎么用华为WeLink进行考勤打卡

    千次阅读 2020-12-29 16:39:13
    现代社会工作和生活节奏加快,人们更追求快捷简便的工作方式,考勤打卡作为每天工作都要做的事情,一款好的考勤打卡软件就能简化打卡流程和自动生成考勤统计报表,大大提升管理者和员工的工作效率。 华为云WeLink ( ...
  • 一、钉钉2021年3月份新增了上传打卡记录的接口,这样就方便集成考勤系统。当然,也方便很多管理员“干坏事了”! 去网站上获取你需要上传的打卡时间。https://tool.lu/timestamp 所有操作都有日志记录:...
  • 学生打卡考勤系统

    2013-11-03 22:48:00
    学生打卡考勤系统 --项目前景和目标文档 1.背景 在当今高速发展的信息社会,计算机技术、网络技术对人类的经济生活、社会生活等各方面都产生了巨大的影响,目前不论是企...
  • 基于 java 的学生考勤信息管理系统设计 摘 要 学生考勤信息管理系统用于实现学校对在校学生的考勤信息的管理是典型的管理 信息系统学生考勤信息的手工登记查询是一项非常繁重而枯燥的劳动在计算机技 师飞速发展的...
  • Asp..net考勤打卡项目

    2013-08-30 13:22:58
    本项目是使用Oracle数据库的,实现公司日常员工加班,考勤,请假,员工管理等功能。 打卡时间支持使用网络时间和系统时间。安全准确。
  • 考勤系统是专为指纹打卡统计而制作,实际上是基本的打卡统计,可以排除节假日,调休等特殊场合,适合公司行政或人力资源使用。结构,引入到MySQL就行。技术:bootstrap,php,mysql config.php是数据库配置环境。...
  • 根据中控C#demo ,获取s60考勤考勤数据

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,862
精华内容 1,144
关键字:

考勤打卡系统