Android在线人脸识别登录系统

Android在线人脸识别登录系统

前言

最近需要做一个Android的在线人脸识别项目,需求是能够在线人脸识别登录,找了很多资料都是价格很高或者是离线保存样本的,最后选择免费的虹软人脸识别,经过查询很多资料,最终完结了该项目需求,现在把它分享出来,希望能够帮助到大家学习。


提示:以下是本篇文章正文内容,下面案例可供参考

一、系统简介

有了解过Android端虹软SDK的都知道,识别样本必须要先注册在本地,进行离线识别,这可能不符合大部分的需求,更多的可能是需要Android端在线识别。该系统使用虹软Java端第三方jar包,实现Android端人脸在线识别登录与注册功能。

二、系统设计

1.客户端

客户端分为注册和登录。注册时调用相机拍照,将回调的图片信息进行bas64格式发送至服务器。登录时调用相机采集视频信息,将图片信息压缩转化后实时发送至服务端登录匹配。

1.1注册

1、注册拍照代码如下(示例):

	/***
     * 拍照
     * @param view
     */
    public void photograph(View view) {
        loadingDialog = new LoadingDialog(RegisterCameraActivity.this,"正在获取照片...", R.drawable.icon_logo);
        loadingDialog.show();
        mCamera.takePicture(null, null, new Camera.PictureCallback() {
            @Override
            public void onPictureTaken(byte[] bytes, Camera camera) {
                File sdRoot = Environment.getExternalStorageDirectory();
                String dir = "/Camera/";
                String resultPath = sdRoot + dir + "IMG_Register.jpg";
                Bitmap bitmap = BitmapFactory.decodeByteArray(bytes,0,bytes.length);
                Bitmap bitmap1 = adjustPhotoRotation(bitmap, 270);
                Imageutils.saveImage(bitmap1);
                if(bitmap != null){
                    bitmapCompress(resultPath);
                }else {
                    camera.stopPreview();
                    camera.release();
                    dismissLoading();
                }
            }
        });
    }

2、上传图片信息代码如下(示例):

		/***
         * 上传图片
         */
        buttonc.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                showLoading();
                File sdRoot = Environment.getExternalStorageDirectory();
                String dir = "/Camera/";
                String resultPath = sdRoot + dir + "IMG_Register.jpg";
                String resultChangePath = sdRoot + dir + "IMG_Register_change.jpg";
                File file = new File(resultChangePath);
                File resultPathFile = new File(resultPath);
                if(!file.exists()){
                    dismissLoading();
                    return;
                }
                String ImgBase = Imageutils.imgTodata(resultChangePath);
                HashMap<String, String> params = new HashMap<>();
                String url = HttpUtils.FACE_ADD;
                params.put("file", ImgBase);
                params.put("username", username);
                HttpUtils.sendRequestToServer(url, params, new Callback() {
                    @Override
                    public void onFailure(Request request, IOException e) {

                    }

                    @Override
                    public void onResponse(Response response) throws IOException {
                        String string = response.body().string();
                        JSONObject jsonObject = null;
                        try {
                            jsonObject = new JSONObject(string);
                            int code = jsonObject.optInt("code");
                            if(code == 14){
                                runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        Toast.makeText(RegisterCameraActivity.this,"注册失败,未检出到人脸",Toast.LENGTH_SHORT).show();
                                    }
                                });
                            }else if(code == 0){
                                if(file.exists()){
                                    file.delete();
                                }
                                if(resultPathFile.exists()){
                                    resultPathFile.delete();
                                }
                                if (loadingDialog != null){
                                    loadingDialog.dismiss();
                                }
                                Intent it = new Intent(RegisterCameraActivity.this, SelectActivity.class);
                                startActivity(it);
                                finish();
                            }else {
                                String message = jsonObject.optString("message");
                                runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        Toast.makeText(RegisterCameraActivity.this,message,Toast.LENGTH_SHORT).show();
                                    }
                                });
                            }
                            if (loadingDialog != null){
                                loadingDialog.dismiss();
                            }
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    }
                });
            }
        });
        Toast.makeText(RegisterCameraActivity.this,"请正视屏幕不要晃动",Toast.LENGTH_SHORT).show();
    }

1.2登录

登录Activity需要实现Camera.PreviewCallback接口,实现回调中的onPreviewFrame()方法进行视频流的采集。将采集到的流数据转化为图片格式,经过压缩处理后转化为bas64格式发送服务器进行匹配,必要时在这里可以使用线程池机制来增加效率。
采集图片信息并上传代码如下(示例):

	@Override
    public void onPreviewFrame(byte[] data, Camera camera) {
        String timeName = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date())
                .toString();
        String fileName = "IMG_"+ timeName + ".jpg";
        File sdRoot = Environment.getExternalStorageDirectory();
        String dir = "/Camera/";
        File mkDir = new File(sdRoot, dir);
        if (!mkDir.exists())
            mkDir.mkdirs();
        File pictureFile = new File(sdRoot, dir + fileName);
        if (!pictureFile.exists()) {
            try {
                pictureFile.createNewFile();
                Camera.Parameters parameters = camera.getParameters();
                Camera.Size size = parameters.getPreviewSize();
                YuvImage image = new YuvImage(data,
                        parameters.getPreviewFormat(), size.width, size.height,
                        null);
                FileOutputStream filecon = new FileOutputStream(pictureFile);
                image.compressToJpeg(new Rect(0, 0, image.getWidth(), image.getHeight()),
                        90, filecon);
                String path = pictureFile.getPath();

                Bitmap imageBitmap = BitmapFactory.decodeFile(path);
                Bitmap bitmap1 = adjustPhotoRotation(imageBitmap, 270);
                Imageutils.saveLoginImage(bitmap1,timeName);
                String fileLoginName = "IMG_Login_" + timeName + ".jpg";
                String resultChangePath = sdRoot + dir + fileLoginName;
                bitmapCompress(resultChangePath);/*新增压缩*/
                String ImgBase = Imageutils.imgTodata(resultChangePath);
                //开始上传
                ImgBase = ImgBase.replaceAll("[\\s*\t\n\r]", "");
                //上传
                HashMap<String, String> params = new HashMap<>();
                params.put("file", ImgBase);
                uploadImage(params,camera);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

2.服务端

服务端使用Java语言编写,首先部署第三方jar包,配置好appid和key值。服务端接收到客户端传递过来的图片数据进行匹配,如果是注册,将图片信息保存至数据库,如果是登录,则查询数据库进行匹配。
服务器获取客户端发送图片信息处理代码如下(示例):

	/**
     * 人脸识别
     */
    @ApiOperation(value="人脸识别", notes="待识别图像为base64格式字符串、必须指定人脸分组id")
    @RequestMapping(value = "/faceSearch", method = RequestMethod.POST)
    @ResponseBody
    public Result<FaceSearchResDto> faceSearch(@ApiParam(value = "人脸图像数据", required = true)@RequestParam("file")   		String file) throws Exception {
        if (groupId == null) {
            return Results.newFailedResult("groupId is null");
        }
        byte[] decode = Base64.decode(base64Process(file));
        BufferedImage bufImage = ImageIO.read(new ByteArrayInputStream(decode));
        ImageInfo imageInfo = ImageFactory.bufferedImage2ImageInfo(bufImage);
        //人脸特征获取
        byte[] bytes = faceEngineService.extractFaceFeature(imageInfo);
        if (bytes == null) {
            return Results.newFailedResult(ErrorCodeEnum.NO_FACE_DETECTED);
        }
        //人脸比对,获取比对结果
        List<FaceUserInfo> userFaceInfoList = faceEngineService.compareFaceFeature(bytes, groupId);
        if (CollectionUtil.isNotEmpty(userFaceInfoList)) {
            FaceUserInfo faceUserInfo = userFaceInfoList.get(0);
            FaceSearchResDto faceSearchResDto = new FaceSearchResDto();
            BeanUtil.copyProperties(faceUserInfo, faceSearchResDto);
            List<ProcessInfo> processInfoList = faceEngineService.process(imageInfo);
            if (CollectionUtil.isNotEmpty(processInfoList)) {
                //人脸检测
                List<FaceInfo> faceInfoList = faceEngineService.detectFaces(imageInfo);
                int left = faceInfoList.get(0).getRect().getLeft();
                int top = faceInfoList.get(0).getRect().getTop();
                int width = faceInfoList.get(0).getRect().getRight() - left;
                int height = faceInfoList.get(0).getRect().getBottom() - top;
                Graphics2D graphics2D = bufImage.createGraphics();
                graphics2D.setColor(Color.RED);//红色
                BasicStroke stroke = new BasicStroke(5f);
                graphics2D.setStroke(stroke);
                graphics2D.drawRect(left, top, width, height);
                ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                ImageIO.write(bufImage, "jpg", outputStream);
                byte[] bytes1 = outputStream.toByteArray();
                faceSearchResDto.setImage("data:image/jpeg;base64," + Base64Utils.encodeToString(bytes1));
                faceSearchResDto.setAge(processInfoList.get(0).getAge());
                faceSearchResDto.setGender(processInfoList.get(0).getGender().equals(1) ? "女" : "男");
                faceSearchResDto.setUsername(faceUserInfo.getUsername());
            }
            return Results.newSuccessResult(faceSearchResDto);
        }
        return Results.newFailedResult(ErrorCodeEnum.FACE_DOES_NOT_MATCH);
    }

照片转化为bas64格式保存至数据库示意图在这里插入图片描述

总结

这次项目查询了很多资料,最终完成了Android人脸识别登录与注册功能,主要是使用Android端图片的压缩与转换,网络通讯,和第三方人脸识别sdk,希望能够对有需要的人有帮助。

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值