基于OpenCV的图像去雾程序(Single Image Haze Removal Using Dark Channel Prior)

基于opencv的单张图像去雾算法(一) 最近对图像去雾算法产生了兴趣,查阅学习了大量论文和大牛博客后,决定动手用自己熟悉的opencv来编写程序完成。文章专门记录了具体算法实现过程以及其中遇见的大量问题。供自己以后参考,当然也希望能给广大博友提供一些参考。本文着重讲实现过程,图像去雾理论会同过参考文献形式给出。整个内容拟大概分成三个章节来介绍。 开发环境:    计算机系统:win10(64-bit)     编译器:MS 阅读详情

去雾算法参考了一篇论文:

Kaiming He, Jian Sun, Xiaoou Tang. Single Image Haze Removal Using Dark Channel Prior

大致内容是提出了一个叫做暗原色先验的东西来对有雾图像进行处理,十分巧妙,有兴趣者可以看看。这里使用OpenCV实现文中的去雾算法,然而论文提到的soft matting未在本程序中实现。

 

 

代码如下:

[cpp]  view plain copy
  1. #include<iostream>  
  2. #include<cv.h>  
  3. #include<highgui.h>  
[cpp]  view plain copy
  1. char tbarname1[] = "调节block";  
  2. //定义两个滑动条,用于调节参数  
  3. char tbarname2[] = "调节w";  
  4. //w是为了保留一部分的雾  
  5. int block=5;  
  6. int w1=80;  
  7. double w;  
  8. IplImage *src=NULL;  
  9. IplImage *dst=NULL;  
  10. using namespace std;  
  11. //定义去雾函数如下  
  12. IplImage *quw(IplImage *src,int block,double w)  
  13. {  
  14.     //图像分别有三个颜色通道  
  15.     IplImage *dst1=NULL;  
  16.     IplImage *dst2=NULL;  
  17.     IplImage *dst3=NULL;  
  18.     IplImage *imgroi1;  
  19.     //dst1的ROI  
  20.     IplImage *imgroi2;  
  21.     //dst2的ROI  
  22.     IplImage *imgroi3;  
  23.     //dst3的ROI  
  24.     IplImage *roidark;  
  25.     //dark channel的ROI  
  26.     IplImage *dark_channel=NULL;  
  27.     //暗原色先验的指针  
  28.     IplImage *toushelv=NULL;  
  29.     //透射率  
  30.   
  31.     //去雾算法运算后的三个通道  
  32.     IplImage *j1=NULL;  
  33.     IplImage *j2=NULL;  
  34.     IplImage *j3=NULL;  
  35.     //去雾后的图像,三通道合并成  
  36.     IplImage *dst=NULL;  
  37.     //源图像ROI位置以及大小  
  38.     CvRect ROI_rect;  
  39.   
  40.     //分离的三个通道  
  41.     dst1=cvCreateImage(cvSize(src->width,src->height),IPL_DEPTH_8U,1);  
  42.     dst2=cvCreateImage(cvSize(src->width,src->height),IPL_DEPTH_8U,1);  
  43.     dst3=cvCreateImage(cvSize(src->width,src->height),IPL_DEPTH_8U,1);  
  44.   
  45.     //为各个ROI分配内存  
  46.     imgroi1=cvCreateImage(cvSize(block,block),IPL_DEPTH_8U,1);  
  47.     imgroi2=cvCreateImage(cvSize(block,block),IPL_DEPTH_8U,1);  
  48.     imgroi3=cvCreateImage(cvSize(block,block),IPL_DEPTH_8U,1);  
  49.     roidark=cvCreateImage(cvSize(block,block),IPL_DEPTH_8U,1);  
  50.   
  51.     //为j1 j2 j3分配大小  
  52.     j1=cvCreateImage(cvSize(src->width,src->height),IPL_DEPTH_8U,1);  
  53.     j2=cvCreateImage(cvSize(src->width,src->height),IPL_DEPTH_8U,1);  
  54.     j3=cvCreateImage(cvSize(src->width,src->height),IPL_DEPTH_8U,1);  
  55.   
  56.     //为暗原色先验指针分配大小  
  57.     dark_channel=cvCreateImage(cvSize(src->width,src->height),IPL_DEPTH_8U,1);  
  58.     //为透射率指针分配大小  
  59.     toushelv=cvCreateImage(cvSize(src->width,src->height),IPL_DEPTH_8U,1);  
  60.     //dst分配大小  
  61.     dst=cvCreateImage(cvSize(src->width,src->height),IPL_DEPTH_8U,3);  
  62.     //将原彩色图像分离成三通道  
  63.     cvSplit(src,dst1,dst2,dst3,NULL);  
  64.     //求暗原色  
  65.     ROI_rect.width=block;  
  66.     ROI_rect.height=block;  
  67.     ROI_rect.x=0;  
  68.     ROI_rect.y=0;  
  69.   
  70.   
  71.     int i;  
  72.     int j;  
  73.     double min1=0;  
  74.     double max1=0;  
  75.     double min2=0;  
  76.     double max2=0;  
  77.     double min3=0;  
  78.     double max3=0;  
  79.     double min=0;  
  80.     CvScalar value;  
  81.     for(i=0;i<src->width/block;i++)  
  82.     {        for(j=0;j<src->height/block;j++)  
  83.     {  
  84.         //分别计算三个通道内ROI的最小值  
  85.         cvSetImageROI(dst1,ROI_rect);  
  86.         cvCopy(dst1,imgroi1,NULL);  
  87.         cvMinMaxLoc(imgroi1,&min1,&max1,NULL,NULL);  
  88.         cvSetImageROI(dst2,ROI_rect);  
  89.         cvCopy(dst2,imgroi2,NULL);  
  90.         cvMinMaxLoc(imgroi2,&min2,&max2,NULL,NULL);  
  91.         cvSetImageROI(dst3,ROI_rect);  
  92.         cvCopy(dst3,imgroi3,NULL);  
  93.         cvMinMaxLoc(imgroi3,&min3,&max3,NULL,NULL);  
  94.         //求三个通道内最小值的最小值  
  95.         if(min1<min2)  
  96.             min=min1;  
  97.         else  
  98.             min=min2;  
  99.         if(min>min3)  
  100.             min=min3;//min为这个ROI中暗原色  
  101.         value=cvScalar(min,min,min,min);//min放在value中  
  102.         //min赋予dark_channel中相应的ROI  
  103.         cvSetImageROI(dark_channel,ROI_rect);  
  104.         cvSet(roidark,value,NULL);  
  105.         cvCopy(roidark,dark_channel,NULL);  
  106.         //释放各个ROI  
  107.         cvResetImageROI(dst1);  
  108.         cvResetImageROI(dst2);  
  109.         cvResetImageROI(dst3);  
  110.         cvResetImageROI(dark_channel);  
  111.         //转入下一个ROI  
  112.         ROI_rect.x=block*i;  
  113.         ROI_rect.y=block*j;  
  114.     }  
  115.     }  
  116.     //保存暗原色先验的图像  
  117.     //cvSaveImage("F:/人脸图片样本/1W 测试图库/T04950003.jpg",dark_channel);  
  118.     //利用得到的暗原色先验dark_channel_prior.jpg求大气光强  
  119.     double min_dark;  
  120.     double max_dark;  
  121.     CvPoint min_loc;  
  122.     CvPoint max_loc;//max_loc是暗原色先验最亮一小块的原坐标  
  123.     cvMinMaxLoc(dark_channel,&min_dark,&max_dark,&min_loc,&max_loc,NULL);  
  124.     cout<<max_loc.x<<" "<<max_loc.y<<endl;  
  125.     ROI_rect.x=max_loc.x;  
  126.     ROI_rect.y=max_loc.y;  
  127.     double A_dst1;//定义大气光成分的估计值  
  128.     double dst1_min;  
  129.     double A_dst2;  
  130.     double dst2_min;  
  131.     double A_dst3;  
  132.     double dst3_min;  
  133.     cvSetImageROI(dst1,ROI_rect);  
  134.     //按照论文方法求大气光强估计值  
  135.     cvCopy(dst1,imgroi1,NULL);  
  136.     cvMinMaxLoc(imgroi1,&dst1_min,&A_dst1,NULL,NULL);  
  137.     cvSetImageROI(dst2,ROI_rect);  
  138.     cvCopy(dst2,imgroi2,NULL);  
  139.     cvMinMaxLoc(imgroi2,&dst2_min,&A_dst2,NULL,NULL);  
  140.     cvSetImageROI(dst3,ROI_rect);  
  141.     cvCopy(dst3,imgroi3,NULL);  
  142.     cvMinMaxLoc(imgroi3,&dst3_min,&A_dst3,NULL,NULL);  
  143.     cout<<A_dst1<<" "<<A_dst2<<" "<<A_dst3<<endl;//这三值为大气光强度估计值  
  144.     //求透射率  
  145.     int k;  
  146.     int l;  
  147.     CvScalar m;  
  148.     CvScalar n;//暗原色先验各元素值  
  149.   
  150.     for(k=0;k<src->height;k++)  
  151.     {  
  152.         for(l=0;l<src->width;l++)  
  153.         {  
  154.             m=cvGet2D(dark_channel,k,l);  
  155.             n=cvScalar(255-w*m.val[0]);  
  156.             //w目的是保留一部分的雾,使图像看起来真实些  
  157.             cvSet2D(toushelv,k,l,n);  
  158.         }  
  159.     }  
  160.     //cvSaveImage("F:/人脸图片样本/1W 测试图库/T04950005.jpg",toushelv);  
  161.   
  162.     //求无雾图像  
  163.     int p,q;  
  164.     double tx;  
  165.     double jj1,jj2,jj3;  
  166.     CvScalar ix,jx;  
  167.     for(p=0;p<src->height;p++)  
  168.     {  
  169.         for(q=0;q<src->width;q++)  
  170.         {  
  171.             tx=cvGetReal2D(toushelv,p,q);  
  172.             tx=tx/255;  
  173.             if(tx<0.1)  
  174.                 tx=0.1;  
  175.             ix=cvGet2D(src,p,q);  
  176.             jj1=(ix.val[0]-A_dst1)/tx+A_dst1;//根据雾产生模型运算,还原出无雾图像  
  177.             jj2=(ix.val[1]-A_dst2)/tx+A_dst2;  
  178.             jj3=(ix.val[2]-A_dst3)/tx+A_dst3;  
  179.             jx=cvScalar(jj1,jj2,jj3,0.0);  
  180.             cvSet2D(dst,p,q,jx);  
  181.         }  
  182.     }  
  183.     //cvSaveImage("f:/removed_haze.jpg",dst);  
  184.   
  185.     //释放指针  
  186.     cvReleaseImage(&dst1);  
  187.     cvReleaseImage(&dst2);  
  188.     cvReleaseImage(&dst3);  
  189.     cvReleaseImage(&imgroi1);  
  190.     cvReleaseImage(&imgroi2);  
  191.     cvReleaseImage(&imgroi3);  
  192.     cvReleaseImage(&roidark);  
  193.     cvReleaseImage(&dark_channel);  
  194.     cvReleaseImage(&toushelv);  
  195.     cvReleaseImage(&j1);  
  196.     cvReleaseImage(&j2);  
  197.     cvReleaseImage(&j3);  
  198.     return dst;  
  199. }  
  200.   
  201. void on_trackbar1(int h)  
  202. {  
  203.     dst=quw(src,block,w);  
  204.     cvShowImage("目的图像",dst);  
  205.     //      cvWaitKey(0);  
  206. }  
  207. void on_trackbar2(int h)  
  208. {  
  209.   
  210.     w=(double)w1/100;  
  211.     dst=quw(src,block,w);  
  212.     cvShowImage("目的图像",dst);  
  213.     //      cvWaitKey(0);  
  214. }  
  215. //主函数如下  
  216. void main()  
  217. {  
  218.     //打开图像  
  219.     src=cvLoadImage("c:/2008414867469_2.jpg");  
  220.     //创造窗口  
  221.     cvNamedWindow("有雾图像");  
  222.     cvShowImage("有雾图像",src);  
  223.     cvNamedWindow("目的图像");  
  224.     cvShowImage("目的图像",src);  
  225.     cvCreateTrackbar(tbarname1, "目的图像", &block, 15, on_trackbar1);  
  226.     cvCreateTrackbar(tbarname2, "目的图像", &w1, 100, on_trackbar2);  
  227.     cvWaitKey(0);  
  228.     cvReleaseImage(&src);  
  229.     cvReleaseImage(&dst);  
  230. }  

opencv实现视频实时去雾算法 现在一系列的文章,有不少算法都于去雾有关,比如限制对比度自适应直方图均衡化算法原理、实现及效果、局部自适应自动色阶/对比度算法在图像增强上的应用这两个增强算法都有一定的去雾能力,而最直接的就是《Single Image Haze Removal Using Dark Channel Prior》一文中图像去雾算法的原理、实现、效果及其他 一文,描述了暗通道去雾这一state-of-the-art a 阅读详情

相关推荐

图像去雾算法opencv实现

图像去雾算法opencv实现图像去雾算法opencv实现 暗原色的opencv实现

openCV实战——图像去雾

全 局直方图处理通过对 RGB 图像的 R、G、B 三层通道分别进行直方图均衡化,再整合到新的图 像的方式进行。将整幅图像分成很多小块,然后再对每一个小块分别进行直方图均衡化,最后进行拼接。掩膜的主要是用来提取感兴趣区域。即自适应直方图均衡化。

qq_35732321的博客 3300

Retinex快速图像去雾

通过对汪荣贵基于暗原色先验的Retinex去雾的学习而编写的对应的matlab去雾程序,对于雾不是特别浓的时候去雾效果还是不错的,这里共享matlab源码,里卖弄注释很全,都是自己注释的。

图像去雾的OpenCV程序

去雾算法参考了一篇论文: Kaiming He, Jian Sun, Xiaoou Tang. Single Image Haze Removal Using Dark Channel Prior 大致内容是提出了一个叫做暗原色先验的东西来对有雾图像进行处理,十分巧妙,有兴趣者可以看看。这里使用OpenCV实现文中的去雾算法,然而论文提到的soft matting未在本程序中实现。

燕子lovinglife 3269

DELL服务器BIOS下配置RAID阵列

dell服务器配置raid阵列

weixin_58250887的博客 1万+

Quartus的Signal Tap II的使用技巧

Signal Tap II全称Signal Tap II Logic Analyzer,是第二代系统级调试工具,它集成在Quartus II软件中,可以捕获和显示实时信号,是一款功能强大、极具实用性的FPGA片上调试工具软件。传统的FPGA板级调试是由外接的逻辑分析仪连接到FPGA的控制引脚,将内部引号引出至引脚I/O上,接着进行板级调试。

qq_37624854的博客 5897

opencv 图像去雾的C++实现

去雾原理原理是根据何凯明博士的《Single Image Haze Removal Using Dark Channel Prior》这篇文章,介绍见https://www.cnblogs.com/Imageshop/p/3281703.html。及Python代码见:https://blog.youkuaiyun.com/wsp_1138886114/article/details/95012769。 本...

qq_34902877的博客 3676

PCL体素滤波器【2026最新版】

PCL实现的VoxelGrid类和ApproximateVoxelGrid体素滤波,详细记录。博客长期更新,本文最近一次更新时间为:2026年3月14日。

点云侠的博客 39万+

(2020)Single Image Haze Removal Using Dark Channel Prior论文笔记

Single Image Haze Removal Using Dark Channel Prior 本文2009年CVPR最佳论文,作者何凯明,是国内第一个在计算机视觉与模式识别会议上获得该奖项Doctor 如果是涉及到图像去雾领域这篇论文可以说是无人不晓。论文在的引用量已达到4000+。 论文读起来十分易懂,而读完只想说 :何凯明 ???? ????(怪我我才学浅薄,找不到更好的词形容)​ 整体思路 描述雾图像的等式(这个是前人已经提出的) 上述公式:I(x)=J(x)t(x)+A(1−t(

Troublemaker丶的博客 847

Qt —— 在Win11下“Qt for Android“开发环境,通过USB在真机(华为Meta60 PRO)上调试运行,并打包APK并在真实手机运行

Qt —— 在Win11下“Qt for Android“开发环境,打包APK并在真实手机运行

310

26、多级快速多极子算法(MLFMA)在大规模电磁问题中的应用

本文探讨了多级快速多极子算法(MLFMA)在大规模电磁问题中的高效应用。通过分层分区策略,MLFMA在分布式内存架构上实现了高效并行化,能够求解包含数亿未知数的复杂电磁问题。文章分析了介质球体、半球透镜、周期性结构和损耗介质阵列等典型案例,验证了MLFMA的高精度与广泛适用性。同时,MLFMA被应用于实际场景如隐身目标Flamme的外部共振分析和含分裂环谐振器的超材料设计,展示了其在航空航天、超材料和生物医学等领域的广阔前景。未来发展方向包括算法优化、多物理场耦合和实时计算,进一步拓展其应用潜力。

t8u9v0w1x的博客 117

Single Image Haze Removal 图像去雾 -CVPR 09 Best Paper

Single Image Haze Removal 图像去雾 -CVPR 09 Best Paper

kahncc的博客 194

wxComboBox类的使用方法及示例代码

其中,parent表示该控件的父窗口,ID_COMBOBOX是该控件的ID,用于在事件处理函数中区分不同的控件,"默认选项"是下拉列表框的默认选项,options是wxArrayString类型的数组,用于存储下拉列表框中的选项,style可以指定wxComboBox的样式。wxComboBox是wxWidgets中的一个常用控件,它可以被用来显示一组在下拉列表框中的选项,并允许用户从中选择一个选项。上述就是wxComboBox类的基本使用方法,使用这个控件可以方便地实现下拉列表框的功能。

学习使你进步。 712

暗通道先验去雾算法实现

本文实现了一种基于暗通道先验(DCP)的图像去雾算法。该算法首先计算输入图像的暗通道,通过取RGB三通道最小值获得;然后估计大气光值,选择暗通道中最亮0.1%像素在原始图像中的最大值;接着计算透射率图并利用物理模型恢复无雾图像。实验表明该算法在浅雾场景效果较好,但存在一定局限性。评估采用PSNR和SSIM指标,结果显示去雾后图像质量有显著提升。该实现支持PyTorch框架,可方便应用于不同尺寸的输入图像。

m0_62919535的博客 1660

博途PLC模糊PID控制(量化因子和比例因子)

参数"量化因子和比例因子",都是为了对清晰值进行比例变换而设置的,其作用是使变量按一定比例进行放大或缩小,以便和我们的模糊论域相匹配完成一一映射。这种变换对整个系统的工作性能也是有影响的。(其实相当于额外引入了比例作用,所以说模糊PID的调节是个系统工程)。限于本人能力,文中难免出现错误和不足,欢迎大家批评和指正。博途PLC的模糊PID控制完整算法可以参看下面这篇文章博途PLC模糊PID控制详解(SCL完整源代码+参数)_RXXW_Dor的博客-优快云博客。......

RXXW_Dor的博客 5268

【小白深度教程 1.32】手把手教你从多视角图像进行 3D 重建(SfM 算法)

重建的目标是从一组照片中推导场景的几何结构,假设摄像机位置和内部参数是已知的或可以从图像集中猜测。 这是通过使用多个照片,在其中应用运动结构法(Structure from Motion,SfM)来解决像素级对应问题,部分地恢复3D信息来实现的。

2401_87064292的博客 2158

Single Image Haze Removal Using Dark Channel Prior

import cv2 import numpy as np from matplotlib import pyplot as plt %matplotlib inlineStep1. Get Dark Channel 求出每个像素RGB分量中的最小值,存入一副和原始图像大小相同的灰度图中; 灰度图进行最小值滤波,滤波的半径由窗口大小决定,一般有WindowSize = 2 * Radius + 1;

空城记 1557

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Single Image Haze Removal(图像去雾)-CVPR’09 Best Paper

 出处:http://blog.youkuaiyun.com/abcjennifer/article/details/6662706 真正了解了什么叫最简单的就是最美好的 真正的好文章不需要大堆公式堆积显得充实,而是最最平实的思想! 这篇文章的:原文PDF、数据集、幻灯片、视频。感兴趣的可以了解一下。 这篇文章的目的就是以最简单的思路将图像达到去雾效果。用Matlab编了一下,效果图

3757

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

Single Image Haze Removal Using Dark Channel Prior翻译

转载此处http://blog.youkuaiyun.com/lee_cv/article/details/17280479 这篇是Image Dehazing 方向的经典文章,翻译的不错,供大家分享哈! soft matting(软抠图)这块看的不是很明白,还有开始提出的雾天图像成像的模型也不是很明白 继续研究中……

liuyun的专栏 1936

Single Image Haze Removal Using Dark Channel Prior OpenCV Version

Use OpenCV to realize, Here is the main Function 代码 1voidmenu(char*imageFilePath,int*patchSize);2voidDCP(IplImage*src,CvMat*DarkChannelMat,intsize);3voidEAL(IplImage*src,CvMat*Da...

weixin_30852451的博客 107

《Single Image Haze Removal Using Dark Channel Prior》一文中图像去雾算法的原理、实现、效果(速度可实时)

import cv2 import numpy as np 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)+[.

lbaihao的专栏 305

python opencv视频除雾算法

#https://www.pianshen.com/article/949473269/ #author:ljj #time:2021/7 import cv2 import math import numpy as np class RmvFog: #remove fog from video def __init__(self): None def DarkChannel(self,im, sz): b, g, r = cv2.split(im)..

识物专栏 11万+

基于暗通道去雾算法的实现与优化(二)opencv在pc上的实现

上一篇中,学习了何的论文中的去雾方法,这一篇中,我按照何的论文思路借助opencv 2.4.10 进行了实现,效果的确很好,就是耗时太多了,效果见下图:蓝色圆圈代表大气光值的取值点。 突然发现上一篇中忘了介绍大气光值A的求解了,论文中是这样做的: 1.首先取暗通道图中最亮的千分之一的像素点。 2.根据这些像素点的位置在原图中搜索一个最亮的点,这个点的强度(intensity)

CHEN的专栏 1万+
上一篇: Bag-of-words模型
下一篇: OpenCV 2.4.2在VS2010下的安装(使用预编译库)
Savitch
博客等级 码龄16年 84粉丝 130原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值