《基于直方图分布特性的水下图像颜色校正方法》论文代码复现
研究生期间研究的是水下物体检测,对于读过的文献进行了复现,以下代码皆是自己的理解和编程习惯,如有错误,请各位大佬批评指正。
建议在阅读本博客前先阅读原论文:
雷小燕,张卫东,潘细朋.基于直方图分布特性的水下图像颜色校正方法[J].计算机工程与设计,2022,43(08):2284-2293.DOI:10.16208/j.issn1000-7024.2022.08.025.
1.摘要
水下图像由于散射和吸收作用经常存在偏蓝或偏绿的颜色失真现象,为有效解决这类问题,参考陆地自然图像的直方图分布特性,从水下图像的直方图分布考虑,通过调整水下图像的直方图分布改善水下图像的颜色失真。利用具有最高均值的颜色通道自适应补偿另外两个颜色通道,利用均值和标准差动态拉伸每个颜色通道。
注意:本篇博客只复现颜色通道的自适应补偿部分,对拉伸代码不做复现,动态拉伸部分请关注后续更新。
2.本文目的
为了有效解决水下图像颜色偏色问题,本文参考陆地自然图像直方图分布特性,从水下图像直方图分布出发,通过调整水下偏色图像的直方图分布来消除偏色现象。
如下图所示,第一行为原始图像,第二行为第一行图像对应的直方图分布,其中直方图纵坐标为频率,单位为%,横坐标是数目0-255。通过图 (a)、 (b)水下偏色图像对应的直方图分布,发现水下偏色图像三通道直方图分布各异,相对比较集中,且三通道直方图之间没有相似性。通过©陆地自然图像直方图分布,发现自然图像三通道直方图分布相似且分布在整个动态围。
根据此现象我们不难看出,要想让水下的图像成像效果和陆地上的图像效果相近,起码要满足2个条件:
(1)三通道直方图分布相似;
(2)三通道直方图分布遍及整个动态范围;
为了实现这两个条件,我们先对衰减的通道进行补偿;然后对补偿后的图像进行动态拉伸,保证直方图分布遍及整个像素范围。
3.衰减通道补偿算法具体运行步骤
本文用最高像素分布均值颜色通道补偿另外两个颜色通道,因为最高像素分布均值颜色通道相对另外两个颜色通道,衰减最小,用它补偿另外两个颜色通道,能最大程度提高图像直方图分布,同时还能使另外两个颜色通道直方图分布和它相似。
(1)通道分解
把图像分解成红、绿、蓝三颜色通道。
(2)计算红、绿、蓝三颜色通道的平均值
其中,mean是均值函数,r(i,j)/ g(i,j)/ b(i,j)是上一步分解的红绿蓝三颜色通道,(i,j)是像素点,取值范围为0-255,Rmean、Gmean、Bmean是三颜色通道对应的平均值。
(3)颜色通道排序。
按照平均值高低给三颜色通道排序,分别表示为Pfirst(i,j)),Psecond(i,j),Pthird(i,j)。
(4)构建补偿因子。
本文有两个补偿因子。第一个补偿因子表示最高和第二均值分布通道之间的补偿因子;第二个补偿因子表示最高与第三均值分布通道之间的补偿因子。
(5)对第二、第三均值通道补偿。
利用补偿因子和最高均值通道,对第二和第三均值通道进行逐像素补偿,补
偿公式如下:
(6)对补偿后的三通道进行合并。
对补偿后的三通道进行合并,但是仅进行衰减通道补偿,图像效果还不理想,对应直方图分布还比较集中,没有遍及整个动态范围,因此还需要对补偿后的图像进行动态拉伸。(后续动态拉伸静等更新)
4.复现代码
本文代码使用python语言,IDE选择为pycharm。环境配置需要cv2模块和numpy模块。
import cv2
import numpy as np
image = cv2.imread("ok7.png").astype(np.float32) / 255.0
#将图像分为BGR三个颜色通道
B, G, R=cv2.split(image)
#计算蓝色通道的像素平均值
Bavg = np.mean(np.mean(B))
#计算绿色通道的像素平均值
Gavg = np.mean(np.mean(G))
#计算红色通道的像素平均值
Ravg = np.mean(np.mean(R))
# 创建颜色通道平均值的列表
means = [Bavg, Gavg, Ravg]
# 根据平均值从高到低对颜色通道进行排序
sorted_channels = [B, G, R]
sorted_channels = [x for _, x in sorted(zip(means, sorted_channels), reverse=True)]
# 将排序结果分别表示为Pfirst(i,j)、Psecond(i,j)、Pthird(i,j)
Pfirst = sorted_channels[0]#平均值最大的颜色通道
Psecond = sorted_channels[1]
Pthird = sorted_channels[2]#平均值最小的颜色通道,此时的通道是二维数组
#计算补偿因子a,b
a = (np.mean(Pfirst) - np.mean(Psecond))/(np.mean(Pfirst) + np.mean(Psecond))
b = (np.mean(Pfirst) - np.mean(Pthird))/(np.mean(Pfirst) + np.mean(Pthird))
# 对第二均值通道进行逐像素补偿
Psecond_compensated = Psecond + a * Pfirst
# # 对第三均值通道进行逐像素补偿
Pthird_compensated = Pthird + b * Pfirst
#将三个通道(第一均值颜色通道,补偿后的第二、三均值分布通道)进行组合
merged_image = np.dstack((Pfirst, Psecond_compensated, Pthird_compensated))
#为了观察到每一步的运行是否出错,这里将三个原始通道的二维数组统统打印出来
print("B", B)
print("G", G)
print("R", R)
#展示原始图像和三通道图像,便于后续观察步骤的运行和最终变化
cv2.imshow("original_image",image)
cv2.imshow("B",B)
cv2.imshow("G",G)
cv2.imshow("R",R)
#打印计算出的三个通道的均值和标准差
print("Bavg", Bavg)
print("Gavg", Gavg)
print("Ravg", Ravg)
#打印计算出的补偿因子的数
print("a", a)
print("b", b)
#打印补偿后的通道数组排列和合并之后图像的二维数组排列
print("Gafter", Psecond_compensated)
print("Rafter", Pthird_compensated)
print("merged_image", merged_image)
#展示补偿后的各个图像
cv2.imshow("Gafter", Psecond_compensated)
cv2.imshow("Rafter", Pthird_compensated)
cv2.imshow("merge_image", merged_image)
#等待按键,结束本次服务
cv2.waitKey()
cv2.destroyAllWindows()
*5.运行效果
BGR三通道分解后的图片如图所示:
对第二第三通道补偿后的图像:
原图像和合并后的最终图像对比:
根据原图像和颜色补偿合并后的最终图像对比可以看出,由于阳光衰减造成的水下图像偏绿色现象已经被完全的解决,但是图像还是出现色偏,整体偏紫色、红色,需要进一步的动态拉伸才能完全将颜色校正。
笔记至此已经结束,欢迎大家讨论指点,如有侵权,联系速删。