大学四年快毕业了,准备把大学期间做的一些东西给写一下,感兴趣的可以持续关注。
提示:以下是本篇文章正文内容,下面案例可供参考
算法原理可以直接在论文中看,论文好像没有给出代码,所以我自己复现了一下,但没有达到论文中的优秀效果。
环境是OpenCV,C++,软件用的VS 2022
/*自适应暗通道*/
#include
#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<Vec3b>(i, j)[k] < loacalMin)
{
loacalMin = img.at<Vec3b>(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 <node> 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<Vec3b>(nodes[0].x, nodes[0].y)[i] > atmosphericLight)
{
atmosphericLight = img.at<Vec3b>(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<Vec3b>(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<Vec3b>(nodes[i].x, nodes[i].y)[j] > atmosphericLight)
{
atmosphericLight = img.at<Vec3b>(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<float>(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<Vec3b>(i, j)[channel] - atmosphericLight) / transmission[i][j] + atmosphericLight;
if (temp > 255)
{
temp = 255;
}
if (temp < 0)
{
temp = 0;
}
dst.at<Vec3b>(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);
}
有效果,但没有原文中的那么优越。
使用代码请注明出处。