求大神帮我把c++转换成matlab语言,一小段一小段也行
// anny.cpp: implementation of the Canny class.
//
//////////////////////////////////////////////////////////////////////
#include "anny.h"
#include "math.h"
//#include "algorithms.h"
//#include "algorithm.h"
#include "stdlib.h"
//#include "maths.h"
//using namespace std;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
Canny::Canny(int PicHeight,int PicWidth,double ** PicData,double PicSigma,double PicRatioLow,double PicRatioHigh)
{
iHeight=PicHeight;
iWidth=PicWidth;
iData=PicData;
sigma=PicSigma;
dRatioLow=PicRatioLow;
dRatioHigh=PicRatioHigh;
}
Canny::~Canny()
{
}
void Canny::CannyArith(int **iEdgePoint)
{
int i;
int **iGradX ; // 指向x方向导数的指针
int **iGradY ; // 指向y方向导数的指针
int **iExtent ; // 梯度的幅度
iGradX=new int *[iHeight];
for(i=0;i<iHeight;i++)
iGradX[i]=new int[iWidth];
iGradY=new int *[iHeight];
for(i=0;i<iHeight;i++)
iGradY[i]=new int[iWidth];
iExtent=new int *[iHeight];
for(i=0;i<iHeight;i++)
iExtent[i]=new int[iWidth];
// 对原图象进行滤波
GaussionSmooth();
// 计算X,Y方向上的方向导数
DirGrad(iGradX,iGradY);
// 计算梯度的幅度
GradExtent(iGradX,iGradY,iExtent);
// 应用non-maximum 抑制
NonMaxSuppress(iExtent,iGradX,iGradY,iEdgePoint);
// 应用Hysteresis,找到所有的边界
Hysteresis(iExtent,iEdgePoint);
// 释放内存
for(i=0;i<iHeight;i++)
delete []*(iGradX+i);
delete iGradX;
for(i=0;i<iHeight;i++)
delete []*(iGradY+i);
delete iGradY;
for(i=0;i<iHeight;i++)
delete []*(iExtent+i);
delete iExtent;
}
void Canny::GaussionSmooth()
{
int i,j,k; //循环变量
int iWindowSize; //记录模板大小的变量
int iHalfLen; //模板大小的一半
double *pdKernel; //模板各点的权值
double dDotMul; //模板与对应像素点的卷积和
double dWeightSum; //模板的权值累加和
double **dTemp; //记录图像数据的中间变量
//开辟空间
dTemp=new double *[iHeight];
for(i=0;i<iHeight;i++)
dTemp[i]=new double[iWidth];
//获得模板长度和模板的各个权值
MakeGauss(&pdKernel,&iWindowSize);
//得到模板的一半长度
iHalfLen=iWindowSize/2;
//对图像对水方向根据模板进行平滑
for(i=0;i<iHeight;i++)
{
for(j=0;j<iWidth;j++)
{
dDotMul=0;
dWeightSum=0;
for(k=(-iHalfLen);k<=iHalfLen;k++)
{
if((k+j>=0)&&(k+j<iWidth))
{
dDotMul+=iData[i][j+k]*pdKernel[k+iHalfLen];
dWeightSum+=pdKernel[k+iHalfLen];
}
}
dTemp[i][j]=dDotMul/dWeightSum;
}
}
//对图像垂直方向上根据模板的转置进行平滑(注意图像数据是在水平平滑之后进行的)
for(i=0;i<iWidth;i++)
{
for(j=0;j<iHeight;j++)
{
dDotMul=0;
dWeightSum=0;
for(k=(-iHalfLen);k<=iHalfLen;k++)
{
if((k+j>=0)&&(k+j<iHeight))
{
dDotMul+=dTemp[j+k][i]*pdKernel[k+iHalfLen];
dWeightSum+=pdKernel[k+iHalfLen];
}
}
iData[j][i]=dDotMul/dWeightSum;
}
}
//空间释放
delete []pdKernel;
pdKernel=NULL;
for(i=0;i<iHeight;i++)
delete []*(dTemp+i);
delete dTemp;
}
void Canny::MakeGauss(double **pdKernel,int *iWindowSize)
{
int i; //循环变量
int nCenter; //确定高斯模板的一半长度
double dDistance; //一维高斯模板各点离中心点的距离
double PI=3.1415926; //圆周率
double dValue; //中间变量,记录高斯模板各点的权值(未经归一化)
double dSum=0; //中间变量,记录高斯模板各点权值的总和
*iWindowSize=int(1+2*int(3*sigma+0.5)); //确定一维高斯模板长度,根据概率论的知识,选取[-3*sigma, 3*sigma]以内的数据。
nCenter=(*iWindowSize)/2; //得到一半长度
*pdKernel=new double[*iWindowSize];//开辟记录各点权值的空间
//利用高斯分布函数(正太分布)确定各点的权值,主要是根据高斯分布离中心点的距离越远,所取的值就越小,这与图像有些
//相似,离中心点越远,对中心点的影响就越小。
for(i=0;i<(*iWindowSize);i++)
{
dDistance=double(i-nCenter);
//高斯分布函数求值
dValue=exp((-1/2)*dDistance*dDistance/(sigma*sigma))/(sqrt(2*PI)*sigma);
(*pdKernel)[i]=dValue;
dSum+=dValue;
}
//归一化(因为要不改变原图像的灰度区域,就必须保证各权值之和为1
for(i=0;i<(*iWindowSize);i++)
{
(*pdKernel)[i] /= dSum;
}
}
void Canny::DirGrad(int **iGradX,int **iGradY)
{
int i,j,temp1,temp2;
//水平方向的方向导数(下面都是用min和max对边界值做了相应的处理)
for(i=0;i<iHeight;i++)
{
for(j=0;j<iWidth;j++)
{
if(iWidth-1<j+1)
temp1=iWidth-1;
else
temp1=j+1;
if(0<j-1)
temp2=j-1;
else
temp2=0;
iGradX[i][j]=int(iData[i][temp1]-iData[i][temp2]);
}
}
//垂直方向的方向导数
for(i=0;i<iWidth;i++)
{
for(j=0;j<iHeight;j++)
{
if(iHeight-1<j+1)
temp1=iHeight-1;
else
temp1=j+1;
if(0<j-1)
temp2=j-1;
else
temp2=0;
iGradY[j][i]=int(iData[temp1][i]-iData[temp2][i]);
}
}
}
void Canny::GradExtent(int **iGradX,int **iGradY,int **iExtent)
{
int i,j;
double iTemp1,iTemp2;
for(i=0;i<iHeight;i++)
{
for(j=0;j<iWidth;j++)
{
iTemp1=iGradX[i][j]*iGradX[i][j];
iTemp2=iGradY[i][j]*iGradY[i][j];
iExtent[i][j]=int(sqrt(iTemp1+iTemp2)+0.5);
}
}
}
void Canny::NonMaxSuppress(int **iExtent,int **iGradX,int **iGradY,int **dUnchRst)
{
int i,j;
int gx,gy; //记录像素点X,Y 方向的方向导数值
int g1,g2,g3,g4; //各个领域的梯度值
double weight; //比重
double dTemp1,dTemp2,dTemp; //中间变量
//处理边缘值(边缘点不可能是边界点
for(i=0;i<iHeight;i++)
{
dUnchRst[i][0]=0;
dUnchRst[i][iWidth-1]=0;
}
for(j=0;j<iWidth;j++)
{
dUnchRst[0][j]=0;
dUnchRst[iHeight-1][j]=0;
}
//标记有可能是边界点的像素点
for(i=1;i<iHeight-1;i++)
{
for(j=1;j<iWidth-1;j++)
{
//梯度值是0的像素点不可能是边界点
if(iExtent[i][j]==0)
dUnchRst[i][j]=0;
else
{
dTemp=iExtent[i][j];
gx=iGradX[i][j];
gy=iGradY[i][j];
//下面都是判断当前像素点的梯度值和其领域像素点的梯度值,如大于就有可能是边界点,如小于就不可能是边界点
if(abs(gy)>abs(gx))
{
weight=double(abs(gx)/abs(gy));
g2=iExtent[i-1][j];
g4=iExtent[i+1][j];
if(gx*gy>0)
{
g1=iExtent[i-1][j-1];
g3=iExtent[i+1][j+1];
}
else
{
g1=iExtent[i-1][j+1];
g3=iExtent[i+1][j-1];
}
}
else
{
weight=double(abs(gy)/abs(gx));
g2=iExtent[i][j+1];
g4=iExtent[i][j-1];
if(gx*gy>0)
{
g1=iExtent[i+1][j+1];
g3=iExtent[i-1][j-1];
}
else
{
g1=iExtent[i-1][j+1];
g3=iExtent[i+1][j-1];
}
}
dTemp1=weight*g1+(1-weight)*g2;
dTemp2=weight*g3+(1-weight)*g4;
//当大于的时候就有可能是边界点
if(dTemp>=dTemp1&&dTemp>=dTemp2)
{
dUnchRst[i][j] = 128 ;
}
else
{
dUnchRst[i][j]=0 ;
}
}
}
}
}
void Canny::Hysteresis(int **iExtent,int **iEdgePoint)
{
int i,j;
int iThreHigh;
int iThreLow;
SetThreshold(iExtent,&iThreHigh,&iThreLow,iEdgePoint);
for(i=0;i<iHeight;i++)
{
for(j=0;j<iWidth;j++)
{
if((iEdgePoint[i][j]==128)&&(iExtent[i][j]>=iThreHigh))
{
iEdgePoint[i][j]=255;
TraceEdge(i,j,iThreLow,iEdgePoint,iExtent);
}
}
}
// 那些还没有被设置为边界点的象素已经不可能成为边界点
for(i=0;i<iHeight;i++)
{
for(j=0;j<iWidth;j++)
{
if(iEdgePoint[i][j]!=255)
{
// 设置为非边界点
iEdgePoint[i][j] = 0 ;
}
}
}
}
void Canny::SetThreshold(int **iExtent,int *iThreHigh,int *iThreLow,int **iEdgePoint)
{
int i,j,k;
int GradHist[1024]; //统计梯度直方图的数据,梯度最大值不可能超过1024
int iEdgeNum; //边界点的数量
int iGradMax=0; //边界点的梯度最大值
int iHighCount; //根据iRatioHigh小于高阈值像素的个数
//初始化
for(i=0;i<1024;i++)
GradHist[i]=0;
//梯度直方图统计
for(i=0;i<iHeight;i++)
{
for(j=0;j<iWidth;j++)
{
if(iEdgePoint[i][j]==128)
{
GradHist[iExtent[i][j]]++;
}
}
}
iEdgeNum=0;
//找出最大梯度和统计边界点的个数
for(i=0;i<1024;i++)
{
if(GradHist[i]!=0)
iGradMax=i;
iEdgeNum+=GradHist[i];
}
//获得小于高阈值的个数
iHighCount=int(iEdgeNum*dRatioHigh+0.5);
k=1;
iEdgeNum=GradHist[1];
//求出高阈值
while((k<=(iGradMax-1))&&(iEdgeNum<iHighCount))
{
k++;
iEdgeNum+=GradHist[k];
}
*iThreHigh=k;
//根据高阈值和比例关系求得低阈值
*iThreLow=int((*iThreHigh)*dRatioLow+0.5);
}
void Canny::TraceEdge(int y,int x,int iThreLow,int **iEdgePoint,int **iExtent)
{
// 对8邻域象素进行查询
int xNb[8] = {1, 1, 0,-1,-1,-1, 0, 1} ;
int yNb[8] = {0, 1, 1, 1,0 ,-1,-1,-1} ;
int yy ;
int xx ;
int k ;
for(k=0;k<8;k++)
{
yy=y+yNb[k] ;
xx=x+xNb[k] ;
// 如果该象素为可能的边界点,又没有处理过, 并且梯度大于阈值
if(iEdgePoint[yy][xx]==128&&iExtent[yy][xx]>=iThreLow)
{
// 把该点设置成为边界点
iEdgePoint[yy][xx]=255 ;
// 以该点为中心进行跟踪
//TraceEdge(yy,xx,iThreLow,iEdgePoint,iExtent);
}
}
}
编程语言 MATLAB C++
[解决办法]
看明白,理解理论,然后去matlab重写,matlab的数据结构与语法比c++简单了不知多少,翻过去程序至少短一半