掩码未在OpenCV相机预览中显示

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

面部检测教程

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

结果截图

我的代码:

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 maskChannels = new ArrayList(3); ArrayList 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 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 maskChannels = new ArrayList(4); ArrayList 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 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正在submat src的roi.So任何变化完成roi不会影响src,这就是你在相机预览中没有任何东西的原因。 为了使它正确你需要使用像c ++这样的构造函数即使用

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

代替

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