前言
随着深度学习技术的发展,数据扩增已经成为了训练高质量模型的重要步骤之一。然而,传统的数据扩增方法往往不能完全满足需求,因此,研究人员开始探索更加高效和有效的数据扩增方法。本文将介绍一种基于retinex算法的数据扩增方法,该方法可以在不影响图像内容的前提下,提高图像的亮度、对比度和颜色饱和度等方面的表现,从而提高模型的训练效果。
retinex
基于视网膜理论公式:图像=反射率 * 亮度,我们需要的是估计亮度函数。该技术适用于高动态范围图像增强、水下图像增强、雾天图像增强和弱光图像增强。
在这里我们以下图作为原图进行图像变换:
retinex_FM实现
ini
复制代码
def retinex_FM(img,iter=4): if len(img.shape)==2: img=img[...,None] ret=np.zeros(img.shape,dtype='uint8') def update_OP(x,y): nonlocal OP IP=OP.copy() if x>0 and y==0: IP[:-x,:]=OP[x:,:]+R[:-x,:]-R[x:,:] if x==0 and y>0: IP[:,y:]=OP[:,:-y]+R[:,y:]-R[:,:-y] if x<0 and y==0: IP[-x:,:]=OP[:x,:]+R[-x:,:]-R[:x,:] if x==0 and y<0: IP[:,:y]=OP[:,-y:]+R[:,:y]-R[:,-y:] IP[IP>maximum]=maximum OP=(OP+IP)/2 for i in range(img.shape[-1]): R=np.log(img[...,i].astype('double')+1) maximum=np.max(R) OP=maximum*np.ones(R.shape) S=2**(int(np.log2(np.min(R.shape))-1)) while abs(S)>=1: #iterations is slow for k in range(iter): update_OP(S,0) update_OP(0,S) S=int(-S/2) OP=np.exp(OP) mmin=np.min(OP) mmax=np.max(OP) ret[...,i]=(OP-mmin)/(mmax-mmin)*255 return ret.squeeze()
retinex_SSR实现
ini
复制代码
def retinex_SSR(img,sigma): if len(img.shape)==2: img=img[...,None] ret=np.zeros(img.shape,dtype='uint8') for i in range(img.shape[-1]): channel=img[...,i].astype('double') S_log=np.log(channel+1) gaussian=gauss_blur(channel,sigma) #gaussian=cv2.filter2D(channel,-1,get_gauss_kernel(sigma)) #conv may be slow if size too big #gaussian=cv2.GaussianBlur(channel,(0,0),sigma) #always slower L_log=np.log(gaussian+1) r=S_log-L_log R=r #R=np.exp(r)? mmin=np.min(R) mmax=np.max(R) stretch=(R-mmin)/(mmax-mmin)*255 #linear stretch ret[...,i]=stretch return ret.squeeze()
retinex_MSR实现
ini
复制代码
def retinex_MSR(img,sigmas=[15,80,250],weights=None): '''r=∑(log(S)-log(S*G))w, MSR combines various SSR with different(or same) weights, commonly we select 3 scales(sigma) and equal weights, (15,80,250) is a good choice. If len(sigmas)=1, equal to SSR args: sigmas: a list weights: None or a list, it represents the weight for each SSR, their sum should be 1, if None, the weights will be [1/t, 1/t, ..., 1/t], t=len(sigmas) ''' if weights==None: weights=np.ones(len(sigmas))/len(sigmas) elif not abs(sum(weights)-1)<0.00001: raise ValueError('sum of weights must be 1!') ret=np.zeros(img.shape,dtype='uint8') if len(img.shape)==2: img=img[...,None] for i in range(img.shape[-1]): channel=img[...,i].astype('double') r=np.zeros_like(channel) for k,sigma in enumerate(sigmas): r+=(np.log(channel+1)-np.log(gauss_blur(channel,sigma,)+1))*weights[k] mmin=np.min(r) mmax=np.max(r) stretch=(r-mmin)/(mmax-mmin)*255 ret[...,i]=stretch return ret.squeeze()
retinex_gimp实现
ini
复制代码
def retinex_gimp(img,sigmas=[12,80,250],dynamic=2): alpha=128 gain=1 offset=0 img=img.astype('double')+1 # csum_log=np.log(np.sum(img,axis=2)) msr=MultiScaleRetinex(img-1,sigmas) #-1 r=gain*(np.log(alpha*img)-csum_log[...,None])*msr+offset mean=np.mean(r,axis=(0,1),keepdims=True) var=np.sqrt(np.sum((r-mean)**2,axis=(0,1),keepdims=True)/r[...,0].size) mmin=mean-dynamic*var mmax=mean+dynamic*var stretch=(r-mmin)/(mmax-mmin)*255 stretch[stretch>255]=255 stretch[stretch<0]=0 return stretch.astype('uint8')
retinex_MSRCR实现
ini
复制代码
def retinex_MSRCR(img,sigmas=[12,80,250],s1=0.01,s2=0.01): alpha=125 img=img.astype('double')+1 # csum_log=np.log(np.sum(img,axis=2)) msr=MultiScaleRetinex(img-1,sigmas) #-1 r=(np.log(alpha*img)-csum_log[...,None])*msr #beta=46;G=192;b=-30;r=G*(beta*r-b) #deprecated #mmin,mmax=np.min(r),np.max(r) #stretch=(r-mmin)/(mmax-mmin)*255 #linear stretch is unsatisfactory for i in range(r.shape[-1]): r[...,i]=simplest_color_balance(r[...,i],0.01,0.01) return r.astype('uint8')
retinex_MSRCP算法
ini
复制代码
def retinex_MSRCP(img,sigmas=[12,80,250],s1=0.01,s2=0.01): Int=np.sum(img,axis=2)/3 Diffs=[] for sigma in sigmas: Diffs.append(np.log(Int+1)-np.log(gauss_blur(Int,sigma)+1)) MSR=sum(Diffs)/3 Int1=simplest_color_balance(MSR,s1,s2) B=np.max(img,axis=2) A=np.min(np.stack((255/(B+eps),Int1/(Int+eps)),axis=2),axis=-1) return (A[...,None]*img).astype('uint8')
cv2_heq实现
ini
复制代码
def cv2_heq(img,yuv=False): if len(img.shape)==2: img=img[...,None] if yuv: img=cv2.cvtColor(img,cv2.COLOR_BGR2YCrCb) ret=img.copy() for i in range(img.shape[-1]): ret[...,i]=cv2.equalizeHist(img[...,i]) if yuv: break if yuv: return cv2.cvtColor(ret,cv2.COLOR_YCrCb2BGR) return ret.squeeze()
retinex_AMSR算法
ini
复制代码
def retinex_AMSR(img,sigmas=[12,80,250]): img=img.astype('double')+1 # msr=MultiScaleRetinex(img-1,sigmas,flag=False) # y=0.05 for i in range(msr.shape[-1]): v,c=np.unique((msr[...,i]*100).astype('int'),return_counts=True) sort_v_index=np.argsort(v) sort_v,sort_c=v[sort_v_index],c[sort_v_index] #plot hist zero_ind=np.where(sort_v==0)[0][0] zero_c=sort_c[zero_ind] # _=np.where(sort_c[:zero_ind]<=zero_c*y)[0] if len(_)==0: low_ind=0 else: low_ind=_[-1] _=np.where(sort_c[zero_ind+1:]<=zero_c*y)[0] if len(_)==0: up_ind=len(sort_c)-1 else: up_ind=_[0]+zero_ind+1 # low_v,up_v=sort_v[[low_ind,up_ind]]/100 #low clip value and up clip value msr[...,i]=np.maximum(np.minimum(msr[:,:,i],up_v),low_v) mmin=np.min(msr[...,i]) mmax=np.max(msr[...,i]) msr[...,i]=(msr[...,i]-mmin)/(mmax-mmin)*255 msr=msr.astype('uint8') return msr
结尾
Retinex算法在数据扩增领域的应用是十分广泛的。通过对图像的处理,我们可以得到更加清晰、明亮、自然的图像,从而提升了机器学习模型的准确度和稳定性。而且,Retinex算法的优点在于可以针对不同的图像进行不同的处理,满足了数据扩增的个性化需求。因此,在进行图像数据扩增时,Retinex算法是一种十分有效的方法,值得我们深入研究和应用。