![](/img/trans.png)
[英]How to use opencv to acess images to use for alpha blending in java for android
[英]OpenCV java alpha Blending
我正在嘗試移植以下代碼(從 C++ 到 Java)以在我的圖像之間進行良好的 alpha 混合,但它不起作用:
#include opencv2/opencv.hpp
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
// Read the images
Mat foreground = imread("puppets.png");
Mat background = imread("ocean.png");
Mat alpha = imread("puppets_alpha.png");
// Convert Mat to float data type
foreground.convertTo(foreground, CV_32FC3);
background.convertTo(background, CV_32FC3);
// Normalize the alpha mask to keep intensity between 0 and 1
alpha.convertTo(alpha, CV_32FC3, 1.0/255); //
// Storage for output image
Mat ouImage = Mat::zeros(foreground.size(), foreground.type());
// Multiply the foreground with the alpha matte
multiply(alpha, foreground, foreground);
// Multiply the background with ( 1 - alpha )
multiply(Scalar::all(1.0)-alpha, background, background);
// Add the masked foreground and background.
add(foreground, background, ouImage);
// Display image
imshow("alpha blended image", ouImage/255);
waitKey(0);
return 0;
}
代碼可以在這里找到: https : //www.learnopencv.com/alpha-blending-using-opencv-cpp-python/還有我的 Java 版本:
public static Mat alphaBlend(Mat background, Mat foreground) {
Vector<Mat> rgba = new Vector<Mat>();
// split RBGA image for separate channels
Core.split(background, rgba);
// get alpha channel
Mat alpha = rgba.get(3);
// Convert Mat to float data type
foreground.convertTo(foreground, CvType.CV_32FC3);
background.convertTo(background, CvType.CV_32FC3);
// Normalize the alpha mask to keep intensity between 0 and 1
alpha.convertTo(alpha, CvType.CV_32FC3, 1.0/255); //
Imgproc.cvtColor(alpha,alpha, Imgproc.COLOR_GRAY2BGRA,4);
Mat outImage = Mat.zeros(foreground.size(),foreground.type());
// Multiply the foreground with the alpha matte
Core.multiply(alpha, foreground, foreground);
Mat kernel = new MatOfDouble(1.0);
Core.subtract(kernel, alpha, alpha);
// Multiply the background with ( 1 - alpha )
Core.multiply(alpha, background, background);
// Add the masked foreground and background.
Core.add(foreground, background, outImage);
Core.divide(new MatOfDouble(255), outImage,outImage);
return outImage;
}
我認為我的問題是將其移植到 Java 中:
multiply(Scalar::all(1.0)-alpha, background, background);
任何幫助,將不勝感激!
謝謝
編輯:這里是一個工作版本,但邊框不混合透明像素,導致圖像交點的邊框處出現空白像素/線:
private static Mat merge(Mat background, Mat foreground) {
Vector<Mat> rgba = new Vector<Mat>();
// split RBGA image for separate channels
Core.split(background, rgba);
// get alpha channel
Mat alpha = rgba.get(3);
// Convert Mat to float data type
// Normalize the alpha mask to keep intensity between 0 and 1
alpha.convertTo(alpha, CvType.CV_32FC3, 1.0/255); //
Mat dst = new Mat(256,256,CvType.CV_8UC4);
alpha.convertTo(alpha,CvType.CV_8UC1);
Mat alphaInv = new Mat();
// invert the mask
Core.absdiff(new MatOfDouble(1.0), alpha, alphaInv);
foreground.copyTo(dst, alphaInv);
// case where foreground is full JPEG in BGR
if(dst.type() != CvType.CV_8UC4) {
Imgproc.cvtColor(dst, dst, Imgproc.COLOR_BGR2BGRA, 4);
}
background.copyTo(dst, alpha);
return dst;
}
我建議使用 Core 的addWeighted方法進行基本的 alpha 混合。
看起來您想要一個基於掩碼的可變 alpha 混合,您需要按照 api 指定的順序排列參數,以便進行加法/ 減法/ 乘法等基本操作。 對於您的乘法,這意味着標量應該是第二個參數。 對於您的減法,這意味着標量應該再次成為第二個參數(我發現自己將矩陣乘以負 1,然后添加到標量值)。
根據您共享的鏈接,目標似乎只是使用圖像遮罩,我認為有一種更簡單的方法,即使用copyTo函數。 嘗試將它放在您的主要功能中,並在它運行時移動到您的功能:
// Read the images
Mat foreground = Imgcodecs.imread("puppets.png");
Mat background = Imgcodecs.imread("ocean.png");
Mat mask = Imgcodecs.imread("puppets_alpha.png");
Mat notMask = new Mat();
Core.bitwise_not(mask, notMask);
Mat result = new Mat();
Core.copyTo(background, result, mask);
Core.copyTo(foreground, result, notMask);
Imgcodecs.imwrite("result.png", result);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.