interpolacja dwuliniowa - warunki brzegowe

0

witam

mam algorytm na powiększania obrazów interpolacją dwuliniową jednak pewna kwestia nie daje mi spokoju. I nie rozumiem, dlaczego tak jest rozwiązywana. Chodzi o krawędź dolną i prawą.

Otóż przypuśćmy, że mój obraz źródłowy wygląda tak:
3 6
8 4
Powiększe go x2
3 . 6 .
. . . .
8 . 4 .

  • . . .
    I teraz wg. moich obliczeń piksel * powinien przyjąć wartość 4 gdyż:
for (j=0; j<Image2->Height; j++)
    {
      for (i=0; i<Image2->Width; i++)
        {
         x = i*ratiox;
         y = j*ratioy;

         (int)ix = x;         (int)iy = y;
         fx = x - ix;    fy = y - iy;

         p1 = GetRValue(Image1->Canvas->Pixels[ix][iy]);
         p2 = GetRValue(Image1->Canvas->Pixels[ix+1][iy]);
         p3 = GetRValue(Image1->Canvas->Pixels[ix][iy+1]);
         p4 = GetRValue(Image1->Canvas->Pixels[ix+1][iy+1]);

         kolor=((1.0-fx)*(1.0-fy)*p1+(fx)*(1.0-fy)*p2
                    +(1.0-fx)*    (fy)*p3+(fx)*    (fy)*p4);

na podstawie kodu:
ratiox i ratioy=1/2
j=3;
i=0;
x=0; ix=0; fx=0;
y=3/2; iy=1; fy=1/2;
p1=8; p2=4; p3=0; p4=0;
(1-0)(1-1/2)8+0(1-1/2)p2+(1-0)1/20+01/20=4

Wyżej pokazałem, że można obliczyć na krawędziach piksele. Program natomiast tą krawędź (dolna) nie obliczy. To samo tyczy się krawędzi prawej.
Wynik działania programu. (strzałki wskazują nieobliczone piksele) :
user image
Bardzo proszę o pomoc

0

Nie chce Cie w blad wprowadzic, ale czy na pewno metoda Height i Width okresla wysokosc i szerokosc ekranu, czy polozenie ostatniego piksela na osi liczac od 0, bo jesli tak to daj w petlach <=.

0

tak. Height i Width określa położenie ostatniego piksela na osi licząc od 0. Jednak wprowadzenie "<=" nie przyniosło żadnych zmian... Nadal program nie oblicza krawędzi mimo, że rozpisując kod ręcznie powinny pojawić się w tych miejscach piksele.

0

width - 1 i height - 1, przy okazji pozbedziesz sie (prawdopodobnego) problemu bo interpolujac probojesz odczytac pixel o wspolrzednych poza granicami obrazka

0

niestety nie pomogło.
Tak. Wg. powyższych moich obliczeń które tu zamieściłem odczytuje piksele poza granicami obrazka. Są to piksele p3 i p4. Jednak p1=8 który również odczytam wg. obliczeń powinien wystarczyć by w miejscu * wpisać piksel o jasności 4. Program niestety tego nie oblicza. A dlaczego? No właśnie chciałbym się dowiedzieć...

Przedstawie jeszcze raz powyższy przykład i metodę jego obliczenia dokładniej ponieważ zależy mi by się dowiedzieć co jest nie tak. Dlaczego nie ma pikseli na krawędziach mimo tego, że jest możliwość ich obliczenia.

Mam obraz źródłowy(image1) wielkości 3x3 powiększam go do rozmiarów 6x6(image2) czyli x2 w takim razie ratiox i ratioy wynosi 0,5 gdyż (kawałek kodu nie zamieszczonego wcześniej)
ratiox = (Image1->Width1.0)/(Image2->Width1.0);
ratioy = (Image1->Height1.0)/(Image2->Height1.0);

user image

Powiedzmy, że chce obliczyć piksel * na dolnej krawędzi
Analizując krok po kroku kod:

Szukany piksel * dla j-Height przyjmuje współrzędną =5 a dla i-Width= 2

Teraz
x=20,5=1
y=5
0,5=5/2
ix=1
iy=2
fx=1-1=0
fy=5/2-2=0,5
p1=odczytuje z image1(obrazu 3x3) wartośc piksela dla współrzędnych ix=1 i iy=2 – będzie to 16
p2=dla p2 ix=2 iy=2 czyli mamy wartość 5
p3=ix=1 a iy=3 czyli nie ma – wartość poza obrazem czyli 0
p4=również 0

Mając wszystkie dane można przystąpić do obliczenia szukanej jasności piksela
= (1-0)(1-0,5)16 + 0(1-0,5)5 + (1-0)0,50 + 00,50 = 8
Wartość szukana wynosi 8. Jak widać jestem w stanie to rozpisać, program niestety nie potrafi wpisać wartości na tej krawędzi (dolnej) i prawej(analogiczna sytuacja)

Może ktoś potrafi spojrzeć na problem z innej strony. Drugi dzień nad tym siedzę i nie rozumiem dlaczego.

//// albo jest na to inne wyjście
ostatnich krawędzi nie liczy ponieważ do niej nie dochodzi(dolna i prawa)
a to może przed ostatnią liczy tak jak wyjaśniłem powyżej. Dlatego na rysunku w pierwszym poście widać ostatnią krawedz nie policzoną a przed ostatnią taką jakąś jasniejszą. (???) Bo chyba dobrze rozpisałem proces działanie tego algorytmu na przykładzie ?!

0

Czy ty nie widzisz problemu polegającym na złym podejściu?
Formalnie rzecz biorąc to tak naprawdę to jest problem brzegowy dla wszystkich krawędzi. Uprościłeś sobie transformację współrzędnych, więc masz wrażenie, że problem występuje jedynie na dwóch krawędziach.
Prawda jest taka, że dla krawędzi powinieneś mieć osobny kod uwzględniający warunki brzegowe. Najprościej założyć, że piksele na krawędzi obrazu wyjściowego rozciągają się do nieskończoności poza obraz. Bardziej zaawansowane rozwiązanie polegałoby na dopasowaniu wielomianu do pikseli na krawędzi i na tej podstawie interpolować brakujące piksele.

Tu masz proste rozwiązanie:

for (j=0; j<Image2->Height; j++)
    {
      for (i=0; i<Image2->Width; i++)
        {
         double x = (i-0.5)*ratiox; // piksele są przesunięte lekko, więc problem brzegowy równo się rozkłada dookoła obrazu
         double y = (j-0.5)*ratioy;

         int ix = x;
         int iy = y;
         int ix1 = ix+1;
         int iy1 = iy+1;

// sprawdzenie warunków brzegowych
         ix = max(ix,0);
         iy = max(iy,0);
         ix = min(ix,Image1->Width-1);
         iy = min(iy,Image1->Height-1);

         p1 = GetRValue(Image1->Canvas->Pixels[ix][iy]);
         p2 = GetRValue(Image1->Canvas->Pixels[ix1][iy]);
         p3 = GetRValue(Image1->Canvas->Pixels[ix][iy1]);
         p4 = GetRValue(Image1->Canvas->Pixels[ix1][iy1]);

         fx = x - ix;    fy = y - iy;

         kolor=((1.0-fx)*(1.0-fy)*p1+(fx)*(1.0-fy)*p2
                    +(1.0-fx)*    (fy)*p3+(fx)*    (fy)*p4);

         ....
   }
0

okej. dzięki za odpowiedź. Rozumiem zasadę.
To w takim razie co robi mój program na tych brzegach(dolny,prawy) skoro nie oblicza w tym miejscu pikseli? Jak to się dzieje, że je pomija całkowicie?

Bo przecież niby się da:
user image
Jest to zanalizowane prawidłowo?

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