图像去雾算法丨图像去雾算法python
【图像去雾算法丨图像去雾算法python】lot物联网小编为你整理了的相关内容,希望能为你解答。
户外场景拍摄容易受各种因素的影响,如灰、粉、尘、烟、雾等。这些悬浮在空气中的粒子会对场景的反射光和大气光的散射产生影响,使拍摄图像的对比度与颜色产生明显失真,从而降低了场景和目标的可辨识度,直接影响到机器视觉对于图像内容的识别与分析。所以对图像进行去雾处理就显得非常重要。
带雾(受干扰)图像
在众多去云雾算法中,基于暗通道优先的去云雾算法是较为成熟的,在学界讨论和商业应用也比较多。该算法由何恺明(1)于2009年以MSRA实习生的身份提出,并获得当年CVPR的Best Paper奖。
1.暗通道定义
何恺明通过对大量在户外拍摄的自然景物图片进行统计分析得出一个结论:在绝大多数非天空的局部区域里,某一些像素总会(至少一个颜色通道)具有很低的值。换言之,该区域光强度的最小值是个很小的数(趋于0)。
基于上述结论,定义暗通道,对于一幅图像J有如下式子:
暗通道计算
也就是说以像素点x为中心,分别取三个通道内窗口Ω内的最小值,然后再取三个通道的最小值作为像素点x的暗通道的值,如下图所示:
暗通道取值
JC代表J的某一个颜色通道,而Ω(x)是以x为中心的一块方形区域。我们观察得出,除了天空方位,Jdark的强度总是很低并且趋近于0。如果J是户外的无雾图像,我们把Jdark称为J的暗原色,并且把以上观察得出的经验性规律称为暗原色先验。
2.大气物理模型
要想从物理模型角度对有雾图像进行清晰化处理,就要了解有雾图像的物理成因,那么就要了解雾天的大气散射模型。
大气散射物理模型包含两部分,第一部分称为直接衰减项(Direct Attenuation)也称直接传播,第二部分称为大气光照(Airlight)。
大气散射物理模型
用公式表示如下:
带干扰的像素点计算
I是观测到的有雾图像,J是景物反射光强度(也就是清晰的无雾图像),A是全局大气光照强度,t用来描述光线通过介质透射到成像设备过程中没有被散射的部分,去雾的目标就是从I中复原J。
方程右边的第一项J(x)t(x) 叫做直接衰减项,第二项A(1-t(x))则是大气光照。直接衰减项描述的是景物光线在透射媒介中经衰减后的部分,而大气光则是由前方散射引起的,会导致景物颜色的偏移。因为大气层可看成各向同性的,透射率t可表示为:
透射率
β为大气的散射系数,该式表明景物光线是随着景物深度d按指数衰减的。
3.求解透射率t
透射率t的公式如下:
透射率调整
IC为输入的有雾图像,对其除以全局大气光照AC后再利用暗通道定义公式进行求解暗通道。w(0<w<1)是雾的保留系数通常取0.95。
4.求解全局大气光照AC
(1).首先对输入的有雾图像I求解其暗通道图像Jdark。
(2).选择暗通道Jdark内图像总像素点个数(N_imagesize)千分之一(N=N_imagesize/1000)个最亮的像素点,并记录这些像素点(x,y)坐标。
(3).再根据这些点的坐标分别在原图像I的三个通道(r,g,b)内找到这些像素点并加和得到(sum_r,sum_g,sum_b)。
(4).AC=[Ar,AgAb]. 其中Ar=sum_r/N; Ag=sum_g/N; Ab=sum_b/N。
5.求解最后清晰图像
把A和t,那么带入大气模型公式:
成图
这里,t0参数用来限定透射率t的下限值,其作用也就是在输入图像的浓雾区域保留一定的雾。
6.去雾效果
效果图
7.附Java源码
// 读取图片成rgb二维数组 public static Map<String, Object> image2Matrix(String imgfile) { File file = new File(imgfile); BufferedImage bi = null; try { bi = ImageIO.read(file); } catch (Exception e) { e.printStackTrace(); } int width = bi.getWidth(); int height = bi.getHeight(); int minx = bi.getMinX(); int miny = bi.getMinY(); Color[][] allcolor = new Color[height - miny][width - minx]; for (int j = miny; j < height; j ) { for (int i = minx; i < width; i ) { int pixel = bi.getRGB(i, j); // // 下面三行代码将一个数字转换为rgb数字 allcolor[j - miny][i - minx] = new Color(pixel); } } Map<String, Object> map = new HashMap<String, Object>(); map.put("matrix", allcolor); map.put("width", width - minx); map.put("height", height - miny); return map; } public static void writeImageFromArray(String imageFile, String type, int[][] rgbArray) { // 获取数组宽度和高度 int width = rgbArray[0].length; int height = rgbArray.length; // 将二维数组转换为一维数组 int[] data = new int[width * height]; for (int i = 0; i < height; i ) for (int j = 0; j < width; j ) data[i * width j] = rgbArray[i][j]; // 将数据写入BufferedImage BufferedImage bf = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR); bf.setRGB(0, 0, width, height, data, 0, width); // 输出图片 try { File file = new File(imageFile); ImageIO.write(bf, type, file); } catch (IOException e) { e.printStackTrace(); } } public static int[] convertARGBToRGB(int ARGB) { int[] rgb = new int[3]; rgb[0] = (ARGB & 0xff0000) >> 16; rgb[1] = (ARGB & 0xff00) >> 8; rgb[2] = (ARGB & 0xff); return rgb; } public static int convertRGBToARGB(int r, int g, int b) { int color = ((0xFF << 24) | (r << 16) | (g << 8) | b); return color; } public static int[][] removeFog(Map<String, Object> map) { // 1.求暗通道图 Color[][] img = (Color[][]) map.get("matrix"); int height = (Integer) map.get("height"); int width = (Integer) map.get("width"); int k1 = height; int k2 = width; int k = 11; // 5*5的邻域 int i, j, r, c, x; // Mat src(k1,k2,CV_8UC1); int[][] src = new int[k1][k2]; Color color = null; for (r = 0; r < k1; r ) { // 先求出每个像素RGB分量中的最小值 for (c = 0; c < k2; c ) { x = 255; color = img[r][c]; if (color.getRed() < x) x = color.getRed(); if (color.getGreen() < x) x = color.getGreen(); if (color.getBlue() < x) x = color.getBlue(); src[r][c] = x; } } int[][] src1 = new int[k1][k2]; for (r = 0; r < k1; r ) { // 最小值滤波 for (c = 0; c < k2; c ) { x = 255; for (i = -k / 2; i <= k / 2; i ) { for (j = -k / 2; j <= k / 2; j ) { if (r i < 0 || c j < 0 || r i >= k1 || c j >= k2) continue; if (src[r i][c j] < x) x = src[r i][c j]; } } src1[r][c] = x; } } int[][] src2 = src1; // 2.计算大气光值A int Am = 2200; // 设定大气光值最大值 int r1 = 0, c1 = 0; int a[] = { 0, 0, 0 }; int aa[][] = new int[100][2]; // 用以记录暗通道图中亮度最大的100个像素的坐标 // 从暗通道图中按照亮度的大小取前100的像素 for (i = 0; i < 100; i ) { x = 0; for (r = 0; r < k1; r ) { for (c = 0; c < k2; c ) { if (src2[r][c] > x) { x = src2[r][c]; r1 = r; c1 = c; } } } aa[i][0] = r1; aa[i][1] = c1; src2[r1][c1] = 0; } // 在这前100像素中,在原始有雾图像I中寻找对应的具有最高亮度的点的值,作为A值。 for (i = 0; i < 100; i ) { color = img[aa[i][0]][aa[i][1]]; if (color.getBlue() > a[2]) { a[2] = color.getBlue(); } if (color.getGreen() > a[1]) { a[1] = color.getGreen(); } if (color.getRed() > a[0]) { a[0] = color.getRed(); } } // 若A超出阈值 for (i = 0; i < 3; i ) { if (a[i] > Am) a[i] = Am; } // 计算t值 double dst[][] = new double[k1][k2]; double t[][] = new double[k1][k2]; double w = 0.95;// 修正因子 double t0 = 0.2;// t的最小阈值 double y; for (r = 0; r < k1; r ) { for (c = 0; c < k2; c ) { y = 255; color = img[r][c]; if (color.getRed() * 1.0 / a[0] < y) y = color.getRed() * 1.0 / a[0]; if (color.getGreen() * 1.0 / a[1] < y) y = color.getGreen() * 1.0 / a[1]; if (color.getBlue() * 1.0 / a[2] < y) y = color.getBlue() * 1.0 / a[2]; dst[r][c] = y; } } for (r = 0; r < k1; r ) { for (c = 0; c < k2; c ) { y = 255; for (i = -k / 2; i <= k / 2; i ) { for (j = -k / 2; j <= k / 2; j ) { if (r i < 0 || c j < 0 || r i >= k1 || c j >= k2) continue; if (dst[r i][c j] < y) y = dst[r i][c j]; } } dst[r][c] = y; t[r][c] = 1 - y; } } for (r = 0; r < k1; r ) { for (c = 0; c < k2; c ) { if (t[r][c] < t0) t[r][c] = t0; } } int[][] img2 = new int[k1][k2]; for (r = 0; r < k1; r ) { for (c = 0; c < k2; c ) { Color cr = img[r][c]; int rr = ((Double) ((cr.getRed() - a[0]) / t[r][c] a[0])) .intValue(); int gg = ((Double) ((cr.getGreen() - a[1]) / t[r][c] a[1])) .intValue(); int bb = ((Double) ((cr.getBlue() - a[2]) / t[r][c] a[2])) .intValue(); img2[r][c] = convertRGBToARGB(rr, gg, bb); } } return img2; }何恺明简介:
何恺明从小在广州长大,在广州执信中学就读时获得过全国物理竞赛和省化学竞赛的一等奖。
2003年5月,何恺明拿到保送清华的资格,是当年执信中学唯一保送上清华大学的学生。
2011年加入微软亚洲研究院(MSRA)工作,主要研究计算机视觉和深度学习。
2016年,加入Facebook AI Research(FAIR)担任研究科学家。
2020年1月11日,荣登AI全球最具影响力学者榜单。
以上内容为【图像去雾算法丨图像去雾算法python】的相关内容,更多相关内容关注lot物联网。