分水岭算法代码C++Word格式文档下载.docx
- 文档编号:21763835
- 上传时间:2023-02-01
- 格式:DOCX
- 页数:11
- 大小:19.88KB
分水岭算法代码C++Word格式文档下载.docx
《分水岭算法代码C++Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《分水岭算法代码C++Word格式文档下载.docx(11页珍藏版)》请在冰豆网上搜索。
CImageSegWatershed(intImageHeight,intImageWidth,int*ImageData)
{
PicHeight=ImageHeight;
PicWidth=ImageWidth;
PicData=ImageData;
luvData=newMyluv[ImageHeight*ImageWidth];
RgbtoLuvPcm(ImageData,ImageWidth,ImageHeight,luvData);
}
~CImageSegWatershed()
voidCImageSegWatershed:
WaterShedArith()
longPiclen=PicHeight*PicWidth;
inti,j,temp;
//梯度模数组
double*deltar=newdouble[Piclen];
//梯度角度数组
double*deltasita=newdouble[Piclen];
//个点标识数组
int
*flag=newint[Piclen];
*gradientfre=newint[256];
//图像中各点梯度值的频数
*gradientadd=newint[257];
//各梯度起终位置
memset(gradientfre,0,sizeof(int)*256);
memset(gradientadd,0,sizeof(int)*257);
//得到各点的梯度值
GetGradient(deltar,deltasita);
//以下统计各梯度频数;
MyImageGraPt*
graposarr=newMyImageGraPt[Piclen];
longxstart,imagepos,deltapos;
xstart=imagepos=deltapos=0;
for(int
y=0;
y<
PicHeight;
y++)
xstart=y*PicWidth;
for(intx=0;
x<
PicWidth;
x++)
deltapos=xstart+x;
if(deltar[deltapos]>
255)
deltar[deltapos]=255;
//范围在0-255之间
inttempi=(int)(deltar[deltapos]);
gradientfre[tempi]++;
//灰度值频数;
//统计各梯度的累加频数
intadded=0;
gradientadd[0]=0;
//第一个初始位置为0
for(i=1;
i<
256;
i++)
added+=gradientfre[i-1];
gradientadd[i]=added;
gradientadd[256]=Piclen;
//最后累加和为总的像素点的个数
memset(gradientfre,0,256*sizeof(int));
MyImageGraPt*graposarr=newMyImageGraPt[Piclen];
//自左上至右下sorting.....(注意是对所求得的各个像素的累加梯度梯度值进行排序)
for(y=0;
//当前点的梯度值,由于前面的步骤,最大只能为255(0-255);
//根据梯度值决定在排序数组中的位置;
inttempos=gradientadd[tempi]+gradientfre[tempi];
//梯度内指针后移(统计各个像素点的总的个数;
graposarr[tempos].gradient=tempi;
//根据当前点的梯度将该点信息放后排序后数组中的合适位置中去;
graposarr[tempos].x=x;
graposarr[tempos].y=y;
intrgnumber=0;
//记录分割后的区域数
//下面是分水岭算法的核心步骤
//开始淹没泛洪(泛洪函数各个形参的意义)
//第一个参数是按一定规则排好序的个像素的梯度值和该像素在图片中的位置,
//第二个参数是各个像素点的梯度累加和,倒数第二个参数是记录在泛洪过程中各个像素点的信息(属于哪个区域),
//最后一个参数是记录整个泛洪过程产生多少个区域
FloodVincent(graposarr,gradientadd,0,255,flag,rgnumber);
//区域增长步骤
//以下准备计算各个区域的LUV的均值(也可以用其他的颜色空间)
MyRgnInfo*rginfoarrr=newMyRgnInfo[rgnumber+1];
//分割后各个区的一些统计信息,第一个元素不用,图像各点所属区域的信息存放在flag数组中
//清空该数组(对各区域要统计的数据进行初始化)
for(inti=0;
=rgnumber;
rginfoarrr[i].isflag=FALSE;
rginfoarrr[i].l=0;
rginfoarrr[i].u=0;
rginfoarrr[i].v=0;
rginfoarrr[i].ptcount=0;
longxstart;
for(inty=0;
y<
y++)
xstart=y*PicWidth;
for(intx=0;
x<
x++)
intpos=xstart+x;
intrgid=flag[pos];
//当前位置点所属区域在区统计信息数组中的位置。
//以下将该点的信息加到其所属区域信息中区
rginfoarrr[rgid].ptcount++;
rginfoarrr[rgid].l+=luvData[pos].l;
rginfoarrr[rgid].u+=luvData[pos].u;
rginfoarrr[rgid].v+=luvData[pos].v;
//求出各个区域的LUV均值
for(i=0;
rginfoarrr[i].l=double((rginfoarrr[i].l)/rginfoarrr[i].ptcount);
rginfoarrr[i].u=double((rginfoarrr[i].u)/rginfoarrr[i].ptcount);
rginfoarrr[i].v=double((rginfoarrr[i].v)/rginfoarrr[i].ptcount);
//根据各个区域灰度均值和各区之间的邻接关系(用flag计算)进行区域融合(主要是消除不必要的过分割)
int*mergearr=newint[rgnumber+1];
memset(mergearr,-1,sizeof(int)*(rgnumber+1));
intmergednum=0;
//第一个参数是各个区域的信息,第二个参数是图像所分的区域数,第三个参数是各个像素点的标志
//倒数第二个参数和倒数第一个参数用于区域融合
MergeRgs(rginfoarrr,rgnumber,flag,PicWidth,PicHeight,mergearr,mergednum);
//确定合并后各像素点所属区域
for(y=0;
//改点所属区域
flag[pos]=FindMergedRgn(rgid,mergearr);
delete[]mergearr;
mergearr=NULL;
//用各区均值来代替原像素点值
double*luvbuff=NULL;
luvbuff=newdouble[PicWidth*PicHeight*3];
for(y=1;
PicHeight-1;
for(intx=1;
PicWidth-1;
luvData[pos].l=rginfoarrr[rgid].l;
//luvData用于全局保存luv值
luvData[pos].u=rginfoarrr[rgid].u;
luvData[pos].v=rginfoarrr[rgid].v;
luvbuff[pos*3]=rginfoarrr[rgid].l;
//luvbuff用于专递参数给LuvToRgb();
luvbuff[pos*3+1]=rginfoarrr[rgid].u;
luvbuff[pos*3+2]=rginfoarrr[rgid].v;
//求各像素的梯度值
GetGradient(double*deltar,double*deltasita)
//下面计算各像素在水平和垂直方向上的梯度,边缘点梯度计为0;
int*deltaxarr;
int*deltayarr;
intgrawidth=PicWidth;
intgraheight=PicHeight;
intdeltacount=grawidth*graheight;
deltaxarr=newint[deltacount];
deltayarr=newint[deltacount];
//暂不计算边缘点;
for(inty=1;
graheight-1;
for(intx=1;
grawidth-1;
intinarrpos=((y)*PicWidth+(x))*3+1;
//在输入块中的位置;
intdeltaarrpos=y*grawidth+x;
//在梯度数组中的位置;
//卷积计算;
deltaxarr[deltaarrpos]=(int)((
PicData[((y-1)*PicWidth+(x+1))*3+1]//右上
+PicData[((y)*PicWidth+(x+1))*3+1]//右
+PicData[((y+1)*PicWidth+(x+1))*3+1]//右下
-PicData[((y-1)*PicWidth+(x-1))*3+1]//左上
-PicData[((y)*PicWidth+(x-1))*3+1]//左
-PicData[((y+1)*PicWidth+(x-1))*3+1])/3);
//左下
deltayarr[deltaarrpos]=(int)((
+PicData[((y-1)*PicWidth
+(x))*3+1]//上
+PicData[((y-1)*PicWidth+(x-1))*3+1]//左上
-PicData[((y+1)*PicWidth+(x-1))*3+1]//左下
-PicData[((y+1)*PicWidth+(x))*3+1]//下
-PicData[((y+1)*PicWidth+(x+1))*3+1])/3);
//右下
//边缘赋为其内侧点的值;
graheight;
intx1=0;
intpos1=y*grawidth+x1;
deltaxarr[pos1]=deltaxarr[pos1+1];
deltayarr[pos1]=deltayarr[pos1+1];
intx2=grawidth-1;
pos2=y*grawidth+x2;
deltaxarr[pos2]=deltaxarr[pos2-1];
deltayarr[pos2]=deltayarr[pos2-1];
x=0;
grawidth;
y1=0;
pos1=x;
inner=x+grawidth;
//下一行;
deltaxarr[pos1]=deltaxarr[inner];
deltayarr[pos1]=deltayarr[inner];
y2=graheight-1;
intpos2=y2*grawidth+x;
inner=pos2-grawidth;
//上一行;
deltaxarr[pos2]=deltaxarr[inner];
deltayarr[pos2]=deltayarr[inner];
for(x=0;
temppos=y*grawidth+x;
if((deltaxarr[temppos])==0)
if(deltayarr[temppos]!
=0)
deltasita[temppos]=0;
//水平方向;
deltar[temppos]=(double)abs(deltayarr[temppos]);
else
deltasita[temppos]=-1;
//无确定方向;
continue;
deltasita[temppos]=(double)(atan(
(double)deltayarr[temppos]
/(double)deltaxarr[temppos])+PI/2.);
deltar[temppos]=(double)sqrt((double)
(deltayarr[temppos]*deltayarr[temppos]
+deltaxarr[temppos]*deltaxarr[temppos]));
delete[]deltaxarr;
deltaxarr=NULL;
//删除水平和垂直梯度数组;
delete[]deltayarr;
deltayarr=NULL;
FloodVincent(MyImageGraPt*imiarr,int*graddarr,intminh,intmaxh,int*flagarr,int&
outrgnumber)
constintINIT=-2;
constint
MASK=-1;
constintWATERSHED=0;
inth=0;
intimagelen=PicWidth*PicHeight;
for(inti=0;
i<
imagelen;
i++)
flagarr[i]=INIT;
int*imd=newint[imagelen];
//距离数组,直接存取;
for(i=0;
imd[i]=0;
//保存分水岭的队列
std:
queue<
int>
myqueue;
intcurlabel=0;
//各盆地标记;
//下面是从在imiarr记录中的像素从开始泛起
for(h=minh;
h<
=maxh;
h++)
intstpos=graddarr[h];
intedpos=graddarr[h+1];
for(intini=stpos;
ini<
edpos;
ini++)
intx=imiarr[ini].x;
inty=imiarr[ini].y;
intipos=y*PicWidth+x;
flagarr[ipos]=MASK;
//以下检查该点邻域是否已标记属于某区或分水岭,若是,则将该点加入fifo;
intleft=ipos-1;
if(x-1>
if(flagarr[left]>
imd[ipos]=1;
myqueue.push(ipos);
//点位置压入fifo;
}
intright=ipos+1;
if(x+1<
PicWidth)
if(flagarr[right]>
intup=ipos-PicWidth;
if(y-1>
if(flagarr[up]>
intdown=ipos+PicWidth;
if(y+1<
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 分水岭 算法 代码 C+