- 前言
- 一、原文
- 二、代码
- 三、实验效果
- (1)透射率对比
- (2)PSNR与SSIM
- 说明
前言
大学四年快毕业了,准备把大学期间做的一些东西给写一下,感兴趣的可以持续关注。
提示:以下是本篇文章正文内容,下面案例可供参考
一、原文
算法原理可以直接在论文中看,论文好像没有给出代码,所以我自己复现了一下,但没有达到论文中的优秀效果。
环境是OpenCV,C++,软件用的VS 2022
#include三、实验效果 (1)透射率对比#include #include #include #include using namespace cv; using namespace std; int rows, cols; //获取三通道最小值矩阵 int** getMinChannel(cv::Mat img) { rows = img.rows; cols = img.cols; if (img.channels() != 3) { fprintf(stderr, "Input Error!"); exit(-1); } int** imgGray; imgGray = new int* [rows]; for (int i = 0; i < rows; i++) { imgGray[i] = new int[cols]; } for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { int loacalMin = 255; for (int k = 0; k < 3; k++) { if (img.at (i, j)[k] < loacalMin) { loacalMin = img.at (i, j)[k]; } } imgGray[i][j] = loacalMin; } } return imgGray; } //获取自适应暗原色 float** getgoodMinchannel(int** img, int blockSize) { if (blockSize % 2 == 0 || blockSize < 3) { fprintf(stderr, "blockSize is not odd or too small!"); exit(-1); }//判断窗口大小是否合适 int halflength= (blockSize - 1) / 2;//确定窗口边长 7 int newHeight = rows; int newWidth = cols; while(newHeight % blockSize != 0) { newHeight = newHeight + 1; } while (newWidth % blockSize != 0) { newWidth = newWidth + 1; } int** imgGray2; imgGray2 = new int* [newHeight]; for (int i = 0; i < newHeight; i++) { imgGray2[i] = new int[newWidth]; } for (int i = 0; i < newHeight; i++) { for (int j = 0; j < newWidth; j++) { if (i < rows && j < cols) { imgGray2[i][j] = img[i][j]; } else { imgGray2[i][j] = 255; } } }//结束 float** a; float pingjun; int m = halflength, n = halflength; a = new float* [newHeight]; for (int i = 0; i < newHeight; i++) { a[i] = new float[newWidth]; } std::cout << newHeight << ' ' << newWidth << std::endl; for (int i = 0; i < newHeight; i++)//newheight 450/15 = 30 { for (int j = 0; j < newWidth; j++)//newwidth 450/15 = 30 { //std::cout << "imgGray2[i][j]" << imgGray2[i][j] << std::endl; //std::cout << "imgGray2[m][n]" << imgGray2[m][n] << std::endl; a[i][j] = fabs(imgGray2[i][j] - imgGray2[m][n]) / (imgGray2[m][n]+1); // std::cout << "a[i][j]" << a[i][j] << std::endl; n = (j / blockSize) * blockSize + halflength; //(j/15) *15 + 7 //std::cout << "n " << n << std::endl; } m = (i / blockSize) * blockSize + halflength; //std::cout << "m " << m << std::endl; }// std::cout << '2' << std::endl; float f = 0.1; float** imgGray3; imgGray3 = new float* [rows]; for (int i = 0; i < rows; i++) { imgGray3[i] = new float[cols]; } for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { if (double(a[i][j]) > f) { imgGray3[i][j] = 255; } else { imgGray3[i][j] = imgGray2 [i][j]; } } } return imgGray3; } //求暗通道最小值滤波 float** getDarkChannel(float** img, int blockSize ) { if (blockSize % 2 == 0 || blockSize < 3) { fprintf(stderr, "blockSize is not odd or too small!"); exit(-1); } //计算pool Size int poolSize = (blockSize - 1) / 2; int newHeight = rows + blockSize - 1; int newWidth = cols + blockSize - 1; float** imgMiddle; imgMiddle = new float* [newHeight]; for (int i = 0; i < newHeight; i++) { imgMiddle[i] = new float[newWidth]; } for (int i = 0; i < newHeight; i++) { for (int j = 0; j < newWidth; j++) { if (i < rows && j < cols) { imgMiddle[i][j] = img[i][j]; } else { imgMiddle[i][j] = 255; } } }//进行边缘拓展,并赋值为255 float** imgDark; imgDark = new float* [rows]; for (int i = 0; i < rows; i++) { imgDark[i] = new float[cols]; } int localMin = 255; for (int i = poolSize; i < newHeight - poolSize; i++) { for (int j = poolSize; j < newWidth - poolSize; j++) { localMin = 255; for (int k = i - poolSize; k < i + poolSize + 1; k++) { for (int l = j - poolSize; l < j + poolSize + 1; l++) { if (imgMiddle[k][l] < localMin) { localMin = imgMiddle[k][l]; } } } imgDark[i - poolSize][j - poolSize] = localMin; } } return imgDark; } struct node { int x, y, val; node() {} node(int _x, int _y, int _val) :x(_x), y(_y), val(_val) {} bool operator<(const node& rhs) { return val > rhs.val; } }; //估算全局大气光值 float getGlobalAtmosphericLightValue(float** darkChannel, cv::Mat img, bool meanMode = false, float percent = 0.001) { int size = rows * cols; std::vector nodes; for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { node tmp; tmp.x = i, tmp.y = j, tmp.val = darkChannel[i][j]; nodes.push_back(tmp); } } sort(nodes.begin(), nodes.end()); float atmosphericLight = 0; if (int(percent * size) == 0) { for (int i = 0; i < 3; i++) { if (img.at (nodes[0].x, nodes[0].y)[i] > atmosphericLight) { atmosphericLight = img.at (nodes[0].x, nodes[0].y)[i]; } } } //开启均值模式 if (meanMode == true) { int sum = 0; for (int i = 0; i < int(percent * size); i++) { for (int j = 0; j < 3; j++) { sum = sum + img.at (nodes[i].x, nodes[i].y)[j]; } } } //获取暗通道在前0.1%的位置的像素点在原图像中的最高亮度值 for (int i = 0; i < int(percent * size); i++) { for (int j = 0; j < 3; j++) { if (img.at (nodes[i].x, nodes[i].y)[j] > atmosphericLight) { atmosphericLight = img.at (nodes[i].x, nodes[i].y)[j]; } } } return atmosphericLight; } //恢复原图像 // Omega 去雾比例 参数 //t0 最小透射率值 cv::Mat getRecoverScene(cv::Mat img, float omega = 0.95, float t0 = 0.1, int blockSize = 15, bool meanModel = false, float percent = 0.001) { int blocksize2 = 25; int** imgGray = getMinChannel(img); float** imgGray3 = getgoodMinchannel(imgGray, blocksize2); float** imgDark = getDarkChannel(imgGray3, blockSize); float atmosphericLight = getGlobalAtmosphericLightValue(imgDark, img, meanModel = meanModel, percent = percent); std::cout << "atmospher" << atmosphericLight << std::endl; float** imgDark4, ** transmission; imgDark4 = new float* [rows]; for (int i = 0; i < rows; i++) { imgDark4[i] = new float[cols]; } transmission = new float* [rows]; for (int i = 0; i < rows; i++) { transmission[i] = new float[cols]; } for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { imgDark4[i][j] = float(imgDark[i][j]); transmission[i][j] = 1 - omega * imgDark4[i][j] / atmosphericLight; if (transmission[i][j] < 0.1) { transmission[i][j] = 0.1; } } } Mat t(rows, cols, CV_32FC1); for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { t.at (i,j) = transmission[i][j]; } } imshow("改进t", t); cv::imwrite("../透射率k=1.jpg", t); cv::Mat dst(img.rows, img.cols, CV_8UC3); for (int channel = 0; channel < 3; channel++) { for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { int temp = (img.at (i, j)[channel] - atmosphericLight) / transmission[i][j] + atmosphericLight; if (temp > 255) { temp = 255; } if (temp < 0) { temp = 0; } dst.at (i, j)[channel] = temp; } } } return dst; } int main() { cv::Mat src = cv::imread("C:\Users\杨秉霖\Desktop\图片\图_4.png"); rows = src.rows; cols = src.cols; cv::Mat dst = getRecoverScene(src); cv::imshow("origin", src); cv::imshow("result算法改进后", dst); cv::imwrite("../图_4.png", dst); waitKey(0); }
图片是改进前的算法与本文算法对比
有效果,但没有原文中的那么优越。
图片来源于两个图片数据集,可以从以下链接获取
说明
使用代码请注明出处。



