我对图像腌膜的含义一直有些模糊,今天写了几行代码,证明了我这模糊的印象倒是正确的。今天借一个给图片添加水印的小例子,给大家总结一些图像腌膜的常规操作。
首先先了解一下图像腌膜的定义:。。。
额,找了一圈好像并没有啥特别正式的官方定义/我记得曾在书上看到过来着~
其实腌膜可以抽象为一个黑白相间的图,或者膜,黑色的像素值为0,白色为1。将这个膜和你原本的图像重合到一起,黑色区域被忽略,仅剩下白色区域,就是这样。
就像把白色区域的图像抠出来一样,”抠图“就是腌膜Mask最常干的事。
废话少说,咱们开始咱们的小实践吧。
一:普通加水印:图像加和
先看一下今天要处理的水印图,一张白底红字的logo图:

然后再看一下我们的底图:
我们要吧logo,也就是水印加到左上角去,首先我们想到的就是在左上角掏个和logo图片一样大小的ROI区域出来,然后直接将logo添加到ROI区域里,来看代码:
运行效果如下:
可以看到白色的底并不是我们想要的,所以就需要用到腌膜的相关抠图,将五个红色的字”抠“出来。
二:抠图操作加水印
首先我们要完成的操作就是将这五个字识别出来,也就是抠出来,对于我们这个logo自然很简单啦,只需要转灰度,然后阈值化操作一下就可以了:
1,我们先定义一个腌膜Mask,然后将logo图像转为灰度图像存入到Mask中:
处理后得到如下灰度图:
2,对腌膜Mask这个图像矩阵进行取反操作:
对于上面操作我们需要多加解释一下。
图像的基本运算有很多种,比如两幅图像可以相加相减、相乘、相除、位运算、平方根、对数、绝对值等;
图像也可以放大、缩小、旋转,还可以截取其中的一部分作为ROI(感兴趣区域)进行操作,各个颜色通道还可以分别提取及对各个颜色通道进行各种运算操作。
所以我们自然可以对图像进行与,或,非,异或等操作啦。
bitwise_and:对二进制数据进行“与”操作,即对图像(灰度图像或彩色图像均可)每个像素值进行二进制“与”操作,1&1=1,1&0=0,0&1=0,0&0=0
bitwise_or:对图像(灰度图像或彩色图像均可)每个像素值进行二进制“或”操作,1|1=1,1|0=1,0|1=1,0|0=0
bitwise_xor:对图像(灰度图像或彩色图像均可)每个像素值进行二进制“异或”操作,1^1=0,1^0=1,0^1=1,0^0=0
bitwise_not:对图像(灰度图像或彩色图像均可)每个像素值进行二进制“非”操作,~1=0,~0=1
为什么要对我们处理后得灰度图进行取反操作呢?因为我们开头说过,在腌膜中黑色无效,白色有效,而我们得灰度图的底色确实白色的,字确实黑色的,所以进行取反操作,结果如下:
3,对取反后的图进行阈值化操作,抠出五个字:
得到如下图所示:
4,进行图像融合
通过上面步骤,我们得到了如上图所示的黑底白字的腌膜了,下面就把腌膜加入到图像融合中去。
可以看到copyTo方法中,有第二个参数mask,我们只需要传给他就可以了,很多现成的函数接口都有图像腌膜这个参数,现在你知道怎么用了吧。
来看看效果图:
是不是变成水印了呢?
三:添加非矩形的Mask区域
我们选取ROI区域一般都是用矩形,所以圈出来的区域都是矩形的,如何添加非矩形的呢?
首先我们读取我们的logo图片,为了观察方便我们换了如下一个logo:
需要强调的是,接下来我们的操作都是基于这张logo的大小来进行的:
1,在原图开出logo大小的ROI区域:
2,创建一个同logo一样大的纯黑的腌膜mask:
3,在黑色腌膜上画出一个白色内填充的圆:
4,最后就还是一样的操作,将logo复制到原图ROI区域中去,并申明腌膜:
运行效果如下图:
虽然有些丑,但好看又不能拿来找对象,所以就这样叭。
到此,会添加圆形了,其他非规则的形状就要通过关键点来进行确定了,我们只需要将上述步骤中的第三步:在黑色腌膜上画圆变成画不规则多边形就行了,如下:
创建多个点,然后进行轮廓绘制就好了,drawContours这个函数最后传的参数-1为线宽,当为正时为宽度,为负则为向内填充,和画圆函数类似。