OpenCV学习(三)使用mask添加水印

来源:互联网 发布:java执行输入参数命令 编辑:程序博客网 时间:2024/06/11 06:28
上一篇学习了ROI的用法,本节接着上一篇,继续添加水印,但是要去掉讨厌的水印的背景。

关于添加水印,网上有一篇讲的很清楚:
http://www.cnblogs.com/mfryf/archive/2012/03/08/2385304.html

不过他的图像是png格式的,本身是透明背景,本篇将采用普通jpg格式图片做水印。

第一步,分析 copyTo 函数:
    //! copies those matrix elements to "m" that are marked with non-zero mask elements.    void copyTo( OutputArray m, InputArray mask ) const;

关注mask参数。要去掉水印的背景,需要使用mask,对不想修改的部分不做修改(上面的注释很清楚,就是说只对非0的位置做操作)。

那么如何构造这个mask?那么我需要对water_mark图像做二值化,生成一个黑白的mask,其中想留下的水印部分是非0(白色255),需要叠加操作;背景是0(黑色0),不需要叠加操作。


我的图像是白色背景的(用mspaint绘制:) )
首先,通过 cvtColor 把 water_mark 图像变成灰度图 grey:
    Mat     gray(water_mark);    cvtColor(gray, gray, CV_RGB2GRAY);
再通过二值化函数 threshold 把灰度图 gray 转化为黑白图 mask,其中 最后一个参数 type 要看情况而定,我这里是 CV_THRESH_BINARY_INV,表明做一个反转。(如果不反转一下,嘿嘿,那就成了叠加背景和镂空水印了。)
    Mat     mask(gray);    cv::threshold(gray, mask, 128, 255, CV_THRESH_BINARY_INV);

关于门限类型的定义 Opencv解释的很清楚:
/* Threshold types */
enum
{
    CV_THRESH_BINARY      =0,  /* value = value > threshold ? max_value : 0       */
    CV_THRESH_BINARY_INV  =1,  /* value = value > threshold ? 0 : max_value       */
    CV_THRESH_TRUNC       =2,  /* value = value > threshold ? threshold : value   */
    CV_THRESH_TOZERO      =3,  /* value = value > threshold ? value : 0           */
    CV_THRESH_TOZERO_INV  =4,  /* value = value > threshold ? 0 : value           */
    CV_THRESH_MASK        =7,
    CV_THRESH_OTSU        =8  /* use Otsu algorithm to choose the optimal threshold value;
                                 combine the flag with one of the above CV_THRESH_* values */
};

效果图:




这个是叠加式(覆盖式)水印,即直接覆盖掉原来的图像,如果想使用半透明的水印,我这里采用了一个比较土的办法,构造了一个彩色的 color_mask,跟 water_mark 做“与”操作,使 water_mark 背景部分像素值RGB分量全部变成0,再跟 image 做 addWeighted 操作,即可。
color_mask 的构造过程:通过 split 对 water_mark 按通道分割成RGB三个单通道图像,每个图像都拷贝成单通道的 mask,然后重新合并 merge成彩色蒙版。
    Mat color_mask;    std::vector<Mat>    planes;    split(water_mark, planes);    std::vector<Mat>::iterator  it = planes.begin();    for(; it != planes.end(); ++it)    {        mask.copyTo(*it);    }    merge(planes, color_mask);    cv::bitwise_and(water_mark, color_mask, water_mark);    addWeighted(roi, 1.0, water_mark, 0.5, 0, roi); //alpha add

效果图:


原创粉丝点击