基于对话框的MFC图像分割

目录

Dib.h

Dib.cpp

EdgeDetection.h

EdgeDetection.cpp

Threshold.h

Threshold.cpp

基于对话框的MFC图像分割Dlg.h

基于对话框的MFC图像分割Dlg.cpp

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);
			/*************************************/
		}
	}
}

  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值