├── 3f4c794809f5ce702ffdd35c1e846a42.png ├── 4b8a1bbbf586e59aafc9e5e3e57b51f0.png ├── 5db0c02ea6b14e7071d00e49647526eb.png ├── 81b2a3f8f50a37e34d638e7cb52ec5f9.png ├── README.md ├── b37ec214dd957b06861a90020171354d.png └── hist.py /3f4c794809f5ce702ffdd35c1e846a42.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qunshansj/opencv-python-image-dehazing-algorithm/a0d6952b6fa7509e6d57699b0e371b1bb41a0092/3f4c794809f5ce702ffdd35c1e846a42.png -------------------------------------------------------------------------------- /4b8a1bbbf586e59aafc9e5e3e57b51f0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qunshansj/opencv-python-image-dehazing-algorithm/a0d6952b6fa7509e6d57699b0e371b1bb41a0092/4b8a1bbbf586e59aafc9e5e3e57b51f0.png -------------------------------------------------------------------------------- /5db0c02ea6b14e7071d00e49647526eb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qunshansj/opencv-python-image-dehazing-algorithm/a0d6952b6fa7509e6d57699b0e371b1bb41a0092/5db0c02ea6b14e7071d00e49647526eb.png -------------------------------------------------------------------------------- /81b2a3f8f50a37e34d638e7cb52ec5f9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qunshansj/opencv-python-image-dehazing-algorithm/a0d6952b6fa7509e6d57699b0e371b1bb41a0092/81b2a3f8f50a37e34d638e7cb52ec5f9.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |  2 | # 1.图片识别 3 | ![2.png](5db0c02ea6b14e7071d00e49647526eb.png) 4 | 5 | 6 | # 2.视频展示 7 | [[项目分享]Python基于OpenCV的图像去雾算法[完整源码&部署教程]_哔哩哔哩_bilibili](https://www.bilibili.com/video/BV1eB4y1G7dX/?vd_source=bc9aec86d164b67a7004b996143742dc) 8 | 9 | # 3.算法原理 10 | [参考该博客图像增强算法](https://mbd.pub/o/bread/Yp6cmZZu),对图像的亮度、对比度、饱和度、色调等进行调节,增加其清晰度,减少噪点等。图像增强往往经过多个算法的组合,完成上述功能,比如图像去燥等同于低通滤波器,增加清晰度则为高通滤波器,当然增强一副图像是为最后获取图像有用信息服务为主。一般的算法流程可为:图像去燥、增加清晰度(对比度)、灰度化或者获取图像边缘特征或者对图像进行卷积、二值化等,上述四个步骤往往可以通过不同的步骤进行实现,后续将针对此方面内容进行专题实验,列举其应用场景和处理特点。 11 | ## 基于直方图均衡化的图像增强 12 | 图像对比度增强的方法可以分为两种:直接对比度增强方法,间接对比度增强方法。直方图拉伸和直方图均衡化是常见的间接对比度增强方法。直方图拉伸是利用对比度拉伸对直方图进行调整,扩大前景和背景灰度的差别,这种方法可以通过线性和非线性的方法来实现,其中ps中就是利用此方法提高对比度;直方图均衡化则是利用累积函数对灰度值进行调整,实现对比度的增强。 13 | 直方图均衡化处理原理:将原始图像的灰度图从比较集中的某个灰度区间均匀分布在整个灰度空间中,实现对图像的非线性拉伸,重新分配图像像素值。 14 | 15 | 算法应用场景: 16 | 1、算法的本质是重新分布图像的像素值,增加了许多局部的对比度,整体的对比度没有进行太大改变,所以应用图像为图像有用数据的对比度相近是,例如:X光图像,可以将曝光过度或曝光不足照片进行更好的显示,或者是背景及前景太亮或太暗的图像非常有用。 17 | 2、算法当然也有缺点,具体表现为:变换后的图像灰度级减少,某些细节减少;某些图像有高峰值,则处理后对比度不自然的过分增强。 18 | 19 | 算法实现特点: 20 | 1、均衡化过程:直方图均衡化保证在图像像素映射过程中原来的大小关系保持不变,即较亮的区域依旧较亮,较暗的依旧较暗,只是对比度增加,不能明暗颠倒;保证像素映射函数的值域在0和255之间。累积分布函数是单增长函数,并且值域是0到1。 21 | 2、累积分布函数实现过程: 22 | 比较概率分布函数和累积分布函数,前者的二维图像是参差不齐的,后者是单调递增的。直方图均衡化过程中,映射方法是 23 | ![5.png](4b8a1bbbf586e59aafc9e5e3e57b51f0.png) 24 | 其中,n是图像中像素的总和。 25 | 26 | ## 基于拉普拉斯算子的图像增强 27 | [参考博客](https://afdian.net/item?plan_id=52cb7cde5e6611ed9a4852540025c377) 28 | 利用拉普拉斯算子进行图像增强本质是利用图像的二次微分对图像进行蜕化,在图像领域中微分是锐化,积分是模糊,利用二次微分对图像进行蜕化即利用邻域像素提高对比度。在opencv中也有拉普拉斯函数,但那时生成了灰度图像,更多的求取边缘,具体源码还没研究,其中原理可以参考我前一篇文章,针对拉普拉斯有个详细的介绍。 29 | ![6.png](3f4c794809f5ce702ffdd35c1e846a42.png) 30 | 31 | ## 基于对象Log变换的图像增强 32 | 对数变换可以将图像的低灰度值部分扩展,显示出低灰度部分更多的细节,将其高灰度值部分压缩,减少高灰度值部分的细节,从而达到强调图像低灰度部分的目的。变换方法: 33 | 对数变换对图像低灰度部分细节增强的功能过可以从对数图上直观理解: 34 | ![7.png](b37ec214dd957b06861a90020171354d.png) 35 | x轴的0.4大约对应了y轴的0.8,即原图上0~0.4的低灰度部分经过对数运算后扩展到0~0.8的部分,而整个0.4~1的高灰度部分被投影到只有0.8~1的区间,这样就达到了扩展和增强低灰度部分,压缩高灰度部分的值的功能。 36 | 37 | 从上图还可以看到,对于不同的底数,底数越大,对低灰度部分的扩展就越强,对高灰度部分的压缩也就越强。 38 | 39 | # 4.代码实现 40 | ``` 41 | # 图像增强算法,图像锐化算法 42 | # 1)基于直方图均衡化 2)基于拉普拉斯算子 3)基于对数变换 4)基于伽马变换 5)CLAHE 6)retinex-SSR 7)retinex-MSR 43 | # 其中,基于拉普拉斯算子的图像增强为利用空域卷积运算实现滤波 44 | # 基于同一图像对比增强效果 45 | # 直方图均衡化:对比度较低的图像适合使用直方图均衡化方法来增强图像细节 46 | # 拉普拉斯算子可以增强局部的图像对比度 47 | # log对数变换对于整体对比度偏低并且灰度值偏低的图像增强效果较好 48 | # 伽马变换对于图像对比度偏低,并且整体亮度值偏高(对于相机过曝)情况下的图像增强效果明显 49 | 50 | import cv2 51 | import numpy as np 52 | import matplotlib.pyplot as plt 53 | 54 | 55 | # 直方图均衡增强 56 | def hist(image): 57 | r, g, b = cv2.split(image) 58 | r1 = cv2.equalizeHist(r) 59 | g1 = cv2.equalizeHist(g) 60 | b1 = cv2.equalizeHist(b) 61 | image_equal_clo = cv2.merge([r1, g1, b1]) 62 | return image_equal_clo 63 | 64 | 65 | # 拉普拉斯算子 66 | def laplacian(image): 67 | kernel = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]]) 68 | image_lap = cv2.filter2D(image, cv2.CV_8UC3, kernel) 69 | return image_lap 70 | 71 | 72 | # 对数变换 73 | def log(image): 74 | image_log = np.uint8(np.log(np.array(image) + 1)) 75 | cv2.normalize(image_log, image_log, 0, 255, cv2.NORM_MINMAX) 76 | # 转换成8bit图像显示 77 | cv2.convertScaleAbs(image_log, image_log) 78 | return image_log 79 | 80 | 81 | # 伽马变换 82 | def gamma(image): 83 | fgamma = 2 84 | image_gamma = np.uint8(np.power((np.array(image) / 255.0), fgamma) * 255.0) 85 | cv2.normalize(image_gamma, image_gamma, 0, 255, cv2.NORM_MINMAX) 86 | cv2.convertScaleAbs(image_gamma, image_gamma) 87 | return image_gamma 88 | 89 | 90 | # 限制对比度自适应直方图均衡化CLAHE 91 | def clahe(image): 92 | b, g, r = cv2.split(image) 93 | clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8)) 94 | b = clahe.apply(b) 95 | g = clahe.apply(g) 96 | r = clahe.apply(r) 97 | image_clahe = cv2.merge([b, g, r]) 98 | return image_clahe 99 | 100 | 101 | def replaceZeroes(data): 102 | min_nonzero = min(data[np.nonzero(data)]) 103 | data[data == 0] = min_nonzero 104 | return data 105 | 106 | 107 | # retinex SSR 108 | def SSR(src_img, size): 109 | L_blur = cv2.GaussianBlur(src_img, (size, size), 0) 110 | img = replaceZeroes(src_img) 111 | L_blur = replaceZeroes(L_blur) 112 | 113 | dst_Img = cv2.log(img/255.0) 114 | dst_Lblur = cv2.log(L_blur/255.0) 115 | dst_IxL = cv2.multiply(dst_Img, dst_Lblur) 116 | log_R = cv2.subtract(dst_Img, dst_IxL) 117 | 118 | dst_R = cv2.normalize(log_R,None, 0, 255, cv2.NORM_MINMAX) 119 | log_uint8 = cv2.convertScaleAbs(dst_R) 120 | return log_uint8 121 | 122 | 123 | def SSR_image(image): 124 | size = 3 125 | b_gray, g_gray, r_gray = cv2.split(image) 126 | b_gray = SSR(b_gray, size) 127 | g_gray = SSR(g_gray, size) 128 | r_gray = SSR(r_gray, size) 129 | result = cv2.merge([b_gray, g_gray, r_gray]) 130 | return result 131 | 132 | 133 | # retinex MMR 134 | def MSR(img, scales): 135 | weight = 1 / 3.0 136 | scales_size = len(scales) 137 | h, w = img.shape[:2] 138 | log_R = np.zeros((h, w), dtype=np.float32) 139 | 140 | for i in range(scales_size): 141 | img = replaceZeroes(img) 142 | L_blur = cv2.GaussianBlur(img, (scales[i], scales[i]), 0) 143 | L_blur = replaceZeroes(L_blur) 144 | dst_Img = cv2.log(img/255.0) 145 | dst_Lblur = cv2.log(L_blur/255.0) 146 | dst_Ixl = cv2.multiply(dst_Img, dst_Lblur) 147 | log_R += weight * cv2.subtract(dst_Img, dst_Ixl) 148 | 149 | dst_R = cv2.normalize(log_R,None, 0, 255, cv2.NORM_MINMAX) 150 | log_uint8 = cv2.convertScaleAbs(dst_R) 151 | return log_uint8 152 | 153 | 154 | def MSR_image(image): 155 | scales = [15, 101, 301] # [3,5,9] 156 | b_gray, g_gray, r_gray = cv2.split(image) 157 | b_gray = MSR(b_gray, scales) 158 | g_gray = MSR(g_gray, scales) 159 | r_gray = MSR(r_gray, scales) 160 | result = cv2.merge([b_gray, g_gray, r_gray]) 161 | return result 162 | 163 | 164 | if __name__ == "__main__": 165 | image = cv2.imread("example.jpg") 166 | image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) 167 | 168 | plt.subplot(4, 2, 1) 169 | plt.imshow(image) 170 | plt.axis('off') 171 | plt.title('Offical') 172 | 173 | # 直方图均衡增强 174 | image_equal_clo = hist(image) 175 | 176 | plt.subplot(4, 2, 2) 177 | plt.imshow(image_equal_clo) 178 | plt.axis('off') 179 | plt.title('equal_enhance') 180 | 181 | # 拉普拉斯算法增强 182 | image_lap = laplacian(image) 183 | 184 | plt.subplot(4, 2, 3) 185 | plt.imshow(image_lap) 186 | plt.axis('off') 187 | plt.title('laplacian_enhance') 188 | 189 | # LoG对象算法增强 190 | image_log = log(image) 191 | 192 | plt.subplot(4, 2, 4) 193 | plt.imshow(image_log) 194 | plt.axis('off') 195 | plt.title('log_enhance') 196 | 197 | # 伽马变换 198 | image_gamma = gamma(image) 199 | 200 | plt.subplot(4, 2, 5) 201 | plt.imshow(image_gamma) 202 | plt.axis('off') 203 | plt.title('gamma_enhance') 204 | 205 | # CLAHE 206 | image_clahe = clahe(image) 207 | 208 | plt.subplot(4, 2, 6) 209 | plt.imshow(image_clahe) 210 | plt.axis('off') 211 | plt.title('CLAHE') 212 | 213 | # retinex_ssr 214 | image_ssr = SSR_image(image) 215 | 216 | plt.subplot(4, 2, 7) 217 | plt.imshow(image_ssr) 218 | plt.axis('off') 219 | plt.title('SSR') 220 | 221 | # retinex_msr 222 | image_msr = MSR_image(image) 223 | 224 | plt.subplot(4, 2, 8) 225 | plt.imshow(image_msr) 226 | plt.axis('off') 227 | plt.title('MSR') 228 | 229 | plt.show() 230 | 231 | ``` 232 | # 5.系统整合 233 | 下图[完整源码&环境部署视频教程&算法原理](https://s.xiaocichang.com/s/8459b9) 234 | ![1.png](81b2a3f8f50a37e34d638e7cb52ec5f9.png) 235 | 236 | 参考博客[《Python基于OpenCV的图像去雾算法\[完整源码&部署教程\]》](https://mbd.pub/o/qunma/work) 237 | 238 | 239 | 240 | # 6.参考文献 241 | 1、2008,Single image dehazing,R. Fattal,ACM Transactions on Graphics. 242 | *** 243 | 2、2014,Efficient Image Dehazing with Boundary Constraint and Contextual Regularization, G. Meng, Y. Wang, J. Duan, S. Xiang and C. Pan,ICCV 244 | *** 245 | 3、2016,Non-local image dehazing,D. Berman, T. Treibitz and S. Avidan, CVPR. 246 | *** 247 | 4、2009,Single image haze removal using dark channel prior,K. He, J. Sun and X. Tang,CVPR. 248 | *** 249 | 5、2017,Single Image Dehazing Based on the Physical Model and MSRCR Algorithm,J. B. Wang, K. Lu, J. Xue, N. He and L. Shao,TCSVT 250 | *** 251 | 6、2013,Hardware Implementation of a Fast and Efficient Haze Removal Method,Y. H. Shiau, H. Y. Yang, P. Y. Chen and Y. Z. Chuang,TCSVT 252 | *** 253 | 7、2014,Visibility Restoration of Single Hazy Images Captured in Real-World Weather Conditions,S. C. Huang, B. H. Chen and W. J. Wang,TCSVT 254 | *** 255 | 8、2015,Single image dehazing with a physical model and dark channel prior,J. B. Wang, N. He, L. L. Zhang and K. Lu,Neurocomputing 256 | *** 257 | 9、2017,An Efficient Fusion-Based Defogging,J. M. Guo, J. Y. Syue, V. R. Radzicki and H. Lee,Tip 258 | *** 259 | 10、2017,Haze Removal Using the Difference-Structure-Preservation Prior,L. Y He, J. Z. Zhao, N. N. Zheng and D.Y. Bi,TIP 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | --- 268 | #### 如果您需要更详细的【源码和环境部署教程】,除了通过【系统整合】小节的链接获取之外,还可以通过邮箱以下途径获取: 269 | #### 1.请先在GitHub上为该项目点赞(Star),编辑一封邮件,附上点赞的截图、项目的中文描述概述(About)以及您的用途需求,发送到我们的邮箱 270 | #### sharecode@yeah.net 271 | #### 2.我们收到邮件后会定期根据邮件的接收顺序将【完整源码和环境部署教程】发送到您的邮箱。 272 | #### 【免责声明】本文来源于用户投稿,如果侵犯任何第三方的合法权益,可通过邮箱联系删除。 -------------------------------------------------------------------------------- /b37ec214dd957b06861a90020171354d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qunshansj/opencv-python-image-dehazing-algorithm/a0d6952b6fa7509e6d57699b0e371b1bb41a0092/b37ec214dd957b06861a90020171354d.png -------------------------------------------------------------------------------- /hist.py: -------------------------------------------------------------------------------- 1 | 2 | # 图像增强算法,图像锐化算法 3 | # 1)基于直方图均衡化 2)基于拉普拉斯算子 3)基于对数变换 4)基于伽马变换 5)CLAHE 6)retinex-SSR 7)retinex-MSR 4 | # 其中,基于拉普拉斯算子的图像增强为利用空域卷积运算实现滤波 5 | # 基于同一图像对比增强效果 6 | # 直方图均衡化:对比度较低的图像适合使用直方图均衡化方法来增强图像细节 7 | # 拉普拉斯算子可以增强局部的图像对比度 8 | # log对数变换对于整体对比度偏低并且灰度值偏低的图像增强效果较好 9 | # 伽马变换对于图像对比度偏低,并且整体亮度值偏高(对于相机过曝)情况下的图像增强效果明显 10 | 11 | import cv2 12 | import numpy as np 13 | import matplotlib.pyplot as plt 14 | 15 | 16 | # 直方图均衡增强 17 | def hist(image): 18 | r, g, b = cv2.split(image) 19 | r1 = cv2.equalizeHist(r) 20 | g1 = cv2.equalizeHist(g) 21 | b1 = cv2.equalizeHist(b) 22 | image_equal_clo = cv2.merge([r1, g1, b1]) 23 | return image_equal_clo 24 | 25 | 26 | # 拉普拉斯算子 27 | def laplacian(image): 28 | kernel = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]]) 29 | image_lap = cv2.filter2D(image, cv2.CV_8UC3, kernel) 30 | return image_lap 31 | 32 | 33 | # 对数变换 34 | def log(image): 35 | image_log = np.uint8(np.log(np.array(image) + 1)) 36 | cv2.normalize(image_log, image_log, 0, 255, cv2.NORM_MINMAX) 37 | # 转换成8bit图像显示 38 | cv2.convertScaleAbs(image_log, image_log) 39 | return image_log 40 | 41 | 42 | # 伽马变换 43 | def gamma(image): 44 | fgamma = 2 45 | image_gamma = np.uint8(np.power((np.array(image) / 255.0), fgamma) * 255.0) 46 | cv2.normalize(image_gamma, image_gamma, 0, 255, cv2.NORM_MINMAX) 47 | cv2.convertScaleAbs(image_gamma, image_gamma) 48 | return image_gamma 49 | 50 | 51 | # 限制对比度自适应直方图均衡化CLAHE 52 | def clahe(image): 53 | b, g, r = cv2.split(image) 54 | clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8)) 55 | b = clahe.apply(b) 56 | g = clahe.apply(g) 57 | r = clahe.apply(r) 58 | image_clahe = cv2.merge([b, g, r]) 59 | return image_clahe 60 | 61 | 62 | def replaceZeroes(data): 63 | min_nonzero = min(data[np.nonzero(data)]) 64 | data[data == 0] = min_nonzero 65 | return data 66 | 67 | 68 | # retinex SSR 69 | def SSR(src_img, size): 70 | L_blur = cv2.GaussianBlur(src_img, (size, size), 0) 71 | img = replaceZeroes(src_img) 72 | L_blur = replaceZeroes(L_blur) 73 | 74 | dst_Img = cv2.log(img/255.0) 75 | dst_Lblur = cv2.log(L_blur/255.0) 76 | dst_IxL = cv2.multiply(dst_Img, dst_Lblur) 77 | log_R = cv2.subtract(dst_Img, dst_IxL) 78 | 79 | dst_R = cv2.normalize(log_R,None, 0, 255, cv2.NORM_MINMAX) 80 | log_uint8 = cv2.convertScaleAbs(dst_R) 81 | return log_uint8 82 | 83 | 84 | def SSR_image(image): 85 | size = 3 86 | b_gray, g_gray, r_gray = cv2.split(image) 87 | b_gray = SSR(b_gray, size) 88 | g_gray = SSR(g_gray, size) 89 | r_gray = SSR(r_gray, size) 90 | result = cv2.merge([b_gray, g_gray, r_gray]) 91 | return result 92 | 93 | 94 | # retinex MMR 95 | def MSR(img, scales): 96 | weight = 1 / 3.0 97 | scales_size = len(scales) 98 | h, w = img.shape[:2] 99 | log_R = np.zeros((h, w), dtype=np.float32) 100 | 101 | for i in range(scales_size): 102 | img = replaceZeroes(img) 103 | L_blur = cv2.GaussianBlur(img, (scales[i], scales[i]), 0) 104 | L_blur = replaceZeroes(L_blur) 105 | dst_Img = cv2.log(img/255.0) 106 | dst_Lblur = cv2.log(L_blur/255.0) 107 | dst_Ixl = cv2.multiply(dst_Img, dst_Lblur) 108 | log_R += weight * cv2.subtract(dst_Img, dst_Ixl) 109 | 110 | dst_R = cv2.normalize(log_R,None, 0, 255, cv2.NORM_MINMAX) 111 | log_uint8 = cv2.convertScaleAbs(dst_R) 112 | return log_uint8 113 | 114 | 115 | def MSR_image(image): 116 | scales = [15, 101, 301] # [3,5,9] 117 | b_gray, g_gray, r_gray = cv2.split(image) 118 | b_gray = MSR(b_gray, scales) 119 | g_gray = MSR(g_gray, scales) 120 | r_gray = MSR(r_gray, scales) 121 | result = cv2.merge([b_gray, g_gray, r_gray]) 122 | return result 123 | 124 | 125 | if __name__ == "__main__": 126 | image = cv2.imread("example.jpg") 127 | image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) 128 | 129 | plt.subplot(4, 2, 1) 130 | plt.imshow(image) 131 | plt.axis('off') 132 | plt.title('Offical') 133 | 134 | # 直方图均衡增强 135 | image_equal_clo = hist(image) 136 | 137 | plt.subplot(4, 2, 2) 138 | plt.imshow(image_equal_clo) 139 | plt.axis('off') 140 | plt.title('equal_enhance') 141 | 142 | # 拉普拉斯算法增强 143 | image_lap = laplacian(image) 144 | 145 | plt.subplot(4, 2, 3) 146 | plt.imshow(image_lap) 147 | plt.axis('off') 148 | plt.title('laplacian_enhance') 149 | 150 | # LoG对象算法增强 151 | image_log = log(image) 152 | 153 | plt.subplot(4, 2, 4) 154 | plt.imshow(image_log) 155 | plt.axis('off') 156 | plt.title('log_enhance') 157 | 158 | # 伽马变换 159 | image_gamma = gamma(image) 160 | 161 | plt.subplot(4, 2, 5) 162 | plt.imshow(image_gamma) 163 | plt.axis('off') 164 | plt.title('gamma_enhance') 165 | 166 | # CLAHE 167 | image_clahe = clahe(image) 168 | 169 | plt.subplot(4, 2, 6) 170 | plt.imshow(image_clahe) 171 | plt.axis('off') 172 | plt.title('CLAHE') 173 | 174 | # retinex_ssr 175 | image_ssr = SSR_image(image) 176 | 177 | plt.subplot(4, 2, 7) 178 | plt.imshow(image_ssr) 179 | plt.axis('off') 180 | plt.title('SSR') 181 | 182 | # retinex_msr 183 | image_msr = MSR_image(image) 184 | 185 | plt.subplot(4, 2, 8) 186 | plt.imshow(image_msr) 187 | plt.axis('off') 188 | plt.title('MSR') 189 | 190 | plt.show() 191 | 192 | --------------------------------------------------------------------------------