今天学习的目标依旧是研究图像的合成,重点还是在 ROI 与掩膜相关知识
本文的最终目标,把下面这个章扣在任意图片上,当然你可以把这个章更换成任意的,例如发票章。
PNG 图片相关通道说明
读取图片比较简单,直接进行操作即可,重点注意 imread
中第三个参数即可。
# 读取图片
def read_img(path):
img = cv.imread(path,-1)
print(img.shape)
dst = cv.resize(img,(130,124))
cv.imshow("img", dst)
if __name__ == "__main__":
# png 透明图片路径
path = r"./18_png.png"
read_img(path)
cv.waitKey()
cv.destroyAllWindows()
下面的步骤是将 PNG 图片,透明部分修改为黑色。
def alpha2black_opencv2(img):
width,height,channels = img.shape
for yh in range(height):
for xw in range(width):
color_d = img[xw, yh]
# 找到alpha通道为 0 的像素
if(color_d[3] == 0):
# 改变像素颜色为黑色
img[xw, yh] = [0, 0, 0, 0]
# 返回一个不透明的BGR图片
return cv.cvtColor(img, cv.COLOR_BGRA2BGR)
循环每一个像素点,当发现 alpha 通道为 0 的时候,就修改该点像素为 [0,0,0,0]。
这里要注意的是 png 图片每个像素点的颜色为 [ 76 112 71 0]
格式,其中最后一个值表示 alpha 通道值。
该通道透明部分都为 0,所以修改该值即可。
运行效果截图:
如果你还有疑问,可以这样进行测试。
获取任意透明部分的像素颜色值,或者获取任意有颜色部分像素值。
透明部分的值为:[ 76 112 71 0]
非透明部分的值为:[ 0 0 255 255]
那 alpha 部分有其他值吗?肯定存在呀,这个是透明度,可以做如下尝试,就拿本案例提供的图片来说
当 alpha 通道为 255 的时候,我们将其调整为 100,看一下对比效果。
def alpha2black_opencv2(img):
width, height, channels = img.shape
print(img[50, 30])
print(img[50, 30][0])
for yh in range(height):
for xw in range(width):
color_d = img[xw, yh]
if(color_d[3] == 255):
img[xw, yh, 3] = 100
print(img[62, 62])
print(img[62, 62][0])
# 返回一个不透明的BGR图片
print(img.shape)
cv.imwrite("./1.png", img)
return img
# return cv.cvtColor(img, cv.COLOR_BGRA2BGR)
注意上述代码在运行之后,不要通过 cv.imshow()
展示,要通过 cv.imwrite()
写入到文件中,才可查看效果。
加载待盖章图片
加载背景图,并且在背景图上找到 ROI 区域。
先整理逻辑,一会在查看代码:
第一步:找到目标 ROI 区域,这个区域要和印章图片大小一致,不一致无法进行图片相加操作
第二步:在目标区域中把印章红色区域抠出来,采用任何方式都可以,但是要把印章红色区域全部置为黑色
第三步:将印章图片与第二步合成的图片进行二次相加操作,因为在第二步已经将印章区域像素值设置为 0,所以在于印章合并的时候,黑色区域会显示成印章
第四步:将合成好的图片还原回去。
最终完整呈现的代码如下:
import cv2 as cv
def alpha2black_opencv2(img):
width, height, channels = img.shape
for yh in range(height):
for xw in range(width):
color_d = img[xw, yh]
if(color_d[3] == 0):
img[xw, yh] = [0, 0, 0, 0]
return cv.cvtColor(img, cv.COLOR_BGRA2BGR)
# 读取图片
def read_img(path):
img = cv.imread(path, -1)
print(img.shape)
dst = cv.resize(img, (130, 124))
# cv.imshow("img", dst)
# 接下来将 png 透明部分处理成黑色
ret = alpha2black_opencv2(dst)
# cv.imshow("ret", ret)
# 加载背景图
bg = cv.imread("./bg.jpeg")
# 获取目标 roi
roi = bg[300:424, 400:530]
# cv.imshow("roi",roi)
# 将印章与roi进行叠加
mask = cv.cvtColor(ret, cv.COLOR_BGR2GRAY)
# 想要得到红色印章和背景融合的图
# 获取印章的二值化图像,红色印章为纯白色
thresh, new_mask = cv.threshold(mask, 10, 255, cv.THRESH_BINARY)
# 获取反向图
mask_inv = cv.bitwise_not(new_mask)
# cv.imshow("mask_inv",mask_inv)
# 第一步:在原图中抠出印章区域,即印章区域为黑色
new_img = cv.add(roi, 1, mask = mask_inv)
# cv.imshow("new_img", new_img)
# 第二步,将抠出印章区域得到的图片与印章相加,获取到合成图
replace_img = cv.add(new_img,ret)
print(replace_img.shape)
# cv.imshow("bg", bg)
# 第三步,将合成好的图片,送回到原图
bg[300:424, 400:530] = replace_img
cv.imshow("bg",bg)
if __name__ == "__main__":
# png 透明图片路径
path = r"./18_png.png"
read_img(path)
cv.waitKey()
cv.destroyAllWindows()
两张单独的图片如下:
合成之后的效果图如下,整体效果满意,但是还是存在黑边,接下来我们还是继续研究这个东东,下篇博客见。
OpenCV 尾声
1 个小时又过去了,对 Python OpenCV 相关的知识点,你掌握了吗?
空闲之余,可以订阅橡皮擦的爬虫百例课程学习爬虫知识。
想学 Python 爬虫,可以订阅橡皮擦专栏哦~
点击发现惊喜
今天是持续写作的第 57 / 100 天。
如果你有想要交流的想法、技术,欢迎在评论区留言。
如果你想跟博主建立亲密关系,可以关注同名公众号 梦想橡皮擦,近距离接触一个逗趣的互联网高级网虫。
博主 ID:梦想橡皮擦,希望大家点赞、评论、收藏。