C++ Opencv——图像预处理——滤波
程序员文章站
2022-07-13 08:53:47
...
#include <opencv2/opencv.hpp>
#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\imgproc\imgproc.hpp>
#include <iostream>
using namespace cv;
using namespace std;
/*
边缘突出
用高通——拉普拉斯
锐化处理
去噪点
用低通——均值、中值
偏色问题解决
用白平衡进行处理
【空域与频域之间是有一定关系。均值滤波器是一种低通滤波;拉普拉斯算子滤波(边缘检测)是一种高通滤波】
*/
class Blur_Class
{
public:
/*
双边滤波——保留纹理的滤波
三通道图,返回三通道图
Shuangbian_Bialteral_Filter(src, src);
*/
void Shuangbian_Bialteral_Filter(Mat src, Mat dst, int R = 10, double sigmaC = 20, double sigmaS = 20);
/*
高分差滤波——类似锐化增加噪声点
三通道图,返回三通道图
HighPass(src, dst);
*/
void HighPass(Mat src, Mat dst, int r = 3, int k = 3);
/*
LOG变换——使整体图片亮度均衡(强度大)
三通道图,返回三通道图
log_Filter(src, src);
*/
void log_Filter(Mat src, Mat dst);
/*
均衡化——一定程度上亮度均衡,增强边缘强度
输入单通道、三通道
junheng_equalizeHist(src, src);
*/
void junheng_equalizeHist(Mat src, Mat dst);
/*
中值滤波——可以去除多个零散密集的噪声点
输入单通道、三通道图
zhongzhi_Median_Filter(src, src);
*/
void zhongzhi_Median_Filter(Mat src, Mat dst, int k = 10);
/*
膨胀腐蚀——默认膨胀
输入单通道、三通道
PF_Filter(src, dst);
*/
void PF_Filter(Mat src, Mat dst, bool flag = true, int k = 1);
/*
自己定义卷积核
0 -1 0
-1 5 -1
0 -1 0
filter(dst2, dst2)
*/
void filter(Mat src, Mat dst, Mat kerne = (Mat_<char>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0));
public:
/* RGB分离 */
void RGB_Split(Mat src, Mat r = Mat(), Mat g = Mat(), Mat b = Mat(), Mat R = Mat(), Mat G = Mat(), Mat B = Mat());
/*白平衡*/
void baipingheng(Mat src, Mat dst);
public:
/*
lab
*/
void RGB2LAB(Mat& rgb, Mat& Lab);
/*
偏色检验
*/
float colorCheck(const Mat& imgLab);
};
/*——————————————————————————————————————————————————————————————*/
/*
双边滤波——保留纹理的滤波
三通道图,返回三通道图
Shuangbian_Bialteral_Filter(src, src);
*/
void Blur_Class::Shuangbian_Bialteral_Filter(Mat src, Mat dst, int R, double sigmaC, double sigmaS)
{
Mat dst_;
bilateralFilter(src, dst_, R, sigmaC, sigmaS);
dst_.copyTo(dst);
}
/*
高反差滤波——类似锐化增加噪声点——叠加边缘后的效果图 = 原图 + r*(原图-滤波)
三通道图,返回三通道图
HighPass(src, dst);
*/
void Blur_Class::HighPass(Mat src, Mat dst, int r, int k)
{
Mat temp;
int n = 2 * k + 1;
Size ksize = Size(n, n);
GaussianBlur(src, temp, ksize, 1.6, 1.6);
Mat diff = src + r*(src - temp); //高反差保留算法
diff.copyTo(dst);
}
/*
LOG变换——使整体图片亮度均衡(强度大)
三通道图,返回三通道图
log_Filter(src, src);
*/
void Blur_Class::log_Filter(Mat src, Mat dst)
{
Mat imageLog(src.size(), CV_32FC3);
for (int i = 0; i < src.rows; i++)
{
for (int j = 0; j < src.cols; j++)
{
imageLog.at<Vec3f>(i, j)[0] = log(1 + src.at<Vec3b>(i, j)[0]);
imageLog.at<Vec3f>(i, j)[1] = log(1 + src.at<Vec3b>(i, j)[1]);
imageLog.at<Vec3f>(i, j)[2] = log(1 + src.at<Vec3b>(i, j)[2]);
}
}
//归一化到0~255
normalize(imageLog, imageLog, 0, 255, CV_MINMAX);
//转换成8bit图像显示
convertScaleAbs(imageLog, imageLog);
imageLog.copyTo(dst);
}
/*
均衡化——一定程度上亮度均衡,增强边缘强度
输入单通道、三通道
junheng_equalizeHist(src, src);
*/
void Blur_Class::junheng_equalizeHist(Mat src, Mat dst)
{
if (src.channels() == 3)
{
dst.create(src.size(), src.type());
Mat imageRGB[3];
split(src, imageRGB);
for (int i = 0; i < 3; i++)
{
equalizeHist(imageRGB[i], imageRGB[i]);
}
merge(imageRGB, 3, dst);
}
else if (src.channels() == 1)
{
dst.create(src.size(), src.type());
equalizeHist(src, dst);
}
}
/*
中值滤波——可以去除多个零散密集的噪声点
输入单通道、三通道图
zhongzhi_Median_Filter(src, src);
*/
void Blur_Class::zhongzhi_Median_Filter(Mat src, Mat dst, int k)
{
int n = 2 * k + 1;
dst.create(src.size(), src.type());
medianBlur(src, dst, n);
}
/*
膨胀腐蚀——默认膨胀
输入单通道、三通道
PF_Filter(src, dst);
*/
void Blur_Class::PF_Filter(Mat src, Mat dst, bool flag, int k)
{
int n = 2 * k + 1;
Size Ksize = Size(k, k);
Mat element = getStructuringElement(MORPH_RECT, Ksize);
if (flag == true)
{
// 进行膨胀操作
dilate(src, dst, element);
}
else
{
// 进行腐蚀操作
erode(src, dst, element);
}
}
/*
自己定义卷积核
0 -1 0
-1 5 -1
0 -1 0
filter(dst2, dst2)
*/
void Blur_Class::filter(Mat src, Mat dst, Mat kerne)
{
//Mat kerne = (Mat_<char>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0); // 生成一个掩模核 大小为 3x3 , 通过<< 输入到矩阵Mat_<char> 中,然后隐式转换成Mat类型
dst.create(src.size(), src.type());
filter2D(src, dst, CV_8UC3, kerne);
}
/*
RGB
分离成r、g、b
合并成R、G、B
*/
void Blur_Class::RGB_Split(Mat src, Mat r, Mat g, Mat b, Mat R, Mat G, Mat B)
{
Mat imageRGB[3];
split(src, imageRGB);
r.create(src.size(), src.type());
g.create(src.size(), src.type());
b.create(src.size(), src.type());
b = imageRGB[0];
g = imageRGB[1];
r = imageRGB[2];
Mat black = Mat::zeros(Size(src.cols, src.rows), CV_8UC1);
vector<Mat> channels_r;
channels_r.push_back(black);
channels_r.push_back(black);
channels_r.push_back(r);
merge(channels_r, R);
vector<Mat> channels_g;
channels_g.push_back(black);
channels_g.push_back(g);
channels_g.push_back(black);
merge(channels_g, G);
vector<Mat> channels_b;
channels_b.push_back(b);
channels_b.push_back(black);
channels_b.push_back(black);
merge(channels_b, B);
}
/*
白平衡
*/
void Blur_Class::baipingheng(Mat src, Mat dst)
{
vector<Mat> imageRGB;
split(src, imageRGB);
//求原始图像的RGB分量的均值
double R, G, B;
B = mean(imageRGB[0])[0];
G = mean(imageRGB[1])[0];
R = mean(imageRGB[2])[0];
//需要调整的RGB分量的增益
double KR, KG, KB;
KB = (R + G + B) / (3 * B);
KG = (R + G + B) / (3 * G);
KR = (R + G + B) / (3 * R);
//调整RGB三个通道各自的值
imageRGB[0] = imageRGB[0] * KB;
imageRGB[1] = imageRGB[1] * KG;
imageRGB[2] = imageRGB[2] * KR;
//RGB三通道图像合并
dst.create(src.size(), src.type());
merge(imageRGB, dst);
namedWindow("白平衡调整后", 0);
imshow("白平衡调整后", dst);
waitKey();
}
/*转换成lab*/
void Blur_Class::RGB2LAB(Mat& rgb, Mat& Lab)
{
Mat XYZ(rgb.size(), rgb.type());
Mat_<Vec3b>::iterator begainRGB = rgb.begin<Vec3b>();
Mat_<Vec3b>::iterator endRGB = rgb.end<Vec3b>();
Mat_<Vec3b>::iterator begainXYZ = XYZ.begin<Vec3b>();
int shift = 22;
for (; begainRGB != endRGB; begainRGB++, begainXYZ++)
{
(*begainXYZ)[0] = ((*begainRGB)[0] * 199049 + (*begainRGB)[1] * 394494 + (*begainRGB)[2] * 455033 + 524288) >> (shift - 2);
(*begainXYZ)[1] = ((*begainRGB)[0] * 75675 + (*begainRGB)[1] * 749900 + (*begainRGB)[2] * 223002 + 524288) >> (shift - 2);
(*begainXYZ)[2] = ((*begainRGB)[0] * 915161 + (*begainRGB)[1] * 114795 + (*begainRGB)[2] * 18621 + 524288) >> (shift - 2);
}
int LabTab[1024];
for (int i = 0; i < 1024; i++)
{
if (i>9)
LabTab[i] = (int)(pow((float)i / 1020, 1.0F / 3) * (1 << shift) + 0.5);
else
LabTab[i] = (int)((29 * 29.0 * i / (6 * 6 * 3 * 1020) + 4.0 / 29) * (1 << shift) + 0.5);
}
const int ScaleLC = (int)(16 * 2.55 * (1 << shift) + 0.5);
const int ScaleLT = (int)(116 * 2.55 + 0.5);
const int HalfShiftValue = 524288;
begainXYZ = XYZ.begin<Vec3b>();
Mat_<Vec3b>::iterator endXYZ = XYZ.end<Vec3b>();
Lab.create(rgb.size(), rgb.type());
Mat_<Vec3b>::iterator begainLab = Lab.begin<Vec3b>();
for (; begainXYZ != endXYZ; begainXYZ++, begainLab++)
{
int X = LabTab[(*begainXYZ)[0]];
int Y = LabTab[(*begainXYZ)[1]];
int Z = LabTab[(*begainXYZ)[2]];
int L = ((ScaleLT * Y - ScaleLC + HalfShiftValue) >> shift);
int A = ((500 * (X - Y) + HalfShiftValue) >> shift) + 128;
int B = ((200 * (Y - Z) + HalfShiftValue) >> shift) + 128;
(*begainLab)[0] = L;
(*begainLab)[1] = A;
(*begainLab)[2] = B;
}
}
/*偏色检测*/
float Blur_Class::colorCheck(const Mat& imgLab)
{
Mat_<Vec3b>::const_iterator begainIt = imgLab.begin<Vec3b>();
Mat_<Vec3b>::const_iterator endIt = imgLab.end<Vec3b>();
float aSum = 0;
float bSum = 0;
for (; begainIt != endIt; begainIt++)
{
aSum += (*begainIt)[1];
bSum += (*begainIt)[2];
}
int MN = imgLab.cols*imgLab.rows;
double Da = aSum / MN - 128; // 必须归一化到[-128,,127]范围内
double Db = bSum / MN - 128;
//平均色度
double D = sqrt(Da*Da + Db*Db);
begainIt = imgLab.begin<Vec3b>();
double Ma = 0;
double Mb = 0;
for (; begainIt != endIt; begainIt++)
{
Ma += abs((*begainIt)[1] - 128 - Da);
Mb += abs((*begainIt)[2] - 128 - Db);
}
Ma = Ma / MN;
Mb = Mb / MN;
//色度中心距
double M = sqrt(Ma*Ma + Mb*Mb);
//偏色因子
float K = (float)(D / M);
cout << "K=" << K << endl;
return K;
}
上一篇: Eloquent ORM —— 快速入门
下一篇: 数据库迁移1292错误
推荐阅读
-
Java OpenCV图像处理之自定义图像滤波算子
-
Java OpenCV图像处理之自定义图像滤波算子
-
opencv-12-高斯滤波-双边滤波(附C++代码实现)
-
C++实现OpenCV方框滤波的代码
-
图像预处理之opencv卷积/滤波api
-
python&opencv 图像的双边滤波
-
OpenCV图像处理教程C++(十五)边缘检测算法--sobel算子、拉普拉斯算子、Canny算子
-
OpenCV C++开发 第二节:图像处理(五、均值模糊、高斯模糊、中值模糊、双边模糊、腐蚀、膨胀)
-
【OpenCV】 5种图像滤波辨析:方框、均值、高斯、中值、双边
-
Opencv之图像模糊处理--均值滤波/高斯滤波/中值滤波