单幅图像基于暗通道的图像去雾

来源:互联网 发布:java工程师的直接上级 编辑:程序博客网 时间:2024/04/28 14:41

该代码部分实现了何凯明博士的论文暗通道去雾Single Image Haze Removal Using Dark Channel Prior,导向滤波算法尚未实现。

基于暗通道先验的单幅图去雾算法大致如下:
雾图I,目标无雾图J,雾图形成模型I=J*t+A(1-t)。
1、暗通道,窗口。
2、大气光成分:A。
3、去雾因子:w。
4、透射图:1-w*min(min(I/A))

5、导向滤波求透射率:t。
6、还原无雾图:J=(I-A)/t+A。
涉及到的滤波技术为soft matting和guidedfilter,boxfilter。(matlab和opencv实现导向滤波)


#include "cv.h"#include "highgui.h" //#include "GuidedFilter.h"/*//这个求暗通道过于简单粗暴,与何凯明论文中的描述有出入!!!//正确的方法是求像素邻域的局部最小值,类似局部最小值滤波。//方法不难,请自行实现。IplImage* MinFilter(IplImage *img,int y,int x){IplImage *img_dark=cvCreateImage(cvSize(img->width,img->height),img->depth,1);IplImage *temp=cvCreateImage(cvSize(x,y),img->depth,img->nChannels);IplImage *temp0=cvCreateImage(cvSize(x,y),img->depth,1);CvScalar scalar={0.};double min=0.;double min1=0.;double min2=0.;double min3=0.;CvRect rect=cvRect(0,0,x,y);CvRect rect0=cvRect(0,0,x,y);int img_h=img->height;int img_w=img->width;for(int i=0;i<=img_h/y;i++){if(i*y+1>img_h)continue;rect.y=i*y;if(i*y>img_h-y){rect.height=img_h-i*y;rect0.height=img_h-i*y;}rect.width=x;rect0.width=x;for(int j=0;j<=img_w/x;j++){if(j*x+1>img_w)continue;rect.x=j*x;if(j*x>img_w-x){rect.width=img_w-j*x;rect0.width=img_w-j*x;}cvSetImageROI(img,rect);cvSetImageROI(temp,rect0);cvCopy(img,temp);cvResetImageROI(img);cvSetImageCOI(temp,1);cvMinMaxLoc(temp,&min1,NULL,NULL,NULL);cvSetImageCOI(temp,2);cvMinMaxLoc(temp,&min2,NULL,NULL,NULL);cvSetImageCOI(temp,3);cvMinMaxLoc(temp,&min3,NULL,NULL,NULL);cvSetImageCOI(temp,0);if(min1<min2)min=min1;elsemin=min2;if(min>min3)min=min3;scalar=cvScalar(min,0,0,0);cvSet(temp0,scalar,NULL);cvSetImageROI(temp0,rect0);cvSetImageROI(img_dark,rect);cvCopy(temp0,img_dark);cvResetImageROI(temp0);cvResetImageROI(img_dark);}}cvReleaseImage(&temp);cvReleaseImage(&temp0);return img_dark;}*/int main(){int block_y=4;int block_x=4;double w=0.98;IplImage *img=cvLoadImage("train.bmp",-1);//定义原始图像int img_h=img->height;int img_w=img->width;IplImage *des=cvCreateImage(cvSize(img->width,img->height),img->depth,img->nChannels);IplImage *img_dark=cvCreateImage(cvSize(img->width,img->height),img->depth,1);IplImage *img_t=cvCreateImage(cvSize(img->width,img->height),img->depth,1);img_dark=MinFilter(img,block_y,block_x);//暗通道图//计算大气光值CvPoint max_point;double a_max=0.;cvMinMaxLoc(img_dark,NULL,&a_max,NULL,&max_point,NULL);int x=(max_point.x>(img_w-block_x))?(img_w-block_x):max_point.x;int y=(max_point.y>(img_h-block_y))?(img_h-block_y):max_point.y;CvScalar a={0.};double a_max0=0;double a_max1=0;double a_max2=0;for(int i=y;i<y+block_y;i++){for(int j=x;j<x+block_x;j++){a=cvGet2D(img,i,j);if(a_max0<a.val[0])a_max0=a.val[0];if(a_max1<a.val[1])a_max1=a.val[1];if(a_max2<a.val[2])a_max2=a.val[2];}}//计算透射率CvScalar p={0.};CvScalar q={0.}; for(int i=0;i<img->height;i++){for(int j=0;j<img->width;j++){p=cvGet2D(img_dark,i,j);//q.val[0]=1-w*p.val[0]/a_max;q=cvScalar(255-w*p.val[0]);cvSet2D(img_t,i,j,q);}}cvSmooth(img_t,img_t,CV_BLUR,block_y*3,block_x*3);//还原图像CvScalar I={0.};CvScalar t={0.};CvScalar dst={0.};double dst0,dst1,dst2;for(int i=0;i<img->height;i++){for(int j=0;j<img->width;j++){I=cvGet2D(img,i,j);double t=cvGetReal2D(img_t,i,j);t=t/255;if(t<0.1)t=0.1;//dst.val[0]=(I.val[0]-a_max0)/t+a_max0;//dst.val[1]=(I.val[1]-a_max1)/t+a_max1;//dst.val[2]=(I.val[2]-a_max2)/t+a_max2;dst0=(I.val[0]-a_max0)/t+a_max0;dst1=(I.val[1]-a_max1)/t+a_max1;dst2=(I.val[2]-a_max2)/t+a_max2;dst=cvScalar(dst0,dst1,dst2,0);cvSet2D(des,i,j,dst);}}cvNamedWindow("原图",CV_WINDOW_AUTOSIZE);cvShowImage("原图",img);cvNamedWindow("暗通道先验图",CV_WINDOW_AUTOSIZE);cvShowImage("暗通道先验图",img_dark);cvNamedWindow("透射率图",CV_WINDOW_AUTOSIZE);cvShowImage("透射率图",img_t);cvNamedWindow("目标图",CV_WINDOW_AUTOSIZE);cvShowImage("目标图",des);cvWaitKey(0);cvReleaseImage(&img);cvReleaseImage(&img_dark);cvReleaseImage(&img_t);cvReleaseImage(&des);cvDestroyWindow("原图");cvDestroyWindow("暗通道先验图");cvDestroyWindow("透射率图");cvDestroyWindow("目标图");return 0;} 


0 0
原创粉丝点击