2016-08-03 126 views
2

我想作一個簡單的Android應用程序,它把口罩上檢測到的面部與OpenCV的像這樣的例子:面膜在OpenCV的攝像頭預覽不顯示

Mask on face detection tutorial

我翻譯C++到Java我app.The掩模是公調整尺寸並消除了白色部分(I顯示在預覽的ImageView的測試的結果),但在掩模上的檢測到的面部不會出現INT綠色矩形:

Screenshot of the result

我的代碼:

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 :)這裏的工作代碼:

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; 
} 
+0

你能分享,以供參考完整的代碼?我也必須實現相同的功能。 –

+0

不,我很抱歉,這是一個公司工作,但我覺得我給了工作代碼是相當齊全,你有攝像頭的代碼「onCameraFrame」(OpenCV的框架),並計算。其餘的幾乎是基本的OpenCV Android相機示例。 –

回答

1

src.submat(roi)不equalent在C src(roi) ++。因爲在C++ src(roi)實際修改src數據矩陣ROI區域,但在Java中submat正在src.So的投資回報率做了投資回報率的任何更改將不會影響SRC這就是爲什麼你在什麼都沒有的克隆相機預覽。 使其糾正你需要使用類似的構造函數C++ 即使用

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

代替

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

我改爲「m1.copyTo(new Mat(src,roi));」但結果仍然是一樣的...我也試圖改變「src.submat(roi).copyTo(src1);」到「src1 = new Mat(src,roi);」但結果相同。我還是不明白,爲什麼在預覽照相機的ROI不會被修改 –

+0

你沒有改變「src.submat(ROI).copyTo(SRC1)」;在C++版本也是他們here.there製作副本可能是你的代碼中的其他問題。你確定嗎 ? C++中的255-mask2等於Core.subtract(mask2,new Scalar(255),mask2);我認爲操作數應該是相反的,即Core.subtract(新標量(255),mask2,mask2); – hariprasad

+0

我不知道在所有的,但沒有在Java SDK中的Core.subtract(標量,墊,墊)的方法,所以我不知道怎麼寫掩碼2 = 255,掩碼2 .... –