-
时我们需要给一张图片添加logo,例如下图这样
-
掩膜操作思路它的思想是:
1.1 先将彩色图像转换为灰度图,然后利于阈值将图像二值化,变成非黑即白的形式,这样logo的蒙版就做好来了(学过PS的人应该很容易理解);
1.2 蒙版中黑色的区域表示删除掉该区域像素,白色表示保留该区域像素。黑色是0,白色是255;
1.3 所以利用二值化得到的蒙版(掩膜)是剔除logo区域的。反之,是用来提出logo上的多余区域的;
1.4 如何剔除掉小姐姐照片中的logo区和logo上的空白区域呢,用cv2.bitwise_and方法。因为0(黑色)与非0数and后为0,这样就可以把该区域剔除啦;
1.5 最后,将logo补到小姐姐照片上就可以了。 -
完整代码
import cv2
img1 = cv2.imread('person.jpg')
logo = cv2.imread('food.jpg')
rows, cols, channels = logo.shape # 获取图像2的属性
roi = img1[0:rows, 0:cols] # 选择roi范围
logo2gray = cv2.cvtColor(logo, cv2.COLOR_BGR2GRAY) # 转换为灰度图像
ret, mask = cv2.threshold(logo2gray, 175, 255, cv2.THRESH_BINARY) # 设置阈值,大于175的置为255,小于175的置为0 logo黑色
mask_inv = cv2.bitwise_not(mask) # 非运算 logo白色
img1_bg = cv2.bitwise_and(roi, roi, mask=mask) # 删除了ROI中的logo区域(mask的logo为黑色,故and后该区域被舍去)---》上图中的图一
logo_fg = cv2.bitwise_and(logo, logo, mask=mask_inv) #删除了logo中的空白区域(mask_inv的logo为百度色,故and后该区域被保留)----》上图中的图二
dst = cv2.add(img1_bg, logo_fg) # 两个像插销一样,一个被镂空,一个被保留,两者相加,刚刚好
img1[0:rows, 0:cols] = dst # 将贴图后的区域图,覆盖到原图
cv2.imshow('res', img1)
cv2.waitKey(0)
cv2.destroyAllWindows()
- 可能的报错信息
3.1 尺寸不一致导致
报错如下:
person_ = cv2.bitwise_and(roi, roi, mask=mask)
'cv2.error: OpenCV(4.5.1) C:UsersappveyorAppDataLocalTemp1pip-req-build-6uw63onyopencvmodulescoresrcarithm.cpp:250: error: (-215:Assertion failed) (mtype == CV_8U || mtype == CV_8S) && _mask.sameSize(*psrc1) in function 'cv::binary_op'
原因:roi和mask的尺寸(长和宽)不一致导致的,比如img.shape=(800,600),roi截取img一部分是,可能超出原本的大小,比如roi=img[0:610,0:610],roi.shape实际等于(610,600),造成与mask.shape=(610,610)不一致,从而报错
注意:roi是RGB,mask是二值图,通道本身就不等,我们进要求长和宽一致即可