模板类
空间滤波就是在原图像上做卷积运算,这里给出一个改进过的模板类。
BOOL WINAPI Template(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, int iTempH, int iTempW, int iTempMX, int iTempMY, FLOAT* fpArray, FLOAT fCoef, LONG lLineBytes, FLOAT thre);
//最后在传统模板类加上 float 阈值,使模板类可以完成反色
函数库.cpp
/*************************************************************************
*
* 函数名称:
* Template()
*
* 参数:
* LPSTR lpDIBBits - 指向源DIB图像指针
* LONG lWidth - 源图像宽度(象素数)
* LONG lHeight - 源图像高度(象素数)
* int iTempH - 模板的高度
* int iTempW - 模板的宽度
* int iTempMX - 模板的中心元素X坐标 ( < iTempW - 1)
* int iTempMY - 模板的中心元素Y坐标 ( < iTempH - 1)
* FLOAT * fpArray - 指向模板数组的指针
* FLOAT fCoef - 模板系数
*
* 返回值:
* BOOL - 成功返回TRUE,否则返回FALSE。
*
* 说明:
* 该函数用指定的模板(任意大小)来对图像进行操作,参数iTempH指定模板
* 的高度,参数iTempW指定模板的宽度,参数iTempMX和iTempMY指定模板的中心
* 元素坐标,参数fpArray指定模板元素,fCoef指定系数。
*
************************************************************************/
BOOL WINAPI Template(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, int iTempH, int iTempW, int iTempMX, int iTempMY, FLOAT* fpArray, FLOAT fCoef,LONG lLineBytes, FLOAT thre)
{
// 指向复制图像的指针
LPSTR lpNewDIBBits;
HLOCAL hNewDIBBits;
// 指向源图像的指针
unsigned char* lpSrc;
// 指向要复制区域的指针
unsigned char* lpDst;
// 循环变量
LONG i;
LONG j;
LONG k;
LONG l;
// 计算结果
FLOAT fResult;
// 暂时分配内存,以保存新图像
hNewDIBBits = LocalAlloc(LHND, lLineBytes * lHeight);
// 判断是否内存分配失败
if (hNewDIBBits == NULL)
{
// 内存分配失败
return FALSE;
}
// 锁定内存
lpNewDIBBits = (char*)LocalLock(hNewDIBBits);
// 初始化图像为原始图像
memcpy(lpNewDIBBits, lpDIBBits, lLineBytes * lHeight);
// 行(除去边缘几行)
for (i = iTempMY; i < lHeight - iTempH + iTempMY + 1; i++)
{
// 列(除去边缘几列)
for (j = iTempMX; j < lWidth - iTempW + iTempMX + 1; j++)
{
// 指向新DIB第i行,第j个象素的指针
lpDst = (unsigned char*)lpNewDIBBits + lLineBytes * (lHeight - 1 - i) + j;
fResult = 0;
// 计算
for (k = 0; k < iTempH; k++)
{
for (l = 0; l < iTempW; l++)
{
// 指向DIB第i - iTempMY + -0.1行,第j - iTempMX + l个象素的指针
lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i + iTempMY - k) + j - iTempMX + l;
// 保存象素值
fResult += (*lpSrc) * fpArray[k * iTempW + l];
}
}
// 乘上系数
fResult *= fCoef;
fResult += thre;
// 取绝对值
fResult = (FLOAT)fabs(fResult);
// 判断是否超过255
if (fResult > 255)
{
// 直接赋值为255
*lpDst = 255;
}
else
{
// 赋值
*lpDst = (unsigned char)(fResult + 0.5);
}
}
}
// 复制变换后的图像
memcpy(lpDIBBits, lpNewDIBBits, lLineBytes * lHeight);
// 释放内存
LocalUnlock(hNewDIBBits);
LocalFree(hNewDIBBits);
// 返回
return TRUE;
}
xxxxview.cpp
void CImgView::Onfilter()//滤镜操作
{
CImgDoc* pDoc = GetDocument();
long lSrcLineBytes; //图象每行的字节数
long lSrcWidth; //图象的宽度和高度
long lSrcHeight;
int lpSrcBitCount; //图像的位深
LPSTR lpSrcDib; //指向源图象的指针
LPSTR lpSrcStartBits; //指向源像素的指针
lpSrcDib = (LPSTR) ::GlobalLock((HGLOBAL)pDoc->GetHObject());// 锁定DIB
if (!lpSrcDib) return;
if (pDoc->m_dib.GetColorNum(lpSrcDib) != 256)// 判断是否是8-bpp位图
{
AfxMessageBox(L"对不起,不是256色位图!");// 警告
::GlobalUnlock((HGLOBAL)pDoc->GetHObject());// 解除锁定
return; //返回
} //判断是否是8-bpp位图,不是则返回
lpSrcStartBits = pDoc->m_dib.GetBits(lpSrcDib); // 找到DIB图象像素起始位置
lSrcWidth = pDoc->m_dib.GetWidth(lpSrcDib); // 获取图象的宽度
lSrcHeight = pDoc->m_dib.GetHeight(lpSrcDib); // 获取图象的高度
lpSrcBitCount = pDoc->m_dib.GetBitCount(lpSrcDib); //获取图像位深
lSrcLineBytes = pDoc->m_dib.GetReqByteWidth(lSrcWidth * 8); // 计算图象每行的字节数
/
int iTempH; // 模板高度
int iTempW; // 模板宽度
FLOAT fTempC; // 模板系数
int iTempMX; // 模板中心元素X坐标
int iTempMY; // 模板中心元素Y坐标
FLOAT aValue[9]; // 模板元素数组
float thre;
CDlgFilter Dlgfil;
Dlgfil.lSrcHeight = lSrcHeight;
Dlgfil.lSrcWidth = lSrcWidth;
Dlgfil.lpSrcStartBits = lpSrcStartBits;
Dlgfil.Doc = pDoc;
Dlgfil.lSrcLineBytes = lSrcLineBytes;
Dlgfil.lpSrcDib = lpSrcDib;
if (Dlgfil.DoModal() != IDOK)
{
return;
}
aValue[0] = Dlgfil.Num[0];
aValue[1] = Dlgfil.Num[1];
aValue[2] = Dlgfil.Num[2];
aValue[3] = Dlgfil.Num[3];
aValue[4] = Dlgfil.Num[4];
aValue[5] = Dlgfil.Num[5];
aValue[6] = Dlgfil.Num[6];
aValue[7] = Dlgfil.Num[7];
aValue[8] = Dlgfil.Num[8];
// 设定平移量(3*3)
iTempH = 3;
iTempW = 3;//这里用的都是3x3的模板,直接赋值为3了
iTempMX = Dlgfil.m_iTempMX;
iTempMY = Dlgfil.m_iTempMY;
fTempC = Dlgfil.m_fTempC;
thre = Dlgfil.Thre;
delete Dlgfil;
// 更改光标形状
BeginWaitCursor();
// 调用Template()函数
if (Template(lpSrcStartBits, lSrcWidth, lSrcHeight, iTempH, iTempW, iTempMX, iTempMY, aValue, fTempC, lSrcLineBytes,thre))
{
pDoc->SetModifiedFlag(TRUE);// 设置脏标记
pDoc->UpdateAllViews(NULL);// 更新视图
}
else
{
// 提示用户
AfxMessageBox(L"分配内存失败!");
}
// 解除锁定
::GlobalUnlock((HGLOBAL)pDoc->GetHObject());
// 恢复光标
EndWaitCursor();
}
算子总结
m_iTempH :模板的高度
m_iTempW :模板的宽度
m_iTempMX :模板中心坐标x
m_iTempMY :模板中心坐标y
m_fTempC :模板系数
Thre :为了把反色统一进模板类单独加的,反色是255,其他均为0
高斯模糊
m_iTempH = 3;
m_iTempW = 3;
m_iTempMX = 1;
m_iTempMY = 1;
m_fTempC = (FLOAT)(1.0 / 16.0);
Thre =0;
Num[0] = 1.0;
Num[1] = 2.0;
Num[2] = 1.0;
Num[3] = 2.0;
Num[4] = 4.0;
Num[5] = 2.0;
Num[6] = 1.0;
Num[7] = 2.0;
Num[8] = 1.0;
均值模糊
m_iTempH = 3;
m_iTempW = 3;
m_iTempMX = 1;
m_iTempMY = 1;
m_fTempC = (FLOAT)(1.0 / 9.0);
Thre = 0;
Num[0] = 1.0;
Num[1] = 1.0;
Num[2] = 1.0;
Num[3] = 1.0;
Num[4] = 1.0;
Num[5] = 1.0;
Num[6] = 1.0;
Num[7] = 1.0;
Num[8] = 1.0;
反色
m_iTempH = 3;
m_iTempW = 3;
m_iTempMX = 1;
m_iTempMY = 1;
m_fTempC = -1;
Thre = 255;
Num[0] = 0;
Num[1] = 0;
Num[2] = 0;
Num[3] = 0;
Num[4] = 1.0;
Num[5] = 0;
Num[6] = 0;
Num[7] = 0;
Num[8] = 0;
拉普拉斯锐化
m_iTempH = 3;
m_iTempW = 3;
m_iTempMX = 1;
m_iTempMY = 1;
m_fTempC = 1;
Thre = 0;
Num[0] = 1.0;
Num[1] = 1.0;
Num[2] = 1.0;
Num[3] = 1.0;
Num[4] = -8.0;
Num[5] = 1.0;
Num[6] = 1.0;
Num[7] = 1.0;
Num[8] = 1.0;
浮雕
m_iTempH = 3;
m_iTempW = 3;
m_iTempMX = 1;
m_iTempMY = 1;
m_fTempC = 1.0;
Thre = 0;
Num[0] = -2;
Num[1] = -1;
Num[2] = 0;
Num[3] = -1;
Num[4] = 1;
Num[5] = 1;
Num[6] = 0;
Num[7] = 1;
Num[8] = 2;
Sobel
m_iTempH = 3;
m_iTempW = 3;
m_iTempMX = 1;
m_iTempMY = 1;
m_fTempC = 1.0;
Gy:
Num[0] = -1;
Num[1] = 0;
Num[2] = 1;
Num[3] = -2;
Num[4] = 0;
Num[5] = 2;
Num[6] = -1;
Num[7] = 0;
Num[8] = 1;
Gx:
Num[0] = 1;
Num[1] = 2;
Num[2] = 1;
Num[3] = 0;
Num[4] = 0;
Num[5] = 0;
Num[6] = -1;
Num[7] = -2;
Num[8] = -1;
Prewitt
m_iTempH = 3;
m_iTempW = 3;
m_iTempMX = 1;
m_iTempMY = 1;
m_fTempC = 1.0;
Thre = 0;
Gx:
Num[0] = 1;
Num[1] = 1;
Num[2] = 1;
Num[3] = 0;
Num[4] = 0;
Num[5] = 0;
Num[6] = -1;
Num[7] = -1;
Num[8] = -1;
Gy:
Num[0] = -1;
Num[1] = 0;
Num[2] = 1;
Num[3] = -1;
Num[4] = 0;
Num[5] = 1;
Num[6] = -1;
Num[7] = 0;
Num[8] = 1;