Problem z rekurencja

0

Pomocy!! Musze napisac metode rekurencyjna ktora bedzie mi znajdowala krawedz interesujacego mnie obiektu graficznego. Moj program dziala w ten sposob ze laduje rysunek testowy ktory sklada sie z 0 i 1 akurat tak jakos glupio sie zlozylo ze 0 oznacza piksel czarny a 1 piksel bialy. W kazdym razie stosujac klase WritableRaster przepisuje caly obrazek *.jpg do dwuwymiarowej tablicy bo na takiej latwiej mi operowac. Algorytm wykrywania krawedzi jest taki.

  1. Znajdz pierwszy czarny punkt (to mam zrobione metoda znajdzPierwszyCzarnyPunkt(int[][] obrazek))
    2.Wez pierwszy czarny punkt i sprawdzaj jego piksele "sasiadow" wokol niego zgodnie z ruchem wskazowek zegara rozpoczynajac od prawego sasiada ma to wygladac mniej wiecej tak

                                                                                                                            678
                                                                                                                            5x1
                                                                                                                            432
    

gdy np 1 bedzie czarnym pikselem czyli w tablicy bedzie miec wartosc 0 to zapisz ten punkt do ArrayList o nazwie krawedz i wywolaj rekurencyjnie metode z tym obiektem.
No i to sie ma tak krecic. Wiadomo musi byc jakis warunek stopu. Pomyslalem ze moglby nim byc sytuacja w ktorej pierwszy punkt sie powtarza.
Metoda ktora ma to realizowac jest w jakims tam stopniu napisana, ale dziala zle poniewaz oscyluje ciagle miedzy tymi samymymi punktami az wkoncu wywala blad. Wiem gdzie jest blad, ale cienias jeszcze ze mnie a nie programista no i nie wiem jak sobie z tym poradzic. Z gory dzieki!!! Ponizej zamieszczam kod tej pokreconej metody.

 public void wykryjKrawedz(Punkt punkt)
   {
       poprzedni = (Punkt)krawedz.get(licznik-1);
       Punkt operacyjny = new Punkt();
       int y = punkt.y;
       int x = punkt.x;
       int warunek = 0;
       if (punkt.equals(poczatek)) {
           warunek++;
           System.out.println("dodalem");
       }

           if (obrazekTab[x + 1][y - 1] == 0 && !poprzedni.isChecked()) {

               operacyjny.x = x + 1;
               operacyjny.y = y - 1;
               System.out.println("Warunek 1");
               krawedz.add(operacyjny);
               poprzedni.setSprawdzony(true);
               licznik++;
               wykryjKrawedz(operacyjny);
           }
          if (obrazekTab[x + 1][y] == 0 && !poprzedni.isChecked()) {

               operacyjny.x = x - 1;
               operacyjny.y = y;
               System.out.println("Warunek 2");
               krawedz.add(operacyjny);
               poprzedni.setSprawdzony(true);
               licznik++;
               wykryjKrawedz(operacyjny);
               
           }
           if (obrazekTab[x + 1][y + 1] == 0 && !poprzedni.isChecked()) {

               operacyjny.x = x + 1;
               operacyjny.y = y + 1;
               System.out.println("Warunek 3");
               krawedz.add(operacyjny);
               poprzedni.setSprawdzony(true);
               licznik++;
               wykryjKrawedz(operacyjny);
           }
           if (obrazekTab[x][y + 1] == 0 && !poprzedni.isChecked()) {

               operacyjny.x = x;
               operacyjny.y = y + 1;
               System.out.println("Warunek 4");
               krawedz.add(operacyjny);
               poprzedni.setSprawdzony(true);
               licznik++;
               wykryjKrawedz(operacyjny);
           }
           if (obrazekTab[x - 1][y + 1] == 0 && !poprzedni.isChecked()) {

               operacyjny.x = x - 1;
               operacyjny.y = y + 1;
               System.out.println("Warunek 5");
               krawedz.add(operacyjny);
               poprzedni.setSprawdzony(true);
               licznik++;
               wykryjKrawedz(operacyjny);
           }
           if (obrazekTab[x - 1][y] == 0 && !poprzedni.isChecked()) {

               operacyjny.x = x - 1;
               operacyjny.y = y;
               System.out.println("Warunek 6");
               krawedz.add(operacyjny);
               poprzedni.setSprawdzony(true);
               licznik++;
               wykryjKrawedz(operacyjny);
           }

           if (obrazekTab[x - 1][y - 1] == 0 && !poprzedni.isChecked()) {

               operacyjny.x = x - 1;
               operacyjny.y = y - 1;
               System.out.println("Warunek 7");
               krawedz.add(operacyjny);
               poprzedni.setSprawdzony(true);
               licznik++;
               wykryjKrawedz(operacyjny);
           }
           if (obrazekTab[x][y - 1] == 0 && !poprzedni.isChecked()) {

               operacyjny.x = x - 1;
               operacyjny.y = y;
               System.out.println("Warunek 8");
               krawedz.add(operacyjny);
               poprzedni.setSprawdzony(true);
               licznik++;
               wykryjKrawedz(operacyjny);
           }
   }

i jeszcze klasa Punkt choc ona nie rozni sie zbyt wiele od swego pierwowzoru

public class Punkt extends Point {
    boolean sprawdzany = false;
    public Punkt() {
    }
    public void setSprawdzony(boolean war)
    {
    sprawdzany = war;
    }
    public boolean isChecked()
    {return sprawdzany;}
}

P.S. jezeli bedziecie potrzebowali wiecej kodu to napiszcie ale reszta jest ok na 100%

// powiększanie czcionki nie prowadzi do zwiększenia szansy na odpowiedź, za to wybitnie zwiększa szansę na wylądowanie posta w koszu - Q

0

Brakuje mi czegoś co by sprawdzało czy dany punkt jest już w tablicy. W prawdzie ustawiasz flagę i sprawdzasz ją, ale robisz to TYLKO dla punktu poprzedniego, z którego przychodzi wezwanie. Dobrał bym się do tego w troszkę inny sposób. Bardzo ogólny kod:

public void wykryjKrawedz(Punkt punkt){
   Punkt[] sasiedzi = getSasiedzi(punkt.x, punkt.y);
   for(int i = 0; i< sasiedzi.length; i++){
      if(!sasiedzi[i].isCheched && sasiedzi[i]==0){
        //zapis do tablicy, zmiana flagi rekurencja
      }
   }
}

pobieram wszystkich sąsiadów punktu,
dla każdego sąsiada:
jeżeli nie został jeszcze sprawdzony i jest czarny (==0), zapisz do tablicy, zmień flagę, wywołaj rekurencyjnie dla niego tą metodę.

Żeby było ciekawie funkcja nie wymaga wprost zdefiniowanego warunku bazowego rekurencji. Rekurencja zakończy się w momencie wyczerpania wszystkich dostępnych punktów.

0

Jezeli dobrze zrozumialem to mialem zrobic cos takiego:

 public Punkt[] getSasiedzi(int x , int y)
   {
       Punkt[] sasiedzi = new Punkt[8];
       Punkt sasiad;
       int incr = 0;
       
       sasiad = new Punkt(x + 1, y - 1);
       sasiad.setKolor(obrazekTab[x + 1][y - 1]);
       sasiedzi[incr++] = sasiad;
       // System.out.println("Warunek 1");
       
       sasiad = new Punkt(x - 1,y);
       sasiad.setKolor(obrazekTab[x + 1][y]);
       sasiedzi[incr++] = sasiad;
       //System.out.println("Warunek 2");
       
       sasiad = new Punkt(x + 1,y + 1);
       sasiad.setKolor(obrazekTab[x + 1][y + 1]);
       sasiedzi[incr++] = sasiad;
       //System.out.println("Warunek 3");

       sasiad = new Punkt(x, y + 1);
       sasiad.setKolor(obrazekTab[x][y + 1]);
       sasiedzi[incr++] = sasiad;
       //System.out.println("Warunek 4");

       sasiad = new Punkt(x - 1,y + 1);
       sasiad.setKolor(obrazekTab[x - 1][y + 1]);
       sasiedzi[incr++] = sasiad;
       //System.out.println("Warunek 5");
       
       sasiad =new Punkt(x - 1, y);
       sasiad.setKolor(obrazekTab[x - 1][y]);
       sasiedzi[incr++] = sasiad;
       //System.out.println("Warunek 6");
       
       sasiad = new Punkt(x - 1, y - 1);
       sasiad.setKolor(obrazekTab[x - 1][y - 1]);
       sasiedzi[incr++] = sasiad;
       //System.out.println("Warunek 7");
       
       sasiad = new Punkt(x - 1, y);
       sasiad.setKolor(obrazekTab[x][y - 1]);
       sasiedzi[incr++] = sasiad;
       
       //System.out.println("Warunek 8");
           return sasiedzi;
   }
   public void wykryjKrawedz(Punkt punkt)
   {
       Punkt[] sasiedzi = getSasiedzi(punkt.x, punkt.y);
       for(int i = 0 ; i < sasiedzi.length ; i++){
               
               if(!sasiedzi[i].isChecked() && sasiedzi[i].getKolor()==0)
               {
                   
                   krawedz.add(sasiedzi[i]);
                   sasiedzi[i].setSprawdzony(true);
                   //System.out.print(sasiedzi[i].getKolor()+" "+sasiedzi[i].x+" "+sasiedzi[i].y);
                   wykryjKrawedz(sasiedzi[i]);
                   
                   
               }
           }
       }

problem polega na tym ze sie sypie dalej. Moze cos pomieszalem napisalbys mi ten fragment kodu :-) :-) z gory dzieki.

0

Co rozumiesz przez krawędź ? Jeśli odcinek, to proponowany algorytm jest zbyt prosty i zbyt skomplikowany jednocześnie.

  • jeśli szukany odcinek jest "poziomy" lub "pionowy", to znajdziesz go bez żadnej rekurencji: jeśli np. sąsiad o numerze 1 jest czarny, to posuwasz się w prawo tak długo jak są czarne piksele
  • jeśli odcinek jest "pod kątem", to (poprawiwszy swój) program dostaniesz ciąg sąsiadujących ze sobą czarnych pikseli i musisz zdecydować czy te piksele tworzą odcinek
    pozdrawiam
0
bogdans napisał(a)

Co rozumiesz przez krawędź ? Jeśli odcinek, to proponowany algorytm jest zbyt prosty i zbyt skomplikowany jednocześnie.

  • jeśli szukany odcinek jest "poziomy" lub "pionowy", to znajdziesz go bez żadnej rekurencji: jeśli np. sąsiad o numerze 1 jest czarny, to posuwasz się w prawo tak długo jak są czarne piksele
  • jeśli odcinek jest "pod kątem", to (poprawiwszy swój) program dostaniesz ciąg sąsiadujących ze sobą czarnych pikseli i musisz zdecydować czy te piksele tworzą odcinek
    pozdrawiam

To moze rzucisz jakis przykladowy kod, bo jak juz mowilem nie jestem programista!!! Domyslam sie ze wszystko powinno byc w jakims while'u, a co do rekurencji to uzylem jej dlatego bo wydawalo mi sie ze szybko i latwo bedzie mi aktualizowala warunek, ktory nie wiem jak mam zmieniac w trakcie dzialania Twojego algorytmu, a warunek musi byc zmieniany w zaleznosci od pochylenia krawedzi.

0

Nadal nie wiem, co u Ciebie znaczy słowo krawędź
pozdrawiam

0

No coz krawedzia w moim przypadku jest zbior skrajnych punktow obiektu. Obrazek jak wiesz jest czarno- bialy. Gdzie piksele czarne sa oznaczone 0 a biale 1. Obiekt znajduje sie na bialym tle.Czyli punkty skrajne to te punkty(czarne) ktore stykaja sie bezposrednio z bialymi np takie kolo
0000000000
0001111000
0011111100
0011111100
0001111000
0000000000
a teraz krawedz
0000000000
0001111000
0010000100
0010000100
0001111000
0000000000
mam nadzieje ze udalo mi sie dobrze to wyjasnic pozdrawiam

0

Imho wystarczy wyzerować te jedynki, które mają 4 (8) jedynkowatych sąsiadów.

0
Pawel200x.5 napisał(a)

Imho wystarczy wyzerować te jedynki, które mają 4 (8) jedynkowatych sąsiadów.

Nie specjalnie wiem o co Ci chodzi. poza tym niech ktos napisze jakis kod!!!Dzieki . Pozdrawiam

1 użytkowników online, w tym zalogowanych: 0, gości: 1