You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

377 lines
7.1 KiB
C++

2 years ago
#include "stdafx.h"
#include "histProject.h"
#include "omp.h" // <20><><EFBFBD>˱<EFBFBD><CBB1><EFBFBD>
// <20><><EFBFBD>ܣ<EFBFBD>ֱ<EFBFBD><D6B1>ͼͶӰ<CDB6><D3B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD>Աȶ<D4B1>
// <20><><EFBFBD>
// src<72><63> <20><><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// dst: <20><><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC>
// <20><><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD><C9B9><EFBFBD><EFBFBD><EFBFBD>true<75><65><EFBFBD><EFBFBD><EFBFBD>򷵻<EFBFBD>false
bool HP(cv::Mat& dst, const cv::Mat &src)
{
try
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD><D0A7><EFBFBD><EFBFBD>֤
if (src.empty() == true || src.type() != 0)
{
return false;
}
// <20><><EFBFBD><EFBFBD>ֱ<EFBFBD><D6B1>ͼ
int channels[1];
channels[0] = 0;
int histSize[1];
histSize[0] = 256;
float hranges[2];
hranges[0] = 0.0f;
hranges[1] = 255.0f;
const float * ranges[1];
ranges[0] = hranges;
cv::MatND hist;
cv::calcHist(&src, 1, channels, cv::Mat(), hist, 1, histSize, ranges);
// ֱ<><D6B1>ͼͳ<CDBC><CDB3>
cv::Mat ZeroValuesStat(1, 256, CV_8UC1);
ZeroValuesStat = 0;
double srcMaxVal = 0;
uchar zeroCount = 0;
for (int i = 0; i < 256; i++)
{
ZeroValuesStat.at<uchar>(0, i) = zeroCount;
if (hist.at<float>(i) == 0)
{
zeroCount++;
}
else
{
srcMaxVal = i;
}
}
if (zeroCount == 0)
{
src.copyTo(dst);
return true;
}
dst.release();
dst = cv::Mat(src.rows, src.cols, CV_8UC1);
// <20>޳<EFBFBD><DEB3><EFBFBD><EFBFBD>ظ<EFBFBD><D8B8><EFBFBD>Ϊ0<CEAA><30><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD>ͽ<EFBFBD>ѹ<EFBFBD><D1B9>
#pragma omp parallel for
for (int r = 0; r < src.rows; r++)
{
for (int c = 0; c < src.cols; c++)
{
dst.at<uchar>(r, c) = src.at<uchar>(r, c) - ZeroValuesStat.at<uchar>(0, src.at<uchar>(r, c));
}
}
// <20>ҶȽ<D2B6><C8BD><EFBFBD><EFBFBD><EFBFBD>
double maxVal = 255 - ZeroValuesStat.at<uchar>(0, 255);
double ratio = 1.0;
if (maxVal > 0)
{
ratio = 255.0 / maxVal;
}
dst.convertTo(dst, CV_8U, ratio, 0);
return true;
}
catch(cv::Exception &e)
{
e.msg;
return false;
}
catch(...)
{
return false;
}
}
// <20><><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6>ֱֵ<D6B5><D6B1>ͼͶӰ<CDB6><D3B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD>Աȶ<D4B1>
bool SAHP(cv::Mat &dst,const cv::Mat& src)
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD><D0A7><EFBFBD><EFBFBD>֤
if (src.empty() == true || src.type() != CV_8UC1)
{
return false;
}
// <20><><EFBFBD><EFBFBD>ֱ<EFBFBD><D6B1>ͼ
int channels[1];
channels[0] = 0;
int histSize[1];
histSize[0] = 256;
float hranges[2];
hranges[0] = 0.0f;
hranges[1] = 255.0f;
const float * ranges[1];
ranges[0] = hranges;
// ͳ<><CDB3>ֱ<EFBFBD><D6B1>ͼ
cv::MatND hist;
cv::calcHist(&src, 1, channels, cv::Mat(), hist, 1, histSize, ranges);
// ֱ<><D6B1>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD>
cv::Mat ZeroValuesStat(1, 256, CV_8UC1);
ZeroValuesStat = 0;
uchar zeroCount = 0;
int threshold = (src.rows * src.cols) / (256 * 33); // <20><>ֵ<EFBFBD><D6B5>3%<25><>
for (int i = 0; i < 256; i++)
{
ZeroValuesStat.at<uchar>(0, i) = zeroCount;
if (hist.at<float>(i) < threshold)
{
zeroCount++;
}
}
if (zeroCount == 0)
{
src.copyTo(dst);
return true;
}
dst.release();
dst = cv::Mat(src.rows, src.cols, CV_8UC1);
// <20>޳<EFBFBD><DEB3><EFBFBD><EFBFBD>ظ<EFBFBD><D8B8><EFBFBD>Ϊ0<CEAA><30><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD>ͽ<EFBFBD>ѹ<EFBFBD><D1B9>
for (int r = 0; r < src.rows; r++)
{
for (int c = 0; c < src.cols; c++)
{
dst.at<uchar>(r, c) = src.at<uchar>(r, c) - ZeroValuesStat.at<uchar>(0, src.at<uchar>(r, c));
}
}
// <20>ҶȽ<D2B6><C8BD><EFBFBD><EFBFBD><EFBFBD>
double maxVal = 255 - ZeroValuesStat.at<uchar>(0, 255);
double ratio = 1.0;
if (maxVal > 0)
{
ratio = 255.0 / maxVal;
}
dst.convertTo(dst, CV_8UC1, ratio);
return true;
}
// <20><>˹<EFBFBD><CBB9>Լ<EFBFBD><D4BC>ֱ<EFBFBD><D6B1>ͼͶӰ<CDB6><EFBFBD><E3B7A8> <20><><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>ٶȿ<D9B6>
bool GNRHP(cv::Mat& dst, const cv::Mat &src, bool bDeNoise)
{
try
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD><D0A7><EFBFBD><EFBFBD>֤
if (src.empty() == true || src.type() != CV_8UC1)
{
return false;
}
// <20><><EFBFBD><EFBFBD>
cv::Mat srcCopy;
src.copyTo(srcCopy);
// <20><>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>ɢ<EFBFBD><C9A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˲<EFBFBD>
if (bDeNoise == true)
{
cv::medianBlur(srcCopy, srcCopy, 3);
}
// <20>ڶ<EFBFBD><DAB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˹<EFBFBD><CBB9>Լ<EFBFBD><D4BC>ϸ<EFBFBD><CFB8><EFBFBD><EFBFBD>ǿ
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> T
double minVal = 0, maxVal = 0;
cv::minMaxLoc(srcCopy, &minVal, &maxVal);
double T = 2 * (maxVal - minVal);
if (T == 0)
{
src.copyTo(dst);
return false;
}
// <20><>ͼ
cv::Mat BaseImg;
srcCopy.convertTo(BaseImg, CV_32FC1);
// <20><>˹ģ<CBB9><C4A3> <20><>ȡ<EFBFBD><C8A1>ͼ 3 * 1.667 = 5
cv::GaussianBlur(BaseImg, BaseImg, cv::Size(5,5), 1.667);
// ϸ<><CFB8>ͼ
cv::Mat DetailImg;
cv::Mat srcF;
srcCopy.convertTo(srcF, CV_32FC1);
DetailImg = srcF - BaseImg;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD><CFB5> <20><><EFBFBD><EFBFBD>Ӧ
cv::minMaxLoc(BaseImg, &minVal, &maxVal);
double BaseImgSpan = maxVal - minVal;
cv::minMaxLoc(DetailImg, &minVal, &maxVal);
double DetailImgSpan = maxVal - minVal;
double ratio = BaseImgSpan / DetailImgSpan * 2.0;
// ͼ<><CDBC><EFBFBD>ϳ<EFBFBD> <20>ɸĽ<C9B8>
cv::Mat dstimg;
cv::addWeighted(BaseImg, 1.0, DetailImg, ratio, 0, dstimg);
cv::minMaxLoc(dstimg, &minVal, &maxVal);
dstimg = dstimg - minVal;
maxVal -= minVal;
dstimg.convertTo(dstimg, CV_8U, 255.0 / maxVal, 0);
// ϸ<><CFB8><EFBFBD><EFBFBD>ǿͼ<C7BF><CDBC>HP(ֱ<><D6B1>ͼͶӰ<CDB6><D3B0>
return HP(dst, dstimg);
}
catch(cv::Exception &e)
{
e.msg;
return false;
}
catch(...)
{
return false;
}
}
// <20><>˹Լ<CBB9><D4BC>ֱ<EFBFBD><D6B1>ͼͶӰ<CDB6><EFBFBD><E3B7A8> <20><><EFBFBD><EFBFBD><EFBFBD>á<EFBFBD><C3A1>ٶ<EFBFBD><D9B6><EFBFBD>
bool GRHP(cv::Mat& dst, const cv::Mat &src, bool bDeNoise)
{
try
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD><D0A7><EFBFBD><EFBFBD>֤
if (src.empty() == true || src.type() != 0)
{
return false;
}
// <20><><EFBFBD><EFBFBD>
cv::Mat srcCopy;
src.copyTo(srcCopy);
// <20><>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>ɢ<EFBFBD><C9A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˲<EFBFBD>
if (bDeNoise == true)
{
cv::medianBlur(srcCopy, srcCopy, 3); // <20><><EFBFBD><EFBFBD>ֵ<EFBFBD>˲<EFBFBD><CBB2><EFBFBD><EFBFBD><EFBFBD>
}
// <20><>˹<EFBFBD>˲<EFBFBD><CBB2>˳ߴ<CBB3>
int kernelSize = 7;
double delta = 2.0;
// <20><>Ե<EFBFBD><D4B5><EFBFBD><EFBFBD>
cv::copyMakeBorder(srcCopy, srcCopy, kernelSize, kernelSize, kernelSize, kernelSize, BORDER_REPLICATE);
// <20>ڶ<EFBFBD><DAB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˹Լ<CBB9><D4BC>ϸ<EFBFBD><CFB8><EFBFBD><EFBFBD>ǿ
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> T
double minVal = 0, maxVal = 0;
cv::minMaxLoc(srcCopy, &minVal, &maxVal);
double T = 2 * (maxVal - minVal);
if (T == 0)
{
src.copyTo(dst);
return false;
}
// <20><>ͼ
cv::Mat BaseImg;
srcCopy.convertTo(BaseImg, CV_32FC1);
#pragma omp parallel for
for (int r = kernelSize; r < srcCopy.rows - kernelSize; r++)
{
for (int c = kernelSize; c < srcCopy.cols - kernelSize; c++)
{
double val = 0;
double sumS = 0;
for (int i = -kernelSize; i < kernelSize + 1; i++)
{
for (int j = -kernelSize; j < kernelSize + 1; j++)
{
// <20><>˹<EFBFBD>˲<EFBFBD><CBB2><EFBFBD>ϵ<EFBFBD><CFB5><EFBFBD><EFBFBD>GC
double GC = exp(-(i * i + j * j)/ (2 * delta * delta));
// <20>ҶȲ<D2B6>ֵԼ<D6B5><D4BC>ϵ<EFBFBD><CFB5><EFBFBD><EFBFBD>DR
double diff = srcCopy.at<uchar>(r + i, c + j) - srcCopy.at<uchar>(r, c);
double DR = T / (pow(diff, 2) + T);
// <20>ϳ<EFBFBD>ϵ<EFBFBD><CFB5>
double CC = GC * DR;
// <20>ۺ<EFBFBD>
val += CC * srcCopy.at<uchar>(r + i, c + j);
sumS += CC;
}
}
val = val / sumS;
BaseImg.at<float>(r, c) = float(val);
}
}
// ϸ<><CFB8>ͼ
cv::Mat DetailImg;
cv::Mat srcF;
srcCopy.convertTo(srcF, CV_32FC1);
DetailImg = srcF - BaseImg;
// BaseImg DetailImg <20>ñ<EFBFBD>
BaseImg = BaseImg(cv::Range(kernelSize, BaseImg.rows - kernelSize), cv::Range(kernelSize, BaseImg.cols - kernelSize));
DetailImg = DetailImg(cv::Range(kernelSize, DetailImg.rows - kernelSize), cv::Range(kernelSize, DetailImg.cols - kernelSize));
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD><CFB5> <20><><EFBFBD><EFBFBD>Ӧ
cv::minMaxLoc(BaseImg, &minVal, &maxVal);
double BaseImgSpan = maxVal - minVal;
cv::minMaxLoc(DetailImg, &minVal, &maxVal);
double DetailImgSpan = maxVal - minVal;
double ratio = BaseImgSpan / DetailImgSpan * 2.0;
// ͼ<><CDBC><EFBFBD>ϳ<EFBFBD> <20>ɸĽ<C9B8>
cv::Mat dstimg;
cv::addWeighted(BaseImg, 1.0, DetailImg, ratio, 0, dstimg);
cv::minMaxLoc(dstimg, &minVal, &maxVal);
dstimg = dstimg - minVal;
maxVal -= minVal;
dstimg.convertTo(dstimg, CV_8U, 255.0 / maxVal, 0);
// ϸ<><CFB8><EFBFBD><EFBFBD>ǿͼ<C7BF><CDBC>HP(ֱ<><D6B1>ͼͶӰ<CDB6><D3B0>
return HP(dst, dstimg);
}
catch(cv::Exception &e)
{
e.msg;
return false;
}
catch(...)
{
return false;
}
}