本篇博客介绍使用两种方式来实现将透明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; }
原图:
结果图:
第二种方法:
代码:
#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; }
示例:
原图:
结果图: