本文已参与「新人创作礼」活动,一起开启掘金创作之路。
想做图像的色偏检测,网上的资料全是同一套代码,就是2013年那个计算等价圆,然后直接用D-r>9 and K>0.6) or K>1.5,判断的代码(相信大家都查到过了)
但是色偏问题并不是这样简单的判断就可以的,还分为本质色偏和真实色偏,比如草地或天空的图像,本来就应该偏绿和偏蓝,那么就是本质色偏,不是真正的色偏。
然后我就找相关论文来看了,发现在这块的研究其实也不多,基本上就是重庆大学和武汉理工大学有硕士做相关研究,所以看了看他们的硕士论文,然后自己实现了2017年武汉理工那篇硕士论文。
第一次看到论文里写NNO区域我是懵逼的,查博客也没有相关的介绍,更别提怎么提取NNO的代码了,本着自利利他的原则,我还是开启下这里的空白吧!
NNO区域介绍
NNO全称near neutral objects,代表无色差表面,就是图像中本质色为白色或灰色的表面。
为什么要提取NNO区域做色偏检测呢,因为白色区域的表现色有效反应了图像的整体颜色,所以一般做法是根据原图像的等效圆参数与NNO区域的等效圆参数进行对比,利用变化趋势去判断图像是否偏色。
NNO区域提取步骤
1、此论文为了提高计算速率,首先将图像进行分块,可以大大缩短计算时间。
2、此论文提出一种自适应提取NNO区域的方法,按基于空间汇集策略的等效圆计算方法,完成分块、颜色空间转换、标记暗色块,计算得到等效圆圆心和半径
def NNO(h, w, image):
m, n = 64, 64 # 划分为64*64的块
h_new = h-(h%m)
w_new = w-(w%n)
image = image[0:h_new,0:w_new]
block_h = h_new//m
block_w = w_new//n
averaged = block(block_h,block_w,image, m, n)
lab = cv2.cvtColor(averaged,cv2.COLOR_BGR2LAB)
l,a,b = cv2.split(lab)
h, w = l.shape
l1 = (l/255*100).astype(np.uint8)
L_area = np.zeros((h,w))
L_area[np.where(l1>=20)and np.where(l1<=95)] = 1
abvalue = np.zeros((m,n))
for i in range(m):
for j in range(n):
aij = (a[i,j]-128)*(a[i,j]-128)
bij = (b[i,j]-128)*(b[i,j]-128)
abvalue[i,j] = math.sqrt(aij*aij+bij*bij)
F = abvalue.sum()
T = 0
for i in range(m):
for j in range(n):
T += ((F-abvalue[i,j])/((m*n-1)*F))*abvalue[i,j]
T = 1/2 * T
mask = np.zeros((h,w))
mask[np.where(abvalue<T)] = 1
NNO = L_area * mask
image_copy = copy.deepcopy(averaged)
image_copy[np.where(NNO!=1)] = 0
lab_nno = cv2.cvtColor(image_copy,cv2.COLOR_BGR2LAB)
l_nno, a_nno,b_nno = cv2.split(lab_nno)
u,D_sigma,sigma = DKr(a, b, m, n)
u_nno,D_sigma_nno,sigma_nno = DKr(a_nno,b_nno, m, n)
try:
D_sigma_cr = (D_sigma - D_sigma_nno)/D_sigma
u_cr = (u - u_nno)/u
sigma_cr = (sigma - sigma_nno)/sigma
except:
if D_sigma == 0:
D_sigma_cr = 0
if u == 0:
u_cr = 0
if sigma == 0:
sigma_cr = 0
return D_sigma_cr, u_cr, sigma_cr,D_sigma_nno
全部代码
写在了我的github
如果对你有帮助,可以给个star~~~
复现数据不能保证和原文一模一样,但是测试结果还是可以的。