树莓派搭建nexus2.x私服
树莓派搭建视频监控平台
树莓派视频监控平台实现录制归档
1. 功能设计树莓派人脸打卡机,主要包括两个大方向的功能要求:
a. 人脸采集存档
b. 人脸识别签到
这两个功能配合使用就能实现人脸打卡了, 通过人脸采集将人脸信息预存档在系统中,签到的时候,当人靠近摄像头时实时采集人脸,然后比对现有人脸,如果信息匹配则认为签到成功。
下面是签到的效果:
当人脸签到成功后,程序界面底部会显示签到时间和签到人的工号。
人脸采集模块主要的工作就是从摄像头采集视频帧,然后交给界面回显,这里使用的是JavaCV中的opencv模块。
频繁采集视频帧是一个很耗CPU的过程,我在这里做了一些优化处理,即:当检测到没有人脸的时候,程序休眠更长的时间(1秒),而当检测到人脸时,采集间隔调整为180毫秒。
下面是完整的代码:
/** * @author itqn */ public class FaceCapture implements Runnable { private VideoCapture capture; private CascadeClassifier classifier; private OpenCVFrameConverter.ToMat matConvert; private JavaFXFrameConverter converter; private BiConsumer<Image, Rect> videoConsumer; public FaceCapture(BiConsumer<Image, Rect> videoConsumer) { this.videoConsumer = videoConsumer; init(); } private void init() { capture = new VideoCapture(); classifier = new CascadeClassifier("samples//haarcascade_frontalface_alt.xml"); matConvert = new OpenCVFrameConverter.ToMat(); converter = new JavaFXFrameConverter(); capture.open(0); } private void destroy() { capture.close(); } @Override public void run() { boolean find; Mat image = new Mat(); RectVector vector = new RectVector(); while (capture.isOpened()) { find = false; capture.read(image); classifier.detectMultiScale(image, vector); for (Rect rect : vector.get()) { find = true; Image video = converter.convert(matConvert.convert(image)); videoConsumer.accept(video, rect); break; } // if no face sleep 1 second try { if (find) { TimeUnit.MILLISECONDS.sleep(180); } else { TimeUnit.SECONDS.sleep(1); } } catch (InterruptedException ignore) { } } } }这里调用者通过注册videoConsumer,来消费采集到的人脸图片,以及人脸区域。
3. 开发人脸识别模块人脸识别这里直接采用opencv的native API,采用直方图对比的方式对比,这里采用相关性数据作为人脸识别成功的基准,如果相关度高于0.7则认为人脸匹配。
程序通过将采集到的人脸信息跟已经存档的人脸信息注意对比,到达基准0.7以上则返回工号(图片是以工号命名的)。
这里也可以将图片灰度化处理再对比。
Imgproc.cvtColor(dst, hsv, Imgproc.COLOR_BGR2GRAY); 4. 开发界面控制层界面使用JavaFX来开发,功能比较单一,只要程序启动的时候,启动视频采集线程即可。
这里需要注意的是,当长时间没有识别到人脸的时候,界面不应该显示之前的人脸信息, 所以需要另起一个线程来监控是否有人脸识别信息,如果没有,则显示默认的图片。
人脸采集回显部分
private void startVideoCapture() { new Thread(new FaceCapture((v, r) -> { Image tmp = FaceUtils.sub(v, r.x(), r.y(), r.width(), r.height()); try { FaceUtils.store(tmp, tmpPath); String id = FaceParser.parser(tmpPath, dir); if (id != null) { Platform.runLater(() -> { message.setText(sdf.format(new Date()) + ", 工号:" + id + "签到成功。"); // for sign service }); } } catch (IOException e) { alert.setContentText(e.getMessage()); alert.show(); } Platform.runLater(() -> { video.setImage(v); timestamp.set(System.currentTimeMillis()); if (!find.get()) { avatar.setImage(tmp); find.set(true); } }); })).start(); }空闲监控,显示默认图部分