|
|
|
![]() |
|
Strumenti |
![]() |
#1 |
Senior Member
Iscritto dal: May 2003
Messaggi: 1113
|
[PASCAL] Stack Overflow Error e Ricorsione
Ragazzi ho un problema, ho scritto un algoritmo ricorsivo per il calcolo della COMPONENTE CONNESSA di una immagine.
I Pixel di questa immagine sono memorizzati in un Array bidimensionale, quindi la Componente Connessa viene calcolata a partire da un pixel dell'immagine (k quindi sarebbe un elemento dell'array). Questo è l'algoritmo: Codice:
{Procedure per il Calcolo della Componente Connessa} procedure CalcolaCC(Riga,Colonna,PixelIniziale,s,ToniMax:integer; VAR i,j:integer); var new_i, new_j:integer; begin {Verifica se gli indici individuano ancora una locazione della matrice} If ((i<=Riga) And (j<=Colonna)) And ((i>0) And (j>0)) Then begin {Verifica se il pixel appartiene alla componente connessa} If (Dati[i, j] - PixelIniziale) < s Then begin {Modifica della matrice che individuer… la componente connessa} DatiAppoggio[i,j]:=1; {Modifica del valore della matrice per far modo che la ricorsione non sia infinita} Dati[i,j]:=2*ToniMax; {Autoattivazione ("destra","sotto", "sinistra", "sopra")} new_j:=j+1; CalcolaCC(Riga, Colonna, PixelIniziale, s, ToniMax, i, new_j); new_i:=i+1; CalcolaCC(Riga, Colonna, PixelIniziale, s, ToniMax, new_i, j); new_j:=j-1; CalcolaCC(Riga, Colonna, PixelIniziale, s, ToniMax, i, new_j); new_i:=i-1; CalcolaCC(Riga, Colonna, PixelIniziale, s, ToniMax, new_i, j); End; End; end;
__________________
| Athlon XP Barton 3000+ | CoolerMaster HAC-V81 | ASUS A7N8X DELUXE v2.0 | 2*256 PC3200 + 1*512 PC3200 = 1GB DDR400| ATI Radeon 9250 | HD 80Gb Maxtor SATA | Ali Q-TEC 550W Dual Fan GOLD PFC |
![]() |
![]() |
![]() |
#2 | |
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
Quote:
![]() allora, secondo me devi trasformare l'algoritmo ricorsivo in iterativo, quindi vuol dire che partendo da un pixel devi (ad esempio) trovare tutti quelli della componente connessa nella sua stessa scanline; poi se il pixel che gli sta sopra fa parte anch'esso della stessa componente, sali di una scanline e cerchi tutti i pixel della scanline superiore; vai avanti fino a che non trovi un pixel diverso e fai la stessa cosa di sotto. il problema di questo algoritmo è che funziona solo coi poligoni convessi e con pochi casi di poligoni concavi. un approccio alternativo potrebbe essere quello di cercare tutti i pixel nell'immagine che potrebbero far parte della tua componente e poi cercare di capire quali sono quelli della componente che contiene il pixel indicato, ma mi sembra più difficile. |
|
![]() |
![]() |
![]() |
#3 |
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
ecco qua, mi è venuta una mezza idea: ti descrivo quello che dovresti fare andando verso l'alto, ma poi devi fare lo stesso scendendo verso il basso.
allora, hai il tuo pixel che sta nella tua scanline; del pixel te ne freghi, cerchi subito l'inizio di quella scanline (a partire dal primo pixel della componente), dopodiché la analizzi un pixel alla volta: per ogni pixel fai una ulteriore iterazione verso l'alto e quindi controlli pure quelli della stessa colonna; è chiaro dunque che parte delle scanlines superiori le avrai già analizzate in questo modo, perciò quando sali ne devi tenere conto: non devi salire semplicemente alla scanline superiore, ma a quella dove la componente si allarga (o a destra o a sinistra), perché se si allarga vuol dire che ci sono dei pixel laterali che non hai avuto la possibilità di analizzare. dunque passi all'analisi di questa nuova scanline, che però non è necessario analizzare completamente: la maggior parte l'hai già fatta, quindi ogni volta che sali in questo modo devi tenerti in qualche variabile gli indici delle colonne che hai sicuramente già analizzato. per i pixel rimanenti l'analisi avviene nello stesso modo della scanline inferiore: per ciascuno fai anche una iterazione verso l'alto finché non tocchi un bordo della componente. poi continui a salire e così via. volendo migliorare l'algoritmo si potrebbero unire le due analisi verticali: ogni volta che analizzi una colonna corrispondente a un pixel, cerchi direttamente il margine superiore e la analizzi verso il basso (oppure il contrario). Ultima modifica di 71104 : 02-07-2005 alle 10:05. |
![]() |
![]() |
![]() |
#4 |
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
un ulteriore possibile approccio potrebbe essere quello di "camminare lungo il bordo" della componente: se ad es. il tuo scopo è quello di modificare tutti i pixel di una certa componente (come accade nell'esempio che hai mostrato in Pascal), prima devi trovare un modo per camminare sul bordo esterno, e ad ogni pixel che "calpesti" (
![]() siccome questa cosa mi interessa molto, oggi se ho tempo farò qualche prova. ![]() ciao |
![]() |
![]() |
![]() |
#5 |
Senior Member
Iscritto dal: May 2003
Messaggi: 1113
|
uhm...alcune domande forse banali ma per me utili...:
Cosa è una "ScanLine"? Inoltre ho notato che il mio algoritmo (k in C/C++, in VB ed in Delphi funziona bene) non va in Stack Overflow se invece delle 4 chiamate ricorsive per volta gliene faccio fare 3, in pratica se abolisco una sola di queste: Codice:
{Autoattivazione ("destra","sotto", "sinistra", "sopra")} new_j:=j+1; CalcolaCC(Riga, Colonna, PixelIniziale, s, ToniMax, i, new_j); new_i:=i+1; CalcolaCC(Riga, Colonna, PixelIniziale, s, ToniMax, new_i, j); new_j:=j-1; CalcolaCC(Riga, Colonna, PixelIniziale, s, ToniMax, i, new_j); new_i:=i-1; CalcolaCC(Riga, Colonna, PixelIniziale, s, ToniMax, new_i, j); però questo mi ha dato un'idea...ovvero che potrei far richiamare questa procedura ricorsiva da una iterativa aumentando di una il numero delle variabili passate e che questa serva a selezionare quali ricorsioni attivare...esempio: Codice:
procedure CalcolaCC(RAMO,Riga,Colonna,PixelIniziale,s,ToniMax:integer; VAR i,j:integer); ... if RAMO=1 then begin {Autoattivazione ("destra","sotto", "sinistra", "sopra")} new_j:=j+1; CalcolaCC(1,Riga, Colonna, PixelIniziale, s, ToniMax, i, new_j); new_i:=i+1; CalcolaCC(1,Riga, Colonna, PixelIniziale, s, ToniMax, new_i, j); end else begin new_j:=j-1; CalcolaCC(2,Riga, Colonna, PixelIniziale, s, ToniMax, i, new_j); new_i:=i-1; CalcolaCC(2,Riga, Colonna, PixelIniziale, s, ToniMax, new_i, j); end; ed il tutto sarebbe richiamato da una procedura normale tipo: Codice:
Procedura SperiamoCheVa; begin CalcolaCC(1,.....); CalcolaCC(2,.....); end; so che lato codice è bruttissimo... cmq la tua idea mi sembra più "Professional" ![]()
__________________
| Athlon XP Barton 3000+ | CoolerMaster HAC-V81 | ASUS A7N8X DELUXE v2.0 | 2*256 PC3200 + 1*512 PC3200 = 1GB DDR400| ATI Radeon 9250 | HD 80Gb Maxtor SATA | Ali Q-TEC 550W Dual Fan GOLD PFC |
![]() |
![]() |
![]() |
#6 |
Senior Member
Iscritto dal: May 2003
Messaggi: 1113
|
no...ho scoperto che la situazione seppur migliora non va...ci sono alcune zone particolari dove non calcola la componente connessa...
inoltre ho notato un piccolo problema, k nn riguarda la CC, abbastanza strano..si verifica quando salvo l'immagine creata tramite la CC...mi manca l'ultima riga della matrice...il bello è che la funzione è la stessa che uso per salvare l'immagine prodotta dalla funzione che calcola il negativo dell'immagine...e questo lo salva bene...vabbè problema secondario... ritorniamo alla CC...
__________________
| Athlon XP Barton 3000+ | CoolerMaster HAC-V81 | ASUS A7N8X DELUXE v2.0 | 2*256 PC3200 + 1*512 PC3200 = 1GB DDR400| ATI Radeon 9250 | HD 80Gb Maxtor SATA | Ali Q-TEC 550W Dual Fan GOLD PFC |
![]() |
![]() |
![]() |
#7 |
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
per "scanline" intendo semplicemente una intera riga nella matrice contenente l'immagine; tu hai un pixel, che risiede in una certa scanline: l'idea è quella di analizzare la scanline partendo dall'inizio (cioè cercando il margine sinistro della componente in quella scanline) fino alla fine (cioè fino al margine destro); per ogni pixel fai l'analisi anche in verticale (cioè cerchi i margini superiore e inferiore della componente in quella colonna) e poi quando sali (o scendi) alla scanline successiva fai lo stesso per le colonne che non hai ancora analizzato (per sapere quali colonne non hai analizzato devi tenerti i range che hai analizzato in un array). adesso spero sia più chiaro, cmq domani se ci riesco faccio le mie prove
![]() ciao |
![]() |
![]() |
![]() |
#8 |
Senior Member
Iscritto dal: May 2003
Messaggi: 1113
|
ti ringrazio...aspetto tue notizie
![]()
__________________
| Athlon XP Barton 3000+ | CoolerMaster HAC-V81 | ASUS A7N8X DELUXE v2.0 | 2*256 PC3200 + 1*512 PC3200 = 1GB DDR400| ATI Radeon 9250 | HD 80Gb Maxtor SATA | Ali Q-TEC 550W Dual Fan GOLD PFC |
![]() |
![]() |
![]() |
#9 | |
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
Quote:
![]() ![]() ![]() quindi non aspettare me per quel lavoro, specie se hai una scadenza, se è per l'università o per il lavoro. ciao |
|
![]() |
![]() |
![]() |
#10 | |
Senior Member
Iscritto dal: May 2003
Messaggi: 1113
|
Quote:
il fatto è che non è detto che tutti i pixel di una determinata scanline appartengano alla componente connessa...quando trovo uno di questi che non appartiene che faccio? mi fermo? inoltre l'algoritmo che ti ho passato in effetti fa questo...prende un pixel e ne analizza tutta la colonna e la riga in cui si trova... mi si sta incasinando il cervello...
__________________
| Athlon XP Barton 3000+ | CoolerMaster HAC-V81 | ASUS A7N8X DELUXE v2.0 | 2*256 PC3200 + 1*512 PC3200 = 1GB DDR400| ATI Radeon 9250 | HD 80Gb Maxtor SATA | Ali Q-TEC 550W Dual Fan GOLD PFC |
|
![]() |
![]() |
![]() |
#11 | ||
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
Quote:
Quote:
1) manca l'idea delle ranges 2) è ricorsivo e sputtana lo stack ![]() la mia idea invece è completamente iterativa ![]() |
||
![]() |
![]() |
![]() |
#12 |
Senior Member
Iscritto dal: May 2003
Messaggi: 1113
|
vediamo se ho capito bene...
Allora io ho la matrice e come punto di partenza dell'utente ho il punto (3,5) che vale ad esempio 255. Ora non tenendo in considerazione quel punto, ma solo il suo valore contenuto, parto dal punto (1,1) e: 1) analizzo in pratica l'intera colonna (scendendo verso il basso...quindi (1+x,1)) o almeno finchè non trovo un valore che non rientra nella componente connessa. 2) mi memorizzo le coordinate di partenza e di arrivo, in questo caso (1,1) e (x,y) 3) procedo col punto (1,2), quindi mi sposto di una colonna a destra, ed analizzao tutta la colonna (scendendo verso il basso...quindi (1+x,2)) finchè non finisce la colonna o non trovo un valore che non rientra nella componente connessa. e ripeto sempre questo MA se ad esempio al punto 3 vedo che invece di scorrere fino al punto (x,y) sono andato fino a (x,y+1) allora da qui comincerò a prendere come punto di partenza (x+1,y+1) ovvero il punto di lato a destra e faccio sempre il procedimento del punto 2 e 3. una cosa del genere? P.S. continuo a ringraziarti per la pazienza...
__________________
| Athlon XP Barton 3000+ | CoolerMaster HAC-V81 | ASUS A7N8X DELUXE v2.0 | 2*256 PC3200 + 1*512 PC3200 = 1GB DDR400| ATI Radeon 9250 | HD 80Gb Maxtor SATA | Ali Q-TEC 550W Dual Fan GOLD PFC |
![]() |
![]() |
![]() |
#13 | ||||||
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
Quote:
![]() non devi partire da (1, 1): piuttosto, nella scanline che ha index 5 devi cercare il margine sinistro della componente ed effettuare l'analisi fino al margine destro. quando dicevo "te ne freghi del punto" intendevo dire che te ne freghi della coordinata X, in questo caso 3 ^^ mi ero spiegato male io Quote:
Quote:
![]() ![]() Quote:
Quote:
![]() Quote:
|
||||||
![]() |
![]() |
![]() |
#14 |
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
dimenticavo: una volta che hai realizzato l'algoritmo, per metterlo alla prova prova a vedere come va con un caso estremo: la componente connessa a forma di SPIRALE!!!!
![]() ![]() se riesci a colorare una spirale penso proprio che ce l'hai fatta ![]() ![]() ![]() o addirittura una spirale che a un certo punto si divide e torna indietro, perché no? ![]() ![]() |
![]() |
![]() |
![]() |
#15 | |
Senior Member
Iscritto dal: May 2003
Messaggi: 1113
|
Quote:
eh...se lo riesco a realizzare :P è un casino...
__________________
| Athlon XP Barton 3000+ | CoolerMaster HAC-V81 | ASUS A7N8X DELUXE v2.0 | 2*256 PC3200 + 1*512 PC3200 = 1GB DDR400| ATI Radeon 9250 | HD 80Gb Maxtor SATA | Ali Q-TEC 550W Dual Fan GOLD PFC |
|
![]() |
![]() |
![]() |
#16 |
Senior Member
Iscritto dal: May 2003
Messaggi: 1113
|
niente...mi serve uno spunto...non riesco a fare il concetto mio ed a realizzare un algoritmo...
mi hai dato miliardi di informazioni lo so....e mi sento un po idiota a nn riuscire a concretizzare...ma mi sto esaurendo... P.S. ho sistemato alcune cose nel resto del progetto ed in DevPascal funziona tutto bene, in FreePascal non so perchè si blocca la procedura di lettura del file, mentre in TP7 mi da sempre stack overflow nel calcolo della CC...bah tre compilatori e 3 risultati differenti ![]() ho una settimana ancora......mi serve aiuto... ![]()
__________________
| Athlon XP Barton 3000+ | CoolerMaster HAC-V81 | ASUS A7N8X DELUXE v2.0 | 2*256 PC3200 + 1*512 PC3200 = 1GB DDR400| ATI Radeon 9250 | HD 80Gb Maxtor SATA | Ali Q-TEC 550W Dual Fan GOLD PFC |
![]() |
![]() |
![]() |
#17 |
Senior Member
Iscritto dal: May 2003
Messaggi: 1113
|
...non mi abbandonate...help....
![]()
__________________
| Athlon XP Barton 3000+ | CoolerMaster HAC-V81 | ASUS A7N8X DELUXE v2.0 | 2*256 PC3200 + 1*512 PC3200 = 1GB DDR400| ATI Radeon 9250 | HD 80Gb Maxtor SATA | Ali Q-TEC 550W Dual Fan GOLD PFC |
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 02:41.