如何在OpenCV中实现覆盖实时摄像头的透明图像

4
我需要在实时摄像头图像上绘制一个透明的图像。以下是要显示为相机覆盖层的PNG文件。
下面是从相机获取帧并在屏幕上显示它的代码片段。我也尝试将圆形绘制为覆盖层,但圆形不透明。我认为下面的代码有误或遗漏了一些内容?
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>

using namespace cv;
using namespace std;

int main () {

 Mat src;
 Mat overlay = imread ( "circle.png", -1 );

 VideoCapture cap ( 0 );

 while ( 1 ) {

 cap >> src;
 cvtColor( src, src, CV_BGR2BGRA );
 overlay.copyTo( src.colRange(0,400).rowRange(0,400));
 imshow ( "src",src );
 waitKey( 10 );

 }

 return 0;
 }

嘿,那不会很容易。为什么不直接绘制一个椭圆呢? - berak
确保圆形的白色区域具有适当的 alpha 通道(值为 255)。此外,在 waitKey 周围添加 if 和 break 语句。 - baci
@berak 这只是一个例子.. 我需要在相机反馈上绘制另一张图片,而不是椭圆形。 - user2727765
您当前的代码只是用一个图像替换另一个图像,不管它是否具有alpha通道。OpenCV中不存在能够支持alpha通道的操作,所以您需要进行一些改进,例如使用alpha通道的反向作为add()操作的掩码。再次强调,这是一个计算机视觉库,不是用来在人们脸上贴搞笑胡子的。 - berak
1
@berak,终于成功了。http://jepsonsblog.blogspot.in/2012/10/overlay-transparent-image-in-opencv.html - user2727765
2个回答

3
如果您的覆盖图像具有alpha通道(假设图像大小相同),则可以像这样操作。
cv::Mat display_img( src.size(), src.type() );
for (int y = 0; y < src.rows; y++)
{
    const cv::Vec3b* src_pixel = src.ptr<cv::Vec3b>(y);
    const cv::Vec4b* ovl_pixel = overlay.ptr<cv::Vec4b>(y);
    cv::Vec3b* dst_pixel = display_img.ptr<cv::Vec3b>(y);
    for (int x = 0; x < src.cols; x++, ++src_pixel, ++ovl_pixel, ++dst_pixel)
    {
        double alpha = (*ovl_pixel).val[3] / 255.0;
        for (int c = 0; c < 3; c++)
        {
            (*dst_pixel).val[c] = (uchar) ((*ovl_pixel).val[c] * alpha + (*src_pixel).val[c] * (1.0 -alpha));
        }
    }
}

3
这篇文章介绍了如何在OpenCV中叠加一张透明的图片。具体实现方法可以参考网址:http://jepsonsblog.blogspot.in/2012/10/overlay-transparent-image-in-opencv.html。 - user2727765

2

我刚刚解决了完全相同的问题,我的解决方案是找出覆盖中有东西的像素,并将这些像素在图像中清零。现在你知道两幅图像中每个像素都为零,然后你可以简单地将两幅图像相加。

在 Python 中:

import numpy as np
import cv2

# load the overlay file
overlay = cv2.imread('overlay.png')

# detect which pixels in the overlay have something in them
# and make a binary mask out of it
overlayMask = cv2.cvtColor( overlay, cv2.COLOR_BGR2GRAY )
res, overlayMask = cv2.threshold( overlayMask, 10, 1, cv2.THRESH_BINARY_INV)

# expand the mask from 1-channel to 3-channel
h,w = overlayMask.shape
overlayMask = np.repeat( overlayMask, 3).reshape( (h,w,3) )


# here's where the work gets done :

# mask out the pixels that you want to overlay
img *= overlayMask

# put the overlay on
img += overlay

# Show the image.
cv2.imshow(WINDOW_NAME, img)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接