Смекни!
smekni.com

Система автоматизированного анализа пространственной структуры изображений Подсистема линейной сегментации (стр. 16 из 17)

//---------------------------------------------------------------------------

void __fastcall TfrmLineSeg::NeigNode(int x, int y, int n)

{

int i,j;

AnsiString s;

if(x<0 || y<0 || x>=w || y>=h) return; //если не принадлежит области изображения

if(apix[x][y][0]!=1) return; // если не является точкой

if(apix[x][y][2]!=-1) return; // если уже обработана на принадлежность узлу

if(NeigCount(x,y)<=2) return;// если мало соседей для сегментации

if(apix[x][y][2]==-1) // если точка не обработана

apix[x][y][2]=n; // точка будет принадлежать узлу n

// wlog(IntToStr(x)+","+IntToStr(y));

// обрабатываем ее соседей

NeigNode(x-1,y-1,n); NeigNode(x,y-1,n); NeigNode(x+1,y-1,n);

NeigNode(x-1,y ,n); NeigNode(x+1,y ,n);

NeigNode(x-1,y+1,n); NeigNode(x,y+1,n); NeigNode(x+1,y+1,n);

}

//---------------------------------------------------------------------------

void __fastcall TfrmLineSeg::actAnalyzeNodeExecute(TObject *Sender)

{

sb1->SimplePanel=true; sb1->SimpleText="Поиск узлов ...";

AnsiString s;

TPoint p;

int i,j,x,y,x1,y1,x2,y2,ssize,nsegs, v,oldv;

for(i=0;i<=w-1;i++) // maxw-1

for(j=0;j<=h-1;j++) // maxh-1

apix[i][j][2]=-1;

i=0; j=0;

nsegs=0;

wlog("Поиск узлов ...");

while(j<h)

{

while(i<w)

{

if( apix[i][j][0]==1 // есть точка

&& apix[i][j][2]==-1 // не обработана на принадлежность узлу

&& NeigCount(i,j)>2 ) // является частью узла

{// начинаем выделение узла

nsegs+=1;

wlog("Найден узел №"+IntToStr(nsegs));

// wlog("Точки в области узла:");

NeigNode(i,j,nsegs); // обрабатываем точки вокруг узла

p=NodeCentre(nsegs);

wlog("Координаты узла: "+IntToStr(p.x)+","+IntToStr(h-1-p.y));

}

i+=1;

} // while i

i=0; j+=1;

} // while j

DrawGrid();

wlog("Поиск узлов завершен");

wlog("ВСЕГО УЗЛОВ: "+IntToStr(nsegs));

sb1->SimpleText=""; sb1->SimplePanel=false;

}

//---------------------------------------------------------------------------

void __fastcall TfrmLineSeg::NeigLine(int x,int y, int n)

{

int nc=NeigCount(x,y);

if(nc==1 || nc==2) // если начало или продолжение линии

{

apix[x][y][1]=n;

wlog(IntToStr(x)+","+IntToStr(h-1-y));

// если ( есть точка И не обработана на принадлежность линии )

if(apix[x-1][y-1][0]==1 && apix[x-1][y-1][1]==-1) NeigLine(x-1,y-1,n);

if(apix[x ][y-1][0]==1 && apix[x ][y-1][1]==-1) NeigLine(x ,y-1,n);

if(apix[x+1][y-1][0]==1 && apix[x+1][y-1][1]==-1) NeigLine(x+1,y-1,n);

if(apix[x-1][y ][0]==1 && apix[x-1][y ][1]==-1) NeigLine(x-1,y ,n);

if(apix[x+1][y ][0]==1 && apix[x+1][y ][1]==-1) NeigLine(x+1,y ,n);

if(apix[x-1][y+1][0]==1 && apix[x-1][y+1][1]==-1) NeigLine(x-1,y+1,n);

if(apix[x ][y+1][0]==1 && apix[x ][y+1][1]==-1) NeigLine(x ,y+1,n);

if(apix[x+1][y+1][0]==1 && apix[x+1][y+1][1]==-1) NeigLine(x+1,y+1,n);

}

elseif(nc>2) // соединение с узлом

{

apix[x][y][1]=n;

}

}

//---------------------------------------------------------------------------

void __fastcall TfrmLineSeg::actAnalyzeSegExecute(TObject *Sender)

{

sb1->SimplePanel=true; sb1->SimpleText="Поиск сегментов линий ...";

AnsiString s;

int i,j,x,y,x1,y1,x2,y2,llen,nlines, v,oldv;

for(i=0;i<=w-1;i++) // maxw-1

for(j=0;j<=h-1;j++) // maxh-1

apix[i][j][1]=-1;

i=0; j=0;

nlines=0;

wlog("Поиск сегментов ...");

while(j<h)

{

while(i<w)

{

if( apix[i][j][0]==1 // есть точка

&& apix[i][j][1]==-1 // и она не обработана на принадлежность сегменту линии

&& (NeigCount(i,j)==1 // и является началом (1 сосед)

|| NeigCount(i,j)==2 )) // или продолжением линии (2 соседа)

{// начинаем выделение сегмента

nlines+=1;

wlog("Найден сегмент №"+IntToStr(nlines)+": ["+IntToStr(i)+","+IntToStr(h-1-j)+"]");

wlog("Точки сегмента:");

NeigLine(i,j,nlines); // обрабатываем сегмент линии

}

i+=1;

} // while i

i=0; j+=1;

} // while j

DrawGrid();

wlog("Поиск сегментов завершен");

wlog("ВСЕГО СЕГМЕНТОВ: "+IntToStr(nlines));

sb1->SimpleText=""; sb1->SimplePanel=false;

}

//---------------------------------------------------------------------------

void __fastcall TfrmLineSeg::actMatchLinesExecute(TObject *Sender)

{

sb1->SimplePanel=true; sb1->SimpleText="Поиск линий ...";

int i,j,cline,cseg,x,y;

double dist,mindist;

TPoint p;

wlog("Поиск линий ...");

for(i=0;i<=w-1;i++) // maxw-1

for(j=0;j<=h-1;j++) // maxh-1

apix[i][j][3]=-1;

i=0; j=0;

while(j<h)

{

while(i<w)

{

if(apix[i][j][1]>0 && apix[i][j][2]>0 // есть соединение с сегментом

&& apix[i][j][3]==-1 // точка не обработана

)

{ // обрабатываем точку и выполняем поиск ей соответствующей

apix[i][j][3]=1;

cline=apix[i][j][1]; // текущая линия

cseg=apix[i][j][2]; // текущий сегмент

p=NodeCentre(cseg);

mindist=MAXDOUBLE;

x=y=-1;

wlog("Поиск соответствия фрагменту "+IntToStr(apix[i][j][1])+" ["+IntToStr(i)+","+IntToStr(j)+"]");

wlog("Центр сегмента "+IntToStr(cseg)+" ["+IntToStr(p.x)+","+IntToStr(p.y)+"]");

for(intj1=0;j1<h;j1++) // поиск точки соответствия

for(int i1=0;i1<w;i1++)

{

if(apix[i1][j1][0]==1 // есть точка

&& apix[i1][j1][3]==-1 // не обработана на соответствие линий

&& apix[i1][j1][1]>0 && apix[i1][j1][2]==cseg // является пересечением этого сегмента с одной из линий

)

{

if((dist=plDistance(p.x,p.y,i,j,i1,j1))<=mindist) // если образует наименьшее отклонение от центра сегмента

{ // запоминаем точку как самую подходящую

x=i1; y=j1;

mindist=dist;

wlog("["+IntToStr(i1)+","+IntToStr(j1)+"] - соотв.:"+FloatToStr(dist));

}

else

{

wlog("["+IntToStr(i1)+","+IntToStr(j1)+"] - не соотв:"+FloatToStr(dist));

}

}

}

if(x>0 && y>0)

{

wlog("Найдено соответствие фрагментов: "+IntToStr(cline)+" и "+IntToStr(apix[x][y][1]));

apix[x][y][3]=1; // точка обработана

FillLine(apix[x][y][1],cline); // заполняем линию

}

}

i+=1;

} // while i

i=0; j+=1;

} // while j

DrawGrid();

wlog("Line matching end");

sb1->SimpleText=""; sb1->SimplePanel=false;

}

//---------------------------------------------------------------------------

void __fastcall TfrmLineSeg::FillLine(int n1, int n2)

{

for(int i=0;i<=w-1;i++) // maxw-1

for(int j=0;j<=h-1;j++) // maxh-1

if(apix[i][j][1]==n1) apix[i][j][1]=n2;

}

//---------------------------------------------------------------------------

TPoint TfrmLineSeg::NodeCentre(int n)

{

int i=0, j=0, cnt=0, xsum=0, ysum=0,x=0,y=0;

while(j<h)

{

while(i<w)

{

if( apix[i][j][2]==n // точка принадлежит этому узлу

// && apix[i][j][1]>0 // есть пересечение с линией

)

{

xsum+=i;

ysum+=j;

cnt+=1;

}

i+=1;

} // while i

i=0; j+=1;

} // while j

if(cnt>0)

{

x=xsum/cnt;

y=ysum/cnt;

}

return Point(x,y);

}

//---------------------------------------------------------------------------

void __fastcall TfrmLineSeg::actZoomWndExecute(TObject *Sender)

{

if(w>0 || h>0)

{

zoom=min(scb1->Width,scb1->Height)/max(w,h);

ZoomTo(zoom);

}

}

//---------------------------------------------------------------------------

void __fastcall TfrmLineSeg::GetLineVect(int x,int y,int n)

{

TPointp;

if(apix[x][y][1]==n && apix[x][y][3]==-1) // принадлежит этой линии и не обработана в код

{

// обработка текущей точки

apix[x][y][3]=1;

if(linecode=="")

linecode+=IntToStr(x)+","+IntToStr(y);

else

linecode+=","+IntToStr(x)+","+IntToStr(h-1-y);

// обрабтка продолжения линии

if(apix[x][y][2]>0) // если пересечение с сегментом

{// обработка линии внутри сегмента

p=FindMatch(x,y);

CodeLine(x,y,p.x,p.y); // вывод кода линии внутри сегмента

x=p.x;

y=p.y;

apix[x][y][3]=1;

if(linecode=="")

linecode+=IntToStr(x)+","+IntToStr(y);

else

linecode+=","+IntToStr(x)+","+IntToStr(h-1-y);

}

GetLineVect(x-1,y-1,n); GetLineVect(x,y-1,n); GetLineVect(x+1,y-1,n);

GetLineVect(x-1,y ,n); GetLineVect(x+1,y ,n);

GetLineVect(x-1,y+1,n); GetLineVect(x,y+1,n); GetLineVect(x+1,y+1,n);

}

}

//---------------------------------------------------------------------------

void __fastcall TfrmLineSeg::CodeLine(int x1,int y1,int x2,int y2)

{

wlog("Кодирование линии ["+IntToStr(x1)+","+IntToStr(h-1-y1)+"]-["+IntToStr(x2)+","+IntToStr(h-1-y2)+"]:");

if(abs(x1-x2)>abs(y1-y2)) // точек по x больше

{

wlog("Цикл по оси x. Точки линии:");

int x, y, xa=min(x1,x2), xb=max(x1,x2);

double k=double(y2-y1)/(x2-x1), b=y1-x1*k;

x=xa+1;

while(x<xb)

{

y=k*x+b;

if(linecode=="")

linecode+=IntToStr(x)+","+IntToStr(h-1-y);

else

linecode+=","+IntToStr(x)+","+IntToStr(h-1-y);

wlog(IntToStr(x)+","+IntToStr(h-1-y));

x+=1;

}

}

else // точек по y больше

{

wlog("Цикл по оси y. Точки линии:");

int x, y, ya=min(y1,y2), yb=max(y1,y2);

double k=double(x2-x1)/(y2-y1), b=x1-y1*k;

y=ya+1;

while(y<yb)

{

x=k*y+b;

if(linecode=="")

linecode+=IntToStr(x)+","+IntToStr(h-1-y);

else

linecode+=","+IntToStr(x)+","+IntToStr(h-1-y);

wlog(IntToStr(x)+","+IntToStr(h-1-y));

y+=1;

}

}

}

//---------------------------------------------------------------------------

TPoint __fastcall TfrmLineSeg::FindMatch(int x, int y)

{

int i,j;

TPoint p;

p.x=x;

p.y=y;

i=0; j=0;

while(j<h)

{

while(i<w)

{

if(apix[i][j][1]==apix[x][y][1] // если принадлежит той же линии

&& apix[i][j][2]==apix[x][y][2] // и принадлежит тому же сегменту

&& (i!=x || j!=y) // и это другая точка

)

{ // это искомая точка

p.x=i;

p.y=j;

}

i+=1;

} // while i

i=0; j+=1;

} // while j

return p;

}

//---------------------------------------------------------------------------

void __fastcall TfrmLineSeg::actMatchOutExecute(TObject *Sender)

{

int i,j,lineno,lnum;

sb1->SimplePanel=true; sb1->SimpleText="Вывод кода линий ...";

for(j=0;j<h;j++) // инициализация массива временных атрибутов

for(i=0;i<w;i++)

apix[i][j][3]=-1;

MemoOut->Clear();

lnum=0;

for(j=0;j<h;j++)

for(i=0;i<w;i++)

{

if( apix[i][j][1]>0// есть линия

&& apix[i][j][3]==-1 // и она не обработана

&& (NeigCount(i,j)==1 // точка является началом линии

|| apix[i][j][2]>0) // или узлом

)

{ // формируем код для этой линии

lineno=apix[i][j][1];

lnum+=1;

linecode="";

GetLineVect(i,j,lineno);

MemoOut->Lines->Add(IntToStr(lnum)+":"+linecode);

wlog(IntToStr(lnum)+"(line #"+IntToStr(lineno)+"):"+linecode);

}

}

sb1->SimpleText=""; sb1->SimplePanel=false;

}

//---------------------------------------------------------------------------

void __fastcall TfrmLineSeg::actOpenArrayExecute(TObject *Sender)

{

int i,j;

AnsiString s;

OpenDialog1->Title="Открыть массив точек";

OpenDialog1->Filter="Файлы массивов точек (*.dat)|*.dat|Все файлы (*.*)|*.*";

if(OpenDialog1->Execute())

{

sb1->SimplePanel=true; sb1->SimpleText="Открытие массива точек ...";

mArray->Lines->LoadFromFile(OpenDialog1->FileName);

try

{

w=StrToInt(mArray->Lines->Strings[0]);

h=StrToInt(mArray->Lines->Strings[1]);

if(w>0 & h>0)

{

Image1->Picture->Bitmap->Width=w;

Image1->Picture->Bitmap->Height=h;

Image1->Width=w;

Image1->Height=h;

Image1->Canvas->FillRect(Image1->ClientRect);

scb1->Enabled=true;

ZoomTo(zoom);

for(j=0;j<h;j++)

{

s=mArray->Lines->Strings[j+2];

for(i=0;i<w;i++)

{

apix[i][j][1]=apix[i][j][2]=apix[i][j][3]=-1;

if(s[i+1]=='1') // есть точка

{

apix[i][j][0]=1;

Image1->Canvas->Pixels[i][j]=c0;

}

else // нет точки

{

apix[i][j][0]=0;

Image1->Canvas->Pixels[i][j]=c1;

}

}

}

}

else

throw Exception("");

}

catch (...)

{

MessageBox(Handle,"Ошибка открытия массива", "ОШИБКА", MB_OK);

}

sb1->SimpleText=""; sb1->SimplePanel=false;

}

}

//---------------------------------------------------------------------------

void __fastcall TfrmLineSeg::actSaveArrayExecute(TObject *Sender)

{

int i,j;

AnsiString s;

SaveDialog1->Filter="Файлы массивов точек (*.dat)|*.dat|Все файлы (*.*)|*.*";

SaveDialog1->DefaultExt="*.dat";

SaveDialog1->Title="Сохранить массив точек";

if(SaveDialog1->Execute())

{

sb1->SimplePanel=true; sb1->SimpleText="Запись массива точек ...";

mArray->Clear();

mArray->Lines->Add(IntToStr(w));

mArray->Lines->Add(IntToStr(h));

for(j=0;j<h;j++)

{

s="";

for(i=0;i<w;i++)

{

s+=apix[i][j][0]==1 ? '1' : '0';

}

mArray->Lines->Add(s);

}

mArray->Lines->SaveToFile(SaveDialog1->FileName);

sb1->SimpleText=""; sb1->SimplePanel=false;

}

}

//---------------------------------------------------------------------------

void __fastcall TfrmLineSeg::actOptionsExecute(TObject *Sender)

{

frmOptions->Label1->Font->Color=c5;

frmOptions->Label2->Font->Color=c2;