2000字范文,分享全网优秀范文,学习好帮手!
2000字范文 > python-opencv五种自动白平衡算法 附源码直接可用(均值 完美反射 灰度世界 动态

python-opencv五种自动白平衡算法 附源码直接可用(均值 完美反射 灰度世界 动态

时间:2019-03-12 15:55:08

相关推荐

python-opencv五种自动白平衡算法 附源码直接可用(均值 完美反射 灰度世界 动态

最近研究了自动白平衡的几种方法,参考了不少,最为感谢python opencv白平衡算法(但是这篇文章提供的算法没有考虑到uint8格式问题,产生了图像的局部失真,这里做了改进):(<-原图,失真图->)

谈谈总体理解:

(本来目标是同一张图,无论在什么样子的滤镜、光照下最后白平衡结果要尽可能相同,最后发现都太难了)

1.均值、灰度世界都建立一种计算平均的算法基础上,适用于色彩分布比较全面平均的场景,其实在很多场合都不适用

2.完美反射、动态阈值建立在白点的基础上,比如完美反射认为最亮的点为白点,以白点为基础进行整体的调节,导致的问题在于如果整张图没有白点算法效果非常不好,其次,由于不同色温下白点所呈现的数值差异性很大,导致白平衡结果不尽如人意。且Ratio的选取也有效果差异。还有一种做法是固定某一区域为白色区域然后算法计算,延展全图,效果展示使用uint8格式时一定要注意的问题(python-opencv完美反射白平衡算法)

3.基于图像分析的偏色检测及颜色校正,看了这篇原文,感觉整体意思是提供一种偏色检测的做法,然后还是采用基于完美反射、灰度世界的改进算法进行白平衡,效果同样局限。

结果展示,在不同的场景下每种白平衡结果都有不同,没有通用性的最好算法:

第一张: 原图第二张:均值白平衡法第三张: 完美反射第四张: 灰度世界假设第五张: 基于图像分析的偏色检测及颜色校正方法第六张: 动态阈值算法

源码:

import cv2import numpy as npimport randomdef white_balance_1(img):'''第一种简单的求均值白平衡法:param img: cv2.imread读取的图片数据:return: 返回的白平衡结果图片数据'''# 读取图像r, g, b = cv2.split(img)r_avg = cv2.mean(r)[0]g_avg = cv2.mean(g)[0]b_avg = cv2.mean(b)[0]# 求各个通道所占增益k = (r_avg + g_avg + b_avg) / 3kr = k / r_avgkg = k / g_avgkb = k / b_avgr = cv2.addWeighted(src1=r, alpha=kr, src2=0, beta=0, gamma=0)g = cv2.addWeighted(src1=g, alpha=kg, src2=0, beta=0, gamma=0)b = cv2.addWeighted(src1=b, alpha=kb, src2=0, beta=0, gamma=0)balance_img = cv2.merge([b, g, r])return balance_imgdef white_balance_2(img_input):'''完美反射白平衡STEP 1:计算每个像素的R\G\B之和STEP 2:按R+G+B值的大小计算出其前Ratio%的值作为参考点的的阈值TSTEP 3:对图像中的每个点,计算其中R+G+B值大于T的所有点的R\G\B分量的累积和的平均值STEP 4:对每个点将像素量化到[0,255]之间依赖ratio值选取而且对亮度最大区域不是白色的图像效果不佳。:param img: cv2.imread读取的图片数据:return: 返回的白平衡结果图片数据'''img = img_input.copy()b, g, r = cv2.split(img)m, n, t = img.shapesum_ = np.zeros(b.shape)for i in range(m):for j in range(n):sum_[i][j] = int(b[i][j]) + int(g[i][j]) + int(r[i][j])hists, bins = np.histogram(sum_.flatten(), 766, [0, 766])Y = 765num, key = 0, 0ratio = 0.01while Y >= 0:num += hists[Y]if num > m * n * ratio / 100:key = YbreakY = Y - 1sum_b, sum_g, sum_r = 0, 0, 0time = 0for i in range(m):for j in range(n):if sum_[i][j] >= key:sum_b += b[i][j]sum_g += g[i][j]sum_r += r[i][j]time = time + 1avg_b = sum_b / timeavg_g = sum_g / timeavg_r = sum_r / timemaxvalue = float(np.max(img))# maxvalue = 255for i in range(m):for j in range(n):b = int(img[i][j][0]) * maxvalue / int(avg_b)g = int(img[i][j][1]) * maxvalue / int(avg_g)r = int(img[i][j][2]) * maxvalue / int(avg_r)if b > 255:b = 255if b < 0:b = 0if g > 255:g = 255if g < 0:g = 0if r > 255:r = 255if r < 0:r = 0img[i][j][0] = bimg[i][j][1] = gimg[i][j][2] = rreturn imgdef white_balance_3(img):'''灰度世界假设:param img: cv2.imread读取的图片数据:return: 返回的白平衡结果图片数据'''B, G, R = np.double(img[:, :, 0]), np.double(img[:, :, 1]), np.double(img[:, :, 2])B_ave, G_ave, R_ave = np.mean(B), np.mean(G), np.mean(R)K = (B_ave + G_ave + R_ave) / 3Kb, Kg, Kr = K / B_ave, K / G_ave, K / R_aveBa = (B * Kb)Ga = (G * Kg)Ra = (R * Kr)for i in range(len(Ba)):for j in range(len(Ba[0])):Ba[i][j] = 255 if Ba[i][j] > 255 else Ba[i][j]Ga[i][j] = 255 if Ga[i][j] > 255 else Ga[i][j]Ra[i][j] = 255 if Ra[i][j] > 255 else Ra[i][j]# print(np.mean(Ba), np.mean(Ga), np.mean(Ra))dst_img = np.uint8(np.zeros_like(img))dst_img[:, :, 0] = Badst_img[:, :, 1] = Gadst_img[:, :, 2] = Rareturn dst_imgdef white_balance_4(img):'''基于图像分析的偏色检测及颜色校正方法:param img: cv2.imread读取的图片数据:return: 返回的白平衡结果图片数据'''def detection(img):'''计算偏色值'''img_lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)l, a, b = cv2.split(img_lab)d_a, d_b, M_a, M_b = 0, 0, 0, 0for i in range(m):for j in range(n):d_a = d_a + a[i][j]d_b = d_b + b[i][j]d_a, d_b = (d_a / (m * n)) - 128, (d_b / (n * m)) - 128D = np.sqrt((np.square(d_a) + np.square(d_b)))for i in range(m):for j in range(n):M_a = np.abs(a[i][j] - d_a - 128) + M_aM_b = np.abs(b[i][j] - d_b - 128) + M_bM_a, M_b = M_a / (m * n), M_b / (m * n)M = np.sqrt((np.square(M_a) + np.square(M_b)))k = D / Mprint('偏色值:%f' % k)returnb, g, r = cv2.split(img)# print(img.shape)m, n = b.shape# detection(img)I_r_2 = np.zeros(r.shape)I_b_2 = np.zeros(b.shape)sum_I_r_2, sum_I_r, sum_I_b_2, sum_I_b, sum_I_g = 0, 0, 0, 0, 0max_I_r_2, max_I_r, max_I_b_2, max_I_b, max_I_g = int(r[0][0] ** 2), int(r[0][0]), int(b[0][0] ** 2), int(b[0][0]), int(g[0][0])for i in range(m):for j in range(n):I_r_2[i][j] = int(r[i][j] ** 2)I_b_2[i][j] = int(b[i][j] ** 2)sum_I_r_2 = I_r_2[i][j] + sum_I_r_2sum_I_b_2 = I_b_2[i][j] + sum_I_b_2sum_I_g = g[i][j] + sum_I_gsum_I_r = r[i][j] + sum_I_rsum_I_b = b[i][j] + sum_I_bif max_I_r < r[i][j]:max_I_r = r[i][j]if max_I_r_2 < I_r_2[i][j]:max_I_r_2 = I_r_2[i][j]if max_I_g < g[i][j]:max_I_g = g[i][j]if max_I_b_2 < I_b_2[i][j]:max_I_b_2 = I_b_2[i][j]if max_I_b < b[i][j]:max_I_b = b[i][j][u_b, v_b] = np.matmul(np.linalg.inv([[sum_I_b_2, sum_I_b], [max_I_b_2, max_I_b]]), [sum_I_g, max_I_g])[u_r, v_r] = np.matmul(np.linalg.inv([[sum_I_r_2, sum_I_r], [max_I_r_2, max_I_r]]), [sum_I_g, max_I_g])# print(u_b, v_b, u_r, v_r)b0, g0, r0 = np.zeros(b.shape, np.uint8), np.zeros(g.shape, np.uint8), np.zeros(r.shape, np.uint8)for i in range(m):for j in range(n):b_point = u_b * (b[i][j] ** 2) + v_b * b[i][j]g0[i][j] = g[i][j]# r0[i][j] = r[i][j]r_point = u_r * (r[i][j] ** 2) + v_r * r[i][j]if r_point>255:r0[i][j] = 255else:if r_point<0:r0[i][j] = 0else:r0[i][j] = r_pointif b_point>255:b0[i][j] = 255else:if b_point<0:b0[i][j] = 0else:b0[i][j] = b_pointreturn cv2.merge([b0, g0, r0])def white_balance_5(img):'''动态阈值算法算法分为两个步骤:白点检测和白点调整。只是白点检测不是与完美反射算法相同的认为最亮的点为白点,而是通过另外的规则确定:param img: cv2.imread读取的图片数据:return: 返回的白平衡结果图片数据'''b, g, r = cv2.split(img)"""YUV空间"""def con_num(x):if x > 0:return 1if x < 0:return -1if x == 0:return 0yuv_img = cv2.cvtColor(img, cv2.COLOR_BGR2YCrCb)(y, u, v) = cv2.split(yuv_img)# y, u, v = cv2.split(img)m, n = y.shapesum_u, sum_v = 0, 0max_y = np.max(y.flatten())# print(max_y)for i in range(m):for j in range(n):sum_u = sum_u + u[i][j]sum_v = sum_v + v[i][j]avl_u = sum_u / (m * n)avl_v = sum_v / (m * n)du, dv = 0, 0# print(avl_u, avl_v)for i in range(m):for j in range(n):du = du + np.abs(u[i][j] - avl_u)dv = dv + np.abs(v[i][j] - avl_v)avl_du = du / (m * n)avl_dv = dv / (m * n)num_y, yhistogram, ysum = np.zeros(y.shape), np.zeros(256), 0radio = 0.5 # 如果该值过大过小,色温向两极端发展for i in range(m):for j in range(n):value = 0if np.abs(u[i][j] - (avl_u + avl_du * con_num(avl_u))) < radio * avl_du or np.abs(v[i][j] - (avl_v + avl_dv * con_num(avl_v))) < radio * avl_dv:value = 1else:value = 0if value <= 0:continuenum_y[i][j] = y[i][j]yhistogram[int(num_y[i][j])] = 1 + yhistogram[int(num_y[i][j])]ysum += 1# print(yhistogram.shape)sum_yhistogram = 0# hists2, bins = np.histogram(yhistogram, 256, [0, 256])# print(hists2)Y = 255num, key = 0, 0while Y >= 0:num += yhistogram[Y]if num > 0.1 * ysum: # 取前10%的亮点为计算值,如果该值过大易过曝光,该值过小调整幅度小key = YbreakY = Y - 1# print(key)sum_r, sum_g, sum_b, num_rgb = 0, 0, 0, 0for i in range(m):for j in range(n):if num_y[i][j] > key:sum_r = sum_r + r[i][j]sum_g = sum_g + g[i][j]sum_b = sum_b + b[i][j]num_rgb += 1avl_r = sum_r / num_rgbavl_g = sum_g / num_rgbavl_b = sum_b / num_rgbfor i in range(m):for j in range(n):b_point = int(b[i][j]) * int(max_y) / avl_bg_point = int(g[i][j]) * int(max_y) / avl_gr_point = int(r[i][j]) * int(max_y) / avl_rif b_point>255:b[i][j] = 255else:if b_point<0:b[i][j] = 0else:b[i][j] = b_pointif g_point>255:g[i][j] = 255else:if g_point<0:g[i][j] = 0else:g[i][j] = g_pointif r_point>255:r[i][j] = 255else:if r_point<0:r[i][j] = 0else:r[i][j] = r_pointreturn cv2.merge([b, g, r])'''img : 原图img1:均值白平衡法img2: 完美反射img3: 灰度世界假设img4: 基于图像分析的偏色检测及颜色校正方法img5: 动态阈值算法'''img = cv2.imread('./dataset/1/3.JPG')# img = cv2.imread('./dataset/2/1_'+str(i)+'.JPG')img1 = white_balance_1(img)img2 = white_balance_2(img)img3 = white_balance_3(img)img4 = white_balance_4(img)img5 = white_balance_5(img)print('----------------------')img_stack = np.vstack([img,img1,img2,img3,img4,img5])# cv2.imwrite("./dataset/"+str(i)+'.JPG',img_stack)cv2.imshow('image',img_stack)cv2.waitKey(0)

python-opencv五种自动白平衡算法 附源码直接可用(均值 完美反射 灰度世界 动态阈值 基于图像分析的偏色检测及颜色校正)

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。