opencv将透明PNG图片填充为白色背景

时间:2022-01-28 09:13:11

本篇博客介绍使用两种方式来实现将透明PNG图片填充为白色背景。

第一种方法:


代码:

#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/highgui/highgui.hpp>
using namespace cv;

int i, j;

Mat overlayImage(const Mat &background, const Mat &foreground)
{
	Mat output;
	background.copyTo(output);

	for (int y = std::max(0, 0); y < background.rows; ++y)
	{
		int fY = y - 0; 
		if (fY >= foreground.rows)
			break;

		for (int x = std::max(0, 0); x < background.cols; ++x)
		{
			int fX = x - 0; 

			if (fX >= foreground.cols)
				break;

			double opacity =
				((double)foreground.data[fY * foreground.step + fX * foreground.channels() + 3])

				/ 255.;


			for (int c = 0; opacity > 0 && c < output.channels(); ++c)
			{
				unsigned char foregroundPx =
					foreground.data[fY * foreground.step + fX * foreground.channels() + c];
				unsigned char backgroundPx =
					background.data[y * background.step + x * background.channels() + c];
				output.data[y*output.step + output.channels()*x + c] =
					backgroundPx * (1. - opacity) + foregroundPx * opacity;
			}
		}
	}
	return output;
}

int main() {
	Mat srcImg = imread("img\\1.png", -1);
	
	if (!srcImg.data) {
		return 0;
	}
	
	namedWindow("src");
	imshow("src", srcImg);
	IplImage *img = cvCreateImage(cvSize(srcImg.cols, srcImg.rows), IPL_DEPTH_8U, 3);
	

	for (i = 0;i<img->height;i++)
		for (j = 0;j<img->width;j++)
			cvSet2D(img, i, j, cvScalar(255, 255, 255));
	Mat m = img;
	imshow("m", m);
	Mat result;
	result = overlayImage(img, srcImg);
	imshow("result", result);
	waitKey(0);

	return 0;
}

原图:


opencv将透明PNG图片填充为白色背景

结果图:

opencv将透明PNG图片填充为白色背景




第二种方法:

代码:

#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/highgui/highgui.hpp>
using namespace cv;

void overlayImage2(const cv::Mat &srcAlpha, cv::Mat &dest)
{
	int nc = 3;
	int alpha = 0;

	for (int j = 0; j < srcAlpha.rows; j++)
	{
		for (int i = 0; i < srcAlpha.cols * 3; i += 3)
		{
			// 目的图片为三通道,所以是三通道的遍历、四通道的源图
			// i/3*4表示第i/3个像素的位置 
			// i/3*4 + 3表示本像素的alpha通道的值
			alpha = srcAlpha.ptr<uchar>(j)[i / 3 * 4 + 3];
			//alpha = 255-alpha;
			if (alpha != 0) //4通道图像的alpha判断
			{
				for (int k = 0; k < 3; k++)
				{
					// if (src1.ptr<uchar>(j)[i / nc*nc + k] != 0)
					if ((j  < dest.rows) && (j  >= 0) &&
						((i) / 3 * 3 + k < dest.cols * 3) && ((i) / 3 * 3 + k >= 0) &&
						(i / nc * 4 + k < srcAlpha.cols * 4) && (i / nc * 4 + k >= 0))
					{
						dest.ptr<uchar>(j)[(i) / nc*nc + k] = srcAlpha.ptr<uchar>(j)[(i) / nc * 4 + k];
					}
				}
			}
		}
	}
}

int main() {
	Mat srcImg = imread("img\\1.png", -1);
	
	if (!srcImg.data) {
		return 0;
	}
	
	namedWindow("src");
	imshow("src", srcImg);
	IplImage *img = cvCreateImage(cvSize(srcImg.cols, srcImg.rows), IPL_DEPTH_8U, 3);
	

	for (i = 0;i<img->height;i++)
		for (j = 0;j<img->width;j++)
			cvSet2D(img, i, j, cvScalar(255, 255, 255));
	Mat m = img;
	imshow("m", m);
	Mat result;
	overlayImage2(srcImg,m);
     imshow("result", srcImg);
     namedWindow("result");
     imshow("result", m);
waitKey(0);return 0;

}

示例:

原图:

opencv将透明PNG图片填充为白色背景


结果图:

opencv将透明PNG图片填充为白色背景