问题复现
今天写代码时,需要将图片的亮度进行调整,我是直接在读出来的 R、G、B三个通道上分别增加了一个固定的值。由于颜色值是在[0, 255]区间内的,正常来讲,即使超出了这个范围,利用 opencv 进行展示之前的合并中,也是会自动截断的。但是还是出现了颜色改变的问题。代码如下:
调整亮度的函数:
def imgeAdjustmentLightness(img) :
B, G, R = cv2.split(img)
b = copy.deepcopy(B)
g = copy.deepcopy(G)
r = copy.deepcopy(R)
for row in range(len(b)) :
for col in range(len(b[row])) :
b[row][col] = b[row][col] + 20
g[row][col] = g[row][col] + 20
r[row][col] = r[row][col] + 20
merged = cv2.merge([b, g, r])
cv2.imshow("after adjust lightness", merged)
主函数:
# -*- coding: UTF-8 -*-
import numpy as np
import cv2
import copy
# 读取图片信息
img = cv2.imread("01.bmp")
cv2.imshow("origin image", img)
imgeAdjustmentLightness(img)
cv2.waitKey(0)
改变之前的原图:
调整亮度,改变之后的图片:
可以看到,很多原来白色的地方都已经变了颜色,一猜就知道,肯定是溢出的问题,但是,为什么会发生溢出呢?为什么没有自动截断呢?
原因
原因其实很简单,因为在调整亮度,加一个特定值的时候,由于通道里的数据类型已经是 np.int8 了,也就是说只有一个子节,最大的存储值也只是 255, 当发生溢出的时候,直接从 0 开始了。。。
也就是说,还没等我们对其进行截断呢,它自己就已经限制住存储范围了。
解决方法
找到问题的原因了,解决发法也比较简单,直接在改变之前进行亮度调整就可以了。
更改调整亮度的函数为:
def imgeAdjustmentLightness(img) :
B, G, R = cv2.split(img)
b = copy.deepcopy(B)
g = copy.deepcopy(G)
r = copy.deepcopy(R)
for row in range(len(b)) :
for col in range(len(b[row])) :
if b[row][col] > 235 :
b[row][col] = 255
else :
b[row][col] = b[row][col] + 20
if g[row][col] > 235 :
g[row][col] = 255
else :
g[row][col] = g[row][col] + 20
if r[row][col] > 235 :
r[row][col] = 255
else :
r[row][col] = r[row][col] + 20
merged = cv2.merge([b, g, r])
cv2.imshow("after adjust lightness", merged)
改变之后的效果:
其实,就是在增加亮度之前就先判断一波。如果是调低亮度,也是一样的,可以在调低之前,先判断是否能够减去那个亮度的变化值,以防溢出。
调整亮度也可以直接使用 HLS 这个颜色空间,L 就代表了亮度,改变它的效果与 RGB 单通道增加特定值是一样的。但是,溢出的问题就没有这么容易解决了。所以,改变亮度的话,还是 RGB 比较方便一点。