[bcb6]filtrowanie obrazu

0

filtrowanie ma polegac na tym ze filtr o zadanej rozdzielczosci powinien badac wartosc rgb pixela ktory jest w jego srodku i przypisywac mu wartosci rgb rowne sredniej wszystkich pixeli w filtrze...

probowalem czegos takiego
[code]
double **filtr;
filtr=new double [w];
for(int i=0;i<w;i++)
filtr[i]=new double [k];
double wartosc=1/w
k;
for(int i=0;i<w;i++)
for(int j=0;j<k;j++)
filtr[i][j]=wartosc;
int xw=(int)w/2+1; //wsp x srodka filtra
int yw=(int)k/2+1; //wsp y srodka filtra
int width=Image1->Picture->Width;
int height=Image1->Picture->Height;
for(int i=0;i<width;i++) //petla po kolejnych wierszach obrazu
for(int j=0;j<height;j++) //petla po kolumnach
{
if(i>xw&&i<width-xw&&j>yw&&j<height-yw) //jezeli caly filtr w obrazie
{
unsigned int r,g,b;
unsigned int wr=0,wg=0,wb=0;
unsigned int lr=0,lg=0,lb=0;
for(int z=i-xw;z<i+xw;z++) //petla po wierszach otaczajacych aktualny pixel
{
int fi=0; //identyfikator wiersza filrta
for(int x=j-yw;x<j+yw;x++) //petla po kolumnach otaczajacych aktualny pixel
{
int fj=0; //identyfikator kolumny filtra
RGB2Color(Image1->Canvas->Pixels[z][x],r,g,b); //funkcja przypisuje r,g,b aktualne wartosci RGB podanego pixela
wr+=rfiltr[fi][fj]; //obliczanie wartosci RGB.red w zaleznosci od wartosci filtra
lr+=r; //zliczanie wartosc RGB.red
wg+=g
filtr[fi][fj];
lg+=g;
wb+=b*filtr[fi][fj];
lb+=b;
fj++;
}
fi++;
}
Image1->Canvas->Pixels[i][j] = RGB_Color( wr/lr, wg/lg, wb/lb ); //wr/lr- srednia wazona natezenia barwy
}
}
[/code]
ale obraz robi sie caly czarny....
moze ktos ma jakies pomysly?

0

inicjujesz tablice filtr[][] całą wartościami 1/wk, które nigdy się w tej tablicy nie zmieniają - w takim radzie to po co ta tablica, skoro filtr[fi][fj] zawsze da wynik 1/wk ? Jest ona niepotrzebana.

lr+=r;
czyli lr = suma(r)

wr+=rfiltr[fi][fj];
czyli wr = suma(r
filtr[fi][fj]) = suma(r) * filtr[fi][fj]

RGB_Color( wr/lr,
czyli wr/lr = suma(r) * filtr[fi][fj] / suma(r) = filtr[fi][fj] - zawsze ta sama wartość 1/w*k

Licząć średnie r wokół jakiegoś piksla - zrób pętle, która zsumuje wszystkie wartości r wokół piksla, a następnie tą sume podziel przez ilość sumowanych piksli. Jeśli cały 'filtr' się nie mieści to licz średnią z piksli które się mieszczą.
Zamiast 4 zmiennych xw, yw, k, w użyj tylko dwóch np
fx - ilość piksli od środka do pionowej krawędzi
fy - ilość piksli od środka do poziomej krawędzi
wtedy współrzędna środka to 0, 0

Wyniki zapisuj w jakimś oddzielnym obrazku, bo np policzysz średnią, zpiszesz wynik w tym samym obrazku, a nastęny piksel będzi liczył śrdnią z już zmodyfikowanego fragmentu obrazka, a nie tego pierwotnego.

//pomocnicza funkcja do sumowania wartości r g b
AddRGB(TColor Color, unsigned int &r, unsigned int &g, unsigned int &b)
{
   r += Color & 0xFF;
   g += (Color  >> 8) & 0xFF;
   b += (Color  >> 16) & 0xFF;
}

...

//rozmiary filtra
const fx = 3;
const fy = 3;

//rozmiary obrazka
int width = Image1->Picture->Width;
int height = Image1->Picture->Height;

//bitmapa pomocnicza będąca kopią Image1
Graphics::TBitmap *bitmap = new Graphics::TBitmap;
bitmap->Assign(Image1->Picture->Bitmap);

//pętla po wszystkich pikslach obrazka
for(int i = 0; i < width; i++)
for(int j = 0; j < height; j++)
{
   unsigned int r = 0, g = 0, b = 0; //suma, a pozniej srednia wartosci r g b

   //liczymy mieszczące się krawędzie
   int left = max(i - fx, 0);
   int right = min(i + fx, width - 1);
   int top = max(j - fy, 0);
   int bottom = min(j + fy, height - 1);


   //pętle po mieszczących się w filtrze pikslach
   for(int x = left; x <= right; x++)
   for(int y = top; y <= bottom; y++)
   {
      AddRGB(bitmap->Canvas->Pixels[x][y], r, g, b); //sumujemy warosci r g b
   }

   //z sumy robimy śrenią
   int piksle = (right - left + 1) * (bottom - top + 1); //ilośc sumowanych piksli
   r /= piksle;
   g /= piksle;
   b /= piksle;
   Image1->Canvas->Pixels[i][j] = RGB(r, g, b);
}
delete bitmap;
0

wielkie dzieki za pomoc.. zaraz to postaram sie wdrozyc:)

0

dziala znakomicie jeszcze raz wielkie dzieki
teraz mam z kolei problem z filtrem medianowym- dziala na zasadzie takiej ze badana jest jasnosc wszystkich pixeli filtra i w miejsce aktualnego badanego wstawiana jest srodkowa wartosc filtra(w filtrze 3x3 bedzie to 5 co do jasnosci)

zrobilem to tak
[code]
void __fastcall TForm1::FiltrmedClick(TObject Sender)
{
const double fx=szer->Text.ToDouble();
const double fy=wys->Text.ToDouble();
const double n=fx
fy; //dlugosc tablicy
//rozmiary obrazka
int width = Image1->Picture->Width;
int height = Image1->Picture->Height;

//tablica ktora bedzie przechowywac pixele znajdujace sie w filtrze
TColor *tab;
tab= new TColor[n];

//bitmapa pomocnicza będąca kopią Image1
Graphics::TBitmap *bitmap = new Graphics::TBitmap;
bitmap->Assign(Image1->Picture->Bitmap);

//pętla po wszystkich pikslach obrazka
for(int i = 0; i < width; i++)
for(int j = 0; j < height; j++)
{

//liczymy mieszczące się krawędzie
int left = max(i - fx, 0);
int right = min(i + fx, width - 1);
int top = max(j - fy, 0);
int bottom = min(j + fy, height - 1);

//pętle po mieszczących się w filtrze pikslach
for(int x = left; x <= right; x++)
for(int y = top; y <= bottom; y++)
{
int tn=0;
bool ok=true;
while(ok) //wstawianie do tablicy pixeli
{
if(tab[tn])tn++ ;
else {tab[tn]=Image1->Canvas->Pixels[x][y]; ok=false;}
}
}

sort(tab,n); //sortowanie babelkowe tablicy
int srodek=n/2;
Image1->Canvas->Pixels[i][j] = tab[srodek];
}
delete bitmap;
}
[/code]

program sie kompiluje i uruchamia bez zadnych ostrzezen ale gdy probuje wywolac pojawia sie error i program sie zawiesza z tego co zrozumialem chodzi o dostep do pamieci(?) i znak stopu pojawia sie w petli for(j=0;j<height;j++)

0

o i jeszcze jedno mi sie przypomnialo:p
chodzi o ten 1 filtr: a co zrobic jak pixele w filtrze maja rozne wagi?(np srodkowy 8 a pozostale -1)
kompletnie nie mam pomyslu jak to zrealizowac...

0
nadir napisał(a)

o i jeszcze jedno mi sie przypomnialo:p
chodzi o ten 1 filtr: a co zrobic jak pixele w filtrze maja rozne wagi?(np srodkowy 8 a pozostale -1)
kompletnie nie mam pomyslu jak to zrealizowac...

int waga = ((x==i) && (y==j)) ? 8 : -1;

wartosci r, g, b zadeklaruj jako double i sumuj kolory mnożąc przez odpowiednią wage. Powstałą średnią podziel przez sume wszystkich wag.

0

ale suma wag wynosi 0 w podanym przeze mnie przykladzie... i sie nie da podzielic
(to ze suma wag jest 0 jest wymogiem filtru medianowego...)

0

mimo wszystko sprobowalem zastosowac twoja rade odnosnie tych wag zrobilem to tak

//pętle po mieszczących się w filtrze pikslach
   for(int x = left; x <= right; x++)
   for(int y = top; y <= bottom; y++)
   {
    RGB2Color(bitmap->Canvas->Pixels[x][y],r,g,b);//przypisuje r,g,b  ich wartosci z podanego pixla
    r*=filtr[x][y];
    g*=filtr[x][y];
    b*=filtr[x][y];
    AddRGB(bitmap->Canvas->Pixels[x][y],r,g,b);
    waga=((x==i) && (y==j)) ? 8 : -1;
    sumawag+=waga;
   }
    r /= sumawag;
    g /= sumawag;
    b /= sumawag;
   Image1->Canvas->Pixels[i][j] = RGB_Color(r,g,b);

i zadnych bledow kompilacji i przerywania dzialania ale obrazek robi sie caly czarny

co do tego filtru medianowego to doszedlem gdzie jest blad pamieci ale nie wiem dlaczego

// tablica na pixele
 double n=fx*fy;
 TColor *tab;
 tab= new TColor[n];
 for(int i=0;i<n;i++)tab[i]=NULL;
.....
//pętle po mieszczących się w filtrze pikslach
   for(int x = left; x <= right; x++)
   for(int y = top; y <= bottom; y++)
   {
     int tn=0;
     bool ok=false;
     while(!ok)
      {
       if(tab[tn]!=NULL)tn++ ;  //tu pojawia sie przerwanie z powodu zlego dostepu do pamieci
       else {tab[tn]=bitmap->Canvas->Pixels[x][y]; ok=true;}
      }
   }
0
adf88 napisał(a)
int waga = ((x==i) && (y==j)) ? 8 : -1;

wartosci r, g, b zadeklaruj jako double i sumuj kolory mnożąc przez odpowiednią wage. Powstałą średnią podziel przez sume wszystkich wag.

no dobra zrobilem to tak:

//pętle po mieszczących się w filtrze pikslach
   for(int x = left; x <= right; x++)
   for(int y = top; y <= bottom; y++)
   {
    RGB2Color(bitmap->Canvas->Pixels[x][y],r,g,b);
    waga=((x==i) && (y==j)) ? 8 : -1;
    r*=waga;
    g*=waga;
    b*=waga;
    fr+=r;                      //fr,fg,fb suma kolejnych r g b mnozonych przez wage
    fg+=g;
    fb+=b;
    sumawag+=waga;
   }
    fr /= sumawag;
    fg /= sumawag;
    fb /= sumawag;
   Image1->Canvas->Pixels[i][j] = RGB_Color(fr,fg,fb);

no i cale czarne to moze nie jest ale na pewno nie wyglada jak obrazek ktory filtruje...

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