opencv暗通道图像去雾(Mat风格代码)

最近《数字图像处理》课需要做图像去雾的工作,然后我们百度了一下,找到下面的链接(主要的方法有图像增强和图像复原两大类):

http://www.cspmag.cn/jscx/spjk/201406/1336.html

最终,我和队友选择了使用暗通道先验的方法,我们参考的是下面的代码:

http://blog.sina.com.cn/s/blog_4d8730df0100m8lz.html

上面的代码是对何恺明博士Single Image Haze Removal Using Dark Channel Prior》 一文的实现,但是没有使用soft matting,在最小值滤波以及求A的时候也有一些出入,我们直接跑了一下,大致的效果还行,但是代码的风格是OpenCV1.0的风格,使用的是IplImage,我们决定将它改成OpenCV2.0风格的代码,我们修改的代码如下,具体的思路没有改变:

我们使用的环境是VS2013+OpenCV3.1

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

#include<iostream>
#include<opencv2\opencv.hpp>


using namespace std;
using namespace cv;


string tbarname1 = "block:";
//定义两个滑动条,用于调节参数
string tbarname2 = "w:";
//w是为了保留一部分的雾
int block = 5;
int w1 = 95;
double w = (double)w1/100;
Mat src;
Mat dst;


//定义去雾函数如下
Mat haze_removal(Mat src, int block, double w)
{
//图像分别有三个颜色通道
vector<cv::Mat>dst(src.channels());
Mat imgROI1;
//dst[0]的ROI
Mat imgROI2;
//dst[1]的ROI
Mat imgROI3;
//dst[2]的ROI
Mat darkROI;
//dark channel的ROI
Mat darkChannel;
//暗原色先验
Mat imgTransmissivity;
//透射率


//去雾算法运算后的三个通道
Mat removalDst1;
Mat removalDst2;
Mat removalDst3;
//去雾后的图像,三通道合并成
Mat dst3D;
//源图像ROI位置以及大小
Rect ROI_rect;


//为各个ROI分配内存
imgROI1 = Mat(block, block, CV_8UC1);
imgROI2 = Mat(block, block, CV_8UC1);
imgROI3 = Mat(block, block, CV_8UC1);
darkROI = Mat(block, block, CV_8UC1);


//为removalDst1 removalDst2 removalDst3分配大小
removalDst1 = Mat(src.rows, src.cols, CV_8UC1);
removalDst2 = Mat(src.rows, src.cols, CV_8UC1);
removalDst3 = Mat(src.rows, src.cols, CV_8UC1);


//为暗原色先验分配大小
darkChannel = Mat(src.rows, src.cols, CV_8UC1);
//为透射率分配大小
imgTransmissivity = Mat(src.rows, src.cols, CV_8UC1);
//dst3D分配大小
dst3D = Mat(src.rows, src.cols, CV_8UC3);
//将原彩色图像分离成三通道
split(src, dst);
//求暗原色
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;
for (i = 0; i<src.cols / block; i++)
{
for (j = 0; j<src.rows / block; j++)
{
//分别计算三个通道内ROI的最小值
imgROI1 = dst[0](ROI_rect);
minMaxIdx(imgROI1, &min1, &max1);
imgROI2 = dst[1](ROI_rect);
minMaxIdx(imgROI2, &min2, &max2);
imgROI3 = dst[2](ROI_rect);
minMaxIdx(imgROI3, &min3, &max3);
//求三个通道内最小值的最小值
if (min1<min2)
min = min1;
else
min = min2;
if (min>min3)
min = min3;//min为这个ROI中暗原色
//min赋予darkChannel中相应的ROI
darkROI = darkChannel(ROI_rect);
Mat tmp = Mat(block, block, CV_8UC1, Scalar(min));
tmp.copyTo(darkROI);
//转入下一个ROI
ROI_rect.x = block*i;
ROI_rect.y = block*j;
}
}
//保存暗原色先验的图像
imwrite("F:\\My_Desktop\\Haze_Removal\\darkChannel.jpg", darkChannel);
//利用得到的暗原色先验dark_channel_prior.jpg求大气光强
double minDark;
double maxDark;
int minLoc[2] = { 255, 255 };
int maxLoc[2] = { 255, 255 };//maxLoc是暗原色先验最亮一小块的原坐标
minMaxIdx(darkChannel, &minDark, &maxDark, minLoc, maxLoc);
cout << maxLoc[1] << " " << maxLoc[0] << endl;
ROI_rect.x = maxLoc[1];
ROI_rect.y = maxLoc[0];
double dst1A;//定义大气光成分的估计值
double minDst1;
double dst2A;
double minDst2;
double dst3A;
double minDst3;

//按照论文方法求大气光强估计值
imgROI1 = dst[0](ROI_rect);
minMaxIdx(imgROI1, &minDst1, &dst1A);
imgROI2 = dst[1](ROI_rect);
minMaxIdx(imgROI2, &minDst2, &dst2A);
imgROI3 = dst[2](ROI_rect);
minMaxIdx(imgROI3, &minDst3, &dst3A);
cout << dst1A << " " << dst2A << " " << dst3A << endl;//这三值为大气光强度估计值
//求透射率
int k;
int l;
uchar m;
uchar n;//暗原色先验各元素值


for (k = 0; k<src.rows; k++)
{
for (l = 0; l<src.cols; l++)
{
m = darkChannel.at<uchar>(k, l);
n = 255 - w * m;
//w目的是保留一部分的雾,使图像看起来真实些
imgTransmissivity.at<uchar>(k, l) = n;
}
}
imwrite("F:\\My_Desktop\\Haze_Removal\\imgTransmissivity.jpg", imgTransmissivity);


//求无雾图像
int p, q;
double tx;
uchar srcB, srcG, srcR;
CvScalar ix, jx;
for (p = 0; p<src.rows; p++)
{
for (q = 0; q<src.cols; q++)
{
tx = imgTransmissivity.at<uchar>(p, q);
tx = tx / 255;
if (tx<0.1)
tx = 0.1;
srcB = (src.at<Vec3b>(p, q)[0] - dst1A) / tx + dst1A;//根据雾产生模型运算,还原出无雾图像
srcG = (src.at<Vec3b>(p, q)[1] - dst2A) / tx + dst2A;
srcR = (src.at<Vec3b>(p, q)[2] - dst3A) / tx + dst3A;
dst3D.at<Vec3b>(p, q)[0] = srcB;
dst3D.at<Vec3b>(p, q)[1] = srcG;
dst3D.at<Vec3b>(p, q)[2] = srcR;
}
}
imwrite("F:\\My_Desktop\\Haze_Removal\\removed_haze.jpg", dst3D);
return dst3D;
}


void on_trackbar1(int h,void *pt)
{
dst = haze_removal(src, block, w);
imshow("目的图像", dst);
}
void on_trackbar2(int h,void *pt)
{
w = (double)w1 / 100;
dst = haze_removal(src, block, w);
imshow("目的图像", dst);
}
//主函数如下
void main()
{
//打开图像
src = imread("F:\\My_Desktop\\Haze_Removal\\wu-035.jpg");
//创造窗口
namedWindow("有雾图像", CV_WINDOW_AUTOSIZE);
imshow("有雾图像", src);
namedWindow("目的图像", CV_WINDOW_AUTOSIZE);
createTrackbar(tbarname1, "目的图像", &block, 15, on_trackbar1);
createTrackbar(tbarname2, "目的图像", &w1, 100, on_trackbar2);
waitKey(0);
}

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
OpenCV暗通道去雾的步骤如下: 1. 读取待去雾的图像I(x)和全球大气光成分A。 2. 计算暗通道图像Jdark(x),其中Jdark(x) = min{min{I(x)}|x∈Ω},Ω为图像块的集合,一般取3*3或者15*15的块。 3. 估计全球大气光成分A,其中A = max{J(x)|x∈Ω},Ω为图像块的集合,一般取3*3或者15*15的块。 4. 估计折射率t,其中t = 1 - w * min{Jdark(x)/A|x∈Ω},w为权重系数,一般取0.95。 5. 对每个颜色通道进行去雾处理,其中J(x) = (I(x) - A) / t + A。 6. 输出去雾后的图像J(x)。 下面是OpenCV暗通道去雾的Python代码示例: ```python import cv2 import numpy as np def dark_channel(image, block_size): # 计算暗通道图像 b, g, r = cv2.split(image) min_channel = cv2.min(cv2.min(r, g), b) kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (block_size, block_size)) dark_channel = cv2.erode(min_channel, kernel) return dark_channel def estimate_atmosphere(image, dark_channel): # 估计全球大气光成分 h, w = image.shape[:2] flat_image = image.reshape(h * w, 3) flat_dark = dark_channel.reshape(h * w) indices = np.argsort(flat_dark)[::-1][:h * w // 100] atmosphere = np.max(flat_image[indices], axis=0) return atmosphere def estimate_transmission(dark_channel, atmosphere, w): # 估计折射率 transmission = 1 - w * (dark_channel / atmosphere) return transmission def dehaze(image, block_size=15, w=0.95): # OpenCV暗通道去雾 dark = dark_channel(image, block_size) atmosphere = estimate_atmosphere(image, dark) transmission = estimate_transmission(dark, atmosphere, w) transmission = cv2.max(transmission, 0.1) result = np.empty_like(image) for i in range(3): result[:, :, i] = (image[:, :, i] - atmosphere[i]) / transmission + atmosphere[i] result = cv2.normalize(result, None, 0, 255, cv2.NORM_MINMAX) return result.astype(np.uint8) ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值