OpenCV编程->OpenMP优化入门

找了个去雾源码,做了简单的优化:

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;
}
编译运行后:


OpenCV编程->OpenMP优化入门_第1张图片

得到结果如下:

OpenCV编程->OpenMP优化入门_第2张图片

其实上面的代码还可以再优化:

三通道可以分配三个线程分别计算,然后同步再做计算,应该效果会更好,本人的计算机就个双核,所以优势也体现不出来,就没做过多的优化了,就当入门。








你可能感兴趣的:(OpenCV编程->OpenMP优化入门)