本文作为之前水下图像增强的补充,增加了所提到的不同的算法python程序,可供参考。
HE和CLAHE都可以使用opencv自带的库,不过在处理三通道图像时需要先将各个通道分离再进行直方图均衡的操作。
### HE
def he(image):
B,G,R = cv2.split(image)
B = cv2.equalizeHist(B)
G = cv2.equalizeHist(G)
R = cv2.equalizeHist(R)
result = cv2.merge((B,G,R))
return result
### HE
### CLAHE
def clahe(image,clipLimit=2.0, tileGridSize=(8, 8)):
B,G,R = cv2.split(image)
clahe = cv2.createCLAHE(clipLimit, tileGridSize)
clahe_B = clahe.apply(B)
clahe_G = clahe.apply(G)
clahe_R = clahe.apply(R)
result = cv2.merge((clahe_B,clahe_G,clahe_R))
return result
### CLAHE
defog此处是参考的暗通道去雾算法,这个作者是根据何凯明的论文编写,具体代码如下。
### defog
# reference https://www.bbsmax.com/A/MAzAEV2ez9/
def zmMinFilterGray(src, r=7):
'''最小值滤波,r是滤波器半径'''
'''if r <= 0:
return src
h, w = src.shape[:2]
I = src
res = np.minimum(I , I[[0]+range(h-1) , :])
res = np.minimum(res, I[range(1,h)+[h-1], :])
I = res
res = np.minimum(I , I[:, [0]+range(w-1)])
res = np.minimum(res, I[:, range(1,w)+[w-1]])
return zmMinFilterGray(res, r-1)'''
return cv2.erode(src, np.ones((2*r+1, 2*r+1))) #使用opencv的erode函数更高效
def guidedfilter(I, p, r, eps):
'''引导滤波,直接参考网上的matlab代码'''
height, width = I.shape
m_I = cv2.boxFilter(I, -1, (r,r))
m_p = cv2.boxFilter(p, -1, (r,r))
m_Ip = cv2.boxFilter(I*p, -1, (r,r))
cov_Ip = m_Ip-m_I*m_p
m_II = cv2.boxFilter(I*I, -1, (r,r))
var_I = m_II-m_I*m_I
a = cov_Ip/(var_I+eps)
b = m_p-a*m_I
m_a = cv2.boxFilter(a, -1, (r,r))
m_b = cv2.boxFilter(b, -1, (r,r))
return m_a*I+m_b
def getV1(m, r, eps, w, maxV1): #输入rgb图像,值范围[0,1]
'''计算大气遮罩图像V1和光照值A, V1 = 1-t/A'''
V1 = np.min(m,2) #得到暗通道图像
V1 = guidedfilter(V1, zmMinFilterGray(V1,7), r, eps) #使用引导滤波优化
bins = 2000
ht = np.histogram(V1, bins) #计算大气光照A
d = np.cumsum(ht[0])/float(V1.size)
for lmax in range(bins-1, 0, -1):
if d[lmax]<=0.999:
break
A = np.mean(m,2)[V1>=ht[1][lmax]].max()
V1 = np.minimum(V1*w, maxV1) #对值范围进行限制
return V1,A
def defog(m, r=81, eps=0.001, w=0.95, maxV1=0.80, bGamma=False):
m = m/255.0
Y = np.zeros(m.shape)
V1,A = getV1(m, r, eps, w, maxV1) #得到遮罩图像和大气光照
for k in range(3):
Y[:,:,k] = (m[:,:,k]-V1)/(1-V1/A) #颜色校正
Y = np.clip(Y, 0, 1)
if bGamma:
Y = Y**(np.log(0.5)/np.log(Y.mean())) #gamma校正,默认不进行该操作
return Y*255
### defog
MSRCR参考的是这篇博客,博客较为详细的介绍了Retinex理论,具体代码如下。文章来源:https://www.toymoban.com/news/detail-708147.html
### msrcr
# reference https://blog.csdn.net/weixin_38285131/article/details/88097771
def singleScaleRetinex(img, sigma):
retinex = np.log10(img) - np.log10(cv2.GaussianBlur(img, (0, 0), sigma))
return retinex
def multiScaleRetinex(img, sigma_list):
retinex = np.zeros_like(img)
for sigma in sigma_list:
retinex += singleScaleRetinex(img, sigma)
retinex = retinex / len(sigma_list)
return retinex
def colorRestoration(img, alpha, beta):
img_sum = np.sum(img, axis=2, keepdims=True)
color_restoration = beta * (np.log10(alpha * img) - np.log10(img_sum))
return color_restoration
def simplestColorBalance(img, low_clip, high_clip):
total = img.shape[0] * img.shape[1]
for i in range(img.shape[2]):
unique, counts = np.unique(img[:, :, i], return_counts=True)
current = 0
for u, c in zip(unique, counts):
if float(current) / total < low_clip:
low_val = u
if float(current) / total < high_clip:
high_val = u
current += c
img[:, :, i] = np.maximum(np.minimum(img[:, :, i], high_val), low_val)
return img
def MSRCR(img, sigma_list=[15, 80, 200], G=5.0, b=25.0, alpha=125.0, beta=46.0, low_clip=0.01, high_clip=0.99):
img = np.float64(img) + 1.0
img_retinex = multiScaleRetinex(img, sigma_list)
img_color = colorRestoration(img, alpha, beta)
img_msrcr = G * (img_retinex * img_color + b)
for i in range(img_msrcr.shape[2]):
img_msrcr[:, :, i] = (img_msrcr[:, :, i] - np.min(img_msrcr[:, :, i])) / \
(np.max(img_msrcr[:, :, i]) - np.min(img_msrcr[:, :, i])) * \
255
img_msrcr = np.uint8(np.minimum(np.maximum(img_msrcr, 0), 255))
img_msrcr = simplestColorBalance(img_msrcr, low_clip, high_clip)
return img_msrcr
### msrcr
如果需要在目标检测算法中使用,则对dataloader部分进行修改即可。尽量不要在训练时使用在线增强,会大大增长训练的时间,可以做离线的增强。最后附上简单的脚本对上述代码进行运用,可以对比不同算法处理图像的时长。文章来源地址https://www.toymoban.com/news/detail-708147.html
import cv2
import os
import numpy as np
import time
IMAGE = "/home/paliya/images/XXX.jpg"
RESULT = "/home/paliya/images/result/"
if __name__ == "__main__":
image = cv2.imread(IMAGE)
t = time.time()
he_image = he(image)
print("HE done! Use {}ms".format((time.time()-t)*1000))
t = time.time()
clahe_image = clahe(image)
print("CLAHE done! Use {}ms".format((time.time()-t)*1000))
t = time.time()
defog_image = defog(image)
print("Defog done! Use {}ms".format((time.time()-t)*1000))
t = time.time()
msrcr_image = MSRCR(image)
print("MSRCR done! Use {}ms".format((time.time()-t)*1000))
cv2.imwrite(RESULT+"he_XXX.jpg", he_image)
cv2.imwrite(RESULT+"clahe_XXX.jpg", clahe_image)
cv2.imwrite(RESULT+"defog_XXX.jpg", defog_image)
cv2.imwrite(RESULT+"msrcr_XXX.jpg", msrcr_image)
到了这里,关于水下图像增强程序归纳的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!