OpenCV 图像处理

Color Constancy - 色彩恒常

典型方法包括

  1. Static Method

    Gray world algorithm

    White Patch Retinex

    Specular highlight detection method

    Dichromatic Reflection Model

  2. Gamut mapping method

  3. Learning-Based Method
  4. ……

Gray World White Balance

灰度世界算法以灰度世界假设为基础,该假设认为:对于一幅有着大量色彩变化的图像, R,G,B三个分量的平均值趋于同一灰度值 Gray 。 从物理意义上讲,灰色世界法假设自然界景物对于光线的平均反射的均值在总体上是个定值,这个定值近似地为“灰色”。一般将这个定值设为RGB三分量的平均值. 颜色平衡算法将这一假设强制应用于待处理图像,可以从图像中消除环境光的影响,获得原始场景图像。

在OpenCV中通过createGrayworldWB函数实现.

Simple White Balance

完美反射算法假设图片中最亮的点就是一面镜子,完美地反射了外部光照,并根据这些白点进行白平衡。它定义为R+G+B的最大值。让这些白点的RGB三个通道按照比例拉伸到255,并将其他的点的三个通道按照同样比例拉伸,超过255的设为255,是一个归一化过程。

OpenCV中将完美反射的白点比例设为1%, 通过createSimpleWB函数实现.

程序代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import cv2
import numpy as np
img = cv2.imread('./blue-buildings.png')# 加载原图像
cv2.imshow("Original", img)
# grayworld WB
grayWB = cv2.xphoto.createGrayworldWB()
#grayWB.setSaturationThreshold(0.95)# 0.95 = Maximum saturation for a pixel to be included in the gray-world assumption.
imggw = grayWB.balanceWhite(img)# 计算白平衡后图像
cv2.imshow("GrayWorld WB", imggw)
# Simple WB
simpleWB = cv2.xphoto.createSimpleWB()
imgs = simpleWB.balanceWhite(img)# 计算白平衡后图像
cv2.imshow("Simple WB", imgs)
cv2.waitKey(0) #关闭窗口/键盘ESC退出
cv2.destroyAllWindows()

运行结果

原始图像

Original

Gray World WB 图像

grayworld

Simple WB 图像

simple

可以看出,针对这张照片,Gray World White Balancing算法的效果更好

Color Transfer - 色彩转换

对图像中的颜色进行判断,并通过改变值生成不同颜色的图像

需要注意,OpenCV中,HSV的范围是

1
H: [0,180] S: [0,255] V: [0,255]

与一般的颜色分布

HSV

1
H: [0,360] S: [0,100] V: [0,100]

相比做了如下变换

1
2
3
h= H/2;  
s = (float)S/100*255;
v = (float)v/100*255;

所以在OpenCV中颜色的分布如下

img

程序代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import cv2
import numpy as np
infmg=cv2.imread("lixiaolong.png",1)# flags>0,以BGR格式读入,忽略透明度的channel
cv2.imshow("Original",infmg)# 显示图像
infmg_hsv=cv2.cvtColor(infmg,cv2.COLOR_BGR2HSV)# 转换为HSV图像
rows,cols,channels=infmg.shape# 获取图像尺寸及通道(BGR三通道)
frame=infmg_hsv.copy()# 复制一个新的图像对其进行操作
# 进行色彩转换
for r in range(0,rows):# 因图中干扰色块较少,直接对整个图进行遍历,找到需要转换的像素
for c in range(0,cols):
if((frame[r,c,0]>100) and (frame[r,c,0]<124)):# 通道0为H,范围100~124为蓝色
frame[r,c,0]=frame[r,c,0]-89 # 转换为橙色 11~25
out_img=cv2.cvtColor(frame,cv2.COLOR_HSV2BGR)# 转换回BGR图像
cv2.imshow("Color Transferred Image",out_img)
cv2.waitKey(0) #关闭窗口/键盘ESC退出
cv2.destroyAllWindows()

运行结果

原始图像

第一次运行后图像

可以看出衣服上有部分蓝点未被识别为蓝色,我用颜色拾取器拾取RGB值,然后将他们转换为HSV值,发现未转换部分的颜色H值较低

改进后运行的图像

将代码中if((frame[r,c,0]>100)的阈值修改为了90,可以看出取得了较好的效果

0%