void overlayImage(const cv::Mat &background, const cv::Mat &foreground, cv::Mat &output, cv::Point2i location, double opacity = 1.0)
{
background.copyTo(output);
// start at the row indicated by location, or at row 0 if location.y is negative.
for (int y = std::max(location.y , 0); y < background.rows; ++y) {
int fY = y - location.y; // because of the translation
// we are done of we have processed all rows of the foreground image.
if (fY >= foreground.rows)
break;
// start at the column indicated by location, or at column 0 if location.x is negative.
for (int x = std::max(location.x, 0); x < background.cols; ++x) {
int fX = x - location.x; // because of the translation.
// we are done with this row if the column is outside of the foreground image.
if (fX >= foreground.cols)
break;
// determine the opacity of the foregrond pixel, using its fourth (alpha) channel.
double opacity_level = ((double)foreground.data[fY * foreground.step + fX * foreground.channels() + 3]) / 255.;
if (opacity >= 0.0 && opacity < 1.0)
opacity_level *= opacity;
// and now combine the background and foreground pixel, using the opacity, but only if opacity > 0.
for (int c = 0; opacity_level > 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_level) + foregroundPx * opacity_level;
}
}
}
}
2条答案
按热度按时间au9on6nz1#
几周前,A对我在互联网上其他地方看到的一个函数进行了一些更改,以便能够:
以下是用于测试的输入图像:* 左 * 是 * 背景 *,而 * 右 * 上的图像是 * 前景 *。
要将前景完全复制到背景上,只需执行以下操作:
并以50%的透明度执行复制:
以下是结果:
此实现对于生产用途来说并不是无懈可击的,因此使用它要自担风险。
nlejzf6q2#
感谢大家尝试回答我的问题。最后,我采取了枚举的背景图像的条件,并将其转换为相同的通道数,然后使用加权求和的路径。不知道这是否是正确的方式来处理它,但它似乎为我工作,除了透明背景PNG。有什么建议吗?