#include<opencv2/opencv.hpp>
#include<cmath>
cv::Mat anr_denoising(cv::Mat img,int kszie=3,double sigma=2.0, double base_threshold=0.1, double interlength_threshold=0.01){
//高斯滤波
cv::Mat img_blur;
cv::GaussianBlur(img,img_blur,cv::Size(kszie,kszie),sigma);
//计算每个像素在全通道中的导数值
cv::Mat dx,dy;
cv::Sobel(img_blur,dx,CV_64F,1,0);
cv::Sobel(img_blur,dy,CV_64F,0,1);
cv::Mat d;
cv::magnitude(dx,dy,d);
//统计每个像素在全通道中的导数值的方差
cv::Mat var;
// cv::reduce(d, var, 2, cv::REDUCE_STD);
//在OpenCV 4.1.2中,计算方差的函数为cv::meanStdDev(),可以使用以下代码替换掉原有的cv::reduce()函数。
cv::Scalar mean, stddev;
cv::meanStdDev(d, mean, stddev);
double variance = stddev.val[0] * stddev.val[0];
// cv::reduce(d, var, 2, cv::REDUCE_SUM);
// var /= d.size().area(); cv::Scalar mean, stddev;
// cv::meanStdDev(var, mean, stddev);
// double var_value = stddev.val[0] * stddev.val[0]
// 根据方差值确定基函数阈值
double base_thresholds = base_threshold * cv::mean(variance)[0];
// 进行噪声过滤
int h = img.rows,w=img.cols;
cv::Mat img_denoise = cv::Mat::zeros(h,w,CV_8UC1);
for (int i = 0; i < h; i++){
for (int j = 0; j < w; j++) {
//判断是否为平坦区域
bool flat = cv::norm(d.at<cv::Vec3d>(i,j)) <= base_thresholds;
//判断是否为噪声像素
bool nosiy = !flat && (d.at<cv::Vec3d>(i,j)[0] >= base_thresholds ||
d.at<cv::Vec3d>(i,j)[1] >= base_thresholds ||
d.at<cv::Vec3d>(i,j)[2] >= base_thresholds);
if (!nosiy)
{
img_denoise.at<uchar>(i,j) = img_blur.at<cv::Vec3b>(i,j)[0];
}else {
//NORM_L2SQR表示使用欧几里得距离(L2范数)的平方来计算向量之间的距离。具体地说,NORM_L2SQR
//用公式∑(xi-yi)²计算两个向量间的距离,其中xi和yi分别是两个向量的第i个元素。在上述代码中,NORM_L2SQR是被用于计算dc4向量的长度平方。
cv::Mat dc4 = img_blur(cv::Range(std::max(0,i-1),std::min(i+2,h)),cv::Range(std::max(0,
j-1),std::min(j+2,w)));
double dc4_var = cv::norm(dc4,cv::NORM_L2SQR) / dc4.total();
if (dc4_var <= interlength_threshold){
//如果dc4 pass为平坦,则提高基函数阈值
base_threshold *=1.1;
img_denoise.at<uchar>(i,j) = img_blur.at<cv::Vec3b>(i,j)[0];
}else{
cv::Mat dc4_1d;
cv::cvtColor(dc4,dc4_1d,cv::COLOR_BGR2GRAY);
cv::Mat blurrd;
cv::medianBlur(dc4_1d,blurrd,3);
img_denoise.at<uchar>(i, j) = blurrd.at<uchar>(1, 1); }
//这里的at是opencv库中的一个函数,用于访问矩阵中指定位置的像素值。在这段代码中,img_denoise、dc4_1d和cv::medianBlur(dc4_1d, 3)都是opencv库中的Mat矩阵,
//而.at<uchar>(i, j)表示获取矩阵中第i行、第j列位置的像素值(以uchar类型返回)。在这段代码中,获取到的值被重置为中值滤波后的像素值。
}
}
}
return img_denoise;
}
int main() {
// 读取图像
cv::Mat img = cv::imread("D:/Pluto2023/Python/jupyter/AI/Qualcomm_2xx/ANR/O1.png", cv::IMREAD_COLOR);
// 调用去噪函数
cv::Mat img_denoise = anr_denoising(img);
// 显示原始图像和去噪后的图像
cv::imshow("Original Image", img);
cv::imshow("Denoised Image", img_denoise);
cv::waitKey(0);
return 0;
}