基于单文档的MFC图像分割

目录

Dib.h

Dib.cpp

EdgeDetection.h

EdgeDetection.cpp

Threshold.h

Threshold.cpp

基于单文档的图像分割View.h

基于单文档的图像分割View.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;
}

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;
        }
}

基于单文档的图像分割View.h


// 基于单文档的图像分割View.h : C基于单文档的图像分割View 类的接口
//

#pragma once
#include "Dib.h"  内容: 设备无关位图类-头文件


class C基于单文档的图像分割View : public CView
{
protected: // 仅从序列化创建
	C基于单文档的图像分割View();
	DECLARE_DYNCREATE(C基于单文档的图像分割View)

// 特性
public:
	C基于单文档的图像分割Doc* GetDocument() const;

// 操作
public:

// 重写
public:
	virtual void OnDraw(CDC* pDC);  // 重写以绘制该视图
	virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
	virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
	virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
	virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);

// 实现
public:
	virtual ~C基于单文档的图像分割View();
#ifdef _DEBUG
	virtual void AssertValid() const;
	virtual void Dump(CDumpContext& dc) const;
#endif

protected:

// 生成的消息映射函数
protected:
	DECLARE_MESSAGE_MAP()
public:
	CDib m_PhotoImage;//照片图像
	BOOL flag;//打开照片图像标记变量  要在默认

	afx_msg void OnOpenImage();
	afx_msg void OnRoberts();
	afx_msg void OnSobel();
	afx_msg void OnPrewitt();
	afx_msg void OnKrisch();
	afx_msg void OnLaplacian();
	afx_msg void OnGuassLaplacian();
	afx_msg void OnOtusthreshold();
	afx_msg void OnAdapthresh();
};

#ifndef _DEBUG  // 基于单文档的图像分割View.cpp 中的调试版本
inline C基于单文档的图像分割Doc* C基于单文档的图像分割View::GetDocument() const
   { return reinterpret_cast<C基于单文档的图像分割Doc*>(m_pDocument); }
#endif

基于单文档的图像分割View.cpp


// 基于单文档的图像分割View.cpp : C基于单文档的图像分割View 类的实现
//

#include "stdafx.h"
// SHARED_HANDLERS 可以在实现预览、缩略图和搜索筛选器句柄的
// ATL 项目中进行定义,并允许与该项目共享文档代码。
#ifndef SHARED_HANDLERS
#include "基于单文档的图像分割.h"
#endif

#include "基于单文档的图像分割Doc.h"
#include "基于单文档的图像分割View.h"
#include "EdgeDetection.h"边缘检测类
#include "Threshold.h"//阈值分割法类

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// C基于单文档的图像分割View

IMPLEMENT_DYNCREATE(C基于单文档的图像分割View, CView)

BEGIN_MESSAGE_MAP(C基于单文档的图像分割View, CView)
	// 标准打印命令
	ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CView::OnFilePrintPreview)
	ON_COMMAND(ID_OPEN_IMAGE, &C基于单文档的图像分割View::OnOpenImage)
	ON_COMMAND(ID_ROBERTS, &C基于单文档的图像分割View::OnRoberts)
	ON_COMMAND(ID_SOBEL, &C基于单文档的图像分割View::OnSobel)
	ON_COMMAND(ID_PREWITT, &C基于单文档的图像分割View::OnPrewitt)
	ON_COMMAND(ID_KRISCH, &C基于单文档的图像分割View::OnKrisch)
	ON_COMMAND(ID_LAPLACIAN, &C基于单文档的图像分割View::OnLaplacian)
	ON_COMMAND(ID_GUASS_LAPLACIAN, &C基于单文档的图像分割View::OnGuassLaplacian)
	ON_COMMAND(ID_OTUSTHRESHOLD, &C基于单文档的图像分割View::OnOtusthreshold)
	ON_COMMAND(ID_ADAPTHRESH, &C基于单文档的图像分割View::OnAdapthresh)
END_MESSAGE_MAP()

// C基于单文档的图像分割View 构造/析构

C基于单文档的图像分割View::C基于单文档的图像分割View()
{
	// TODO:  在此处添加构造代码
	flag = FALSE;//初始化标志位

}

C基于单文档的图像分割View::~C基于单文档的图像分割View()
{
}

BOOL C基于单文档的图像分割View::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO:  在此处通过修改
	//  CREATESTRUCT cs 来修改窗口类或样式

	return CView::PreCreateWindow(cs);
}

// C基于单文档的图像分割View 绘制

void C基于单文档的图像分割View::OnDraw(CDC* /*pDC*/)
{
	C基于单文档的图像分割Doc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	// TODO:  在此处为本机数据添加绘制代码
}


// C基于单文档的图像分割View 打印

BOOL C基于单文档的图像分割View::OnPreparePrinting(CPrintInfo* pInfo)
{
	// 默认准备
	return DoPreparePrinting(pInfo);
}

void C基于单文档的图像分割View::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO:  添加额外的打印前进行的初始化过程
}

void C基于单文档的图像分割View::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO:  添加打印后进行的清理过程
}


// C基于单文档的图像分割View 诊断

#ifdef _DEBUG
void C基于单文档的图像分割View::AssertValid() const
{
	CView::AssertValid();
}

void C基于单文档的图像分割View::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

C基于单文档的图像分割Doc* C基于单文档的图像分割View::GetDocument() const // 非调试版本是内联的
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(C基于单文档的图像分割Doc)));
	return (C基于单文档的图像分割Doc*)m_pDocument;
}
#endif //_DEBUG


// C基于单文档的图像分割View 消息处理程序


void C基于单文档的图像分割View::OnOpenImage()
{
	// 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();
	m_PhotoImage.Draw(pDC, point, size);

}

//Roberts算子 响应事件函数
void C基于单文档的图像分割View::OnRoberts()
{
	// 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);//绘制处理前的图像


	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);//绘制处理后的图像
		}
	}
}

//Sobel算子 响应事件函数
void C基于单文档的图像分割View::OnSobel()
{
	// 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);//绘制处理前的图像

	//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);//绘制处理后的图像
		}
	}
}


//Prewitt算子 响应事件函数
void C基于单文档的图像分割View::OnPrewitt()
{
	// 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);//绘制处理前的图像


	//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);//绘制处理后的图像
		}
	}
}

//Krisch算子 响应事件函数
void C基于单文档的图像分割View::OnKrisch()
{
	//Krisch算子 响应事件函数
	// 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);//绘制处理前的图像


	//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);//绘制处理后的图像
		}
	}
}


//Laplacian算子 响应事件函数
void C基于单文档的图像分割View::OnLaplacian()
{
	// TODO:  在此添加命令处理程序代码
	//Laplacian算子 响应事件函数
	//如果之前没加载图像,将在这里提示
	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);//绘制处理前的图像

	//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);//绘制处理后的图像
		}
	}
}


//Guass - Laplacian算子 响应事件函数
void C基于单文档的图像分割View::OnGuassLaplacian()
{
	// TODO:  在此添加命令处理程序代码
	//Guass - Laplacian算子 响应事件函数
	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);//绘制处理前的图像

	//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);//绘制处理后的图像
		}
	}
}


//最大方差阈值分割 响应事件函数
//此函数调用多次后,图像不会显示 这个是什么原因?!!
void C基于单文档的图像分割View::OnOtusthreshold()
{
	// 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);//绘制处理前的图像


	//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);//绘制处理后的图像
		}
	}
}


//自适应阈值分割 响应事件函数
void C基于单文档的图像分割View::OnAdapthresh()
{
	// 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);//绘制处理前的图像


	//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);//绘制处理后的图像
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值