持续记录中~~~ 这个函数求取三个通道中最小值,然后以最小值组成一幅灰度图-darkchannel,并返回大气强度A double darkChannel(const cv::Mat &src,cv::Mat &dst){ cv::Mat rawtemp; rawtemp.create(src.size(),src.type()); for (int i = 0; i < height; i++) { const uchar* imgP = src.ptr<uchar>(i); uchar* dstP = rawImage.ptr<uchar>(i); for (int j = 0; j < width; j++) { int b=imgP[3*j]; int g=imgP[3*j+1]; int r=imgP[3*j+2]; dstP[j] = IMAGE_MIN(IMAGE_MIN(b,g),r); } } //把图像分成patch,求patch框内的最小值,得到dark_channel image//range 0-255 center(i,j),every pixel (i,j) of rawtemp's value is Rect minvalue// dx is patchSize/2//rawtemp is the return of function of minChannel cv::Mat rect_img; for(int j=0;j<height;j++){ for(int i=0;i<width;i++){ cv::getRectSubPix(rawtemp,cv::Size(patchSize,patchSize),cv::Point(j,i),rect_img); double min_value = 0; cv::minMaxLoc(rect_img,&min_value,0,0,0); //using saturate_cast to set pixel value [0,255] dst.at<uchar>(j,i)= cv::saturate_cast<uchar>(min_value); } } //求大气强度A,并没有分开求各个通道的A,取了整体的A值double maxval; int minAtomsLight = 220;//经验值 minMaxLoc(dst,NULL,&maxval); double A = min(minAtomsLight, (int)maxval);return A;} /////////////////////////////////////////////////////////////////////////// //当然如果你对opencv比较熟悉的话,可以看出,上面那段代码的后半部分,也就是图像patch块的那部分可以简单的用中值滤波来代替,也就是上面那段代码可以这样写 double darkChannel(const cv::Mat &src,cv::Mat &dst){ Mat rawtemp; rawtemp.create(src.size(),CV_8UC1); for(int i=0; i<src.rows; i++) { const uchar* imgP = src.ptr<uchar>(i); uchar* dstP = rawImage.ptr<uchar>(i); for(int j=0; j<src.cols; j++) { int b=imgP[3*j]; int g=imgP[3*j+1]; int r=imgP[3*j+2]; dstP[j] = IMAGE_MIN(IMAGE_MIN(b,g),r); } } // GaussianBlur(rgbmin, MDCP, Size(patch,patch),0); //imshow("DCP",MDCP); medianBlur(rawtemp, rawtemp, patchSize); //求大气强度A,并没有分开求各个通道的A,取了整体的A值 double maxval; int minAtomsLight = 220;//经验值 minMaxLoc(dst,NULL,&maxval); double A = min(minAtomsLight, (int)maxval); return A; }
用查找表求粗透射率 cv::Mat image_trans; image_trans.create(nHeight,nWidth,CV_8UC1); cv::Mat look_up; look_up.create(1,256,CV_8UC1); uchar* look_up_ptr = look_up.data; //reservation_factor =0.95 for (int k = 0;k < 256; k++) { int value = 255*(1- w * k / A); look_up_ptr[k] = cv::saturate_cast<uchar>(value); } cv::LUT(rawtemp,look_up,transmission);
如果不考虑细介质透射率,直接用上面求出的粗透射率来求去雾图,则
//dehazing image //t 是得到的transmission //al是大气强度 Mat getDehaze(Mat source, Mat t, int A) { double tmin = 0.1; double tmax; Scalar tran; Vec3b src; Mat dehazed = Mat::zeros(source.rows, source.cols, CV_8UC3); // Mat lookup; // look_up.create(1,256,CV_8UC1); // uchar* look_up_ptr = look_up.data; for(int i=0; i<source.rows; i++) { for(int j=0; j<source.cols; j++) { tran = t.at<uchar>(i,j); src = source.at<Vec3b>(i,j); tmax = (tran.val[0]/255) < tmin ? tmin : (tran.val[0]/255); //(I-A)/t +A for(int k=0; k<3; k++) { dehazed.at<Vec3b>(i,j)[k] = abs((src.val[k] - A) / tmax + al) > 255 ? 255 : abs((src.val[k] - A) / tmax + al); } } } return dehazed; }