#include "stdafx.h"
#include "Segment.h"
#include "math.h"
/***********************************************************************
* 函数名称:
* ImgSegment()
*
*说明:无参数的构造函数,对成员变量进行初始化
***********************************************************************/
ImgSegment::ImgSegment()
{
m_pImgDataOut=NULL;//输出图像位图数据指针为空
m_lpColorTableOut=NULL;//输出图像颜色表指针为空
m_nColorTableLengthOut=0;//输出图像颜色表长度为0
m_nBitCountOut=0;//输出图像每像素位数为0
m_imgWidthOut=0;//输出图像的宽为0
m_imgHeightOut=0;//输出图像的高为0
}
/***********************************************************************
* 函数名称:
* ImgSegment()
*
*函数参数:
* CSize size -图像大小(宽、高)
* int nBitCount -每像素所占位数
* LPRGBQUAD lpColorTable -颜色表指针
* unsigned char *pImgData -位图数据指针
*
*返回值:
* 无
*
*说明:本函数为带参数的构造函数,给定位图的大小、每像素位数、颜色表
* 及位图数据,调用ImgCenterDib()对基类成员初始化,并初始化派生类的
* 数据成员
***********************************************************************/
ImgSegment::ImgSegment(CSize size, int nBitCount, LPRGBQUAD lpColorTable, unsigned char *pImgData):
ImgCenterDib(size, nBitCount, lpColorTable, pImgData)
{
m_pImgDataOut=NULL;//输出图像位图数据指针为空
m_lpColorTableOut=NULL;//输出图像颜色表指针为空
m_nColorTableLengthOut=0;//输出图像颜色表长度为0
m_nBitCountOut=0;//输出图像每像素位数为0
m_imgWidthOut=0;//输出图像的宽为0
m_imgHeightOut=0;//输出图像的高为0
}
/***********************************************************************
* 函数名称:
* ~ImgSegment()
*
*说明:析构函数,释放资源
***********************************************************************/
ImgSegment::~ImgSegment()
{
//释放输出图像位图数据缓冲区
if(m_pImgDataOut!=NULL){
delete []m_pImgDataOut;
m_pImgDataOut=NULL;
}
//释放输出图像颜色表
if(m_lpColorTableOut!=NULL){
delete []m_lpColorTableOut;
m_lpColorTableOut=NULL;
}
}
/***********************************************************************
* 函数名称:
* GetDimensions()
*
*函数参数:
* 无
*
*返回值:
* 图像的尺寸,用CSize类型表达
*
*说明:返回输出图像的宽和高
***********************************************************************/
CSize ImgSegment::GetDimensions()
{
if(m_pImgDataOut == NULL) return CSize(0, 0);
return CSize(m_imgWidthOut, m_imgHeightOut);
}
/***********************************************************************
* 函数名称:
* threshOtus()
*
*函数参数:
* int histArray[256] -图像的统计直方图
*
* 返回值:
* 最佳阈值
*
*说明:大津阈值选择函数,给定直方图数组,根据方差最大原理自动选择阈值,
* 对于彩色图像,该函数根据亮度直方图计算阈值
***********************************************************************/
int ImgSegment::threshOtus(int histArray[256])
{
//c0和c1组的均值
float u0,u1;
//c0和c1组产生的概率
float w0,w1;
//c0组的像素数
int count0;
//阈值t及记录方差最大时的最佳阈值maxT
int t, maxT;
//方差及最大方差
float devi, maxDevi=0;
//循环变量
int i;
//统计直方图中像素的个数,存放在sum中
int sum=0;
for(i=0;i<256;i++)
sum = sum+histArray[i];
for(t=0;t<255;t++){
//计算阈值为t时,c0组的均值和产生的概率
u0=0;
count0=0;
for(i=0; i<=t;i++){
u0 += i*histArray[i];
count0 += histArray[i];
}
u0=u0/count0;
w0=(float)count0/sum;
//计算阈值为t时,c1组的均值和产生的概率
u1=0;
for(i=t+1; i<256;i++)
u1+=i*histArray[i];
//C0组像素数与C1组像素数之和为图像总像素数。
u1=u1/(sum-count0);
w1=1-w0;
//两组间的方差
devi=w0*w1*(u1-u0)*(u1-u0);
//记录最大的方差及最佳阈值位置
if(devi>maxDevi){
maxDevi=devi;
maxT=t;
}
}
//返回最佳阈值
return maxT;
}
/***********************************************************************
* 函数名称:
* Roberts()
*
*函数参数:
* 无
*
*返回值:
* 无
*
*说明:Roberts边缘检测,函数将图像看作若干通道数据的合成,在不同通道上
* 完成了边缘检测,因此可同时适用于灰度和彩色图像
***********************************************************************/
void ImgSegment::Roberts()
{
//释放m_pImgDataOut指向的图像数据空间
if(m_pImgDataOut!=NULL){
delete []m_pImgDataOut;
m_pImgDataOut=NULL;
}
//释放颜色表空间
if(m_lpColorTableOut!=NULL){
delete []m_lpColorTableOut;
m_lpColorTableOut=NULL;
}
//输出图像与输入图像为同一类型
m_nBitCountOut=m_nBitCount;
//输出图像颜色表长度
m_nColorTableLengthOut=ComputeColorTabalLength(m_nBitCountOut);
//输出图像颜色表,与输入图像相同
if(m_nColorTableLengthOut!=0){
m_lpColorTableOut=new RGBQUAD[m_nColorTableLengthOut];
memcpy(m_lpColorTableOut,m_lpColorTable,sizeof(RGBQUAD)*m_nColorTableLengthOut);
}
//输出图像的宽高,与输入图像相等
m_imgWidthOut=m_imgWidth;
m_imgHeightOut=m_imgHeight;
//每行像素所占字节数,输出图像与输入图像相同
int lineByte=(m_imgWidth*m_nBitCount/8+3)/4*4;
//申请输出图像缓冲区
m_pImgDataOut=new unsigned char[lineByte*m_imgHeight];
//循环变量,图像的坐标
int i,j;
//每像素占字节数,输出图像与输入图像相同
int pixelByte=m_nBitCount/8;
//循环变量,遍历像素的每个通道,比如彩色图像三个分量
int k;
//中间变量
int x, y, t;
//Roberts算子
for(i=1;i<m_imgHeight-1;i++){
for(j=1;j<m_imgWidth-1;j++){
for(k=0;k<pixelByte;k++){
//x方向梯度
x=*(m_pImgData+i*lineByte+j*pixelByte+k)
-*(m_pImgData+(i+1)*lineByte+(j+1)*pixelByte+k);
//y方向梯度
y=*(m_pImgData+(i+1)*lineByte+j*pixelByte+k)
-*(m_pImgData+i*lineByte+(j+1)*pixelByte+k);
t=sqrt(x*x+y*y)+0.5;
if(t>255)
t=255;
*(m_pImgDataOut+i*lineByte+j*pixelByte+k)=t;
}
}
}
}
/***********************************************************************
* 函数名称:
* Sobel()
*
*函数参数:
* 无
*
*返回值:
* 无
*
*说明:Sobel边缘检测,函数将图像看作若干通道数据的合成,在不同通道上
* 完成了边缘检测,因此可同时适用于灰度和彩色图像
***********************************************************************/
void ImgSegment::Sobel()
{
//释放m_pImgDataOut指向的图像数据空间
if(m_pImgDataOut!=NULL){
delete []m_pImgDataOut;
m_pImgDataOut=NULL;
}
//释放颜色表空间
if(m_lpColorTableOut!=NULL){
delete []m_lpColorTableOut;
m_lpColorTableOut=NULL;
}
//输出图像与输入图像为同一类型
m_nBitCountOut=m_nBitCount;
//输出图像颜色表长度
m_nColorTableLengthOut=ComputeColorTabalLength(m_nBitCountOut);
//输出图像颜色表,与输入图像相同
if(m_nColorTableLengthOut!=0){
m_lpColorTableOut=new RGBQUAD[m_nColorTableLengthOut];
memcpy(m_lpColorTableOut,m_lpColorTable,sizeof(RGBQUAD)*m_nColorTableLengthOut);
}
//输出图像的宽高,与输入图像相等
m_imgWidthOut=m_imgWidth;
m_imgHeightOut=m_imgHeight;
//每行像素所占字节数,输出图像与输入图像相同
int lineByte=(m_imgWidth*m_nBitCount/8+3)/4*4;
//申请输出图像缓冲区
m_pImgDataOut=new unsigned char[lineByte*m_imgHeight];
//循环变量,图像的坐标
int i,j;
//每像素占字节数,输出图像与输入图像相同
int pixelByte=m_nBitCount/8;
//循环变量,遍历像素的每个通道,比如彩色图像三个分量
int k;
//中间变量
int x, y, t;
//Sobel算子
for(i=1;i<m_imgHeight-1;i++){
for(j=1;j<m_imgWidth-1;j++){
for(k=0;k<pixelByte;k++){
//x方向梯度
x= *(m_pImgData+(i-1)*lineByte+(j+1)*pixelByte+k)
+ 2 * *(m_pImgData+i*lineByte+(j+1)*pixelByte+k)
+ *(m_pImgData+(i+1)*lineByte+(j+1)*pixelByte+k)
- *(m_pImgData+(i-1)*lineByte+(j-1)*pixelByte+k)
- 2 * *(m_pImgData+i*lineByte+(j-1)*pixelByte+k)
- *(m_pImgData+(i+1)*lineByte+(j-1)*pixelByte+k);
//y方向梯度
y= *(m_pImgData+(i-1)*lineByte+(j-1)*pixelByte+k)
+ 2 * *(m_pImgData+(i-1)*lineByte+j*pixelByte+k)
+ *(m_pImgData+(i-1)*lineByte+(j+1)*pixelByte+k)
- *(m_pImgData+(i+1)*lineByte+(j-1)*pixelByte+k)
- 2 * *(m_pImgData+(i+