一、设计思路
- 新建CZQLImgPro类## 标题
私有数据成员:高斯滤波器的大小(nwindowsize),高斯滤波器方差(sigma),高斯滤波器(Mat Gauss),二值化阈值(binaryT)。
私有成员函数:生成高斯滤波器函数。
共有成员函数:设置高斯滤波参数;设置二值化阈值函数;阈值分割函数;高斯滤波函数。
重载两个构造函数:初始化高斯滤波参数;初始化阈值分割参数。
- 阈值分割算法过程
设置一个二值化阈;
判断每一个像素的灰度值:灰度值大于阈值的赋值为255,灰度值小于阈值的赋值为0。
- 高斯滤波算法过程
由高斯滤波器窗口大小nwindowsize计算gauss滤波器空间;
计算高斯滤波器:利用高斯函数求出每一个像素的值后,进行归一化处理。
利用高斯滤波器进行卷积。
- 对话框类接口
二值化按钮:判断是否读入原始影像并且输入的二值化阈值为[0,255]的数,如果是则调用阈值分割函数。
高斯滤波按钮:判断是否读入元使用想并且输入额高斯滤波器大小nwindowsize为正奇数,如果是则调用高斯滤波函数。
二、主要代码
//ZLImgPro.h 头文件
#pragmaonce
#include"opencv2\core\core.hpp"
usingnamespace cv;
classCZQLImgPro
{
public:
CZQLImgPro(void);
~CZQLImgPro(void);
CZQLImgPro(int n_windowsize,floatd_sigma);//构造函数重载(设置高斯滤波参数)
CZQLImgPro(int i_binaryT); //构造函数重载(设置阈值分割参数)
private:
int nwindowsize; //高斯滤波器的大小
float sigma; //高斯滤波器方差
MatGauss; //高斯滤波器
int binaryT; //二值化阈值
private:
void CreatGauss(); //生成高斯滤波器
public:
void setGauss(intn_windowsize,float d_sigma); //设置高斯滤波参数
void setBinaryT(inti_binaryT); //设置二值化阈值
void BinaryImg(constMat srcimg,Mat &result); //阈值分割函数
void Gaussianfilter(constMat srcimg,Mat &result);//高斯滤波
};
//ZLImgPro.cpp 实现文件
#include"StdAfx.h"
#include"ZQLImgPro.h"
#include"math.h"
constfloat PI=4.0*atan(1.0);
//默认构造函数
CZQLImgPro::CZQLImgPro(void)
{
nwindowsize=0;
sigma=0;
Gauss.create(nwindowsize,nwindowsize,CV_32F);
}
//析构函数
CZQLImgPro::~CZQLImgPro(void)
{
}
//构造函数重载(设置高斯滤波参数)
CZQLImgPro::CZQLImgPro(intn_windowsize,float d_sigma)
{
nwindowsize=n_windowsize;
sigma=d_sigma;
Gauss.create(nwindowsize,nwindowsize,CV_32F);
}
//构造函数重载(设置阈值分割参数)
CZQLImgPro::CZQLImgPro(intiBinaryT)
{
binaryT=iBinaryT;
}
//设置高斯滤波参数
voidCZQLImgPro::setGauss(int n_windowsize,float d_sigma)
{
nwindowsize=n_windowsize;
sigma=d_sigma;
Gauss.create(nwindowsize,nwindowsize,CV_32F);
}
//设置二值化阈值
voidCZQLImgPro::setBinaryT(int iBinaryT)
{
binaryT=iBinaryT;
}
//阈值分割函数
voidCZQLImgPro::BinaryImg(const Mat srcimg,Mat&result)
{
//给目标影像分配内存
result.create(srcimg.rows,srcimg.cols,srcimg.type());
for (inti=0;i<srcimg.rows;i++)
{
for (intj=0;j<srcimg.cols;j++)
{
int graytmp=srcimg.at<uchar>(i,j);
if (graytmp>binaryT) //大于阈值赋予255否则赋予0
result.at<uchar>(i,j)=255;
else
result.at<uchar>(i,j)=0;
}
}
}
//生成高斯滤波器
voidCZQLImgPro::CreatGauss()
{
floatsum=0;
for(inti=0;i<nwindowsize;i++)
{
for(intj=0;j<nwindowsize;j++)
{
int x=i-(nwindowsize-1)/2;
int y=j-(nwindowsize-1)/2;
Gauss.at<float>(i,j)=exp(-(x*x+y*y)/(2*sigma*sigma))
/(2*PI*sigma*sigma);//利用高斯公式计算计算滤波器
//float m=exp(-(x*x+y*y)/(2*sigma*sigma));
//float q=Gauss.at<float>(i,j);
sum+=Gauss.at<float>(i,j);
}
}
//进行归一化处理
for(inti=0;i<nwindowsize;i++)
{
for (int j=0;j<nwindowsize;j++)
{
Gauss.at<float>(i,j)/=sum;
}
}
}
//高斯滤波
voidCZQLImgPro::Gaussianfilter(const Mat srcimg,Mat&result)
{
CreatGauss();//计算高斯滤波器
//给目标影像分配内存
result.create(srcimg.rows,srcimg.cols,srcimg.type());
int rows=srcimg.rows;
int cols=srcimg.cols;
for (inti=0;i<rows;i++)
{
for (intj=0;j<cols;j++)
{
result.at<uchar>(i,j)=0;
//将结果矩阵初始化为零矩阵
}
}
int nhalfw=nwindowsize/2;
int sum=0;
for (inti=nhalfw;i<rows-nhalfw;i++)
{
for (intj=nhalfw;j<cols-nhalfw;j++)
{
sum=0;
for (intm=-nhalfw;m<nwindowsize-nhalfw;m++)
{
for (intn=-nhalfw;n<nwindowsize-nhalfw;n++)
{
sum+=Gauss.at<float>(m+nhalfw,n+nhalfw)*srcimg.at<uchar>(i+m,j+n);
//利用高斯滤波器进行卷积
}
}
result.at<uchar>(i,j)=sum;
}
}
}
// ZQL_0107150120_1Dlg.h :头文件
#pragmaonce
#include"opencv2/core/core.hpp"
usingnamespace cv;
#include<vector>
usingnamespace std;
// CZQL_0107150120_1Dlg对话框
classCZQL_0107150120_1Dlg :public CDialogEx
{
public:
Matm_srcimg; //原始影像灰度矩阵
Matresult; //结果影像灰度矩阵
CStringstrResultImgName; //结果影像名称
int m_binaryT; //二值化阈值
CStringm_strImgName; //原始影像名称
float fSigma; //高斯滤波器方差sigma
int nwindowsize; //高斯滤波器大小
bool bRead; //判断是否读入影像
afx_msgvoid OnBnClickedBtnOpen(); //打开影像
afx_msgvoid OnBnClickedBtnSave(); //保存影像
afx_msgvoid OnBnClickedBtnGauss(); //高斯滤波
afx_msgvoid OnBnClickedBtnBinarization();//进行图像二值化
};
// ZQL_0107150120_1Dlg.cpp :实现文件
#include"opencv2/highgui/highgui.hpp"
usingnamespace std;
CZQL_0107150120_1Dlg::CZQL_0107150120_1Dlg(CWnd*pParent/*=NULL*/)
:CDialogEx(CZQL_0107150120_1Dlg::IDD, pParent)
,m_binaryT(0)
,m_strImgName(_T(""))
, fSigma(0)
,strResultImgName(_T(""))
,nwindowsize(0)
,bRead(FALSE)
{
m_hIcon =AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
voidCZQL_0107150120_1Dlg::OnBnClickedBtnOpen()
{
// TODO:在此添加控件通知处理程序代码
UpdateData(TRUE);
CFileDialogFileDlg(TRUE,"*.jpg;*.bmp","*.jpg;*.bmp",OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,"影像文件()");
if (FileDlg.DoModal()!=IDOK)
{
return;
}
m_strImgName=FileDlg.GetPathName();
bRead=TRUE; //标记已经读入影像
UpdateData(FALSE); //将影像名字显示到对话框中
m_srcimg=imread(m_strImgName.GetBuffer(),CV_LOAD_IMAGE_GRAYSCALE);//打开影像
imshow("原始影像",m_srcimg);//图像显示
cvWaitKey(); //等待鼠标响应
}
voidCZQL_0107150120_1Dlg::OnBnClickedBtnBinarization()
{
// TODO:在此添加控件通知处理程序代码
UpdateData(TRUE);
if (bRead!=TRUE)
{
MessageBox("请读入影像文件");
return;
}
if (m_binaryT<0||m_binaryT>255)
{
MessageBox("二值化阈值应为一个在区间[0,255]的正数");
return;
}
CZQLImgProimp(m_binaryT);//定义CZQLImgPro对象
imp.BinaryImg(m_srcimg,result);
//图像显示
imshow("二值化影像",result);
cvWaitKey(0); //等待鼠标响应
}
voidCZQL_0107150120_1Dlg::OnBnClickedBtnSave()
{
// TODO:在此添加控件通知处理程序代码
CFileDialogFileDlg(FALSE,_T("jpg"));//创建保存图像对话框
if (FileDlg.DoModal()!=IDOK)
{
return;
}
strResultImgName=FileDlg.GetPathName(); //用于保存结果
if (strResultImgName!="")
{
imwrite(strResultImgName.GetBuffer(),result);//将结果影像写入文件
}
UpdateData(FALSE);
}
voidCZQL_0107150120_1Dlg::OnBnClickedBtnGauss()
{
// TODO:在此添加控件通知处理程序代码
UpdateData(TRUE);
if (bRead!=TRUE)
{
MessageBox("请读入影像文件");
return;
}
if (nwindowsize%2!=1)
{
MessageBox("nwindowsize应为一个正奇数");
return;
}
if (fSigma<=0)
{
MessageBox("sigma应为一个正数");
return;
}
CZQLImgProimp(nwindowsize,fSigma);//定义CZQLImgPro对象
imp.Gaussianfilter(m_srcimg,result);//进行高斯滤波
imshow("高斯平滑影像",result);
cvWaitKey(0); //等待鼠标响应
}
三、运行结果
原始影像
二值化影像
高斯平滑影像(滤波器大小3X3,σ=1.5)