如何在一个框架中实时joinalpha /透明度的png

我正在使用相机检测脸部的OpenCV android 2.4.11的例子。 而不是在find的脸上画一个矩形,我试图把一个面具(PNG图像)在脸上。 但是为了在脸上显示图像,png图像在黑色的背景下透明。

FdActivity.java

public void onCameraViewStarted(int width, int height) { mGray = new Mat(); mRgba = new Mat(); //Load my mask png Bitmap image = BitmapFactory.decodeResource(getResources(), R.drawable.mask_1); mask = new Mat(); Utils.bitmapToMat(image, mask); } public Mat onCameraFrame(CvCameraViewFrame inputFrame) { mRgba = inputFrame.rgba(); mGray = inputFrame.gray(); if (mAbsoluteFaceSize == 0) { int height = mGray.rows(); if (Math.round(height * mRelativeFaceSize) > 0) { mAbsoluteFaceSize = Math.round(height * mRelativeFaceSize); } mNativeDetector.setMinFaceSize(mAbsoluteFaceSize); } MatOfRect faces = new MatOfRect(); if (mDetectorType == JAVA_DETECTOR) { if (mJavaDetector != null) mJavaDetector.detectMultiScale(mGray, faces, 1.1, 2, 2, new Size(mAbsoluteFaceSize, mAbsoluteFaceSize), new Size()); } else if (mDetectorType == NATIVE_DETECTOR) { if (mNativeDetector != null) mNativeDetector.detect(mGray, faces); } else { Log.e(TAG, "Detection method is not selected!"); } Rect[] facesArray = faces.toArray(); for (int i = 0; i < facesArray.length; i++) { overlayImage(mRgba, mask, facesArray[i]); } return mRgba; } public Mat overlayImage(Mat background, Mat foregroundMask, Rect faceRect) { Mat mask = new Mat(); Imgproc.resize(this.mask, mask, faceRect.size()); Mat source = new Mat(); Imgproc.resize(foregroundMask, source, background.size()); mask.copyTo( background.submat( new Rect((int) faceRect.tl().x, (int) faceRect.tl().y, mask.cols(), mask.rows())) ); source.release(); mask.release(); return background; } 

Solutions Collecting From Web of "如何在一个框架中实时joinalpha /透明度的png"

注:我将解释一般原则,并给你一个在Python中的示例实现,因为我没有设置Android开发环境。 把它移植到Java应该是相当简单的。 随意发布您的代码作为一个单独的答案。


你需要做一些类似于addWeighted操作的东西,那就是操作

线性混合公式

然而,在你的情况下,α需要是一个matrix(即我们需要一个不同的每个像素的混合系数)。


示例图像

我们用一些示例图像来说明这一点。 我们可以使用Lena图像作为样本面:

样本面

这个图像作为一个覆盖透明度:

与阿尔法覆盖

而这个图像作为一个覆盖没有透明度:

无Alpha的覆盖


混合matrix

要获得alphamatrix,我们可以使用阈值确定前景(叠加)和背景(面部)蒙版,或者如果可用,则使用input图像中的alpha通道。

在浮点图像上执行此操作是有用的,值范围为0.0..1.0。 那么我们可以把这两个面具之间的关系表示为

 foreground_mask = 1.0 - background_mask 

即加在一起的两个面具结果都是一样的。

对于RGBA格式的叠加图像,我们得到以下前景和背景蒙版:

从透明度的前景面具

从透明度的背景面具

当我们使用阈值,在RGB格式的情况下,侵蚀和模糊,我们得到以下的前景和背景蒙版:

阈值的前景蒙版

从门槛背景蒙版


加权总和

现在我们可以计算两个加权部分:

 foreground_part = overlay_image * foreground_mask background_part = face_image * background_mask 

对于RGBA覆盖,前景和背景部分如下所示:

前景部分(RGBA覆盖)

背景部分(RGBA覆盖)

而对于RGB覆盖,前景和背景部分如下所示:

前景部分(RGB覆盖)

背景部分(RGB覆盖)


最后将它们加在一起,然后将图像转换回0-255范围内的8位整数。

操作的结果如下(分别为RGBA和RGB覆盖):

合并(RGBA覆盖)

合并(RGB覆盖)


代码示例 – RGB覆盖

 import numpy as np import cv2 # ============================================================================== def blend_non_transparent(face_img, overlay_img): # Let's find a mask covering all the non-black (foreground) pixels # NB: We need to do this on grayscale version of the image gray_overlay = cv2.cvtColor(overlay_img, cv2.COLOR_BGR2GRAY) overlay_mask = cv2.threshold(gray_overlay, 1, 255, cv2.THRESH_BINARY)[1] # Let's shrink and blur it a little to make the transitions smoother... overlay_mask = cv2.erode(overlay_mask, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))) overlay_mask = cv2.blur(overlay_mask, (3, 3)) # And the inverse mask, that covers all the black (background) pixels background_mask = 255 - overlay_mask # Turn the masks into three channel, so we can use them as weights overlay_mask = cv2.cvtColor(overlay_mask, cv2.COLOR_GRAY2BGR) background_mask = cv2.cvtColor(background_mask, cv2.COLOR_GRAY2BGR) # Create a masked out face image, and masked out overlay # We convert the images to floating point in range 0.0 - 1.0 face_part = (face_img * (1 / 255.0)) * (background_mask * (1 / 255.0)) overlay_part = (overlay_img * (1 / 255.0)) * (overlay_mask * (1 / 255.0)) # And finally just add them together, and rescale it back to an 8bit integer image return np.uint8(cv2.addWeighted(face_part, 255.0, overlay_part, 255.0, 0.0)) # ============================================================================== # We load the images face_img = cv2.imread("lena.png", -1) overlay_img = cv2.imread("overlay.png", -1) result_1 = blend_non_transparent(face_img, overlay_img) cv2.imwrite("merged.png", result_1) 

代码示例 – RGBA覆盖

 import numpy as np import cv2 # ============================================================================== def blend_transparent(face_img, overlay_t_img): # Split out the transparency mask from the colour info overlay_img = overlay_t_img[:,:,:3] # Grab the BRG planes overlay_mask = overlay_t_img[:,:,3:] # And the alpha plane # Again calculate the inverse mask background_mask = 255 - overlay_mask # Turn the masks into three channel, so we can use them as weights overlay_mask = cv2.cvtColor(overlay_mask, cv2.COLOR_GRAY2BGR) background_mask = cv2.cvtColor(background_mask, cv2.COLOR_GRAY2BGR) # Create a masked out face image, and masked out overlay # We convert the images to floating point in range 0.0 - 1.0 face_part = (face_img * (1 / 255.0)) * (background_mask * (1 / 255.0)) overlay_part = (overlay_img * (1 / 255.0)) * (overlay_mask * (1 / 255.0)) # And finally just add them together, and rescale it back to an 8bit integer image return np.uint8(cv2.addWeighted(face_part, 255.0, overlay_part, 255.0, 0.0)) # ============================================================================== # We load the images face_img = cv2.imread("lena.png", -1) overlay_t_img = cv2.imread("overlay_transparent.png", -1) # Load with transparency result_2 = blend_transparent(face_img, overlay_t_img) cv2.imwrite("merged_transparent.png", result_2)