如何用 OpenCV 制作透明渐变的蒙版?

OpenCV 可以进行一系列的图像处理,也能够直接的绘制图片,但涉及到一些复杂的图像处理时,没有现成的 API 可以使用,这个时候需要我们自己实现代码。

本文介绍如何利用现成的 API 去实现一个比较复杂,但可能比较常见的图像处理操作,那就时给图片添加一个透明渐变的效果。

大家可以看看效果图。

如何用 OpenCV 制作透明渐变的蒙版?_第1张图片

左边的图像是原始图像,右边的图像经过处理添加了一层蒙版。

需要说明的是,本文的代码基于 OpenCV3.3 和 python2.7 版本编写。

如何制作渐变效果?

我的思路是先创立一幅透明的图像,然后在透明的图像上进行像素点颜色值的操作。

如何用 OpenCV 制作透明渐变的蒙版?_第2张图片

上面右边的图像就是我创建的渐变图像,它大小与原图片一样的。

我以垂直渐变为例说明。

如何实现这样的渐变呢?

我们知道 RGB 模式下,每个颜色通道的取值范围是 0 ~ 255。

我们可以给予一个起始颜色,(255,255,0)。

然后再给定一个结束颜色,(0,0,0)。

不难发现,每个通道有颜色的差距。

渐变是有范围的,范围可以用 X 和 Y 轴上的像素距离表示。

那么,建立一个公式让距离与颜色的变化产生联系,也就不难理解。

比如,所有的 y 坐标值为 0 的像素颜色都为 (255,255,0),这个起始颜色用 color_start 表示,所有的 y 坐标值为 512 的像素颜色都为 (0,0,0),用 color_end 表示渐变结束颜色。

渐变的颜色距离 dist 是 512 - 0 = 512

每个颜色通道也有颜色变化,我们分别处理就好了。

以红色通道为例。

渐变距离是 512,颜色变化幅度是 0 - 255 = -255.

我们不难得到一个颜色变化的系数 g_r

g_r = -255 / 512 = -0.498

有了这个系数,就可以通过公式计算出相对于渐变开始的位置的每个坐标颜色值。

color_dst = color_start + dist * g_r

3 个颜色通道分别处理,就可以得到完整的渐变图像。

代码如下:

def vertical_grad(src,color_start,color_end):
    h = src.shape[0]

    print type(src)

    # 创建一幅与原图片一样大小的透明图片
    grad_img = np.ndarray(src.shape,dtype=np.uint8)

    # opencv 默认采用 BGR 格式而非 RGB 格式
    g_b = float(color_end[0] - color_start[0]) / h
    g_g = float(color_end[1] - color_start[1]) / h
    g_r = float(color_end[2] - color_start[2]) / h

    for i in range(h):
        for j in range(src.shape[1]):

                grad_img[i,j,0] = color_start[0] + i * g_b
                grad_img[i,j,1] = color_start[1] + i * g_g
                grad_img[i,j,2] = color_start[2] + i * g_r

    return grad_img

我们可以写代码测试一下。

if __name__ == '__main__':
    img = cv2.imread('../lena.jpg')
    grad_img = vertical_grad(img,(0,0,255),(0,0,0))

    cv2.imshow('lena',img)
    cv2.imshow('gradients',grad_img)

    cv2.waitKey()
    cv2.destroyAllWindows()

如何用 OpenCV 制作透明渐变的蒙版?_第3张图片

但有了渐变图像还不够,我们需要将渐变应用到原始图像当中。

OpenCV 图像混合

这个其实很简单,只要借助于 OpenCV 自带的混合方法就好了。

blend = cv2.addWeighted(img,1.0,test,0.6,0.0)

第一个参数是要混合的原始图片,第二个参数对应第一张图片的 alpha 值,第三个参数是要混合的图像,它与第一张图片的尺寸和通道都是一致的,后面的参数代表混合时,它的 alpha 取值。最后一位是 gamma 参数,默认为 0.

alpha 就是透明度的参数,在上面代码中,我让原始图片保持了 1.0 的透明度,而让它上面的渐变图像只有 0.6,最终实现了图像的混合操作。

测试代码:

img = cv2.imread('../lena.jpg')

grad_img = vertical_grad(img,(0,255,255),(0,0,0))
blend = cv2.addWeighted(img,1.0,grad_img,0.6,0.0)

cv2.imshow('lena',img)
cv2.imshow('gradients',grad_img)
cv2.imshow('blend',blend)

q = cv2.waitKey()
cv2.destroyAllWindows()

效果如下:
如何用 OpenCV 制作透明渐变的蒙版?_第4张图片

本文只讲了一个方向的渐变效果,其他方向大家可以自己思考一下,想想怎么实现,其实思路差不多。

你可能感兴趣的:(OpenCV学习笔记)