一、設計思路
- 建立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); //等待滑鼠響應
}
三、運作結果
原始影像
二值化影像(門檻值為100)
高斯平滑影像(濾波器大小3X3,σ=1.5)