【低照度图像增强系列(2)】Retinex(SSR/MSR/MSRCR)算法详解与代码实现

前言 

 ☀️ 在低照度场景下进行目标检测任务,常存在图像RGB特征信息少提取特征困难目标识别和定位精度低等问题,给检测带来一定的难度。

     🌻使用图像增强模块对原始图像进行画质提升,恢复各类图像信息,再使用目标检测网络对增强图像进行特定目标检测,有效提高检测的精确度。

      ⭐本专栏会介绍传统方法、Retinex、EnlightenGAN、SCI、Zero-DCE、IceNet、RRDNet、URetinex-Net等低照度图像增强算法。

👑完整代码已打包上传至资源→低照度图像增强代码汇总资源-CSDN文库

目录

前言 

🚀一、Retinex简介

🚀二、Retinex原理

🚀三、基于Retinex理论的增强算法

🎄3.1 SSR(Single Scale Retinex)单尺度Retinex算法

简介 

原理

代码实现

🎄3.2 多尺度MSR(Multi-Scale Retinex)多尺度Retinex算法

 简介 

原理

代码实现

🎄3.3 MSRCR(Multi-Scale Retinex with Color Restoration)具有色彩恢复的多尺度Retinex算法

 简介  

原理

代码实现 

🚀总结

🚀整体代码


🚀一、Retinex简介

Retinex是Edwin.H.Land于1963年提出的算法。该算法认为人眼可以感知近似一致的色彩信息,这种性质称为色彩恒定性。这种恒定性是视网膜(Retina)与大脑皮层(Cortex)所共同作用的结果。常见的算法包括:单尺度Retinex(SSR)算法多尺度Retinex(MSR)算法色彩恢复多尺度Retinex(MSRCR)算法,MSRCR算法是对SSR算法及MSR算法进行修正的一种算法。

物体的颜色是由物体对长波(红色)中波(绿色)短波(蓝色)光线的反射能力来决定的,而不是由反射光强度的绝对值来决定的,物体的色彩不受光照非均匀性的影响,具有一致性,即Retinex是以色感一致性(颜色恒常性)为基础的。

不同于传统的线性、非线性的只能增强图像某一类特征的方法,Retinex可以在动态范围压缩、边缘增强颜色恒常三个方面达到平衡,因此可以对各种不同类型的图像进行自适应的增强。

发展历程: 


🚀二、Retinex原理

  • 基本思想:去除照射光影响,保留物体自身的反射属性。
  • 核心思想:保留图像细节信息的前提下,调整图像的对比度和亮度。

Retinex算法认为图像I(x, y)是由照度图像反射图像组成。

  • 前者指的是物体的入射分量的信息,用L(x, y) 表示;
  • 后者指的是物体的反射部分,用R(x, y) 表示。

公式:

I(x, y) =R(x, y) * L(x, y)

式中: I(x,y)代表被观察或照相机接收到的图像信号;L(x,y)代表环境光的照射分量 ;R(x,y)表示携带图像细节信息的目标物体的反射分量 。 

同时,由于对数形式与人类在感受亮度的过程属性最相近,因此将上述过程转换到对数域进行处理,这样做也将复杂的乘法转换为加法: i(x, y) = r(x, y) + l(x, y)


🚀三、基于Retinex理论的增强算法

🎄3.1 SSR(Single Scale Retinex)单尺度Retinex算法

简介 

SSR (Singal Scale Retinex),即单尺度视网膜算法是 Retinex 算法中最基础的一个算法。运用的就是上面的方法,具体步骤如下:

  1. 输入原始图像 I(x,y) 和滤波的半径范围 sigma;
  2. 计算原始图像 I(x,y) 高斯滤波后的结果,得到 L(x,y);
  3. 按照公式计算,得到 Log[R(x,y)];
  4. 将得到的结果量化为 [0, 255] 范围的像素值,然后输出结果图像。 

原理

图像I(x,y)可以看做是入射图像(也有人称之为亮度图像)L(x,y)反射图像R(x,y)构成,入射光照射在反射物体上,通过反射物体的反射,形成反射光进入人眼。其原理图如下所示:

 

最后形成的图像可以如下公式表示:

等式两边取对数得:

L(x,y)由I(x,y)和一个高斯核的卷积来近似表示:

上式中*代表卷积,G(x,y)代表高斯核。

最后,将Log(R(x,y))量化为0-255范围的像素值:


代码实现

# SSR
import cv2
import numpy as npdef replaceZeroes(data):min_nonzero = np.min(data[np.nonzero(data)])  # 找到数组中最小的非零值data = np.where(data == 0, min_nonzero, data)  # 将数组中的零值替换为最小的非零值return data  # 返回替换后的数组def SSR(src_img, size):L_blur = cv2.GaussianBlur(src_img, (size, size), 0)  # 高斯函数img = replaceZeroes(src_img)  # 去除0  L_blur = replaceZeroes(L_blur)  # 去除0dst_Img = cv2.log(img / 255.0)  # 归一化取logdst_Lblur = cv2.log(L_blur / 255.0)  # 归一化取logdst_IxL = cv2.multiply(dst_Img, dst_Lblur)  # 乘  L(x,y)=S(x,y)*G(x,y)log_R = cv2.subtract(dst_Img, dst_IxL)  # 减  log(R(x,y))=log(S(x,y))-log(L(x,y))dst_R = cv2.normalize(log_R, None, 0, 255, cv2.NORM_MINMAX)  # 放缩到0-255log_uint8 = cv2.convertScaleAbs(dst_R)  # 取整return log_uint8def SSR_image(image):size = 3b_gray, g_gray, r_gray = cv2.split(image)  # 拆分三个通道# 分别对每一个通道进行 SSRb_gray = SSR(b_gray, size)g_gray = SSR(g_gray, size)r_gray = SSR(r_gray, size)result = cv2.merge([b_gray, g_gray, r_gray])  # 通道合并。return resultif __name__ == "__main__":input_img = cv2.imread('img_1.png', cv2.IMREAD_COLOR)  # 读取输入图像enhanced_img = SSR_image(input_img)  # 调用 SSR 函数得到增强后的图像cv2.imwrite('img_2.png', enhanced_img)  # 将增强后的图像保存为 img_2.png# 显示原始图像和增强后的图像cv2.imshow('Original Image', input_img)cv2.imshow('Enhanced(SSR) Image', enhanced_img)cv2.waitKey(0)cv2.destroyAllWindows()
  • 实现效果:
 
  •  参数调整:

主要调整是高斯模糊: 

L_blur = cv2.GaussianBlur(src_img, (size, size), 0) 
  • src_img: 是输入图像,即要进行高斯模糊的图像。
  • (size,size): 是高斯核的大小,其中 size 是一个正整数。高斯核的大小决定了模糊的程度,size 越大,模糊程度越高。
  • 0 :是高斯核的标准差,在 x 方向上。如果这个值为 0,则会根据高斯核的大小自动计算。

🎄3.2 多尺度MSR(Multi-Scale Retinex)多尺度Retinex算法

 简介 

MSR (Multi-Scale Retinex),即多尺度视网膜算法是在 SSR 算法的基础上提出的,采用多个不同的 sigma 值,然后将最后得到的不同结果进行加权取值。 

优点是可以保持图像高保真度与对图像的动态范围进行压缩的同时,MSR也可实现色彩增强、颜色恒常性、局部动态范围压缩、全局动态范围压缩,也可以用于X光图像增强


原理

对原始图像进行每个尺度的高斯滤波,得到模糊后的图像Li(x,y),其中小标i表示尺度数

然后对每个尺度下进行累加计算:

其中Weight(i)表示每个尺度对应的权重,要求各尺度权重之和必须为1,经典的取值为等权重。

基本的计算原理:

上式中,I为原始输入图像,G是滤波函数,一般为高斯函数,N为尺度的数量,W为每个尺度的权重,一般都为1/N, R表示在对数域的图像的输出。


代码实现

# MSR
import numpy as np
import cv2def replaceZeroes(data):min_nonzero = min(data[np.nonzero(data)])data[data == 0] = min_nonzeroreturn datadef MSR(img, scales):weight = 1 / 3.0scales_size = len(scales)h, w = img.shape[:2]log_R = np.zeros((h, w), dtype=np.float32)for i in range(scales_size):img = replaceZeroes(img)L_blur = cv2.GaussianBlur(img, (scales[i], scales[i]), 0)L_blur = replaceZeroes(L_blur)dst_Img = cv2.log(img / 255.0)dst_Lblur = cv2.log(L_blur / 255.0)dst_Ixl = cv2.multiply(dst_Img, dst_Lblur)log_R += weight * cv2.subtract(dst_Img, dst_Ixl)dst_R = cv2.normalize(log_R, None, 0, 255, cv2.NORM_MINMAX)log_uint8 = cv2.convertScaleAbs(dst_R)return log_uint8if __name__ == '__main__':img = 'img_1.png'scales = [15, 101, 301] #可调整的位置src_img = cv2.imread(img)b_gray, g_gray, r_gray = cv2.split(src_img)b_gray = MSR(b_gray, scales)g_gray = MSR(g_gray, scales)r_gray = MSR(r_gray, scales)result = cv2.merge([b_gray, g_gray, r_gray])cv2.imshow('Original Image', src_img)cv2.imshow('Enhanced(MSR) Image', result)cv2.waitKey(0)cv2.destroyAllWindows()
  •  实现效果:

(尺度因子为(15,101,301)时) 

(尺度因子为(3,5,9)时)  


  •   参数调整:

 主要调整是尺度因子: 

    scales = [3, 5, 9] #可调整的位置

🎄3.3 MSRCR(Multi-Scale Retinex with Color Restoration)具有色彩恢复的多尺度Retinex算法

 简介  

在以上的两幅测试图像中,特别是第二幅,我们看到明显的偏色效果,这就是SSR和MSR普遍都存在的问题。

为此,研究者又开发出一种称之为带色彩恢复的多尺度视网膜增强算法(MSRCR,Multi-Scale Retinex with Color Restoration) ,具体讨论的过程详见《A Multiscale Retinex for Bridging the Gap Between Color Images and the Human Observation of Scenes》论文。


原理

在前面的增强过程中,图像可能会因为增加了噪声,而使得图像的局部细节色彩失真,不能显现出物体的真正颜色,整体视觉效果变差。

针对这一点不足,MSRCR在MSR的基础上,加入了色彩恢复因子C来调节由于图像局部区域对比度增强而导致颜色失真的缺陷。

论文中提出的算法步骤:

 (注:如果是灰度图像,只需要计算一次即可,如果是彩色图像,如RGB三通道,则每个通道均需要如上进行计算。)

上式参数: 

  • G:增益Gain(一般取值:5)
  • b:偏差Offset(一般取值:25)
  • I (x, y):某个通道的图像
  • C:某个通道的彩色回复因子,用来调节3个通道颜色的比例
  • f(·):颜色空间的映射函数
  • β:增益常数(一般取值:46)
  • α:受控制的非线性强度(一般取值:125)

代码实现 

import cv2
import numpy as np
import mathdef replaceZeroes(data):min_nonzero = min(data[np.nonzero(data)])data[data == 0] = min_nonzeroreturn datadef simple_color_balance(input_img, s1, s2):h, w = input_img.shape[:2]out_img = np.zeros([h, w])sort_img = input_img.copy()one_dim_array = sort_img.flatten()  # 转化为一维数组sort_array = sorted(one_dim_array)  # 对一维数组按升序排序per1 = int((h * w) * s1 / 100)minvalue = sort_array[per1]per2 = int((h * w) * s2 / 100)maxvalue = sort_array[(h * w) - 1 - per2]# 实施简单白平衡算法if (maxvalue <= minvalue):for i in range(h):for j in range(w):out_img[i, j] = maxvalueelse:scale = 255.0 / (maxvalue - minvalue)for m in range(h):for n in range(w):if (input_img[m, n] < minvalue):out_img[m, n] = 0elif (input_img[m, n] > maxvalue):out_img[m, n] = 255else:out_img[m, n] = scale * (input_img[m, n] - minvalue)  # 映射中间段的图像像素out_img = cv2.convertScaleAbs(out_img)return out_imgdef MSRCR(img, scales, s1, s2):h, w = img.shape[:2]# print(h, w)scles_size = len(scales)img = np.array(img, dtype=np.float64)# print(img)log_R = np.zeros((h, w), dtype=np.float64)img_sum = np.add(img[:, :, 0], img[:, :, 1], img[:, :, 2])img_sum = replaceZeroes(img_sum)gray_img = []for j in range(3):img[:, :, j] = replaceZeroes(img[:, :, j])for i in range(0, scles_size):L_blur = cv2.GaussianBlur(img[:, :, j], (scales[i], scales[i]), 0)L_blur = replaceZeroes(L_blur)dst_img = cv2.log(img[:, :, j])dst_Lblur = cv2.log(L_blur)log_R += cv2.subtract(dst_img, dst_Lblur)MSR = log_R / 3.0'''img_sum_log = np.zeros((h, w))for i in range(0, h):for k in range(0, w):img_sum_log[i,k] = 125.0*math.log(img[i,k,j]) - math.log(img_sum[i,k])MSRCR = MSR * (img_sum_log[:, :])print(img_sum)# x = cv2.log(img_sum)'''MSRCR = MSR * (cv2.log(125.0 * img[:, :, j]) - cv2.log(img_sum))gray = simple_color_balance(MSRCR, s1, s2)gray_img.append(gray)return gray_imgif __name__ == '__main__':scales = [15, 101, 301]s1, s2 = 2, 3src_img = cv2.imread('img_1.png')src_img = cv2.cvtColor(src_img, cv2.COLOR_BGR2RGB)cv2.imshow('Original Image', src_img)MSRCR_Out = MSRCR(src_img, scales, s1, s2)result = cv2.merge([MSRCR_Out[0], MSRCR_Out[1], MSRCR_Out[2]])cv2.imshow('Enhanced(MSRCR) Image', result)cv2.waitKey(0)cv2.destroyAllWindows()
  •  实现效果:

  • 参数调整:

同上~


🚀总结

基于Retinex理论形成的图像增强算法,其优势在于光源一般不会对图像中各像素的相对明暗关系造成影响,还能一定程度上改变光源影响下的图像质量,以提高图像增强效果让图像看起来更加清晰。

但是,基于Retinex理论的图像增强算法也并非是完美的:

SSR算法:无法同时提供丰富的动态范围压缩和颜色保真,经低尺度SSR算法增强后的图像存在光晕情况,而经高尺度SSR算法增强后的图像尽管可以消除光晕,但动态范围压缩效果不佳。

MSR 算法:弥补了SSR算法的不足,增强后图像细节更加突出,色彩更加丰富,但其增强过程可能会因噪声的增加而使图像局部区域色彩失真,最终影响整体视觉效果

MSRCR算法:又进一步解决了MSR算法存在的这一问题,处理后的图像效果更佳,但计算过程过于复杂。


🚀整体代码

import numpy as np
from .tools import measure_time,eps,gauss_blur,simplest_color_balance### Frankle-McCann Retinex[2,3]
@measure_time
def retinex_FM(img,iter=4):'''log(OP(x,y))=1/2{log(OP(x,y))+[log(OP(xs,ys))+log(R(x,y))-log(R(xs,ys))]*}, seematlab code in https://www.cs.sfu.ca/~colour/publications/IST-2000/'''if len(img.shape)==2:img=img[...,None]ret=np.zeros(img.shape,dtype='uint8')def update_OP(x,y):nonlocal OPIP=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]=maximumOP=(OP+IP)/2for 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 slowfor 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)*255return ret.squeeze()### Single-Scale Retinex[4]
@measure_time
def retinex_SSR(img,sigma):'''log(R(x,y))=log(S(x,y))-log(S(x,y)*G(x,y))=log(S(x,y))-log(L(x,y)), i.e. r=s-l. S(x,y) and R(x,y) represent input image and retinex output image respectively, L(x,y):=S(x,y)*G(x,y) represents the lightness function, defined as the original image S operated with a gaussian filter G(named as center/surround function)implement ssr on single channel:1) read original image and convert to double(type) as S2) calc coefficient of G with sigma, i.e. normalize the gaussian kernel3) calc r by r=s-l and then convert r to R(from log to real)4) stretch the values of R into the range 0~255issue:we don't convert values from log domain to real domain in step 3 above, because it will bring terrible effect. In fact nobody does this, but the reason still remains unknownnote:gauss blur is the main operation of SSR, its time complexity is O(mnpq), m&n is the shape of image, p&q is the size of filter, we can use recursive gaussian filter(RGF), O(mn), to alternative it(see func fast_gauss_blur). Or transform from time domain to frequency domain using Fourier Transform to reduce complexity[4]'''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 slowerL_log=np.log(gaussian+1)r=S_log-L_logR=r #R=np.exp(r)?mmin=np.min(R)mmax=np.max(R)stretch=(R-mmin)/(mmax-mmin)*255 #linear stretchret[...,i]=stretchreturn ret.squeeze()### Multi-Scale Retinex[4]
@measure_time
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 SSRargs:sigmas: a listweights: 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)*255ret[...,i]=stretchreturn ret.squeeze()def MultiScaleRetinex(img,sigmas=[15,80,250],weights=None,flag=True):'''equal to func retinex_MSR, just remove the outer for-loop. Practice has proven that when MSR used in MSRCR or Gimp, we should add stretch step, otherwise the result color may be dim. But it's up to you, if you select to neglect stretch, set flag as False, have fun'''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!')r=np.zeros(img.shape,dtype='double')img=img.astype('double')for i,sigma in enumerate(sigmas):r+=(np.log(img+1)-np.log(gauss_blur(img,sigma)+1))*weights[i]if flag:mmin=np.min(r,axis=(0,1),keepdims=True)mmax=np.max(r,axis=(0,1),keepdims=True)r=(r-mmin)/(mmax-mmin)*255 #maybe indispensable when used in MSRCR or Gimp, make pic vibrantr=r.astype('uint8')return r'''old version
def retinex_MSRCR(img,sigmas=[12,80,250],s1=0.01,s2=0.01):alpha=125ret=np.zeros(img.shape,dtype='uint8')csum_log=np.log(np.sum(img,axis=2).astype('double')+1)msr=retinex_MSR(img,sigmas)for i in range(img.shape[-1]):channel=img[...,i].astype('double')r=(np.log(alpha*channel+1)-csum_log)*msr[...,i]stretch=simplest_color_balance(r,0.01,0.01)ret[...,i]=stretchreturn retdef retinex_gimp(img,sigmas=[12,80,250],dynamic=2):alpha=128gain=1offset=0ret=np.zeros(img.shape,dtype='uint8')csum_log=np.log(np.sum(img,axis=2)+1)msr=retinex_MSR(img,sigmas)for i in range(img.shape[-1]):channel=img[...,i].astype('double')r=gain*(np.log(alpha*channel+1)-csum_log)*msr[...,i]+offsetmean=np.mean(r)var=np.sqrt(np.sum((r-mean)**2)/r.size)mmin=mean-dynamic*varmmax=mean+dynamic*varstretch=(r-mmin)/(mmax-mmin)*255stretch[stretch>255]=255stretch[stretch<0]=0ret[...,i]=stretchreturn ret
'''### Multi-Scale Retinex with Color Restoration, see[4] Algorithm 1 in section 4
@measure_time
def retinex_MSRCR(img,sigmas=[12,80,250],s1=0.01,s2=0.01):'''r=βlog(αI')MSR, I'=I/∑I, I is one channel of image, ∑I is the sum of all channels, C:=βlog(αI') is named as color recovery factor. Last we improve previously used linear stretch: MSRCR:=r, r=G[MSRCR-b], then doing linear stretch. In practice, it doesn't work well, so we take another measure: Simplest Color Balance'''alpha=125img=img.astype('double')+1 #csum_log=np.log(np.sum(img,axis=2))msr=MultiScaleRetinex(img-1,sigmas) #-1r=(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 unsatisfactoryfor i in range(r.shape[-1]):r[...,i]=simplest_color_balance(r[...,i],0.01,0.01)return r.astype('uint8')@measure_time
def retinex_gimp(img,sigmas=[12,80,250],dynamic=2):'''refer to the implementation in GIMP, it improves the stretch operation based on MSRCR, introduces mean and standard deviation, and a dynamic parameter to eliminate chromatic aberration, experiments show that it works well. see source code in https://github.com/piksels-and-lines-orchestra/gimp/blob/master \/plug-ins/common/contrast-retinex.c'''alpha=128gain=1offset=0img=img.astype('double')+1 #csum_log=np.log(np.sum(img,axis=2))msr=MultiScaleRetinex(img-1,sigmas) #-1r=gain*(np.log(alpha*img)-csum_log[...,None])*msr+offsetmean=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*varmmax=mean+dynamic*varstretch=(r-mmin)/(mmax-mmin)*255stretch[stretch>255]=255stretch[stretch<0]=0return stretch.astype('uint8')### Multi-Scale Retinex with Chromaticity Preservation, see[4] Algorithm 2 in section 4
@measure_time
def retinex_MSRCP(img,sigmas=[12,80,250],s1=0.01,s2=0.01):'''compare to others, simple and very fast'''Int=np.sum(img,axis=2)/3Diffs=[]for sigma in sigmas:Diffs.append(np.log(Int+1)-np.log(gauss_blur(Int,sigma)+1))MSR=sum(Diffs)/3Int1=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')@measure_time
def retinex_AMSR(img,sigmas=[12,80,250]):'''see Proposed Method ii in "An automated multi Scale Retinex with Color Restoration for image enhancement"(doi: 10.1109/NCC.2012.6176791)'''img=img.astype('double')+1 #msr=MultiScaleRetinex(img-1,sigmas,flag=False) #y=0.05for 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 histzero_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=0else:low_ind=_[-1]_=np.where(sort_c[zero_ind+1:]<=zero_c*y)[0]if len(_)==0:up_ind=len(sort_c)-1else:up_ind=_[0]+zero_ind+1#low_v,up_v=sort_v[[low_ind,up_ind]]/100 #low clip value and up clip valuemsr[...,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)*255msr=msr.astype('uint8')return msr'''step of color restoration, maybe all rightr=(np.log(125*img)-np.log(np.sum(img,axis=2))[...,None])*msrmmin,mmax=np.min(r),np.max(r)return ((r-mmin)/(mmax-mmin)*255).astype('uint8')'''

链接:https://pan.baidu.com/s/1JBhvwvhIixPHzoKkNI7WNg?pwd=j666 
提取码:j666

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/225144.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C#与php自定义数据流传输

C#与php自定义数据流传输 介绍一、客户端与服务器数据传输流程图客户端发送数据给服务器&#xff1a;服务器返回数据给客户端&#xff1a; 二、自定义数据流C#版本数据流PHP版本数据流 三、数据传输测试1.在Unity中创建一个C#脚本NetWorkManager.cs2.服务器www目录创建StreamTe…

【Linux驱动】驱动框架的进化 | 总线设备驱动模型

&#x1f431;作者&#xff1a;一只大喵咪1201 &#x1f431;专栏&#xff1a;《Linux驱动》 &#x1f525;格言&#xff1a;你只管努力&#xff0c;剩下的交给时间&#xff01; 目录 &#x1f969;驱动框架的进化&#x1f960;分层&#x1f960;面向对象&#x1f960;编程&am…

使用 Jekyll 构建你的网站 - 初入门

文章目录 一、Jekyll介绍二、Jekyll安装和启动2.1 配置Ruby环境1&#xff09;Windows2&#xff09;macOS 2.2 安装 Jekyll2.3 构建Jekyll项目2.4 启动 Jekyll 服务 三、Jekyll常用命令四、目录结构4.1 主要目录4.2 其他的约定目录 五、使用GitLink构建Jekyll博客5.1 生成Jekyll…

同义词替换器降低论文重复率的最新技术解析

大家好&#xff0c;今天来聊聊同义词替换器降低论文重复率的最新技术解析&#xff0c;希望能给大家提供一点参考。 以下是针对论文重复率高的情况&#xff0c;提供一些修改建议和技巧&#xff0c;可以借助此类工具&#xff1a; 标题&#xff1a;同义词替换器降低论文重复率的最…

跟着LearnOpenGL学习11--材质

文章目录 一、材质二、设置材质三、光的属性四、不同的光源颜色 一、材质 在现实世界里&#xff0c;每个物体会对光产生不同的反应。 比如&#xff0c;钢制物体看起来通常会比陶土花瓶更闪闪发光&#xff0c;一个木头箱子也不会与一个钢制箱子反射同样程度的光。 有些物体反…

使用Clion配置Qt开发过程中的很多坑

如果你想使用Clion开发Qt软件 如果你想在Windows上使用Clion开发Qt 如果你还想使用MSVC编译器开发Qt 但是却遇到了各种各种编译报错&#xff0c;那么恭喜你这些坑都有人帮你踩过了 报错一 CMake Error at CMakeLists.txt:25 (find_package):Could not find a package config…

冒泡排序(C语言)

void BubbleSort(int arr[], int len) {int i, j, temp;for (i 0; i < len; i){for (j len - 1; j > i; j--){if (arr[j] > arr[j 1]){temp arr[j];arr[j] arr[j 1];arr[j 1] temp;}}} } 优化&#xff1a; 设置标志位flag&#xff0c;如果发生了交换flag设置…

西南科技大学计算机网络实验二 (IP协议分析与以太网协议分析)

一、实验目的 通过分析由跟踪执行traceroute程序发送和接收捕获得到的IP 数据报,深入研究在IP 数据报中的各种字段,理解IP协议。基于ARP命令和Ethereal进行以太网帧捕获与分析,理解和熟悉ARP协议原理以及以太网帧格式。 二、实验环境 与因特网连接的计算机网络系统;主机操…

ES-mapping

类似数据库中的表结构定义&#xff0c;主要作用如下 定义Index下的字段名( Field Name) 定义字段的类型&#xff0c;比如数值型、字符串型、布尔型等定义倒排索引相关的配置&#xff0c;比如是否索引、记录 position 等 index_options 用于控制倒排索记录的内容&#xff0c;有如…

敏捷开发 - 知识普及

敏捷开发- Scrum 前言 知乎有一篇文章描写Scrum,我觉得比较好:https://zhuanlan.zhihu.com/p/631459977 简单科普下PM和PMO 原文来源:https://zhuanlan.zhihu.com/p/546820914 PM - 项目经理(Project Manager) ​ 需要具备以下能力 ​ 1.号召力 2.影响力 3.交流能力 4.应…

MySQL 导入数据报错MySQL server has gone away

SQL语句太大了 稍微难以测试和验证&#xff0c;但是MySQL使用最大数据包站站点进行服务器和客户端之间的通信。如果语句包含大字段&#xff0c;则可能由于SQL语句的大小&#xff0c;而被中止。 我们可以通过语句查看一下允许的最大包大小&#xff1a;show global variables lik…

k8s---kubernets

目录 一、Kurbernetes 1.2、K8S的特性&#xff1a; 1.3、docker和K8S&#xff1a; 1.4、K8S的作用&#xff1a; 1.5、K8S的特性&#xff1a; 二、K8S集群架构与组件&#xff1a; 三、K8S的核心组件&#xff1a; 一、master组件&#xff1a; 1、kube-apiserver&#xff1…

蓝桥杯的学习规划

c语言基础&#xff1a; Python语言基础 学习路径&#xff1a;画框的要着重学习

音频修复增强软件iZotope RX 10 mac特点介绍

iZotope RX 10 mac是一款音频修复和增强软件。 iZotope RX 10 mac软件特点 声音修复&#xff1a;iZotope RX 10可以去除不良噪音、杂音、吱吱声等&#xff0c;使音频变得更加清晰干净。 音频增强&#xff1a;iZotope RX 10支持对音频进行音量调节、均衡器、压缩器、限制器等处…

网络安全保障领域

计算机与信息系统安全---最主要领域 云计算安全 IaaS、PasS、SaaS(裸机&#xff0c;装好软件的电脑&#xff0c;装好应用的电脑) 存在风险&#xff1a;开源工具、优先访问权、管理权限、数据处、数据隔离、数据恢复、调查支持、长期发展风险 云计算安全关键技术&#xff1a;可信…

【C++逆向 - 1】C++函数新特性

内联函数 本质&#xff1a;用函数代码替换函数调用 使用方式&#xff1a;在函数声明和函数定义前加上 inline 关键字 笔者感觉跟C语言中的宏定义差不多&#xff0c;但是内联函数更加“智能”&#xff08;应该是编译器更加智能&#xff09;。即使程序员将函数作为内联函数&am…

华为数通方向HCIP-DataCom H12-831题库(多选题:221-240)

第221题 在割接项目的项目调研阶段需要对现网硬件环境进行观察,主要包括以下哪些内容? A、设备的位置 B、ODF位置 C、接口标识 D、光纤接口对应关系 答案:ABCD 解析: 在项目割接前提的项目调研阶段,需要记录下尽可能详细的信息。 第222题 以下哪些项能被正则表达式10*成…

Python 新规范 pyproject.toml 完全解析

多谢&#xff1a;thank Python从PEP 518开始引入的使用pyproject.toml管理项目元数据的方案。 该规范目前已经在很多开源项目中得以支持&#xff1a; Django 这个 Python 生态的顶级项目在 5 个月之前开始使用 pyproject.tomlPytest 这个 Python 生态测试框架的领头羊在 4 个…

智慧幼儿园视频监管方案及实施建议:AI智能技术构建新引擎

一、背景需求 随着科技的快速发展&#xff0c;智慧化监管已成为幼儿园管理的重要趋势。智慧幼儿园监管解决方案通过引入先进的技术手段&#xff0c;提高幼儿园的管理效率&#xff0c;保障幼儿的安全与健康&#xff0c;为家长提供更便捷的服务。为了保障幼儿的安全&#xff0c;…

【通讯录案例-搭建登录界面 Objective-C语言】

一、来看我们这个通讯录案例 1.接下来啊,我们来做这个通讯录案例, 然后呢,做这么一个应用程序啊, 我们第一步呢,先把界面儿搭了, 然后呢,搭之前,简单的来分析一下, 首先呢,这是,中间儿的这一块儿, 1)有个“账户”、“密码”,这一块儿, 这是一个什么控制器,…