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

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

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. }  

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值