📄 segapi.cpp
字号:
#include "GlobalApi.h"
#include "stdafx.h"
#include "cdib.h"
#include "math.h"
#include <direct.h>
#include <complex>
using namespace std;
/*************************************************************************
*
* \函数名称:
* RegionSegFixThreshold()
*
* \输入参数:
* CDib * pDib - 指向CDib类的指针,含有原始图象信息
* int nThreshold - 区域分割的阈值
*
* \返回值:
* 无
*
* \说明:
* 1(逻辑)表示对应象素为前景区域,0表示背景
* 阈值分割的关键问题在于阈值的选取。阈值的选取一般应该视实际的应用而
* 灵活设定。
*
*************************************************************************
*/
void RegionSegFixThreshold(CDib * pDib, int nThreshold)
{
//遍历图象的纵坐标
int y;
//遍历图象的横坐标
int x;
//图象的长宽大小
CSize sizeImage = pDib->GetDimensions();
int nWidth = sizeImage.cx ;
int nHeight = sizeImage.cy ;
//图像在计算机在存储中的实际大小
CSize sizeImageSave = pDib->GetDibSaveDim();
//图像在内存中每一行象素占用的实际空间
int nSaveWidth = sizeImageSave.cx;
//图像数据的指针
LPBYTE pImageData = pDib->m_lpImage;
for(y=0; y<nHeight ; y++ )
for(x=0; x<nWidth ; x++ )
{
if( *(pImageData+y*nSaveWidth+x) < nThreshold)
*(pImageData+y*nSaveWidth+x) = 0;
}
}
/*************************************************************************
*
* \函数名称:
* RegionSegAdaptive()
*
* \输入参数:
* CDib * pDib - 指向CDib类的指针,含有原始图象信息
*
* \返回值:
* 无
*
* \说明:
* 1(逻辑)表示对应象素为前景区域,0表示背景
* 阈值分割的关键问题在于阈值的选取。阈值的选取一般应该视实际的应用而
* 灵活设定。本函数中,阈值不是固定的,而是根据图象象素的实际性质而设定的。
* 这个函数把图像分成四个子图象,然后计算每个子图象的均值,根据均值设置阈值
* 阈值只是应用在对应的子图象
*
*************************************************************************
*/
void RegionSegAdaptive(CDib * pDib)
{
//遍历图象的纵坐标
int y;
//遍历图象的横坐标
int x;
//图象的长宽大小
CSize sizeImage = pDib->GetDimensions();
int nWidth = sizeImage.cx ;
int nHeight = sizeImage.cy ;
//图像在计算机在存储中的实际大小
CSize sizeImageSave = pDib->GetDibSaveDim();
//图像在内存中每一行象素占用的实际空间
int nSaveWidth = sizeImageSave.cx;
//图像数据的指针
LPBYTE lpImage = pDib->m_lpImage;
// 局部阈值
int nThd[2][2] ;
// 子图象的平均值
int nLocAvg ;
// 对左上图像逐点扫描:
nLocAvg = 0 ;
// y方向
for(y=0; y<nHeight/2 ; y++ )
{
// x方向
for(x=0; x<nWidth/2 ; x++ )
{
nLocAvg += lpImage[y*nSaveWidth + x];
}
}
// 计算均值
nLocAvg /= ( (nHeight/2) * (nWidth/2) ) ;
// 设置阈值为子图象的平均值
nThd[0][0] = nLocAvg ;
// 对左上图像逐点扫描进行分割:
// y方向
for(y=0; y<nHeight/2 ; y++ )
{
// x方向
for(x=0; x<nWidth/2 ; x++ )
{
if(lpImage[y*nSaveWidth + x]<nThd[0][0])
lpImage[y*nSaveWidth + x] = 255 ;
else
{
lpImage[y*nSaveWidth + x] = 0 ;
}
}
}
// =============================================
// 对左下图像逐点扫描:
nLocAvg = 0 ;
// y方向
for(y=nHeight/2; y<nHeight ; y++ )
{
// x方向
for(x=0; x<nWidth/2 ; x++ )
{
nLocAvg += lpImage[y*nSaveWidth + x];
}
}
// 计算均值
nLocAvg /= ( (nHeight - nHeight/2) * (nWidth/2) ) ;
// 设置阈值为子图象的平均值
nThd[1][0] = nLocAvg ;
// 对左下图像逐点扫描进行分割:
// y方向
for(y=nHeight/2; y<nHeight ; y++ )
{
// x方向
for(x=0; x<nWidth/2 ; x++ )
{
if(lpImage[y*nSaveWidth + x]<nThd[1][0])
lpImage[y*nSaveWidth + x] = 255 ;
else
{
lpImage[y*nSaveWidth + x] = 0 ;
}
}
}
// =============================================
// 对右上图像逐点扫描:
nLocAvg = 0 ;
// y方向
for(y=0; y<nHeight/2 ; y++ )
{
// x方向
for(x=nWidth/2; x<nWidth ; x++ )
{
nLocAvg += lpImage[y*nSaveWidth + x];
}
}
// 计算均值
nLocAvg /= ( (nHeight/2) * (nWidth - nWidth/2) ) ;
// 设置阈值为子图象的平均值
nThd[0][1] = nLocAvg ;
// 对右上图像逐点扫描进行分割:
// y方向
for(y=0; y<nHeight/2 ; y++ )
{
// x方向
for(x=nWidth/2; x<nWidth ; x++ )
{
if(lpImage[y*nSaveWidth + x]<nThd[0][1])
lpImage[y*nSaveWidth + x] = 255 ;
else
{
lpImage[y*nSaveWidth + x] = 0 ;
}
}
}
// =============================================
// 对右下图像逐点扫描:
nLocAvg = 0 ;
// y方向
for(y=nHeight/2; y<nHeight ; y++ )
{
// x方向
for(x=nWidth/2; x<nWidth ; x++ )
{
nLocAvg += lpImage[y*nSaveWidth + x];
}
}
// 计算均值
nLocAvg /= ( (nHeight - nHeight/2) * (nWidth - nWidth/2) ) ;
// 设置阈值为子图象的平均值
nThd[1][1] = nLocAvg ;
// 对右下图像逐点扫描进行分割:
// y方向
for(y=nHeight/2; y<nHeight ; y++ )
{
// x方向
for(x=nWidth/2; x<nWidth ; x++ )
{
if(lpImage[y*nSaveWidth + x]<nThd[1][1])
lpImage[y*nSaveWidth + x] = 255 ;
else
{
lpImage[y*nSaveWidth + x] = 0 ;
}
}
}
// 为了显示方便显示,逻辑1用黑色显示,逻辑0用白色显示
for(y=0; y<nHeight ; y++ )
{
// x方向
for(x=0; x<nWidth ; x++ )
{
lpImage[y*nSaveWidth + x] = 255 - lpImage[y*nSaveWidth + x] ;
}
}
}
/*************************************************************************
*
* \函数名称:
* RobertsOperator()
*
* \输入参数:
* CDib * pDib - 指向CDib类的指针,含有原始图象信息
* double * pdGrad - 指向梯度数据的指针,含有图像的梯度信息
*
* \返回值:
* 无
*
* \说明:
* Roberts算子
*
*************************************************************************
*/
void RobertsOperator(CDib * pDib, double * pdGrad)
{
// 遍历图象的纵坐标
int y;
// 遍历图象的横坐标
int x;
// 图象的长宽大小
CSize sizeImage = pDib->GetDimensions();
int nWidth = sizeImage.cx ;
int nHeight = sizeImage.cy ;
// 图像在计算机在存储中的实际大小
CSize sizeImageSave = pDib->GetDibSaveDim();
// 图像在内存中每一行象素占用的实际空间
int nSaveWidth = sizeImageSave.cx;
// 图像数据的指针
LPBYTE pImageData = pDib->m_lpImage;
// 初始化
for(y=0; y<nHeight ; y++ )
for(x=0 ; x<nWidth ; x++ )
{
*(pdGrad+y*nWidth+x)=0;
}
// 下面开始利用Roberts算子进行计算,为了保证计算所需要的
// 的数据位于图像数据的内部,下面的两重循环的条件是
// y<nHeight-1 而不是y<nHeight,相应的x方向也是x<nWidth-1
// 而不是x<nWidth
//这两个变量用来表示Roberts算子第一个模板的两个象素值
int nUpLeft;
int nDownRight;
// 这两个变量用来表示Roberts算子第二个模板的两个象素值
int nUpRight;
int nDownLeft;
// 这两个变量用来表示Roberts算子计算的结果
int nValueOne;
int nValueTwo;
// 临时变量
double dGrad;
for(y=0; y<nHeight-1 ; y++ )
for(x=0 ; x<nWidth-1 ; x++ )
{
// Roberts算子第一个模板需要的象素值
nUpLeft =*(pImageData+y*nSaveWidth+x) ;
nDownRight =*( pImageData+(y+1)*nSaveWidth+x+1 );
nDownRight *=-1;
//Roberts算子的第一个模板计算结果
nValueOne =nUpLeft+nDownRight ;
// Roberts算子第二个模板需要的象素值
nUpRight =*( pImageData+y*nSaveWidth+x+1 ) ;
nDownLeft =*( pImageData+(y+1)*nSaveWidth+x );
nDownLeft *=-1;
// Roberts算子的第二个模板计算结果
nValueTwo =nUpRight+nDownLeft;
// 计算两个偏导数的平方和
dGrad=nValueOne*nValueOne + nValueTwo*nValueTwo;
// 开方
dGrad=pow(dGrad,0.5);
// 范数采用欧式距离
*(pdGrad+y*nWidth+x)=dGrad;
}
}
/*************************************************************************
*
* \函数名称:
* LaplacianOperator()
*
* \输入参数:
* CDib * pDib - 指向CDib类的指针,含有原始图象信息
* double * pdGrad - 指向梯度数据的指针,含有图像的梯度信息
*
* \返回值:
* 无
*
* \说明:
* LaplacianOperator算子,是二阶算子,不想Roberts算子那样需要两个模板计算
* 梯度,LaplacianOperator算子只要一个算子就可以计算梯度。但是因为利用了
* 二阶信息,对噪声比较敏感
*
*************************************************************************
*/
void LaplacianOperator(CDib * pDib, double * pdGrad)
{
// 遍历图象的纵坐标
int y;
// 遍历图象的横坐标
int x;
// 图象的长宽大小
CSize sizeImage = pDib->GetDimensions();
int nWidth = sizeImage.cx ;
int nHeight = sizeImage.cy ;
// 图像在计算机在存储中的实际大小
CSize sizeImageSave = pDib->GetDibSaveDim();
// 图像在内存中每一行象素占用的实际空间
int nSaveWidth = sizeImageSave.cx;
// 图像数据的指针
LPBYTE lpImage = pDib->m_lpImage;
// 初始化
for(y=0; y<nHeight ; y++ )
for(x=0 ; x<nWidth ; x++ )
{
*(pdGrad+y*nWidth+x)=0;
}
// 设置模板系数
static int nWeight[3][3] ;
nWeight[0][0] = -1 ;
nWeight[0][1] = -1 ;
nWeight[0][2] = -1 ;
nWeight[1][0] = -1 ;
nWeight[1][1] = 8 ;
nWeight[1][2] = -1 ;
nWeight[2][0] = -1 ;
nWeight[2][1] = -1 ;
nWeight[2][2] = -1 ;
//这个变量用来表示Laplacian算子象素值
int nTmp[3][3];
// 临时变量
double dGrad;
// 模板循环控制变量
int yy ;
int xx ;
// 下面开始利用Laplacian算子进行计算,为了保证计算所需要的
// 的数据位于图像数据的内部,下面的两重循环的条件是
// y<nHeight-2 而不是y<nHeight,相应的x方向也是x<nWidth-2
// 而不是x<nWidth
for(y=1; y<nHeight-2 ; y++ )
for(x=1 ; x<nWidth-2 ; x++ )
{
dGrad = 0 ;
// Laplacian算子需要的各点象素值
// 模板第一行
nTmp[0][0] = lpImage[(y-1)*nSaveWidth + x - 1 ] ;
nTmp[0][1] = lpImage[(y-1)*nSaveWidth + x ] ;
nTmp[0][2] = lpImage[(y-1)*nSaveWidth + x + 1 ] ;
// 模板第二行
nTmp[1][0] = lpImage[y*nSaveWidth + x - 1 ] ;
nTmp[1][1] = lpImage[y*nSaveWidth + x ] ;
nTmp[1][2] = lpImage[y*nSaveWidth + x + 1 ] ;
// 模板第三行
nTmp[2][0] = lpImage[(y+1)*nSaveWidth + x - 1 ] ;
nTmp[2][1] = lpImage[(y+1)*nSaveWidth + x ] ;
nTmp[2][2] = lpImage[(y+1)*nSaveWidth + x + 1 ] ;
// 计算梯度
for(yy=0; yy<3; yy++)
for(xx=0; xx<3; xx++)
{
dGrad += nTmp[yy][xx] * nWeight[yy][xx] ;
}
// 梯度值写入内存
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -