[c++ Builder] filtrowanie

0

Mam taki wycinek programu dający filtr do obrazka, ale filtr nie daje żadnych zmian. Ładujacy obrazek daje na 3 panele.

 double GPrzep[9],P[9];
    int x,y,u,w;
    TColor k;
    double suma = 0, R = 0;

    if (Image2->Picture->Bitmap->Width == 0)
       {
      Application->MessageBox("Najpierw otworz plik.", "Błąd pliku", MB_OK);
       }


    else
      ProgressBar1->Position=0;
      ProgressBar1->Max=Image2->Picture->Bitmap->Width;
    for(x=1;x<Image2->Picture->Bitmap->Width-1;x++)
     {
      for(y=1;y<Image2->Picture->Bitmap->Height-1;y++)
        {
           for (u=0;u<8;u++)
                {


        //filtr
       GPrzep[0] = GPrzep[2] = GPrzep[6] = GPrzep[8] = 1;
       GPrzep[1] = GPrzep[3] = GPrzep[5] = GPrzep[7] = -2;
       GPrzep[4] = 5;

        suma = GPrzep[0] + GPrzep[3] + GPrzep[6] + GPrzep[8] + GPrzep[1] +
               GPrzep[3] + GPrzep[5] + GPrzep[7] + GPrzep[4];

        P[0] = Image2->Picture->Bitmap->Canvas->Pixels[x-1][y+1];
        P[1] = Image2->Picture->Bitmap->Canvas->Pixels[x][y+1];
        P[2] = Image2->Picture->Bitmap->Canvas->Pixels[x+1][y+1];
        P[3] = Image2->Picture->Bitmap->Canvas->Pixels[x-1][y];
        P[4] = Image2->Picture->Bitmap->Canvas->Pixels[x][y];
        P[5] = Image2->Picture->Bitmap->Canvas->Pixels[x+1][y];
        P[6] = Image2->Picture->Bitmap->Canvas->Pixels[x-1][y-1];
        P[7] = Image2->Picture->Bitmap->Canvas->Pixels[x-1][y];
        P[8] = Image2->Picture->Bitmap->Canvas->Pixels[x+1][y-1];
          
        R = GetRValue(P[u]);
        P[u]=R;
        
           k += GPrzep[u] * P[u];

            k /= suma ;

  
         k = RGB(k,k,k);
         Image3->Picture->Bitmap->Canvas->Pixels[x][y]= k;
                   
               }
                   ProgressBar1->Position=x;
                }
                ProgressBar1->Position=0;
         }

      Image3->Picture->Bitmap = Image2->Picture->Bitmap;
0

P musi być 32 bit, np.:

DWORD P[9];

0

no niestety dalej są szumy na filtrowanym obrazku i obraz jest nieczytelny

0

źle te pętle ustawiłeś i nie zerujesz k


  ...
  P[8] = Image2->Picture->Bitmap->Canvas->Pixels[x+1][y-1];

// dopiero tu dajesz pętlę z filtrem:

  int k = 0; // trzeba wyzerować
  for (int u = 0; u <= 8; u++) // 0 do 8 włącznie = 9 sztuk
    k += GPrzep[u] * GetRValue(P[u]); // R nie potrzeba
  
  k /= suma;  
 
  Image2->Picture->Bitmap->Canvas->Pixels[x][y] = RGB(k,k,k);

albo lepiej wyrzucić tablicę P i pętlę z u, i od razu sumować:

k += GPrzep[u]*GetRValue(Image2->Picture->Bitmap->Canvas->Pixels[x+1][y-1]);
...

k /= suma;

będzie ze 100x szybciej poprzez ScanLine zamiast Pixels.

0
bit napisał(a)

będzie ze 100x szybciej poprzez ScanLine zamiast Pixels.

na pewno więcej niż 100x. Około 5000x szybciej.
Artykuł "ScanLine w C"

0
JaskMar napisał(a)

na pewno więcej niż 100x. Około 5000x szybciej.

Może i tak, ale w tym artykule źle sugerujesz 24bpp;
format 32 bity/pixel jest szybszy z uwagi na dostęp do pamięci, cache, itp.

0

To nie jest mój artykół. Poprawiłem w nim tylko rażące błędy w składni przykładowych kodów. Także mnie nie obwiniaj :-P :-)

0

Dzięki działa a czemu tablica P musi być 32 bitowa, Ja pracuje na obrazie 8 bitowym.

A jaką wartość w kodzie mamy podzielić przez 1/16 jeżeli w maska filtru ma postać
1/16*[1,2,1; itd]

0
keslaw napisał(a)

Dzięki działa a czemu tablica P musi być 32 bitowa, Ja pracuje na obrazie 8 bitowym.

Pixels[x][y] zwraca typ TColor, który trzyma 4 bajty:
r, g, i b oraz czwarty bajt nie jest używany.

Jeśli masz obraz monochromatycznych 8bpp to możesz operować bajtami
bezpośrednio na danych obrazu (np. przy pomocy ScanLine),

Są też kolorowe 8bpp - z paletą do 256 kolorów, ale wtedy
lepiej przekonwertować taki obraz na 24/32 bity przed filtrowaniem.

A jaką wartość w kodzie mamy podzielić przez 1/16 jeżeli w maska filtru ma postać
1/16*[1,2,1; itd]

pewnie ta 'suma' wyjdzie tu 16, więc nic więcej nie trzeba robić.

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