如何用alpha/transparency在realtim框架中连接png

2024-09-29 17:11:14 发布

您现在位置:Python中文网/ 问答频道 /正文

我在opencvandroid2.4.11的例子下工作,它使用摄像头检测人脸。 我不是在找到的脸上画一个矩形,而是在脸上画一个蒙版(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;
    }

Tags: 图像newifpngmaskpublicintbackground
1条回答
网友
1楼 · 发布于 2024-09-29 17:11:14

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


您需要执行与addWeighted操作类似的操作,即操作

Linear blend formula

但是,在你的例子中,α需要是一个矩阵(也就是说,我们需要不同的每像素混合系数)。在


示例图像

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

Sample Face

此图像作为透明覆盖:

Overlay with Alpha

这张图片是一张没有透明度的覆盖图:

Overlay without Alpha


混合矩阵

为了获得α矩阵,我们可以使用阈值法确定前景(覆盖)和背景(面部)遮罩,或者使用输入图像中的alpha通道(如果可用)。在

对值在0.0范围内的浮点图像执行此操作非常有用。。1.0条。然后我们可以将两个面具之间的关系表示为

foreground_mask = 1.0 - background_mask

也就是说,两个面具加在一起就得到了所有的面具。在

对于RGBA格式的覆盖图像,我们得到以下前景和背景遮罩:

Foreground mask from transparency

Background mask from transparency

当我们使用RGB格式的阈值、腐蚀和模糊时,我们得到了以下前景和背景遮罩:

Foreground mask from threshold

Background mask from threshold


加权和

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

^{pr2}$

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

Foreground part (RGBA overlay)

Background part (RGBA overlay)

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

Foreground part (RGB overlay)

Background part (RGB overlay)


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

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

Merged (RGBA overlay)

Merged (RGB overlay)


代码示例-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)

相关问题 更多 >

    热门问题