Ask Your Question
0

How to join png with alpha / transparency in a frame in realtime

asked 2016-04-28 12:39:29 -0600

VCS_DEV gravatar image

I'm working under the example of OpenCV android 2.4.11 which detects faces using the camera. Instead of drawing a rectangle on the face found, I'm trying to put a mask (png image) on the face. But to display the image on the face, the png image is coming with a black background where there was transparency.

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;
    }
edit retag flag offensive close merge delete

1 answer

Sort by ยป oldest newest most voted
0

answered 2016-04-28 20:23:25 -0600

Tetragramm gravatar image

Make sure when you read the mask image in that you keep the fourth channel. Then threshold that to get a binary mask that is only the opaque parts. Once you resize the mask image, extract the fourth channel and use it as the mask parameter in the copyTo function. This will prevent it from copying the parts that are transparent.

edit flag offensive delete link more

Comments

Thanks for the reply but I walked searching to understand (in code form) and could not use your answer to a solution ...

VCS_DEV gravatar imageVCS_DEV ( 2016-04-29 15:16:35 -0600 )edit

I'm afraid I have more than enough things of my own to be doing, so I can't write the code for you. You need to use threshold or a similar function to make a binary mask of everywhere that isn't transparent. The copyTo function takes that binary mask as a parameter. It does not copy the pixels where the mask is zero.

Tetragramm gravatar imageTetragramm ( 2016-04-29 16:53:58 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2016-04-28 12:39:29 -0600

Seen: 1,278 times

Last updated: Apr 28 '16