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

该代码部分实现了何凯明博士的论文暗通道去雾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.;d
	ouble 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;
			else
				min=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
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值