您的位置:首页 > 运维架构

OpenCv图像叠加时png图片的透明部分无法透明的解决办法

2015-06-29 13:52 615 查看
这一个月以来都在做虚拟现实的大作业,我们组想要做一个在摄像头读入的视频流中进行人脸识别并且在五官上添加物体这样一个程序。

当然人脸识别什么的就用了网上现有的一些程序,我们要做的就是在画面中加载图片于特定的坐标上。

关于如何叠加图片我参考了下面两篇文章,如果想做加水印、图片叠加相关代码的建议先看这个里面已经讲解的蛮清楚了:
http://www.cnblogs.com/mfryf/archive/2012/03/08/2385304.html http://www.tuicool.com/articles/EvyEfq
***但是***存在一个问题,在第一篇文章下面的回复中也有人提到了,用背景透明的png图像的时候不能实现透明的效果,透明的部分现实的是白色的,png图像是用photoshop挖去背景得到的。经过我到处查资料什么的得出,这个结果的可能原因应该是版本的问题。2.4之后的opencv的imread函数不能显示第四个通道了(?这个结论存疑,我也是在别的文章中看到的)。

然而我想cvshowimage()是可以显示四个通道的吧,但是iplimage和mat格式互相转换还有函数不通用也是有一些困难,这个尝试就失败了。

参考了很多地方的文章和代码都没有能够解决这个问题的办法,一时间有些头大了感觉可能这个作业没法达到需要的效果了……不过还好看别人的文章受到一些启发,就算版本不一样会存在一些问题,利用掩模的话应该也是可以解决的吧?然后抱着试一试的想法实验了下写了个小程序(基于上面文章中的代码改动了一下)。

掩模mask是单通道图像,并且只有黑和白(两个值0和1),0就是不显示,1就是显示。因此我考虑将png图像转化成灰度图进行二值化处理来得到掩模图像。由于背景已经是白色的了,所以直接设置一个阈值吧就设成254(因为不知道咋设置成255的样子)。但是这个阈值分割的结果是保留了背景部分,目标部分的值都是0了,所以再进行一下反色的处理,255减一下就好。

设置感兴趣区域的时候发现了一个问题(大概在大大的眼中并不算问题的问题OTL),就是因为logo图片也是有尺寸的,所以rect()中的坐标设置的时候要计算到logo的尺寸,否则就会超过原图片的边界,出现内存溢出r6010 abort()has been called 的问题。

其实想一想不用非得png格式的图像好像各种格式的图像也都可以这样处理了吧……

#include <opencv2/highgui/highgui.hpp>

#include <opencv2/core/core.hpp>

#include <cv.h>

using namespace cv;

int main(){

Mat image = imread("1.jpg");

Mat logo = imread("2.png");

Mat mask = imread("2.png",0); //注意要是灰度图才行

threshold(mask,mask,254,255,CV_THRESH_BINARY);

Mat mask1 = 255 - mask; //掩模反色

//imshow("img",mask1);

Mat imageROI;

imageROI = image(Rect(480,320,logo.cols,logo.rows));

logo.copyTo(imageROI,mask1);

namedWindow("result");

imshow("result",image);

imwrite("result.jpg",image);

waitKey();

return 0;

}

处理完的结果就是下面这个样子,当然我不是按照水印的做法来做的的,没有改变透明度什么的……写这个东西就是记录一下解决问题的思路,其实代码还有想法都是可以完善的,主要是网上都没有关于这个问题的解决办法(也可能是我没找到)所以赶紧写下来省得以后忘记了……/(ㄒoㄒ)/~~

image:



logo:



result:



1619
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: