OpenCV 支持 alpha 通道吗?或者有什么办法可以使用透明png?我需要合并两个图像,其中第一个是背景,第二个是由 cvWarpAffine 旋转的图像。我可以通过一个一个地合并像素并省略具有某个值的像素来做到这一点,这是我在 cvWarpAffine 的 cvScalar 中设置的。但是,我认为这不是预期的解决方案。感谢您的建议
3 回答
更新答案:使用CV_LOAD_IMAGE_UNCHANGED
标志从图像中加载所有四个通道(包括 Alpha)。然后,使用mixChannels()
和/或split()
将 Alpha 通道与其他通道分开,并在其上设置阈值,如下所述。
很老的答案:
OpenCV 不支持 alpha 通道,只支持遮罩。如果你想用 alpha 读取 PNG,首先使用 imagemagick 来提取 alpha 通道:
convert input.png -channel Alpha -negate -separate input-mask.png
然后在 OpenCV 中你可以这样做:
Mat_<float> mask = imread("input-mask.png", 0);
threshold(mask, mask, 254., 1., THRESH_BINARY);
...获得一个真正的掩码(可用作 OpenCV 操作中的掩码矩阵)。或者您可以在自己的操作中使用它而无需阈值。要应用蒙版,最好将其扩展到三个通道:
std::vector<Mat> marr(3, mask);
Mat_<Vec<float, 3> > maskRGB;
merge(marr, maskRGB);
之后,您可以像这样测试它:
imshow("Target", target);
imshow("Mask", mask*255);
imshow("Applied", target.mul(maskRGB));
waitKey();
注意:这是 OpenCV 2.0 代码。
这是我拼凑在一起的一个 bash 脚本,它将对目录中的所有 png 文件执行 ypnos 提供的 ImageMagick 转换。您可以通过将第三行中的 * 替换为 find 命令来使其递归。
#!/bin/bash
for file in *
do
if [[ $file =~ (.+)-mask\.png ]]; then
echo "Ignoring mask $file"
elif [[ $file =~ (.+)\.png ]]; then
echo "Generating mask for $file"
basefn=${BASH_REMATCH[1]}
convert "$basefn.png" -channel Alpha -negate -separate "$basefn-mask.png"
fi
done
输入:cam_frame-background、media_frame-foreground、media_frame_alpha - alpha。输出:由 alpha 透明混合。如果 media_frame_alpha 是 IPL_DEPTH_8U 使用“cv::merge”,因为矩阵必须具有相同的维度、大小和通道。如果 opencv 使用 sse 或 avx 构建,工作速度很快。如果使用 cv:GpuMat,速度会更快,必须支持 nvidia cuda 并使用 cuda 构建 opencv。
inline cv::Mat frame_mix_alpha(cv::Mat &cam_frame,
cv::Mat &media_frame,
cv::Mat &media_frame_alpha)
{
Mat suba = media_frame_alpha;
//Mat alpha = cvCreateImage(media_frame_alpha.size(), IPL_DEPTH_8U, 1);
//cvtColor(media_frame_alpha, alpha, CV_BGR2GRAY);
//Mat suba;
//Mat rgba[3] = { alpha, alpha, alpha };
//merge(rgba, 3, suba);
Mat subb = ~suba;
//Mat mincam = min(cam_frame, suba);
//Mat minmedia = min(media_frame, subb);
//Mat result = (cam_frame - mincam) + (media_frame - minmedia);
Mat result = (cam_frame - suba) + (media_frame - subb);
return result;
}