喂~ 办章吗?Python OpenCV 互联网+ 项目,图像处理取经之旅第 18 天

今天学习的目标依旧是研究图像的合成,重点还是在 ROI 与掩膜相关知识

本文的最终目标,把下面这个章扣在任意图片上,当然你可以把这个章更换成任意的,例如发票章。

20210117190946120[1].png

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,所以修改该值即可。

运行效果截图:

20210117212525594[1].png

如果你还有疑问,可以这样进行测试。

获取任意透明部分的像素颜色值,或者获取任意有颜色部分像素值。

透明部分的值为:[ 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() 写入到文件中,才可查看效果。

20210117212042707[1].png

加载待盖章图片

加载背景图,并且在背景图上找到 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()

两张单独的图片如下:


20210117220543591[1].png

合成之后的效果图如下,整体效果满意,但是还是存在黑边,接下来我们还是继续研究这个东东,下篇博客见。

20210117220600449[1].png

OpenCV 尾声

1 个小时又过去了,对 Python OpenCV 相关的知识点,你掌握了吗?

空闲之余,可以订阅橡皮擦的爬虫百例课程学习爬虫知识。

想学 Python 爬虫,可以订阅橡皮擦专栏哦~ 点击发现惊喜


今天是持续写作的第 57 / 100 天。
如果你有想要交流的想法、技术,欢迎在评论区留言。


如果你想跟博主建立亲密关系,可以关注同名公众号 梦想橡皮擦,近距离接触一个逗趣的互联网高级网虫。
博主 ID:梦想橡皮擦,希望大家点赞评论收藏

你可能感兴趣的:(喂~ 办章吗?Python OpenCV 互联网+ 项目,图像处理取经之旅第 18 天)