Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

利用虹软的SDK框出人脸 #238

Open
soapgu opened this issue Mar 12, 2024 · 0 comments
Open

利用虹软的SDK框出人脸 #238

soapgu opened this issue Mar 12, 2024 · 0 comments

Comments

@soapgu
Copy link
Owner

soapgu commented Mar 12, 2024

  • 引子

都知道虹软的SDK可以做人脸识别,如果把功能“退化”,只是把当前的的人脸的范围框出来,要怎么处理。
目前已知OpenCV是可以做到的,试试看虹软的SDK能不能做到

这个方法在“原版”的demo中也有使用,主要是利用摄像头的回调来传入nv21格式的图像数据

当然这个数据支持更多格式,理论上可以通过一张图片完成头部位置的检测

具体过程为 jpeg图片 -> 读取为Bitmap位图 -> BGR24格式数据 -> 执行detectFaces

        Bitmap bitmap = BitmapFactory.decodeResource(this.getResources(), current_id);
        Logger.i("origin width:%s,height:%s",bitmap.getWidth(),bitmap.getHeight());
        bitmap = FaceServer.getInstance().getAlignedBitmap(bitmap);
        face_image.setImageBitmap( bitmap );
        Logger.i("image width:%s",face_image.getHeight());

这里的Bitmap先要预处理下,需要把像素尺寸处理为4的倍数

public List<Rect> findFace( Bitmap bitmap ){
        //Bitmap bitmap = ImageUtil.jpegToScaledBitmap(jpeg, ImageUtil.DEFAULT_MAX_WIDTH, ImageUtil.DEFAULT_MAX_HEIGHT);
        //Logger.i("ScaledBitmap width:%s,height:%s",bitmap.getWidth(),bitmap.getHeight());
        byte[] imageData = ArcSoftImageUtil.createImageData(bitmap.getWidth(), bitmap.getHeight(), ArcSoftImageFormat.BGR24);
        int code = ArcSoftImageUtil.bitmapToImageData(bitmap, imageData, ArcSoftImageFormat.BGR24);
        if (code != ArcSoftImageUtilError.CODE_SUCCESS) {
            throw new RuntimeException("bitmapToImageData failed, code is " + code);
        }
        List<FaceInfo> faceInfoList = new ArrayList<>();
        synchronized (faceEngine) {
            code = faceEngine.detectFaces(imageData, bitmap.getWidth(), bitmap.getHeight(), FaceEngine.CP_PAF_BGR24, faceInfoList);
        }
        if (code == ErrorInfo.MOK && !faceInfoList.isEmpty()){
            //Rect rect = faceInfoList.get(0).getRect();
            //Logger.i("find Rect left:%s,top:%s,right:%s,bottom:%s",rect.left,rect.top,rect.right,rect.bottom);
            return faceInfoList.stream().map(FaceInfo::getRect).collect(Collectors.toList());

        }
        return new ArrayList<>();
    }

这里执行完detectFaces后,可以获取到人脸的位置,这里用Rect表示(left/top/bottom/right)

  • 绘制人脸的外框

这里我做一个简化版本的自定义控件

public class SimpleFaceRectView extends View {

    private Paint paint;
    private Rect drawRect = new Rect();
    private double zoom;
    private List<Rect> rectList = new ArrayList<>();

    public SimpleFaceRectView(Context context) {
        super(context);
        init();
    }

    public SimpleFaceRectView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public SimpleFaceRectView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    public SimpleFaceRectView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();
    }

    private void init(){
        paint = new Paint();
        paint.setColor(Color.GREEN);
        paint.setStyle(Paint.Style.STROKE);  // 设置画笔样式为描边,用于画空心图形
        paint.setStrokeWidth(2);  // 设置描边宽度,可根据需求调整
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if( !rectList.isEmpty() ){
            rectList.forEach( rect -> {
                drawRect.left = (int)(rect.left * zoom);
                drawRect.top = (int)(rect.top * zoom);
                drawRect.right = (int)(rect.right * zoom);
                drawRect.bottom = (int)(rect.bottom * zoom);
                canvas.drawRect(drawRect,paint);
            } );
        }

    }

    public void updateFaceRect(int width, int height, List<Rect> rectList ){
        this.zoom = (double) getWidth() / (double)width;
        this.rectList = rectList;
        invalidate();
    }
}

调用部分

        List<Rect> rects = FaceServer.getInstance().findFace(bitmap);
        face_rect.updateFaceRect( bitmap.getWidth(),bitmap.getHeight(),rects );
        msg.setText( String.format( "识别人脸:%s",rects.size()) );
图片
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant