最近,在进行图像处理时候,拿到了用 adobe photoshop 处理的 png 图片, 当我用 ubuntu 电脑打开该图片的时候,就发现了图片出现了如下的阴影,查阅了资料才发现原来是因为在使用 adobe photoshop 设计图片的时候背景内容选择透明背景的原因,如果想要避免还要用代码进一步进行判断和处理,可以在生成图片的时候修改背景色为白色等.
我在缩小该图片的时候发现图片全是黑色的,本以为没什么,但是后来在同事的指点下,发现这个问题是可以解决的,只要造成这个问题是因为导入的 png 图片包含了 alpha 通道,而我在读取该图片的时候没有进行相应的正确处理导致的.
所以,我们先来大概了解下图像的 alpha 通道.
(1) Alpha通道,范围0-1,用来存储这个像素点的透明度
(2 ) 真正让图片变透明的不是A lpha 实际是 Alpha 所代表的数值和其他数值做了一次运算
(3) Alpha 通道使用8位二进制数,就可以表示256级灰度,即256级的透明度。白色(值为255)的 Alpha 像素用以定义不透明的彩色像素,而黑色(值为0)的 Alpha 通道像素用以定义透明像素,介于黑白之间的灰度(值为0-255)的 Alpha 像素用以定义不同程度的半透明像素。
(4) 将图片 a 绘制到另一幅图片 b 上,如果图片 a 没有 alpha 通道,那么就会完全将 b 图片的像素给替换掉。而如果有 alpha 通道,那么最后覆盖的结果值将是 c = a * alpha + b * (1 - alpha)
参考资料: https://www.cnblogs.com/suogasus/p/5311264.html https://blog.csdn.net/woniuye/article/details/89218461
在了解了基本知识后,我查阅了很多资料想把 RGBA 图片抓换成 RGB 图片,看了很多都是使用图片库自带的图片类型转换库,比如 PIL 的 Image.open(img_path).convert(
'RGBA') 类似代码或者opencv使用 cv2.cvtColor(image, cv2.COLOR_RGBA2BGR) ,但是都不是我想要和效果,后来终于找到了正确的解决方法。
参考资料: https://stackoverflow.com/questions/50331463/convert-rgba-to-rgb-in-python
代码:
1 import cv2
2 import numpy as np
3 import matplotlib.pyplot as plt
4
5
6 def rgba2rgb(rgba, background=(255, 255, 255)):
7 row, col, ch = rgba.shape
8
9 if ch == 3:
10 return rgba
11
12 assert ch == 4, 'RGBA image has 4 channels.'
13
14 # 生成一个三维画布图片
15 rgb = np.zeros((row, col, 3), dtype='float32')
16
17 # 获取图片每个通道数据
18 r, g, b, a = rgba[:, :, 0], rgba[:, :, 1], rgba[:, :, 2], rgba[:, :, 3]
19
20 # 把 alpha 通道的值转换到 0-1 之间
21 a = np.asarray(a, dtype='float32') / 255.0
22
23 # 得到想要生成背景图片每个通道的值
24 R, G, B = background
25
26 # 将图片 a 绘制到另一幅图片 b 上,如果有 alpha 通道,那么最后覆盖的结果值将是 c = a * alpha + b * (1 - alpha)
27 rgb[:, :, 0] = r * a + (1.0 - a) * R
28 rgb[:, :, 1] = g * a + (1.0 - a) * G
29 rgb[:, :, 2] = b * a + (1.0 - a) * B
30
31 # 把最终数据类型转换成 uint8
32 return np.asarray(rgb, dtype='uint8')
33
34
35 image_name_have_alpha = "huaxiao/tuxinghuaxiao/img/剪刀/0.png"
36
37 image_have_alpha = cv2.imread(image_name_have_alpha, cv2.IMREAD_UNCHANGED)
38 # 使用opencv自带的库把BGRA图片转换成BGR图片(注意,opencv读取进去的图片格式是 BGR)
39 image_have_alpha_convert_bgr1 = cv2.cvtColor(image_have_alpha, cv2.COLOR_RGBA2BGR)
40 # 使用自己的函数把BGRA图片转换成BGR图片,背景色设置为白色
41 image_have_alpha_convert_bgr2 = rgba2rgb(image_have_alpha)
42 # 使用自己的函数把BGRA图片转换成BGR图片,背景色设置为蓝色
43 image_have_alpha_convert_bgr3 = rgba2rgb(image_have_alpha, background=(0, 0, 255))
44 plt.figure()
45 plt.subplot(2, 2, 1), plt.title("original image"), plt.imshow(image_have_alpha, "gray")
46 plt.subplot(2, 2, 2), plt.title("use function of cv2"), plt.imshow(image_have_alpha_convert_bgr1, "gray")
47 plt.subplot(2, 2, 3), plt.title("use function of myself"), plt.imshow(image_have_alpha_convert_bgr2, "gray")
48 plt.subplot(2, 2, 4), plt.title("use function of myself"), plt.imshow(image_have_alpha_convert_bgr3, "gray")
49 plt.show()
结果如下:
就这样解决了我的实际问题,不知道我说得全不全,如果大家觉得有什么不恰当的地方,欢迎指正和批评。