掩码未在OpenCV相机预览中显示 [英] Mask not displayed in OpenCV camera preview

查看:139
本文介绍了掩码未在OpenCV相机预览中显示的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个简单的Android应用程序,使用OpenCV在检测到的面上放置一个掩码,例如:

I want to make a simple Android app which put a mask on a detected face with OpenCV such as this example :

面部检测教程掩码

我为我的应用程序将C ++翻译成Java。屏幕调整得很好,白色部分被删除了(我在预览中的ImageView中显示了测试结果)但是面板从未出现在绿色的检测到的面上矩形:

I translate the C++ into Java for my app.The mask is well resized and the white part eliminated (I displayed the result for testing in an ImageView on the Preview) but the mask never appear on the detected face int the green rectangle :

结果截图

我的代码:

    public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
             [...]

    for( int i = 0; i < facesArray.length; i++)
        min_face_size = facesArray[0].width*0.7;
        max_face_size = facesArray[0].width*1.5;
        Point center=new Point (facesArray[i].x + facesArray[i].width/2, facesArray[i].y + facesArray[i].height/2);
        mRgba=putMask(mRgba,center, new Size(facesArray[i].width, facesArray[i].height));
    }
    return mRgba;
}

Mat putMask(Mat src, Point center, Size face_size)
{

    //mask : loaded mask image
    Mat mask1 = new Mat(); //resized mask
    src1 = new Mat(); //ROI
    m = new Mat();

    Imgproc.resize(mask ,mask1,face_size);

    // ROI selection
    roi = new Rect((int) (center.x - face_size.width/2), (int) (center.y - face_size.height/2),(int) face_size.width, (int) face_size.height);
    //Rect roi = new Rect(100, 100, (int) face_size.width, (int) face_size.height);
    src.submat(roi).copyTo(src1);


    // to make the white region transparent
    Mat mask2 = new Mat(); //greymask
    m1= new Mat();
    Imgproc.cvtColor(mask1,mask2, Imgproc.COLOR_BGR2GRAY);
    Imgproc.threshold(mask2,mask2,230,255, Imgproc.THRESH_BINARY_INV);

    ArrayList<Mat> maskChannels = new ArrayList<>(3);
    ArrayList<Mat> result_mask = new ArrayList<>(3);
    result_mask.add(new Mat());
    result_mask.add(new Mat());
    result_mask.add(new Mat());

    Core.split(mask1, maskChannels);

    Log.e(TAG, "MASK maskChannels :"+maskChannels.get(0).size());
    Log.e(TAG, "MASK mask2 :"+mask2.size());

    Core.bitwise_and(maskChannels.get(0),mask2, result_mask.get(0));
    Core.bitwise_and(maskChannels.get(1),mask2, result_mask.get(1));
    Core.bitwise_and(maskChannels.get(2),mask2, result_mask.get(2));
    Core.merge(result_mask, m);        


    Core.subtract(mask2, new Scalar(255), mask2);

    ArrayList<Mat> srcChannels = new ArrayList<>(3);
    Core.split(src1, srcChannels);
    Core.bitwise_and(srcChannels.get(0),mask2, result_mask.get(0));
    Core.bitwise_and(srcChannels.get(1),mask2, result_mask.get(1));
    Core.bitwise_and(srcChannels.get(2),mask2, result_mask.get(2));
    Core.merge(result_mask,m1);        


    Core.addWeighted(m,1,m1,1,0,m1);    

    m1.copyTo(src.submat(roi));

    return src;
}

==============

==============

感谢@hariprasad :)这里的工作代码:

Thanks to @hariprasad :) here the working code :

 onCreate(){
          [...]
                try {
                    File file = new File(Environment.getExternalStorageDirectory(), "1-alpha.png");

                    mask = Imgcodecs.imread(file.getPath(), -1);

                }catch (Exception e){
                    e.printStackTrace();
                }
        }


Mat putMask(Mat src, Point center, Size face_size)
{

    //mask : masque chargé depuis l'image
    Mat mask_resized = new Mat(); //masque resizé
    src_roi = new Mat(); //ROI du visage croppé depuis la preview
    roi_gray = new Mat();


    Imgproc.resize(mask ,mask_resized,face_size);

    // ROI selection
    roi = new Rect((int) (center.x - face_size.width/2), (int) (center.y - face_size.height/2),(int) face_size.width, (int) face_size.height);
    //Rect roi = new Rect(10, 10, (int) face_size.width, (int) face_size.height);

    src.submat(roi).copyTo(src_roi);

    Log.e(TAG, "MASK SRC1 :"+ src_roi.size());

    // to make the white region transparent
    Mat mask_grey = new Mat(); //greymask
    roi_rgb = new Mat();
    Imgproc.cvtColor(mask_resized,mask_grey, Imgproc.COLOR_BGRA2GRAY);
    Imgproc.threshold(mask_grey,mask_grey,230,255, Imgproc.THRESH_BINARY_INV);

    ArrayList<Mat> maskChannels = new ArrayList<>(4);
    ArrayList<Mat> result_mask = new ArrayList<>(4);
    result_mask.add(new Mat());
    result_mask.add(new Mat());
    result_mask.add(new Mat());
    result_mask.add(new Mat());

    Core.split(mask_resized, maskChannels);

    Core.bitwise_and(maskChannels.get(0),mask_grey, result_mask.get(0));
    Core.bitwise_and(maskChannels.get(1),mask_grey, result_mask.get(1));
    Core.bitwise_and(maskChannels.get(2),mask_grey, result_mask.get(2));
    Core.bitwise_and(maskChannels.get(3),mask_grey, result_mask.get(3));

    Core.merge(result_mask, roi_gray);        

    Core.bitwise_not(mask_grey,mask_grey);

    ArrayList<Mat> srcChannels = new ArrayList<>(4);
    Core.split(src_roi, srcChannels);
    Core.bitwise_and(srcChannels.get(0),mask_grey, result_mask.get(0));
    Core.bitwise_and(srcChannels.get(1),mask_grey, result_mask.get(1));
    Core.bitwise_and(srcChannels.get(2),mask_grey, result_mask.get(2));
    Core.bitwise_and(srcChannels.get(3),mask_grey, result_mask.get(3));

    Core.merge(result_mask, roi_rgb);          

    Core.addWeighted(roi_gray,1, roi_rgb,1,0, roi_rgb); 

    roi_rgb.copyTo(new Mat(src,roi));

    return src;
}


推荐答案

src.submat(roi)与c ++中的 src(roi)不相同。因为在c ++中 src(roi) 实际修改roi区域中的 src 数据矩阵,但是在java submat 中正在进行克隆src的roi。所以对roi所做的任何更改都不会影响src,这就是为什么你在相机预览中没有任何东西的原因。
使其正确你需要使用像c ++
这样的构造函数即使用

src.submat(roi) is not equalent to src(roi) in c++.Because in c++ src(roi) actually modifying the src data matrix in the roi area but in java submat is making clone of the roi of src.So any changes done to roi will not effect src that is why you got nothing in camera preview. to make it correct you need to use constructor like c++ i.e use

m1.copyTo(new Mat(src,roi));

而不是

 m1.copyTo(src.submat(roi));

这篇关于掩码未在OpenCV相机预览中显示的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆