java opencv png图像与alpha通道视频问题

时间:2017-11-12 11:07:27

标签: java opencv png video-capture alpha

大家。我正在尝试使用java和opencv将“.png”图像放在视频捕获上。

我从官方opencv java网站http://opencv-java-tutorials.readthedocs.io/en/latest/04-opencv-basics.html

执行了教程

在本教程中,一切都与本教程中的png图像一致。但是当我尝试使用alpha通道加载我自己的png图像时,我得到了错误的结果。 Png图像显示带有空格。

以下是两张图片的视频拍摄打印屏幕:

correct output

incorrect output

my png image

以下是加载图片的代码:

@FXML
protected void loadLogo() {
    if(logoCheckBox.isSelected()) {
        this.logo = Imgcodecs.imread("resources/Poli.png", Imgcodecs.IMREAD_COLOR);
    }
}

以下是视频捕获代码并在其上放置png图像:

Mat frame = new Mat();

// read the current frame
this.capture.read(frame);
Rect roi = new Rect(frame.cols() - logo.cols(), frame.rows() - logo.rows(), logo.cols(), logo.rows());
Mat imageROI = frame.submat(roi);

Core.addWeighted(imageROI, 1.0, logo, 1.0f, 0.0, imageROI);

以下是输出图像在ImageView中的位置:

MatOfByte buffer = new MatOfByte();
Imgcodecs.imencode(".png", frame, buffer);
Image imageToShow = new Image(new ByteArrayInputStream(buffer.toArray()));
Image imageToShow = Utils.mat2Image(frame);
currentFrame.setImage(imageToShow);

我知道参数Imgcodecs.IMREAD_COLOR加载带有3个通道的图像,没有alpha,但是当我将此参数更改为IMREAD_UNCHANGED时出现此错误:

  

OpenCV错误:输入参数的大小不匹配(该操作既不是'数组操作数组'(其中数组具有相同的大小和相同的通道数)

这是因为视频捕获的输入Mat只包含3个通道。

我的问题是:如何正确加载png图像并将其放置在视频捕捉上?

P.S当我用黑色填充png图像的背景时,它显示正确,但图像仍保持透明。

1 个答案:

答案 0 :(得分:0)

答案,RGBA图像无法放置在RGB视频捕捉上。仅放置png图像的RBG组件会产生错误的结果"。

目前,我找到的最佳解决方案是在4个通道的RBGA模式COLOR_UNCHANCHED中加载png图像,采用第4个alpha通道并将其用作显示图像功能的掩码" copyTo"而不是" addWeighted"。

但是这种方法不适用于PNG图像的半透明部分,如阴影和不透明度低的物体。

以下是使用单独的RGB和Alpha通道加载图像的代码:

Mat logo = new Mat();
Mat logo_alpha = new Mat();
Mat logo_with_alpha = Imgcodecs.imread("resources/TREE_1.png", Imgcodecs.IMREAD_UNCHANGED);         
Vector<Mat> rgba = new Vector<Mat>();
// split RBGA image for separate channels
Core.split(logo_with_alpha, rgba);
// get alpha channel
logo_alpha = rgba.get(3);
// remove alpha channel to get RGB image
rgba.remove(rgba.size()-1);
// get image with only RGB components
Core.merge(rgba, this.logo);

以下是视频捕捉和放置png图像的代码:

Mat frame = new Mat();
// read the current frame
this.capture.read(frame);
Rect roi = new Rect(frame.cols() - logo.cols(), frame.rows() - logo.rows(), logo.cols(), logo.rows());
Mat imageROI = frame.submat(roi);
// place logo with alpha on the frame
logo.copyTo(imageROI, logo_alpha);