1、打开VS2022软件,创建一个基于对话框(MFC)的应用程序;
2、编辑对话框界面如下:
3、为编辑框设置变量,获取界面输入的数值。
4、为按钮控件设置点击事件代码。如下:OnBnClickedButton1()对应二值化按钮,OnBnClickedButtoncalgauss()对应高斯滤波按钮。
void CxxxxDlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
CFileDialog FileDlg(TRUE, "*.jpg;*.bmp", "*.jpg;*.bmp", OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, "影像文件()");
if (FileDlg.DoModal() != IDOK)
{
return;
}
CString strImgName = FileDlg.GetPathName();
Cxxxx_ImgPro img;
Mat m_srcimg = imread(strImgName.GetBuffer(), IMREAD_GRAYSCALE);
imshow("src image", m_srcimg); //显示
waitKey(); //等待操作,将窗口关闭\回车\ESC等操作会运行以下的程序
Mat binaeryImg;
img.BinaryImg(m_srcimg,100, binaeryImg);
imshow("binaeryImg", binaeryImg); //显示
waitKey();
}
void CxxxxDlg::OnBnClickedButtoncalgauss()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);
UpdateData(FALSE);
CFileDialog FileDlg(TRUE, "*.jpg;*.bmp", "*.jpg;*.bmp", OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, "影像文件()");
if (FileDlg.DoModal() != IDOK)
{
return;
}
CString strImgName = FileDlg.GetPathName();
Cxxxx_ImgPro img;
Mat m_srcimg = imread(strImgName.GetBuffer(), IMREAD_GRAYSCALE);
imshow("src image", m_srcimg); //显示
int nwiddowsize = 3;
nwiddowsize = m_windowsH;
Mat Gauss;
img.CreatGauss(nwiddowsize,m_sigma,Gauss);
img.Gaussianfilter(m_srcimg, nwiddowsize,m_sigma,Gauss);
imshow("高斯滤波结果",m_srcimg);
waitKey(); //等待操作,将窗口关闭\回车\ESC等操作会运行以下的程序
}
5、处理结果。
二值化的结果
高斯滤波结果
6、高斯滤波代码展示
//二值分割函数
void CWGY_ImgPro::BinaryImg(const Mat srcimg, const int binaryT, Mat &dstimg)
{
dstimg.create(srcimg.rows, srcimg.cols, srcimg.type());
//访问图像是一行行访问,从上到下,
for (int i = 0; i < srcimg.rows; i++)
{
//每一行 是从左到右
for (int j = 0; j < srcimg.cols; j++)
{
//访问位置 (i,j) 注意 y在前,x 在后
//返回 uchar (unsigned char 的 代名词)
int graytmp = srcimg.at<uchar>(i, j);
if (graytmp > binaryT) //大于阈值赋予 255
{
dstimg.at<uchar>(i, j) = 255;
}
else
{
dstimg.at<uchar>(i, j) = 0;
}
}
}
}
//高斯模板计算函数,得到卷积核
void CWGY_ImgPro::CreatGauss(const int nwiddowsize, float sigma, Mat &Gauss)
{
Gauss.create(nwiddowsize, nwiddowsize,CV_32FC1); //窗口大小
float a = 1 / (2 * PI*sigma*sigma);
float b;
double dSum=0;
//计算高斯模板,并得到卷积核
for (int i = 0; i < nwiddowsize; i++)
{
for (int j = 0; j < nwiddowsize; j++)
{
int c;
c = i - 1;
int d;
d = j - 1;
b = exp(-(c*c + d * d) / (2 * sigma*sigma));
Gauss.at<float>(i, j) = a * b;
dSum += Gauss.at<float>(i, j);
}
}
//归一化
for (int i = 0; i < nwiddowsize; i++)
{
for (int j = 0; j < nwiddowsize; j++)
{
Gauss.at<float>(i, j) = Gauss.at<float>(i,j) / dSum;
}
}
}
//高斯滤波函数,对图像进行卷积
void CWGY_ImgPro::Gaussianfilter(Mat srcImg, const int nwiddowsize, const float sigma, Mat &Gauss)
{
int k;
k = (nwiddowsize / 2); //计算图像开始卷积像素点坐标
Mat tux; //存放图像卷积结果
tux.create(srcImg.rows, srcImg.cols, CV_32FC1);
double dSum = 0; //用于存储被处理图像的单个像素的卷积结果
for (int m = k; m < srcImg.rows-k; m++)
{
for (int n = k; n <srcImg.cols-k; n++)
{
dSum = 0;
for (int i = 0; i < nwiddowsize; i++)
{
for (int j = 0; j < nwiddowsize; j++)
{
double a;
a = float(srcImg.at<uchar>(m-k+i, n-k+j))*Gauss.at<float>(i, j); //对每个像素进行卷积运算
dSum += a;
}
}
tux.at<float>(m, n) = dSum; //结果图像矩阵
}
}
for (int i = 0; i < srcImg.rows - k; i++)
{
for (int j = 0; j < srcImg.rows - k; j++)
{
srcImg.at<uchar>(i, j) = tux.at<float>(i, j);
}
}
}