找了个去雾源码,做了简单的优化:
IplImage *quw1(IplImage *src,int block,double w) { //图像分别有三个颜色通道 IplImage *dst1=NULL; IplImage *dst2=NULL; IplImage *dst3=NULL; IplImage *imgroi1; //dst1的ROI IplImage *imgroi2; //dst2的ROI IplImage *imgroi3; //dst3的ROI IplImage *roidark; //dark channel的ROI IplImage *dark_channel=NULL; //暗原色先验的指针 IplImage *toushelv=NULL; //透射率 //去雾算法运算后的三个通道 IplImage *j1=NULL; IplImage *j2=NULL; IplImage *j3=NULL; //去雾后的图像,三通道合并成 IplImage *dst=NULL; //源图像ROI位置以及大小 CvRect ROI_rect; //分离的三个通道 dst1=cvCreateImage(cvSize(src->width,src->height),IPL_DEPTH_8U,1); dst2=cvCreateImage(cvSize(src->width,src->height),IPL_DEPTH_8U,1); dst3=cvCreateImage(cvSize(src->width,src->height),IPL_DEPTH_8U,1); //为各个ROI分配内存 imgroi1=cvCreateImage(cvSize(block,block),IPL_DEPTH_8U,1); imgroi2=cvCreateImage(cvSize(block,block),IPL_DEPTH_8U,1); imgroi3=cvCreateImage(cvSize(block,block),IPL_DEPTH_8U,1); roidark=cvCreateImage(cvSize(block,block),IPL_DEPTH_8U,1); //为j1 j2 j3分配大小 j1=cvCreateImage(cvSize(src->width,src->height),IPL_DEPTH_8U,1); j2=cvCreateImage(cvSize(src->width,src->height),IPL_DEPTH_8U,1); j3=cvCreateImage(cvSize(src->width,src->height),IPL_DEPTH_8U,1); //为暗原色先验指针分配大小 dark_channel=cvCreateImage(cvSize(src->width,src->height),IPL_DEPTH_8U,1); //为透射率指针分配大小 toushelv=cvCreateImage(cvSize(src->width,src->height),IPL_DEPTH_8U,1); //dst分配大小 dst=cvCreateImage(cvSize(src->width,src->height),IPL_DEPTH_8U,3); //将原彩色图像分离成三通道 cvSplit(src,dst1,dst2,dst3,NULL); //求暗原色 ROI_rect.width=block; ROI_rect.height=block; ROI_rect.x=0; ROI_rect.y=0; int i; int j; double min1=0; double max1=0; double min2=0; double max2=0; double min3=0; double max3=0; double min=0; CvScalar value; #pragma omp parallel for for(i=0;i<src->width/block;i++) { for(j=0;j<src->height/block;j++) { //分别计算三个通道内ROI的最小值 cvSetImageROI(dst1,ROI_rect); cvCopy(dst1,imgroi1,NULL); cvMinMaxLoc(imgroi1,&min1,&max1,NULL,NULL); cvSetImageROI(dst2,ROI_rect); cvCopy(dst2,imgroi2,NULL); cvMinMaxLoc(imgroi2,&min2,&max2,NULL,NULL); cvSetImageROI(dst3,ROI_rect); cvCopy(dst3,imgroi3,NULL); cvMinMaxLoc(imgroi3,&min3,&max3,NULL,NULL); //求三个通道内最小值的最小值; if(min1<min2) min=min1; else min=min2; if(min>min3) min=min3;//min为这个ROI中暗原色 value=cvScalar(min,min,min,min);//min放在value中; //min赋予dark_channel中相应的ROI; cvSetImageROI(dark_channel,ROI_rect); cvSet(roidark,value,NULL); cvCopy(roidark,dark_channel,NULL); //释放各个ROI; cvResetImageROI(dst1); cvResetImageROI(dst2); cvResetImageROI(dst3); cvResetImageROI(dark_channel); //转入下一个ROI ROI_rect.x=block*i; ROI_rect.y=block*j; } } //保存暗原色先验的图像 cvSaveImage("D:/dark_channel_prior.jpg",dark_channel); //利用得到的暗原色先验dark_channel_prior.jpg求大气光强 double min_dark; double max_dark; CvPoint min_loc; CvPoint max_loc; //max_loc是暗原色先验最亮一小块的原坐标 cvMinMaxLoc(dark_channel,&min_dark,&max_dark,&min_loc,&max_loc,NULL); // cout<<max_loc.x<<" "<<max_loc.y<<endl; ROI_rect.x=max_loc.x; ROI_rect.y=max_loc.y; double A_dst1;//定义大气光成分的估计值 double dst1_min; double A_dst2; double dst2_min; double A_dst3; double dst3_min; cvSetImageROI(dst1,ROI_rect); //按照论文方法求大气光强估计值 cvCopy(dst1,imgroi1,NULL); cvMinMaxLoc(imgroi1,&dst1_min,&A_dst1,NULL,NULL); cvSetImageROI(dst2,ROI_rect); cvCopy(dst2,imgroi2,NULL); cvMinMaxLoc(imgroi2,&dst2_min,&A_dst2,NULL,NULL); cvSetImageROI(dst3,ROI_rect); cvCopy(dst3,imgroi3,NULL); cvMinMaxLoc(imgroi3,&dst3_min,&A_dst3,NULL,NULL); // cout<<A_dst1<<" "<<A_dst2<<" "<<A_dst3<<endl;//这三值为大气光强度估计值 //求透射率 int k; int l; CvScalar m; CvScalar n;//暗原色先验各元素值 #pragma omp parallel for for(k=0;k<src->height;k++) { for(l=0;l<src->width;l++) { m=cvGet2D(dark_channel,k,l); n=cvScalar(255-w*m.val[0]); //w目的是保留一部分的雾,使图像看起来真实些 cvSet2D(toushelv,k,l,n); } } cvSaveImage("D:/toushelv.jpg",toushelv); //求无雾图像 int p,q; double tx; double jj1,jj2,jj3; CvScalar ix,jx; #pragma omp parallel for for(p=0;p<src->height;p++) { for(q=0;q<src->width;q++) { tx=cvGetReal2D(toushelv,p,q); tx=tx/255; if(tx<0.1) tx=0.1; ix=cvGet2D(src,p,q); jj1=(ix.val[0]-A_dst1)/tx+A_dst1;//根据雾产生模型运算,还原出无雾图像 jj2=(ix.val[1]-A_dst2)/tx+A_dst2; jj3=(ix.val[2]-A_dst3)/tx+A_dst3; jx=cvScalar(jj1,jj2,jj3,0.0); cvSet2D(dst,p,q,jx); } } cvSaveImage("3.jpg",dst); //释放指针 cvReleaseImage(&dst1); cvReleaseImage(&dst2); cvReleaseImage(&dst3); cvReleaseImage(&imgroi1); cvReleaseImage(&imgroi2); cvReleaseImage(&imgroi3); cvReleaseImage(&roidark); cvReleaseImage(&dark_channel); cvReleaseImage(&toushelv); cvReleaseImage(&j1); cvReleaseImage(&j2); cvReleaseImage(&j3); return dst; }编译运行后:
得到结果如下:
其实上面的代码还可以再优化:
三通道可以分配三个线程分别计算,然后同步再做计算,应该效果会更好,本人的计算机就个双核,所以优势也体现不出来,就没做过多的优化了,就当入门。