📄 morphology.cpp
字号:
*
*说明:二值闭运算,m_pImgData为输入,m_pImgDataOut为输出
***********************************************************************/
void Morphology::BinaryClose()
{
//如果没有结构元素输入,则返回
if(m_maskBuf==NULL)
return;
//灰度图像每行像素所占字节数
int lineByte=(m_imgWidth+3)/4*4;
//中间结果缓冲区申请,用来存放腐蚀后的中间结果
unsigned char *buf=new unsigned char[lineByte*m_imgHeight];
//先膨胀
BasicDilationForBinary(m_pImgData, buf,m_imgWidth,m_imgHeight,
m_maskBuf, m_maskW, m_maskH);
//后腐蚀
BasicErosionForBinary(buf, m_pImgDataOut,m_imgWidth,m_imgHeight,
m_maskBuf, m_maskW, m_maskH);
//释放缓冲区
delete []buf;
}
/***********************************************************************
* 函数名称:
* BinaryInnerEdge()
*
*函数参数:
* 无
*
*返回值:
* 无
*
*说明:求二值形态学内边界,m_pImgData为输入,m_pImgDataOut为输出
***********************************************************************/
void Morphology::BinaryInnerEdge()
{
//如果没有模板输入,则返回
if(m_maskBuf==NULL)
return;
//灰度图像每行像素所占字节数
int lineByte=(m_imgWidth+3)/4*4;
//腐蚀
BasicErosionForBinary(m_pImgData, m_pImgDataOut,m_imgWidth,m_imgHeight,
m_maskBuf, m_maskW, m_maskH);
//原始数据减腐蚀结果
int i, j;
for(i=0;i<m_imgHeight;i++){
for(j=0;j<lineByte;j++){
*(m_pImgDataOut+i*lineByte+j) =
*(m_pImgData+i*lineByte+j)- *(m_pImgDataOut+i*lineByte+j);
}
}
}
/***********************************************************************
* 函数名称:
* BinaryOuterEdge()
*
*函数参数:
* 无
*
*返回值:
* 无
*
*说明:求二值形态学外边界,m_pImgData为输入,m_pImgDataOut为输出
***********************************************************************/
void Morphology::BinaryOuterEdge()
{
//如果没有结构元素输入,则返回
if(m_maskBuf==NULL)
return;
//灰度图像每行像素所占字节数
int lineByte=(m_imgWidth+3)/4*4;
//腐蚀
BasicDilationForBinary(m_pImgData, m_pImgDataOut,m_imgWidth,m_imgHeight,
m_maskBuf, m_maskW, m_maskH);
//膨胀结果减去原始数据
int i, j;
for(i=0;i<m_imgHeight;i++){
for(j=0;j<lineByte;j++){
*(m_pImgDataOut+i*lineByte+j) -= *(m_pImgData+i*lineByte+j);
}
}
}
/***********************************************************************
* 函数名称:
* BinaryContour()
*
*函数参数:
* 无
*
*返回值:
* 无
*
*说明:求二值形态学边界,m_pImgData为输入,m_pImgDataOut为输出
***********************************************************************/
void Morphology::BinaryContour()
{
//如果没有结构元素输入,则返回
if(m_maskBuf==NULL)
return;
//灰度图像每行像素所占字节数
int lineByte=(m_imgWidth+3)/4*4;
//中间结果缓冲区申请,用来存放腐蚀后的中间结果
unsigned char *buf=new unsigned char[lineByte*m_imgHeight];
//腐蚀
BasicErosionForBinary(m_pImgData, buf,m_imgWidth,m_imgHeight,
m_maskBuf, m_maskW, m_maskH);
//膨胀
BasicDilationForBinary(m_pImgData, m_pImgDataOut,m_imgWidth,m_imgHeight,
m_maskBuf, m_maskW, m_maskH);
//膨胀结果减腐蚀结果
int i, j;
for(i=0;i<m_imgHeight;i++){
for(j=0;j<lineByte;j++){
*(m_pImgDataOut+i*lineByte+j) -= *(buf+i*lineByte+j);
}
}
//释放缓冲区
delete []buf;
}
/***********************************************************************
* 函数名称:
* HitAndMiss()
*
*函数参数:
* unsigned char *imgBufIn -待变换的输入图像
* unsigned char *imgBufOut -输出图像
* int imgWidth -图像宽
* int imgHeight -图像高
* struct ElementPair hitMissMask -击中击不中结构元素对
*
*返回值:
* 无
*
*说明:击中击不中变换,0代表背景,255代表目标
***********************************************************************/
void Morphology::HitAndMiss(unsigned char *imgBufIn, unsigned char *imgBufOut,
int imgWidth,int imgHeight, ElementPair hitMissMask)
{
//循环变量
int i, j;
//标志变量,1表示结构元素对有效,0表示无效
int validateFlag=1;
//检查结构元素对是否交集为空,交集若不为空则为无效结构元素对,算法将退出
for(i=0; i<3;i++){
for(j=0;j<3;j++){
if(hitMissMask.hitElement[i*3+j]&&hitMissMask.missElement[i*3+j]){
validateFlag=0;
break;
}
}
}
//非法结构元素对,返回
if(validateFlag==0)
return;
//图像每行像素所占字节数
int lineByte=(imgWidth+3)/4*4;
//输出图像置0
memset(imgBufOut, 0, lineByte*imgHeight);
//循环变量
int k,l;
//击中标志变量和击不中标志变量
int hitFlag, missFlag;
for(i=1; i<imgHeight-1; i++){
for(j=1;j<imgWidth-1; j++){
hitFlag=1;
missFlag=1;
for(k=-1;k<=1;k++){
for(l=-1;l<=1;l++){
//如果击中结构元素当前位置为1
if(hitMissMask.hitElement[(k+1)*3+l+1]==1){
//判断图像对应点是否为0,如果是,则没有击中图像当前点
if(!*(imgBufIn+(i+k)*lineByte+j+l))
hitFlag=0;
}
//如果击不中结构元素当前位置为1
if(hitMissMask.missElement[(k+1)*3+l+1]==1){
//判断图像对应点是否为0,如果是,则没有击中图像当前点
if(*(imgBufIn+(i+k)*lineByte+j+l))
missFlag=0;
}
}
}
//输出点置255
if(hitFlag&&missFlag)
*(imgBufOut+i*lineByte+j)=255;
}
}
}
/***********************************************************************
* 函数名称:
* DefineElementPair()
*
*函数参数:
* 无
*
*返回值:
* 无
*
*说明:为击中击不中变换的结构元素对m_hitMissMask赋值,共8对
***********************************************************************/
void Morphology::DefineElementPair()
{
//定义8个方向的击中击不中变换结构元素对
int i, k, l;
for(i=0;i<8;i++){
for(k=0;k<3;k++){
for(l=0;l<3;l++){
m_hitMissMask[i].hitElement[k*3+l]=0;
m_hitMissMask[i].missElement[k*3+l]=0;
}
}
}
m_hitMissMask[0].hitElement[0]=1;
m_hitMissMask[0].hitElement[1]=1;
m_hitMissMask[0].hitElement[2]=1;
m_hitMissMask[0].hitElement[4]=1;
m_hitMissMask[0].missElement[6]=1;
m_hitMissMask[0].missElement[7]=1;
m_hitMissMask[0].missElement[8]=1;
m_hitMissMask[1].hitElement[6]=1;
m_hitMissMask[1].hitElement[7]=1;
m_hitMissMask[1].hitElement[8]=1;
m_hitMissMask[1].hitElement[4]=1;
m_hitMissMask[1].missElement[0]=1;
m_hitMissMask[1].missElement[1]=1;
m_hitMissMask[1].missElement[2]=1;
m_hitMissMask[2].hitElement[2]=1;
m_hitMissMask[2].hitElement[5]=1;
m_hitMissMask[2].hitElement[8]=1;
m_hitMissMask[2].hitElement[4]=1;
m_hitMissMask[2].missElement[0]=1;
m_hitMissMask[2].missElement[3]=1;
m_hitMissMask[2].missElement[6]=1;
m_hitMissMask[3].hitElement[0]=1;
m_hitMissMask[3].hitElement[3]=1;
m_hitMissMask[3].hitElement[6]=1;
m_hitMissMask[3].hitElement[4]=1;
m_hitMissMask[3].missElement[2]=1;
m_hitMissMask[3].missElement[5]=1;
m_hitMissMask[3].missElement[8]=1;
m_hitMissMask[4].hitElement[0]=1;
m_hitMissMask[4].hitElement[1]=1;
m_hitMissMask[4].hitElement[3]=1;
m_hitMissMask[4].hitElement[4]=1;
m_hitMissMask[4].missElement[5]=1;
m_hitMissMask[4].missElement[7]=1;
m_hitMissMask[4].missElement[8]=1;
m_hitMissMask[5].hitElement[5]=1;
m_hitMissMask[5].hitElement[7]=1;
m_hitMissMask[5].hitElement[8]=1;
m_hitMissMask[5].hitElement[4]=1;
m_hitMissMask[5].missElement[0]=1;
m_hitMissMask[5].missElement[1]=1;
m_hitMissMask[5].missElement[3]=1;
m_hitMissMask[6].hitElement[1]=1;
m_hitMissMask[6].hitElement[2]=1;
m_hitMissMask[6].hitElement[5]=1;
m_hitMissMask[6].hitElement[4]=1;
m_hitMissMask[6].missElement[3]=1;
m_hitMissMask[6].missElement[6]=1;
m_hitMissMask[6].missElement[7]=1;
m_hitMissMask[7].hitElement[3]=1;
m_hitMissMask[7].hitElement[6]=1;
m_hitMissMask[7].hitElement[7]=1;
m_hitMissMask[7].hitElement[4]=1;
m_hitMissMask[7].missElement[1]=1;
m_hitMissMask[7].missElement[2]=1;
m_hitMissMask[7].missElement[5]=1;
}
/***********************************************************************
* 函数名称:
* MorphoThinning()
*
*函数参数:
* 无
*
*返回值:
* 无
*
*说明:用击中击不中变换对输入图像进行细化
***********************************************************************/
void Morphology::MorphoThinning()
{
//定义8个方向的结构元素对
DefineElementPair();
//灰度图像每行像素所占字节数
int lineByte=(m_imgWidth+3)/4*4;
//申请缓冲区,存放中间结果
unsigned char *buf=new unsigned char[lineByte*m_imgHeight];
memcpy(buf, m_pImgData, lineByte*m_imgHeight);
//循环变量
int i, k, l;
//thinFlag用来记录当前一个循环周期内是否有细化掉的点,如果为0表明没
//有可以细化的点存在,细化终止
int thinFlag=1;
while(thinFlag){
thinFlag=0;
//用8个方向的结构元素对都对图像作一次击中击不中变换,并将输出结果
//从原图中去除
for(i=0;i<8;i++){
HitAndMiss(buf, m_pImgDataOut, m_imgWidth, m_imgHeight,m_hitMissMask[i]);
//将击中击不中变换的输出结果从原数据中去除
for(k=0;k<m_imgHeight;k++){
for(l=0;l<lineByte;l++){
if(*(m_pImgDataOut+k*lineByte+l)==255){
*(buf+k*lineByte+l)=0;
thinFlag=1;
}
}
}
}
}
//把最后细化的结果拷贝到m_pImgDataOut
memcpy(m_pImgDataOut, buf, lineByte*m_imgHeight);
//释放缓冲区
delete []buf;
}
/***********************************************************************
* 函数名称:
* BasicErosionForGray()
*
*函数参数:
* unsigned char *imgBufIn -待腐蚀的图像
* unsigned char *imgBufOut -腐蚀后的结果
* int imgWidth -图像宽
* int imgHeight -图像高
* int *maskBuf -结构元素缓冲区指针
* int maskW -结构元素宽
* int maskH -结构元素高
*
*返回值:
* 无
*
*说明:灰值腐蚀基本运算,后面的灰值开/闭/形态学梯度等操作都要调用这个函数
***********************************************************************/
void Morphology::BasicErosionForGray(unsigned char *imgBufIn,
unsigned char *imgBufOut,int imgWidth,int imgHeight,
int *maskBuf, int maskW, int maskH)
{
//循环 变量
int i,j,k,l;
//灰度图像每行像素所占字节数
int lineByte=(imgWidth+3)/4*4;
//申请缓冲区存放中间结果
unsigned char *buf=new unsigned char[(imgHeight+maskH)*(lineByte+maskW)];
//将输入图像,上下加m_maskH/2个像素的灰度为255的亮边,左右加m_maskW/2个像
//素的灰度为255的亮边,加边后的图像存入buf
for(i=0;i<imgHeight+maskH;i++)
{
for(j=0;j<lineByte+maskW;j++)
{
if(i<maskH/2||i>=imgHeight+maskH/2||j<maskW/2||j>=lineByte+maskW/2)
*(buf+i*(lineByte+maskW)+j)=255;
else
*(buf+i*(lineByte+maskW)+j)=*(imgBufIn+(i-maskH/2)*lineByte+j-maskW/2);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -