目录
1.新建项目布局控件,编辑菜单
为各个菜单项,添加响应函数
2.主要类代码如下
Dib.h
//======================================================================
// 内容: 设备无关位图类-头文件
// 功能: (1)位图的加载与保存;
// (2)判断位图是否有效、获取位图的文件名;
// (3)获取位图的长、宽、大小等信息;
// (4)判断位图是否含有颜色表、获取位图颜色表、根据颜色表生成调
// 色板、使用颜色数、每个像素所占位数、每行像素所占位数;
// (5)获取位图数据;
// (6)显示位图;
// (7)将彩色位图转换成灰度位图;
// (8)将灰度位图转换成彩色位图;
// 作者: 李平科
// 联系: lipingke@126.com
// 日期: 2009-7-26
//======================================================================
#pragma once
#include "afx.h"
class CDib : public CObject
{
public:
// 构造函数
CDib(void);
// 析构函数
~CDib(void);
// 从文件加载位图
BOOL LoadFromFile(LPCTSTR lpszPath);
// 将位图保存到文件
BOOL SaveToFile(LPCTSTR lpszPath);
// 获取位图文件名
LPCTSTR GetFileName();
// 获取位图大小
DWORD GetSize();
// 获取位图宽度
UINT GetWidth();
// 获取位图高度
UINT GetHeight();
// 获取位图的宽度和高度
CSize GetDimension();
// 获取像素所占位数
UINT GetBitCount();
// 获取位图颜色数
UINT GetNumOfColor();
// 获取位图颜色表
LPRGBQUAD GetRgbQuad();
// 获取位图数据
LPBYTE GetData();
// 获取灰度位图数据
LPBYTE GetGradeData();
// 获取彩色位图数据
LPBYTE GetColorData();
// 根据颜色表生成调色板
BOOL MakePalette();
// 显示位图
BOOL Draw(CDC *pDC, CPoint origin, CSize size);
// 获取每行像素所占字节数
UINT GetLineByte();
// 彩色位图转灰度位图
BOOL RgbToGrade();
// 灰度位图转彩色位图
BOOL GradeToRgb();
// 判断是否含有颜色表
BOOL HasRgbQuad();
// 判断是否是灰度图
BOOL IsGrade();
// 判断位图是否有效
BOOL IsValid();
// 清理空间
void Empty();
protected:
// 计算位图颜色数
UINT CalcNumOfColor();
private:
// 位图文件名
char m_fileName[_MAX_PATH];
// 位图文件头指针
LPBITMAPFILEHEADER m_lpBmpFileHeader;
// 位图指针(包含除位图文件头的所有内容)
LPBYTE m_lpDib; // 需要动态分配和释放
// 位图信息指针
LPBITMAPINFO m_lpBmpInfo;
// 位图信息头指针
LPBITMAPINFOHEADER m_lpBmpInfoHeader;
// 位图颜色表指针
LPRGBQUAD m_lpRgbQuad;
// 位图数据指针
LPBYTE m_lpData;
// 灰度位图数据指针(位图转换时用)
LPBYTE m_lpGradeData; // 需要动态分配和释放
// 彩色位图数据指针(位图转换时用)
LPBYTE m_lpColorData; // 需要动态分配和释放
// 颜色表长度
UINT m_uRgbQuadLength;
// 位图颜色数
UINT m_uNumOfColor;
// 每像素占的位数
UINT m_uBitCount;
// 每行像素所占字节数,为4的倍数
UINT m_uLineByte;
// 是否有颜色表
BOOL m_bHasRgbQuad;
// 调色板句柄
HPALETTE m_hPalette;
// 位图是否有效
BOOL m_bValid;
};
Dib.cpp
//======================================================================
// 内容: 设备无关位图类-源文件
// 功能: (1)位图的加载与保存;
// (2)判断位图是否有效、获取位图的文件名;
// (3)获取位图的长、宽、大小等信息;
// (4)判断位图是否含有颜色表、获取位图颜色表、根据颜色表生成调
// 色板、使用颜色数、每个像素所占位数、每行像素所占位数;
// (5)获取位图数据;
// (6)显示位图;
// (7)将彩色位图转换成灰度位图;
// (8)将灰度位图转换成彩色位图;
// 作者: 李平科
// 联系: lipingke@126.com
// 日期: 2009-7-26
//======================================================================
#include "StdAfx.h"
#include "Dib.h"
//=======================================================
// 函数功能: 构造函数
// 输入参数: 无
// 返回值: 无
//=======================================================
CDib::CDib(void)
{
m_lpBmpFileHeader = NULL;
m_lpDib = NULL;
m_lpBmpInfo = NULL;
m_lpBmpInfoHeader = NULL;
m_lpRgbQuad = NULL;
m_lpData = NULL;
m_lpGradeData = NULL;
m_lpColorData = NULL;
m_hPalette = NULL;
m_bHasRgbQuad = FALSE;
m_bValid = FALSE;
}
//=======================================================
// 函数功能: 析构函数
// 输入参数: 无
// 返回值: 无
//=======================================================
CDib::~CDib(void)
{
// 清理空间
Empty();
}
//=======================================================
// 函数功能: 从文件加载位图
// 输入参数: lpszPath-待加载位图文件路径
// 返回值: 位图加载结果:TRUE-成功;FALSE-失败
//=======================================================
BOOL CDib::LoadFromFile(LPCTSTR lpszPath)
{
// 记录位图文件名
strcpy(m_fileName, lpszPath);
// 以读模式打开位图文件
CFile dibFile;
if(!dibFile.Open(m_fileName, CFile::modeRead | CFile::shareDenyWrite))
{
return FALSE;
}
// 清理空间
Empty();
// 读取位图文件头
m_lpBmpFileHeader = (LPBITMAPFILEHEADER)new BYTE[sizeof(BITMAPFILEHEADER)];
int nCount = dibFile.Read((void *)m_lpBmpFileHeader, sizeof(BITMAPFILEHEADER));
if(nCount != sizeof(BITMAPFILEHEADER))
{
return FALSE;
}
// 判断此文件是不是位图文件(“0x4d42”代表“BM”)
if(m_lpBmpFileHeader->bfType == 0x4d42)
{
// 是位图文件
// 计算除位图文件头的空间大小,并分配空间
DWORD dwDibSize = dibFile.GetLength() - sizeof(BITMAPFILEHEADER);
m_lpDib = new BYTE[dwDibSize];
// 读取除位图文件头的所有数据
dibFile.Read(m_lpDib, dwDibSize);
// 关闭位图文件
dibFile.Close();
// 设置位图信息指针
m_lpBmpInfo = (LPBITMAPINFO)m_lpDib;
// 设置位图信息头指针
m_lpBmpInfoHeader = (LPBITMAPINFOHEADER)m_lpDib;
// 设置每像素占的位数
m_uBitCount = m_lpBmpInfoHeader->biBitCount;
// 计算每行像素所占位数
m_uLineByte = (GetWidth() * m_uBitCount / 8 + 3) / 4 * 4;
// 设置位图颜色表指针
m_lpRgbQuad = (LPRGBQUAD)(m_lpDib + m_lpBmpInfoHeader->biSize);
// 计算位图颜色
m_uNumOfColor = CalcNumOfColor();
// 如果位图没有设置位图使用的颜色数,设置它
if(m_lpBmpInfoHeader->biClrUsed == 0)
{
m_lpBmpInfoHeader->biClrUsed = m_uNumOfColor;
}
// 计算颜色表长度
m_uRgbQuadLength = m_uNumOfColor * sizeof(RGBQUAD);
// 设置位图数据指针
m_lpData = m_lpDib + m_lpBmpInfoHeader->biSize + m_uRgbQuadLength;
// 判断是否有颜色表
if(m_lpRgbQuad == (LPRGBQUAD)m_lpData)
{
m_lpRgbQuad = NULL; // 将位图颜色表指针置空
m_bHasRgbQuad = FALSE; // 无颜色表
}
else
{
m_bHasRgbQuad = TRUE; // 有颜色表
MakePalette(); // 根据颜色表生成调色板
}
// 设置位图大小
m_lpBmpInfoHeader->biSizeImage = GetSize();
// 位图有效
m_bValid = TRUE;
return TRUE;
}
else
{
// 不是位图文件
m_bValid = FALSE;
return FALSE;
}
}
//=======================================================
// 函数功能: 将位图保存到文件
// 输入参数: lpszPath-位图文件保存路径
// 返回值: 位图保存结果:TRUE-成功;FALSE-失败
//=======================================================
BOOL CDib::SaveToFile(LPCTSTR lpszPath)
{
// 记录位图文件名
strcpy(m_fileName, lpszPath);
// 以写模式打开文件
CFile dibFile;
if(!dibFile.Open(lpszPath, CFile::modeCreate | CFile::modeReadWrite
| CFile::shareExclusive))
{
return FALSE;
}
// 填写文件头结构
BITMAPFILEHEADER bmpFileHeader;
bmpFileHeader.bfType = 0x4d42; // "0x4d42" 代表 "BM"
bmpFileHeader.bfSize = 0;
bmpFileHeader.bfReserved1 = bmpFileHeader.bfReserved2 = 0;
bmpFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)
+ m_uRgbQuadLength;
// 将文件头结构写进文件
dibFile.Write(m_lpBmpFileHeader, sizeof(BITMAPFILEHEADER));
// 将文件信息头结构写进文件
dibFile.Write(m_lpBmpInfoHeader, sizeof(BITMAPINFOHEADER));
// 如果有颜色表的话,将颜色表写进文件
if(m_uRgbQuadLength != 0)
{
dibFile.Write(m_lpRgbQuad, m_uRgbQuadLength);
}
// 将位图数据写进文件
UINT uDataSize = (GetWidth() * m_uBitCount / 8 + 3) / 4 * 4 * GetHeight();
dibFile.Write(m_lpData, uDataSize);
// 关闭文件
dibFile.Close();
return TRUE;
}
//=======================================================
// 函数功能: 获取位图文件名
// 输入参数: 无
// 返回值: LPCTSTR 位图文件名
//=======================================================
LPCTSTR CDib::GetFileName()
{
return m_fileName;
}
//=======================================================
// 函数功能: 获取位图大小
// 输入参数: 无
// 返回值: DWORD 位图大小
//=======================================================
DWORD CDib::GetSize()
{
if(m_lpBmpInfoHeader->biSizeImage != 0)
{
return m_lpBmpInfoHeader->biSizeImage;
}
else
{
DWORD dwWidth = (DWORD)GetWidth();
DWORD dwHeight = (DWORD)GetHeight();
return dwWidth * dwHeight;
}
}
//=======================================================
// 函数功能: 获取位图宽度
// 输入参数: 无
// 返回值: UINT 位图宽度
//=======================================================
UINT CDib::GetWidth()
{
return (UINT)m_lpBmpInfoHeader->biWidth;
}
//=======================================================
// 函数功能: 获取位图高度
// 输入参数: 无
// 返回值: UINT 位图高度
//=======================================================
UINT CDib::GetHeight()
{
return (UINT)m_lpBmpInfoHeader->biHeight;
}
//=======================================================
// 函数功能: 获取位图的宽度和高度
// 输入参数: 无
// 返回值: 位图的宽度和高度
//=======================================================
CSize CDib::GetDimension()
{
return CSize(GetWidth(), GetHeight());
}
//=======================================================
// 函数功能: 计算位图颜色数
// 输入参数: 无
// 返回值: UINT 位图颜色数
//=======================================================
UINT CDib::CalcNumOfColor()
{
UINT uNumOfColor;
if ((m_lpBmpInfoHeader->biClrUsed == 0)
&& (m_lpBmpInfoHeader->biBitCount < 9))
{
switch (m_lpBmpInfoHeader->biBitCount)
{
case 1: uNumOfColor = 2; break;
case 4: uNumOfColor = 16; break;
case 8: uNumOfColor = 256;
}
}
else
{
uNumOfColor = (UINT) m_lpBmpInfoHeader->biClrUsed;
}
return uNumOfColor;
}
//=======================================================
// 函数功能: 获取像素所占位数
// 输入参数: 无
// 返回值: 像素所占位数
//=======================================================
UINT CDib::GetBitCount()
{
return m_uBitCount;
}
//=======================================================
// 函数功能: 获取位图颜色数
// 输入参数: 无
// 返回值: 位图颜色数
//=======================================================
UINT CDib::GetNumOfColor()
{
return m_uNumOfColor;
}
//=======================================================
// 函数功能: 获取位图颜色表
// 输入参数: 无
// 返回值: LPRGBQUAD 位图颜色表指针
//=======================================================
LPRGBQUAD CDib::GetRgbQuad()
{
return m_lpRgbQuad;
}
//=======================================================
// 函数功能: 获取位图数据
// 输入参数: 无
// 返回值: LPBYTE 位图数据指针
//=======================================================
LPBYTE CDib::GetData()
{
return m_lpData;
}
//=======================================================
// 函数功能: 获取灰度位图数据
// 输入参数: 无
// 返回值: LPBYTE 灰度位图数据指针
//=======================================================
LPBYTE CDib::GetGradeData()
{
// 含有颜色表时已是灰度位图
if(GetRgbQuad())
{
m_lpGradeData = m_lpData;
}
return m_lpGradeData;
}
//=======================================================
// 函数功能: 获取彩色位图数据
// 输入参数: 无
// 返回值: LPBYTE 彩色位图数据指针
//=======================================================
LPBYTE CDib::GetColorData()
{
return m_lpColorData;
}
//=======================================================
// 函数功能: 根据颜色表生成调色板
// 输入参数: 无
// 返回值: 生成结果:TRUE-成功;FALSE-失败
//=======================================================
BOOL CDib::MakePalette()
{
// 如果颜色表长度为0,则不生成逻辑调色板
if(m_uRgbQuadLength == 0)
{
return FALSE;
}
//删除旧的调色板对象
if(m_hPalette != NULL) DeleteObject(m_hPalette);
// 申请缓冲区,生成逻辑调色板
LPLOGPALETTE lpLogPalette = (LPLOGPALETTE) new BYTE[2 * sizeof(WORD)
+ m_uRgbQuadLength * sizeof(PALETTEENTRY)];
lpLogPalette->palVersion = 0x300;
lpLogPalette->palNumEntries = m_uRgbQuadLength;
LPRGBQUAD lpRgbQuad = (LPRGBQUAD) m_lpRgbQuad;
for(int i = 0; i < m_uRgbQuadLength; i++) {
lpLogPalette->palPalEntry[i].peRed = lpRgbQuad->rgbRed;
lpLogPalette->palPalEntry[i].peGreen = lpRgbQuad->rgbGreen;
lpLogPalette->palPalEntry[i].peBlue = lpRgbQuad->rgbBlue;
lpLogPalette->palPalEntry[i].peFlags = 0;
lpRgbQuad++;
}
// 创建逻辑调色板
m_hPalette = CreatePalette(lpLogPalette);
// 释放缓冲区
delete lpLogPalette;
return TRUE;
}
//=======================================================
// 函数功能: 显示位图
// 输入参数:
// pDC-设备环境指针
// origin-显示矩形区域的左上角
// size-显示矩形区域的尺寸
// 返回值:
// 显示结果:TRUE-成功;FALSE-失败
//=======================================================
BOOL CDib::Draw(CDC *pDC, CPoint origin, CSize size)
{
// 旧的调色板句柄
HPALETTE hOldPalette = NULL;
// 如果位图指针为空,则返回FALSE
if(m_lpDib == NULL)
{
return FALSE;
}
// 如果位图有调色板,则选进设备环境中
if(m_hPalette != NULL)
{
hOldPalette = SelectPalette(pDC->GetSafeHdc(), m_hPalette, TRUE);
}
// 设置位图伸缩模式
pDC->SetStretchBltMode(COLORONCOLOR);
// 将位图在pDC所指向的设备上进行显示
StretchDIBits(pDC->GetSafeHdc(), origin.x, origin.y, size.cx, size.cy,
0, 0, GetWidth(), GetHeight(), m_lpData, m_lpBmpInfo, DIB_RGB_COLORS, SRCCOPY);
// 恢复旧的调色板
if(hOldPalette != NULL)
{
SelectPalette(pDC->GetSafeHdc(), hOldPalette, TRUE);
}
return TRUE;
}
//=======================================================
// 函数功能: 获取每行像素所占字节数
// 输入参数: 无
// 返回值: 每行像素所占字节数
//=======================================================
UINT CDib::GetLineByte()
{
return m_uLineByte;
}
//=======================================================
// 函数功能: 彩色位图转灰度位图
// 输入参数: 无
// 返回值: 转换结果:TRUE-成功;FALSE-失败
//=======================================================
BOOL CDib::RgbToGrade()
{
// 颜色表存在时已是灰度图,无须转换,否则需要转换
if(GetRgbQuad())
{
m_lpGradeData = m_lpData;
}
else
{
BYTE r, g, b;
UINT uHeight = GetHeight();
UINT uWidth = GetWidth();
UINT uLineByte = GetLineByte();
// 如果已分配空间,释放原有空间
if((m_lpGradeData != NULL) && (m_lpGradeData != m_lpData))
{
delete [] m_lpGradeData;
}
// 重新分配空间
m_lpGradeData = (LPBYTE)new BYTE[GetSize()];
// 进行转换
for(int i = 0; i < uHeight; i++)
{
for(int j = 0; j < uWidth; j++)
{
b = m_lpData[i * m_uLineByte + 3 * j];
g = m_lpData[i * m_uLineByte + 3 * j + 1];
r = m_lpData[i * m_uLineByte + 3 * j + 2];
m_lpGradeData[i * uWidth + j] = (BYTE)(0.3 * r + 0.59 * g + 0.11 * b);
}
}
// 指向转换换后的位图数据
m_lpData = m_lpGradeData;
// 更新位图头信息
// 每像素所占位数
m_lpBmpInfoHeader->biBitCount = 8;
m_uBitCount = 8;
// 每行像素所占字节数
m_uLineByte = (GetWidth() * m_uBitCount / 8 + 3) / 4 * 4;
}
return TRUE;
}
//=======================================================
// 函数功能: 灰度位图转彩色位图
// 输入参数: 无
// 返回值: 转换结果:TRUE-成功;FALSE-失败
//=======================================================
BOOL CDib::GradeToRgb()
{
// 颜色表存在时是灰度图,需转换,否则不需要转换
if(GetRgbQuad())
{
UINT uHeight = GetHeight();
UINT uWidth = GetWidth();
UINT uLineByte = GetLineByte();
// 如果已分配空间,释放原有空间
if((m_lpColorData != NULL) && (m_lpColorData != m_lpData))
{
delete [] m_lpColorData;
}
// 重新分配空间
m_lpColorData = (LPBYTE)new BYTE[GetSize()*3];
// 进行转换
for(int i = 0; i < uHeight; i++)
{
for(int j = 0; j < uWidth; j++)
{
m_lpColorData[(uHeight - i - 1) * m_uLineByte + 3 * j] =
m_lpData[(uHeight - i - 1) * uWidth + i];
m_lpColorData[(uHeight - i - 1) * m_uLineByte + 3 * j + 1] =
m_lpData[(uHeight - i - 1) * uWidth + i];
m_lpColorData[(uHeight - i - 1) * m_uLineByte + 3 * j + 2] =
m_lpData[(uHeight - i - 1) * uWidth + i];
}
}
// 指向转换换后的位图数据
m_lpData = m_lpColorData;
// 更新位图头信息
// 每像素所占位数
m_lpBmpInfoHeader->biBitCount = 24;
m_uBitCount = 24;
// 每行像素所占字节数
m_uLineByte = (GetWidth() * m_uBitCount / 8 + 3) / 4 * 4;
}
return TRUE;
}
//=======================================================
// 函数功能: 判断是否含有颜色表
// 输入参数: 无
// 返回值: 判断结果:TRUE-含有颜色表;FALSE-不含颜色表
//=======================================================
BOOL CDib::HasRgbQuad()
{
return m_bHasRgbQuad;
}
//=======================================================
// 函数功能: 判断是否是灰度图
// 输入参数: 无
// 返回值: 判断结果:TRUE-是灰度图;FALSE-是彩色图
//=======================================================
BOOL CDib::IsGrade()
{
return (m_uBitCount < 9);
}
//=======================================================
// 函数功能: 判断位图是否有效
// 输入参数: 无
// 返回值: 判断结果:TRUE-位图有效;FALSE-位图无效
//=======================================================
BOOL CDib::IsValid()
{
return m_bValid;
}
//=======================================================
// 函数功能: 清理空间
// 输入参数: 无
// 返回值: 无
//=======================================================
void CDib::Empty()
{
// 释放位图文件头指针空间
if(m_lpBmpFileHeader != NULL)
{
delete [] m_lpBmpFileHeader;
}
// 释放灰度位图数据空间
if((m_lpGradeData != NULL) && (m_lpGradeData != m_lpData))
{
delete [] m_lpGradeData;
}
// 释放彩色位图数据空间
if((m_lpColorData != NULL) && (m_lpColorData != m_lpData))
{
delete [] m_lpColorData;
}
// 释放位图指针空间
if(m_lpDib != NULL)
{
delete [] m_lpDib;
m_lpBmpInfo = NULL;
m_lpBmpInfoHeader = NULL;
m_lpRgbQuad = NULL;
m_lpData = NULL;
}
// 释放调色板
if(m_hPalette != NULL)
{
DeleteObject(m_hPalette);
m_hPalette = NULL;
}
// 设置不含颜色表
m_bHasRgbQuad = FALSE;
// 设置位图无效
m_bValid = FALSE;
}
EdgeDetection.h
#pragma once
//边缘检测类
#include "Dib.h"
class CEdgeDetection
{
public:
CEdgeDetection(CDib *pDib);
void Roberts(void);
void Template(LPBYTE lpData, int nLineByte, int nWidth, int nHeight, int nTemH, int nTemW, int nTemCX, int nTemCY, float *fpArray, float fCoef);
void Sobel(void);
void Prewitt(void);
void Laplacian(void);
void GuassLaplacian(void);
void Krisch(void);
public:
~CEdgeDetection(void);
private:
CDib *m_pDib;
};
EdgeDetection.cpp
#include "StdAfx.h"
#include "EdgeDetection.h"
#include "math.h"
CEdgeDetection::CEdgeDetection(CDib *pDib)
{
m_pDib = pDib;
}
//错误 21 error C4996 : 'strcpy' : This function or variable may be unsafe.Consider using strcpy_s instead.To disable deprecation, use _CRT_SECURE_NO_WARNINGS.See online help for details.d : \20220830\c\基于对话框的mfc图像分割\dib.cpp 59 1 基于对话框的MFC图像分割
CEdgeDetection::~CEdgeDetection(void)
{
}
//=======================================================
// 函数功能: Roberts边缘检测算子
// 输入参数: void
// 返回值: void
//=======================================================
void CEdgeDetection::Roberts(void)
{
// 循环变量
int i, j;
// 原图像数据区指针
LPBYTE lpData;
lpData = m_pDib->GetData();
// 图像每行像素所占的字节数
int nLineByte = m_pDib->GetLineByte();
// 图像的宽度
int nWidth = m_pDib->GetWidth();
// 图像的高度
int nHeight = m_pDib->GetHeight();
// 新图像缓冲区的指针
LPBYTE lpTemp;
lpTemp = new BYTE[nLineByte * nHeight];
// 初始化新分配的内存,设定初始值为255
memset(lpTemp, 255, nLineByte * nHeight);
// Roberts算子
int pixel[4];
// 由于使用2*2的模板,为防止越界,不处理最上边和最右边的边界像素
for(j = 0; j < nHeight - 1; j ++)
for(i = 0; i < nWidth - 1; i ++)
{
//生成Roberts算子
pixel[0] = lpData[j * nLineByte + i];
pixel[1] = lpData[j * nLineByte + i + 1];
pixel[2] = lpData[(j + 1) * nLineByte + i];
pixel[3] = lpData[(j + 1) * nLineByte + i + 1];
// 处理当前像素
lpTemp[j * nLineByte + i] = sqrt(double ( (pixel[0] - pixel[3]) * (pixel[0] - pixel[3])
+ (pixel[1] - pixel[2]) * (pixel[1] - pixel[2]) ) );
lpTemp[j * nLineByte + i] = 255 - lpTemp[j * nLineByte + i];
}
// 将处理后的新图像复制到原图像中
memcpy(lpData,lpTemp, nLineByte * nHeight);
// 释放内存
delete [] lpTemp;
}
//=======================================================
// 函数功能: 灰度模板
// 输入参数: LPBYTE lpData: 指向原图像数据区指针
// int nLineByte: 原图像每行像素所占的字节数
// int nWidth: 原图像宽度
// int nHeight: 原图像高度
// int nTemH: 模板高度
// int nTemW: 模板宽度
// int nTemCX: 模板中心元素的X坐标(<nTemW-1)
// int nTemCY: 模板的中心元素的Y坐标(<nTemH-1)
// float *fpArray: 指向模板数组的指针
// float fCoef:模板系数
// 返回值: void
//=======================================================
void CEdgeDetection::Template(LPBYTE lpData, int nLineByte, int nWidth, int nHeight, int nTemH, int nTemW, int nTemCX, int nTemCY, float *fpArray, float fCoef)
{
// 循环变量
int i, j, k, l;
// 新图像缓冲区的指针
LPBYTE lpTemp;
lpTemp = new BYTE[nLineByte * nHeight];
// 初始化新分配的内存,设定初始值为255
memset(lpTemp, 255, nLineByte * nHeight);
// 像素值计算结果
float fResult;
for(j = nTemCY; j < nHeight - nTemH + nTemCY + 1; j ++)
for(i = nTemCX; i < nWidth - nTemW + nTemCX + 1; i ++)
{
// 计算当前像素值
fResult = 0;
for(k = 0; k < nTemH; k ++)
for(l = 0; l < nTemW; l ++)
// 卷积运算
fResult += lpData[(j - nTemCY + k) * nLineByte + (i - nTemCX + l)]
* fpArray[k * nTemW + l];
//用系数乘以当前像素值计算结果
fResult *= fCoef;
//取绝对值
fResult = (float) fabs(fResult);
// 判断是否超过255
if(fResult > 255)
// 若超过255,在新图像当前像素位置直接赋值为255
lpTemp[j * nLineByte + i] = 255;
else
// 未超过255,在新图像当前像素位置赋值为计算结果
lpTemp[j * nLineByte + i] = (int) (fResult + 0.5);
}
// 将处理后的新图像复制到原图像中
memcpy(lpData,lpTemp, nLineByte * nHeight);
// 释放内存
delete [] lpTemp;
}
//=======================================================
// 函数功能: Sobel边缘检测算子
// 输入参数: void
// 返回值: void
//=======================================================
void CEdgeDetection::Sobel()
{
// 原图像数据区指针
LPBYTE lpData;
lpData = m_pDib->GetData();
// 图像每行像素所占的字节数
int nLineByte = m_pDib->GetLineByte();
// 图像的宽度
int nWidth = m_pDib->GetWidth();
// 图像的高度
int nHeight = m_pDib->GetHeight();
// 模板宽度和高度
int nTemW, nTemH;
// 模板系数
float fCoef;
//模板中心元素的X坐标和Y坐标
int nTemCX, nTemCY;
//模板数组
float arTemplate[9];
//在此添加关键代码
}
//=======================================================
// 函数功能: Prewitt边缘检测算子
// 输入参数: void
// 返回值: void
//=======================================================
void CEdgeDetection::Prewitt(void)
{
// 原图像数据区指针
LPBYTE lpData;
lpData = m_pDib->GetData();
// 图像每行像素所占的字节数
int nLineByte = m_pDib->GetLineByte();
// 图像的宽度
int nWidth = m_pDib->GetWidth();
// 图像的高度
int nHeight = m_pDib->GetHeight();
// 模板宽度和高度
int nTemW, nTemH;
// 模板系数
float fCoef;
//模板中心元素的X坐标和Y坐标
int nTemCX, nTemCY;
//模板数组
float arTemplate[9];
//在此添加关键程序
}
//=======================================================
// 函数功能: Laplacian边缘检测算子
// 输入参数: void
// 返回值: void
//=======================================================
void CEdgeDetection::Laplacian(void)
{
// 原图像数据区指针
LPBYTE lpData;
lpData = m_pDib->GetData();
// 图像每行像素所占的字节数
int nLineByte = m_pDib->GetLineByte();
// 图像的宽度
int nWidth = m_pDib->GetWidth();
// 图像的高度
int nHeight = m_pDib->GetHeight();
// 模板宽度和高度
int nTemW, nTemH;
// 模板系数
float fCoef;
//模板中心元素的X坐标和Y坐标
int nTemCX, nTemCY;
//模板数组
float arTemplate[9];
//在此添加关键代码
}
//=======================================================
// 函数功能: GuassLaplacian边缘检测算子
// 输入参数: void
// 返回值: void
//=======================================================
void CEdgeDetection::GuassLaplacian(void)
{
// 原图像数据区指针
LPBYTE lpData;
lpData = m_pDib->GetData();
// 图像每行像素所占的字节数
int nLineByte = m_pDib->GetLineByte();
// 图像的宽度
int nWidth = m_pDib->GetWidth();
// 图像的高度
int nHeight = m_pDib->GetHeight();
// 模板宽度和高度
int nTemW, nTemH;
// 模板系数
float fCoef;
//模板中心元素的X坐标和Y坐标
int nTemCX, nTemCY;
//模板数组
float arTemplate[25];
// 新图像缓冲区的指针
LPBYTE lpTemp;
lpTemp = new BYTE[nLineByte * nHeight];
// 初始化新分配的内存,复制原图像
memcpy(lpTemp, lpData, nLineByte * nHeight);
// 设置GuassLaplacian模板的参数
nTemW = 5;
nTemH = 5;
fCoef = 0.25;
nTemCX = 4;
nTemCY = 4;
arTemplate[0] = -2.0;
arTemplate[1] = -4.0;
arTemplate[2] = -4.0;
arTemplate[3] = -4.0;
arTemplate[4] = -2.0;
arTemplate[5] = -4.0;
arTemplate[6] = 0.0;
arTemplate[7] = 8.0;
arTemplate[8] = 0.0;
arTemplate[9] = -4.0;
arTemplate[10] = -4.0;
arTemplate[11] = 8.0;
arTemplate[12] = 24.0;
arTemplate[13] = 8.0;
arTemplate[14] = -4.0;
arTemplate[15] = -4.0;
arTemplate[16] = 0.0;
arTemplate[17] = 8.0;
arTemplate[18] = 0.0;
arTemplate[19] = -4.0;
arTemplate[20] = -2.0;
arTemplate[21] = -4.0;
arTemplate[22] = -4.0;
arTemplate[23] = -4.0;
arTemplate[24] = -2.0;
// 调用Template()函数
Template(lpTemp, nLineByte, nWidth, nHeight, nTemH, nTemW, nTemCX, nTemCY, arTemplate, fCoef);
// 将缓存图像复制到原图像中
memcpy(lpData, lpTemp, nLineByte * nHeight);
// 删除缓冲区
delete [] lpTemp;
}
//=======================================================
// 函数功能: Krisch边缘检测算子
// 输入参数: void
// 返回值: void
//=======================================================
void CEdgeDetection::Krisch(void)
{
// 原图像数据区指针
LPBYTE lpData;
lpData = m_pDib->GetData();
// 图像每行像素所占的字节数
int nLineByte = m_pDib->GetLineByte();
// 图像的宽度
int nWidth = m_pDib->GetWidth();
// 图像的高度
int nHeight = m_pDib->GetHeight();
// 模板宽度和高度
int nTemW, nTemH;
// 模板系数
float fCoef;
//模板中心元素的X坐标和Y坐标
int nTemCX, nTemCY;
//模板数组
float arTemplate[9];
// 两幅新图像缓冲区的指针
LPBYTE lpTemp1, lpTemp2;
lpTemp1 = new BYTE[nLineByte * nHeight];
lpTemp2 = new BYTE[nLineByte * nHeight];
// 初始化新分配的内存,复制原图像
memcpy(lpTemp1, lpData, nLineByte * nHeight);
memcpy(lpTemp2, lpData, nLineByte * nHeight);
// 设置Krisch模板一的参数
nTemW = 3;
nTemH = 3;
fCoef = 0.5;
nTemCX = 1;
nTemCY = 1;
arTemplate[0] = 5.0;
arTemplate[1] = 5.0;
arTemplate[2] = 5.0;
arTemplate[3] = -3.0;
arTemplate[4] = 0.0;
arTemplate[5] = -3.0;
arTemplate[6] = -3.0;
arTemplate[7] = -3.0;
arTemplate[8] = -3.0;
// 调用Template()函数
Template(lpTemp1, nLineByte, nWidth, nHeight, nTemH, nTemW, nTemCX, nTemCY, arTemplate, fCoef);
// 设置Krisch模板二的参数
arTemplate[0] = -3.0;
arTemplate[1] = 5.0;
arTemplate[2] = 5.0;
arTemplate[3] = -3.0;
arTemplate[4] = 0.0;
arTemplate[5] = 5.0;
arTemplate[6] = -3.0;
arTemplate[7] = -3.0;
arTemplate[8] = -3.0;
// 调用Template()函数
Template(lpTemp2, nLineByte, nWidth, nHeight, nTemH, nTemW, nTemCX, nTemCY, arTemplate, fCoef);
// 取两幅缓存图像对应像素的最大值,并存放在第一个缓存图像中
for(int j = 0; j < nHeight; j ++)
for(int i = 0; i < nWidth; i ++)
if( lpTemp2[j * nLineByte + i] > lpTemp1[j * nLineByte + i] )
lpTemp1[j * nLineByte + i] = lpTemp2[j * nLineByte + i];
// 将原图像复制到第二个缓存图像中
memcpy(lpTemp2, lpData, nLineByte * nHeight);
// 设置Krisch模板三的参数
arTemplate[0] = -3.0;
arTemplate[1] = -3.0;
arTemplate[2] = 5.0;
arTemplate[3] = -3.0;
arTemplate[4] = 0.0;
arTemplate[5] = 5.0;
arTemplate[6] = -3.0;
arTemplate[7] = -3.0;
arTemplate[8] = 5.0;
// 调用Template()函数
Template(lpTemp2, nLineByte, nWidth, nHeight, nTemH, nTemW, nTemCX, nTemCY, arTemplate, fCoef);
// 取两幅缓存图像对应像素的最大值,并存放在第一个缓存图像中
for(int j = 0; j < nHeight; j ++)
for(int i = 0; i < nWidth; i ++)
if( lpTemp2[j * nLineByte + i] > lpTemp1[j * nLineByte + i] )
lpTemp1[j * nLineByte + i] = lpTemp2[j * nLineByte + i];
// 将原图像复制到第二个缓存图像中
memcpy(lpTemp2, lpData, nLineByte * nHeight);
// 设置Krisch模板四的参数
arTemplate[0] = -3.0;
arTemplate[1] = -3.0;
arTemplate[2] = -3.0;
arTemplate[3] = -3.0;
arTemplate[4] = 0.0;
arTemplate[5] = 5.0;
arTemplate[6] = -3.0;
arTemplate[7] = 5.0;
arTemplate[8] = 5.0;
// 调用Template()函数
Template(lpTemp2, nLineByte, nWidth, nHeight, nTemH, nTemW, nTemCX, nTemCY, arTemplate, fCoef);
// 取两幅缓存图像对应像素的最大值,并存放在第一个缓存图像中
for(int j = 0; j < nHeight; j ++)
for(int i = 0; i < nWidth; i ++)
if( lpTemp2[j * nLineByte + i] > lpTemp1[j * nLineByte + i] )
lpTemp1[j * nLineByte + i] = lpTemp2[j * nLineByte + i];
// 将原图像复制到第二个缓存图像中
memcpy(lpTemp2, lpData, nLineByte * nHeight);
// 设置Krisch模板五的参数
arTemplate[0] = -3.0;
arTemplate[1] = -3.0;
arTemplate[2] = -3.0;
arTemplate[3] = -3.0;
arTemplate[4] = 0.0;
arTemplate[5] = -3.0;
arTemplate[6] = 5.0;
arTemplate[7] = 5.0;
arTemplate[8] = 5.0;
// 调用Template()函数
Template(lpTemp2, nLineByte, nWidth, nHeight, nTemH, nTemW, nTemCX, nTemCY, arTemplate, fCoef);
// 取两幅缓存图像对应像素的最大值,并存放在第一个缓存图像中
for(int j = 0; j < nHeight; j ++)
for(int i = 0; i < nWidth; i ++)
if( lpTemp2[j * nLineByte + i] > lpTemp1[j * nLineByte + i] )
lpTemp1[j * nLineByte + i] = lpTemp2[j * nLineByte + i];
// 将原图像复制到第二个缓存图像中
memcpy(lpTemp2, lpData, nLineByte * nHeight);
// 设置Krisch模板六的参数
arTemplate[0] = -3.0;
arTemplate[1] = -3.0;
arTemplate[2] = -3.0;
arTemplate[3] = 5.0;
arTemplate[4] = 0.0;
arTemplate[5] = -3.0;
arTemplate[6] = 5.0;
arTemplate[7] = 5.0;
arTemplate[8] = -3.0;
// 调用Template()函数
Template(lpTemp2, nLineByte, nWidth, nHeight, nTemH, nTemW, nTemCX, nTemCY, arTemplate, fCoef);
// 取两幅缓存图像对应像素的最大值,并存放在第一个缓存图像中
for(int j = 0; j < nHeight; j ++)
for(int i = 0; i < nWidth; i ++)
if( lpTemp2[j * nLineByte + i] > lpTemp1[j * nLineByte + i] )
lpTemp1[j * nLineByte + i] = lpTemp2[j * nLineByte + i];
// 将原图像复制到第二个缓存图像中
memcpy(lpTemp2, lpData, nLineByte * nHeight);
// 设置Krisch模板七的参数
arTemplate[0] = 5.0;
arTemplate[1] = -3.0;
arTemplate[2] = -3.0;
arTemplate[3] = 5.0;
arTemplate[4] = 0.0;
arTemplate[5] = -3.0;
arTemplate[6] = 5.0;
arTemplate[7] = -3.0;
arTemplate[8] = -3.0;
// 调用Template()函数
Template(lpTemp2, nLineByte, nWidth, nHeight, nTemH, nTemW, nTemCX, nTemCY, arTemplate, fCoef);
// 取两幅缓存图像对应像素的最大值,并存放在第一个缓存图像中
for(int j = 0; j < nHeight; j ++)
for(int i = 0; i < nWidth; i ++)
if( lpTemp2[j * nLineByte + i] > lpTemp1[j * nLineByte + i] )
lpTemp1[j * nLineByte + i] = lpTemp2[j * nLineByte + i];
// 将原图像复制到第二个缓存图像中
memcpy(lpTemp2, lpData, nLineByte * nHeight);
// 设置Krisch模板八的参数
arTemplate[0] = 5.0;
arTemplate[1] = 5.0;
arTemplate[2] = -3.0;
arTemplate[3] = 5.0;
arTemplate[4] = 0.0;
arTemplate[5] = -3.0;
arTemplate[6] = -3.0;
arTemplate[7] = -3.0;
arTemplate[8] = -3.0;
// 调用Template()函数
Template(lpTemp2, nLineByte, nWidth, nHeight, nTemH, nTemW, nTemCX, nTemCY, arTemplate, fCoef);
// 取两幅缓存图像对应像素的最大值,并存放在第一个缓存图像中
for(int j = 0; j < nHeight; j ++)
for(int i = 0; i < nWidth; i ++)
if( lpTemp2[j * nLineByte + i] > lpTemp1[j * nLineByte + i] )
lpTemp1[j * nLineByte + i] = lpTemp2[j * nLineByte + i];
// 将第一个缓存图像复制到原图像中
memcpy(lpData, lpTemp1, nLineByte * nHeight);
// 删除缓冲区
delete [] lpTemp1;
delete [] lpTemp2;
}
Threshold.h
#pragma once
#include "Dib.h"
class CThreshold
{
public:
CThreshold();
CThreshold(CDib *pDib);
public:
~CThreshold(void);
public:
void AdaptiveThreshold(void);
void OtusThreshold(void);
private:
CDib * m_pDib;
};
Threshold.cpp
#include "StdAfx.h"
#include "Threshold.h"
#include "math.h"
CThreshold::CThreshold()
{
}
CThreshold::CThreshold(CDib *pDib)
{
m_pDib = pDib;
}
CThreshold::~CThreshold(void)
{
}
//=======================================================
// 函数功能: 最大方差阈值分割
// 输入参数: 无
// 返回值: 无
//=======================================================
void CThreshold::OtusThreshold(void)
{
// 循环变量
int i, j;
// 原图数据区指针
LPBYTE p_data;
p_data = m_pDib->GetData();
// 图像每行像素所占的字节数
int nLineByte = m_pDib->GetLineByte();
// 图像的宽度
int nWidth = m_pDib->GetWidth();
// 图像的高度
int nHeight = m_pDib->GetHeight();
// 灰度直方图数组,并初始化
int nGrayHistogram[256];
memset(nGrayHistogram, 0, sizeof(nGrayHistogram));
// 统计各个灰度级对应的像素个数,并存放到灰度直方图数组中
int nPixel;
for (j = 0; j < nHeight; j ++)
for (i = 0; i < nWidth; i ++)
{
// 获取当前像素点的灰度值
nPixel = p_data[nLineByte * j + i];
// 对灰度值统计计数
nGrayHistogram[nPixel] ++;
}
// c0组和c1组的均值
float u0, u1;
// c0组和c1组的概率
float w0, w1;
// c0组的像素总数
int nCount0;
// 阈值和最佳阈值(对应方差最大时的阈值)
int nT, nBestT;
// 方差和最大方差
float fVaria, fMaxVaria = 0;
// 统计直方图中像素点的总数,并存放到nSum中
int nSum=0;
for(i = 0; i < 256; i ++)
nSum += nGrayHistogram[i];
// 令阈值nT从0遍历到255
for(nT = 0; nT < 256; nT ++)
{
// 当阈值为nT时,计算c0组的均值和概率
u0 = 0;
nCount0 = 0;
for(i = 0; i <= nT; i++)
{
u0 += i * nGrayHistogram[i];
nCount0 += nGrayHistogram[i];
}
u0 /= nCount0;
w0 = (float) nCount0 / nSum;
// 当阈值为nT时,计算c1组的均值和概率
u1 = 0;
for(i = nT+1; i < 256; i ++)
u1 += i * nGrayHistogram[i];
u1 /= (nSum - nCount0);
w1 = 1 - w0;
// 计算两组间的方差
fVaria = w0 * w1 * (u0 - u1) * (u0 - u1);
// 记录最大方差和最佳阈值
if(fVaria > fMaxVaria)
{
fMaxVaria = fVaria;
nBestT = nT;
}
}
// 利用最佳阈值对原图像作分割处理
for(j = 0; j < nHeight; j ++)
for(i = 0; i < nWidth; i ++)
{
if(p_data[j * nLineByte + i] < nBestT)
p_data[j * nLineByte + i] = 0;
else
p_data[j * nLineByte + i] = 255;
}
}
//=======================================================
// 函数功能: 自适应阈值分割
// 输入参数: 无
// 返回值: 无
//=======================================================
void CThreshold::AdaptiveThreshold(void)
{
// 循环变量
int i,j;
// 原图像数据区指针
LPBYTE p_data;
p_data = m_pDib->GetData();
// 图像每行像素所占的字节数
int nLineByte = m_pDib->GetLineByte();
// 图像的宽度
int nWidth = m_pDib->GetWidth();
// 图像的高度
int nHeight = m_pDib->GetHeight();
// 局部阈值
int nThreshold[2][2];
// 子图像的灰度平均值
int nAvgValue;
// 对左上图像逐点扫描,计算该子图像的灰度平均值
nAvgValue = 0;
for(j = nHeight / 2; j < nHeight; j ++)
for(i = 0; i < nWidth / 2; i ++)
nAvgValue += p_data[j * nLineByte + i];
nAvgValue /= ((nHeight / 2) * (nLineByte / 2));
// 设置阈值为子图像的平均值
nThreshold[0][0] = nAvgValue;
// 对左上图像逐点扫描并进行阈值分割
for(j = nHeight / 2; j < nHeight; j ++)
for(i = 0; i < nWidth / 2; i ++)
{
if(p_data[j * nLineByte + i] < nThreshold[0][0])
p_data[j * nLineByte + i] = 0;
else
p_data[j * nLineByte + i] = 255;
}
// 对右上图像逐点扫描,计算该子图像的灰度平均值
nAvgValue = 0;
for(j = nHeight / 2; j < nHeight; j ++)
for(i = nWidth / 2; i < nWidth; i ++)
nAvgValue += p_data[j * nLineByte + i];
nAvgValue /= ((nHeight / 2) * (nLineByte / 2));
// 设置阈值为子图像的平均值
nThreshold[0][1] = nAvgValue;
// 对右上图像逐点扫描并进行阈值分割
for(j = nHeight / 2; j < nHeight; j ++)
for(i = nWidth / 2; i < nWidth; i ++)
{
if(p_data[j * nLineByte + i] < nThreshold[0][0])
p_data[j * nLineByte + i] = 0;
else
p_data[j * nLineByte + i] = 255;
}
// 对左下图像逐点扫描,计算该子图像的灰度平均值
nAvgValue = 0;
for(j = 0; j < nHeight / 2; j ++)
for(i = 0; i < nWidth / 2; i ++)
nAvgValue += p_data[j * nLineByte + i];
nAvgValue /= ((nHeight / 2) * (nLineByte / 2));
// 设置阈值为子图像的平均值
nThreshold[1][0] = nAvgValue;
// 对左下图像逐点扫描并进行阈值分割
for(j = 0; j < nHeight / 2; j ++)
for(i = 0; i < nWidth / 2; i ++)
{
if(p_data[j * nLineByte + i] < nThreshold[0][0])
p_data[j * nLineByte + i] = 0;
else
p_data[j * nLineByte + i] = 255;
}
// 对右下图像逐点扫描,计算该子图像的灰度平均值
nAvgValue = 0;
for(j = 0; j < nHeight / 2; j ++)
for(i = nWidth / 2; i < nWidth; i ++)
nAvgValue += p_data[j * nLineByte + i];
nAvgValue /= ((nHeight / 2) * (nLineByte / 2));
// 设置阈值为子图像的平均值
nThreshold[1][1] = nAvgValue;
// 对右下下图像逐点扫描并进行阈值分割
for(j = 0; j < nHeight / 2; j ++)
for(i = nWidth / 2; i < nWidth;i ++)
{
if(p_data[j * nLineByte + i] < nThreshold[0][0])
p_data[j * nLineByte + i] = 0;
else
p_data[j * nLineByte + i] = 255;
}
}
基于对话框的MFC图像分割Dlg.h
// 基于对话框的MFC图像分割Dlg.h : 头文件
//
#pragma once
#include "Dib.h"// 内容: 设备无关位图类-头文件
// C基于对话框的MFC图像分割Dlg 对话框
class C基于对话框的MFC图像分割Dlg : public CDialogEx
{
// 构造
public:
C基于对话框的MFC图像分割Dlg(CWnd* pParent = NULL); // 标准构造函数
// 对话框数据
enum { IDD = IDD_MFC_DIALOG };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
// 实现
protected:
HICON m_hIcon;
// 生成的消息映射函数
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
CDib m_PhotoImage;//照片图像
BOOL flag;//打开照片图像标记变量 要在默认构造函数中初始化该对象
afx_msg void On32771();
void ShowImage(UINT nID, CPoint &npoint, CSize &nsize);//在picture控件中显示图像
afx_msg void On32772();
afx_msg void On32773();
afx_msg void On32774();
afx_msg void On32775();
afx_msg void On32776();
afx_msg void On32777();
afx_msg void On32778();
afx_msg void On32779();
};
基于对话框的MFC图像分割Dlg.cpp
// 基于对话框的MFC图像分割Dlg.cpp : 实现文件
//
#include "stdafx.h"
#include "基于对话框的MFC图像分割.h"
#include "基于对话框的MFC图像分割Dlg.h"
#include "afxdialogex.h"
#include "Threshold.h"//阈值分割
#include "EdgeDetection.h"//边缘检测
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// 用于应用程序“关于”菜单项的 CAboutDlg 对话框
class CAboutDlg : public CDialogEx
{
public:
CAboutDlg();
// 对话框数据
enum { IDD = IDD_ABOUTBOX };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
// 实现
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()
// C基于对话框的MFC图像分割Dlg 对话框
C基于对话框的MFC图像分割Dlg::C基于对话框的MFC图像分割Dlg(CWnd* pParent /*=NULL*/)
: CDialogEx(C基于对话框的MFC图像分割Dlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
flag = FALSE;//打开照片图像标记变量 要在默认构造函数中初始化该对象
}
void C基于对话框的MFC图像分割Dlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(C基于对话框的MFC图像分割Dlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_COMMAND(32771, &C基于对话框的MFC图像分割Dlg::On32771)
ON_COMMAND(32772, &C基于对话框的MFC图像分割Dlg::On32772)
ON_COMMAND(32773, &C基于对话框的MFC图像分割Dlg::On32773)
ON_COMMAND(32774, &C基于对话框的MFC图像分割Dlg::On32774)
ON_COMMAND(32775, &C基于对话框的MFC图像分割Dlg::On32775)
ON_COMMAND(32776, &C基于对话框的MFC图像分割Dlg::On32776)
ON_COMMAND(32777, &C基于对话框的MFC图像分割Dlg::On32777)
ON_COMMAND(32778, &C基于对话框的MFC图像分割Dlg::On32778)
ON_COMMAND(32779, &C基于对话框的MFC图像分割Dlg::On32779)
END_MESSAGE_MAP()
// C基于对话框的MFC图像分割Dlg 消息处理程序
BOOL C基于对话框的MFC图像分割Dlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// 将“关于...”菜单项添加到系统菜单中。
// IDM_ABOUTBOX 必须在系统命令范围内。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// 设置此对话框的图标。 当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
// TODO: 在此添加额外的初始化代码
GetDlgItem(IDC_PICTURE_1)->MoveWindow(0, 0, 300, 300);
GetDlgItem(IDC_PICTURE_2)->MoveWindow(320, 0, 300, 300);
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
void C基于对话框的MFC图像分割Dlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialogEx::OnSysCommand(nID, lParam);
}
}
// 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。 对于使用文档/视图模型的 MFC 应用程序,
// 这将由框架自动完成。
void C基于对话框的MFC图像分割Dlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// 使图标在工作区矩形中居中
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
}
//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR C基于对话框的MFC图像分割Dlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void C基于对话框的MFC图像分割Dlg::ShowImage(UINT nID, CPoint &npoint, CSize &nsize)
{
npoint.x = 0;
npoint.y = 0;
CRect rect;
GetDlgItem(nID)->GetClientRect(&rect);//获取控件大小
nsize.cx = rect.Width(); // 获取PICture控件宽度
nsize.cy = rect.Height(); // 获取PICture控件高度
}
//打开图像
void C基于对话框的MFC图像分割Dlg::On32771()
{
// TODO: 在此添加命令处理程序代码
// 本函数功能是打开并显示照片图像
CString filename;
CFileDialog dlg(TRUE, _T("BMP"), _T("*.BMP"), OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, _T("位图文件(*.BMP)|*.BMP|"));
if (IDOK == dlg.DoModal())
filename.Format("%s", dlg.GetPathName());
m_PhotoImage.LoadFromFile(filename);//打开照片图像
flag = TRUE;//照片图像打开后,将标记变量置为真
//显示图像
CPoint point;
CSize size;
///*point.x = 0;
//point.y = 0;*/
//LONG lWidth = m_PhotoImage.GetWidth(); //获得灰度图像的宽度
//LONG lHeight = m_PhotoImage.GetHeight(); //获得灰度图像的高度
//size.cx = lWidth;
//size.cy = lHeight;
//CDC *pDC = GetDC(); 显示在视图中
CDC* pDC = GetDlgItem(IDC_PICTURE_1)->GetDC();//显示在PICture控件内
CRect rect;
GetDlgItem(IDC_PICTURE_1)->GetClientRect(&rect);//获取控件大小
size.cx = rect.Width(); // 获取PICture控件宽度
size.cy = rect.Height(); // 获取PICture控件高度
ShowImage(IDC_PICTURE_1, point, size);
m_PhotoImage.Draw(pDC, point, size);
ReleaseDC(pDC);
}
//Roberts算子 响应事件函数
void C基于对话框的MFC图像分割Dlg::On32772()
{
// TODO: 在此添加命令处理程序代码
//如果之前没加载图像,将在这里提示
if (flag == FALSE)
{
AfxMessageBox("请先加载要处理的照片图像!");
return;
}
/*************************************/
CPoint point;
CSize size;
//point.x = 0;
//point.y = 0;
LONG lWidth = m_PhotoImage.GetWidth(); //获得灰度图像的宽度
LONG lHeight = m_PhotoImage.GetHeight(); //获得灰度图像的高度
//size.cx = lWidth;
//size.cy = lHeight;
//CDC *pDC = GetDC();
//m_PhotoImage.Draw(pDC, point, size); //绘制处理前的图像
CDC* pDC = GetDlgItem(IDC_PICTURE_1)->GetDC();//显示在PICture控件内
ShowImage(IDC_PICTURE_1, point, size);
m_PhotoImage.Draw(pDC, point, size);//绘制处理前的图像
ReleaseDC(pDC);
/*************************************/
if (m_PhotoImage.IsValid())
{
if (!m_PhotoImage.IsGrade())
{
AfxMessageBox("本程序只支持灰度位图!");
return;
}
else
{
CEdgeDetection edgeDetection(&m_PhotoImage);
edgeDetection.Roberts();
/*************************************/
//Invalidate();
//CPoint point1;
//point1.x = lWidth + 20; //+20是为了让两个图像显示时有个间隙
//point1.y = 0;
//m_PhotoImage.Draw(pDC, point1, size);//绘制处理后的图像
pDC = GetDlgItem(IDC_PICTURE_2)->GetDC();//显示在PICture控件内
ShowImage(IDC_PICTURE_2, point, size);
m_PhotoImage.Draw(pDC, point, size);//绘制处理后的图像
ReleaseDC(pDC);
/*************************************/
}
}
}
//Sobel算子 响应事件函数
void C基于对话框的MFC图像分割Dlg::On32773()
{
// TODO: 在此添加命令处理程序代码
//如果之前没加载图像,将在这里提示
if (flag == FALSE)
{
AfxMessageBox("请先加载要处理的照片图像!");
return;
}
/*************************************/
CPoint point;
CSize size;
//point.x = 0;
//point.y = 0;
LONG lWidth = m_PhotoImage.GetWidth(); //获得灰度图像的宽度
LONG lHeight = m_PhotoImage.GetHeight(); //获得灰度图像的高度
//size.cx = lWidth;
//size.cy = lHeight;
//CDC *pDC = GetDC();
//m_PhotoImage.Draw(pDC, point, size); //绘制处理前的图像
CDC* pDC = GetDlgItem(IDC_PICTURE_1)->GetDC();//显示在PICture控件内
ShowImage(IDC_PICTURE_1, point, size);
m_PhotoImage.Draw(pDC, point, size);//绘制处理前的图像
ReleaseDC(pDC);
/*************************************/
//CSegmentDoc *pDoc = GetDocument();
//CDib *pDib = pDoc->GetDib();
if (m_PhotoImage.IsValid())
{
if (!m_PhotoImage.IsGrade())
{
AfxMessageBox("本程序只支持灰度位图!");
return;
}
else
{
CEdgeDetection edgeDetection(&m_PhotoImage);
edgeDetection.Sobel();
//Invalidate();
//CPoint point1;
//point1.x = lWidth + 20; //+20是为了让两个图像显示时有个间隙
//point1.y = 0;
//m_PhotoImage.Draw(pDC, point1, size);//绘制处理后的图像
pDC = GetDlgItem(IDC_PICTURE_2)->GetDC();//显示在PICture控件内
ShowImage(IDC_PICTURE_2, point, size);
m_PhotoImage.Draw(pDC, point, size);//绘制处理后的图像
ReleaseDC(pDC);
/*************************************/
}
}
}
//Prewitt算子 响应事件函数
void C基于对话框的MFC图像分割Dlg::On32774()
{
// TODO: 在此添加命令处理程序代码
//如果之前没加载图像,将在这里提示
if (flag == FALSE)
{
AfxMessageBox("请先加载要处理的照片图像!");
return;
}
/*************************************/
CPoint point;
CSize size;
//point.x = 0;
//point.y = 0;
LONG lWidth = m_PhotoImage.GetWidth(); //获得灰度图像的宽度
LONG lHeight = m_PhotoImage.GetHeight(); //获得灰度图像的高度
//size.cx = lWidth;
//size.cy = lHeight;
//CDC *pDC = GetDC();
//m_PhotoImage.Draw(pDC, point, size); //绘制处理前的图像
CDC* pDC = GetDlgItem(IDC_PICTURE_1)->GetDC();//显示在PICture控件内
ShowImage(IDC_PICTURE_1, point, size);
m_PhotoImage.Draw(pDC, point, size);//绘制处理前的图像
ReleaseDC(pDC);
/*************************************/
//CSegmentDoc *pDoc = GetDocument();
//CDib *pDib = pDoc->GetDib();
if (m_PhotoImage.IsValid())
{
if (!m_PhotoImage.IsGrade())
{
AfxMessageBox("本程序只支持灰度位图!");
return;
}
else
{
CEdgeDetection edgeDetection(&m_PhotoImage);
edgeDetection.Prewitt();
Invalidate();
//CPoint point1;
//point1.x = lWidth + 20; //+20是为了让两个图像显示时有个间隙
//point1.y = 0;
//m_PhotoImage.Draw(pDC, point1, size);//绘制处理后的图像
pDC = GetDlgItem(IDC_PICTURE_2)->GetDC();//显示在PICture控件内
ShowImage(IDC_PICTURE_2, point, size);
m_PhotoImage.Draw(pDC, point, size);//绘制处理后的图像
ReleaseDC(pDC);
/*************************************/
}
}
}
//Krisch算子 响应事件函数
void C基于对话框的MFC图像分割Dlg::On32775()
{
// TODO: 在此添加命令处理程序代码
//如果之前没加载图像,将在这里提示
if (flag == FALSE)
{
AfxMessageBox("请先加载要处理的照片图像!");
return;
}
/*************************************/
CPoint point;
CSize size;
//point.x = 0;
//point.y = 0;
LONG lWidth = m_PhotoImage.GetWidth(); //获得灰度图像的宽度
LONG lHeight = m_PhotoImage.GetHeight(); //获得灰度图像的高度
//size.cx = lWidth;
//size.cy = lHeight;
//CDC *pDC = GetDC();
//m_PhotoImage.Draw(pDC, point, size); //绘制处理前的图像
CDC* pDC = GetDlgItem(IDC_PICTURE_1)->GetDC();//显示在PICture控件内
ShowImage(IDC_PICTURE_1, point, size);
m_PhotoImage.Draw(pDC, point, size);//绘制处理前的图像
ReleaseDC(pDC);
/*************************************/
//CSegmentDoc *pDoc = GetDocument();
//CDib *pDib = pDoc->GetDib();
if (m_PhotoImage.IsValid())
{
if (!m_PhotoImage.IsGrade())
{
AfxMessageBox("本程序只支持灰度位图!");
return;
}
else
{
CEdgeDetection edgeDetection(&m_PhotoImage);
edgeDetection.Krisch();
Invalidate();
//CPoint point1;
//point1.x = lWidth + 20; //+20是为了让两个图像显示时有个间隙
//point1.y = 0;
//m_PhotoImage.Draw(pDC, point1, size);//绘制处理后的图像
pDC = GetDlgItem(IDC_PICTURE_2)->GetDC();//显示在PICture控件内
ShowImage(IDC_PICTURE_2, point, size);
m_PhotoImage.Draw(pDC, point, size);//绘制处理后的图像
ReleaseDC(pDC);
/*************************************/
}
}
}
//Laplacian算子 响应事件函数
void C基于对话框的MFC图像分割Dlg::On32776()
{
// TODO: 在此添加命令处理程序代码
//如果之前没加载图像,将在这里提示
if (flag == FALSE)
{
AfxMessageBox("请先加载要处理的照片图像!");
return;
}
/*************************************/
CPoint point;
CSize size;
//point.x = 0;
//point.y = 0;
LONG lWidth = m_PhotoImage.GetWidth(); //获得灰度图像的宽度
LONG lHeight = m_PhotoImage.GetHeight(); //获得灰度图像的高度
//size.cx = lWidth;
//size.cy = lHeight;
//CDC *pDC = GetDC();
//m_PhotoImage.Draw(pDC, point, size); //绘制处理前的图像
CDC* pDC = GetDlgItem(IDC_PICTURE_1)->GetDC();//显示在PICture控件内
ShowImage(IDC_PICTURE_1, point, size);
m_PhotoImage.Draw(pDC, point, size);//绘制处理前的图像
ReleaseDC(pDC);
/*************************************/
//CSegmentDoc *pDoc = GetDocument();
//CDib *pDib = pDoc->GetDib();
if (m_PhotoImage.IsValid())
{
if (!m_PhotoImage.IsGrade())
{
AfxMessageBox("本程序只支持灰度位图!");
return;
}
else
{
CEdgeDetection edgeDetection(&m_PhotoImage);
edgeDetection.Laplacian();
Invalidate();
//CPoint point1;
//point1.x = lWidth + 20; //+20是为了让两个图像显示时有个间隙
//point1.y = 0;
//m_PhotoImage.Draw(pDC, point1, size);//绘制处理后的图像
pDC = GetDlgItem(IDC_PICTURE_2)->GetDC();//显示在PICture控件内
ShowImage(IDC_PICTURE_2, point, size);
m_PhotoImage.Draw(pDC, point, size);//绘制处理后的图像
ReleaseDC(pDC);
/*************************************/
}
}
}
//Guass - Laplacian算子 响应事件函数
void C基于对话框的MFC图像分割Dlg::On32777()
{
// TODO: 在此添加命令处理程序代码
//如果之前没加载图像,将在这里提示
if (flag == FALSE)
{
AfxMessageBox("请先加载要处理的照片图像!");
return;
}
/*************************************/
CPoint point;
CSize size;
//point.x = 0;
//point.y = 0;
LONG lWidth = m_PhotoImage.GetWidth(); //获得灰度图像的宽度
LONG lHeight = m_PhotoImage.GetHeight(); //获得灰度图像的高度
//size.cx = lWidth;
//size.cy = lHeight;
//CDC *pDC = GetDC();
//m_PhotoImage.Draw(pDC, point, size); //绘制处理前的图像
CDC* pDC = GetDlgItem(IDC_PICTURE_1)->GetDC();//显示在PICture控件内
ShowImage(IDC_PICTURE_1, point, size);
m_PhotoImage.Draw(pDC, point, size);//绘制处理前的图像
ReleaseDC(pDC);
/*************************************/
//CSegmentDoc *pDoc = GetDocument();
//CDib *pDib = pDoc->GetDib();
if (m_PhotoImage.IsValid())
{
if (!m_PhotoImage.IsGrade())
{
AfxMessageBox("本程序只支持灰度位图!");
return;
}
else
{
CEdgeDetection edgeDetection(&m_PhotoImage);
edgeDetection.GuassLaplacian();
Invalidate();
//CPoint point1;
//point1.x = lWidth + 20; //+20是为了让两个图像显示时有个间隙
//point1.y = 0;
//m_PhotoImage.Draw(pDC, point1, size);//绘制处理后的图像
pDC = GetDlgItem(IDC_PICTURE_2)->GetDC();//显示在PICture控件内
ShowImage(IDC_PICTURE_2, point, size);
m_PhotoImage.Draw(pDC, point, size);//绘制处理后的图像
ReleaseDC(pDC);
/*************************************/
}
}
}
//最大方差阈值分割 响应事件函数
//此函数调用多次后,图像不会显示 这个是什么原因?!!
void C基于对话框的MFC图像分割Dlg::On32778()
{
// TODO: 在此添加命令处理程序代码
//如果之前没加载图像,将在这里提示
if (flag == FALSE)
{
AfxMessageBox("请先加载要处理的照片图像!");
return;
}
/*************************************/
CPoint point;
CSize size;
//point.x = 0;
//point.y = 0;
LONG lWidth = m_PhotoImage.GetWidth(); //获得灰度图像的宽度
LONG lHeight = m_PhotoImage.GetHeight(); //获得灰度图像的高度
//size.cx = lWidth;
//size.cy = lHeight;
//CDC *pDC = GetDC();
//m_PhotoImage.Draw(pDC, point, size); //绘制处理前的图像
CDC* pDC = GetDlgItem(IDC_PICTURE_1)->GetDC();//显示在PICture控件内
ShowImage(IDC_PICTURE_1, point, size);
m_PhotoImage.Draw(pDC, point, size);//绘制处理前的图像
ReleaseDC(pDC);
/*************************************/
//CSegmentDoc *pDoc = GetDocument();
//CDib *pDib = pDoc->GetDib();
if (m_PhotoImage.IsValid())
{
if (!m_PhotoImage.IsGrade())
{
AfxMessageBox("本程序只支持灰度位图!");
return;
}
else
{
CThreshold threshold(&m_PhotoImage);
threshold.OtusThreshold();
Invalidate();
//CPoint point1;
//point1.x = lWidth + 20; //+20是为了让两个图像显示时有个间隙
//point1.y = 0;
//m_PhotoImage.Draw(pDC, point1, size);//绘制处理后的图像
pDC = GetDlgItem(IDC_PICTURE_2)->GetDC();//显示在PICture控件内
ShowImage(IDC_PICTURE_2, point, size);
m_PhotoImage.Draw(pDC, point, size);//绘制处理后的图像
ReleaseDC(pDC);
/*************************************/
}
}
}
//自适应阈值分割 响应事件函数
void C基于对话框的MFC图像分割Dlg::On32779()
{
// TODO: 在此添加命令处理程序代码
//如果之前没加载图像,将在这里提示
if (flag == FALSE)
{
AfxMessageBox("请先加载要处理的照片图像!");
return;
}
/*************************************/
CPoint point;
CSize size;
//point.x = 0;
//point.y = 0;
LONG lWidth = m_PhotoImage.GetWidth(); //获得灰度图像的宽度
LONG lHeight = m_PhotoImage.GetHeight(); //获得灰度图像的高度
//size.cx = lWidth;
//size.cy = lHeight;
//CDC *pDC = GetDC();
//m_PhotoImage.Draw(pDC, point, size); //绘制处理前的图像
CDC* pDC = GetDlgItem(IDC_PICTURE_1)->GetDC();//显示在PICture控件内
ShowImage(IDC_PICTURE_1, point, size);
m_PhotoImage.Draw(pDC, point, size);//绘制处理前的图像
ReleaseDC(pDC);
/*************************************/
//CSegmentDoc *pDoc = GetDocument();
//CDib *pDib = pDoc->GetDib();
if (m_PhotoImage.IsValid())
{
if (!m_PhotoImage.IsGrade())
{
AfxMessageBox("本程序只支持灰度位图!");
return;
}
else
{
CThreshold threshold(&m_PhotoImage);
threshold.AdaptiveThreshold();
Invalidate();
//CPoint point1;
//point1.x = lWidth + 20; //+20是为了让两个图像显示时有个间隙
//point1.y = 0;
//m_PhotoImage.Draw(pDC, point1, size);//绘制处理后的图像
pDC = GetDlgItem(IDC_PICTURE_2)->GetDC();//显示在PICture控件内
ShowImage(IDC_PICTURE_2, point, size);
m_PhotoImage.Draw(pDC, point, size);//绘制处理后的图像
ReleaseDC(pDC);
/*************************************/
}
}
}