Zmiana rozmiaru obrazu z interpolacją dwuliniową bez imresize

Znalazłem kilka metod powiększania obrazu, ale nie ma rozwiązania, aby zmniejszyć obraz. Obecnie używam metody najbliższego sąsiada. Jak mogę to zrobić z interpolacją dwuliniową bez użycia funkcji imresize W Matlabie?

Author: rayryeng, 2014-10-01

1 answers

W swoich komentarzach wspomniałeś, że chcesz zmienić rozmiar obrazu za pomocą interpolacji dwuliniowej. Należy pamiętać, że algorytm interpolacji dwuliniowej jest niezależny od wielkości. Możesz bardzo dobrze użyć tego samego algorytmu do powiększania obrazu, a także zmniejszania obrazu. Odpowiednie współczynniki skali do próbkowania lokalizacji w pikselach zależą od określonych wymiarów wyjściowych. To nie zmienia algorytmu rdzenia przy okazji.

Zanim zacznę z jakimkolwiek kodem, idę aby odnieść się do slajdów Richarda Alana Petersa II z interpolacją, a konkretnie slajdu # 59. Ma świetną ilustrację, a także pseudokod na temat tego, jak zrobić dwuliniową interpolację, która jest przyjazna dla MATLAB. Po tym, jak został złapany, został złapany i złapany, a następnie złapany.]}

Tutaj wpisz opis obrazka

Napiszmy funkcję, która zrobi to za nas. Ta funkcja zajmie obraz (który jest odczytywany przez imread) może to być kolor lub skala szarości, a także tablica dwóch elementów-obrazu, który chcesz zmienić rozmiar i wymiary wyjściowe w dwuelementowej tablicy ostatecznego rozmiaru obrazu, który chcesz. Pierwszym elementem tej tablicy będą wiersze, a drugim elementem tej tablicy będą kolumny. Po prostu przejdziemy przez ten algorytm i obliczymy wyjściowe wartości kolorów pikseli / skali szarości za pomocą tego pseudokodu: {]}

function [out] = bilinearInterpolation(im, out_dims)

    %// Get some necessary variables first
    in_rows = size(im,1);
    in_cols = size(im,2);
    out_rows = out_dims(1);
    out_cols = out_dims(2);

    %// Let S_R = R / R'        
    S_R = in_rows / out_rows;
    %// Let S_C = C / C'
    S_C = in_cols / out_cols;

    %// Define grid of co-ordinates in our image
    %// Generate (x,y) pairs for each point in our image
    [cf, rf] = meshgrid(1 : out_cols, 1 : out_rows);

    %// Let r_f = r'*S_R for r = 1,...,R'
    %// Let c_f = c'*S_C for c = 1,...,C'
    rf = rf * S_R;
    cf = cf * S_C;

    %// Let r = floor(rf) and c = floor(cf)
    r = floor(rf);
    c = floor(cf);

    %// Any values out of range, cap
    r(r < 1) = 1;
    c(c < 1) = 1;
    r(r > in_rows - 1) = in_rows - 1;
    c(c > in_cols - 1) = in_cols - 1;

    %// Let delta_R = rf - r and delta_C = cf - c
    delta_R = rf - r;
    delta_C = cf - c;

    %// Final line of algorithm
    %// Get column major indices for each point we wish
    %// to access
    in1_ind = sub2ind([in_rows, in_cols], r, c);
    in2_ind = sub2ind([in_rows, in_cols], r+1,c);
    in3_ind = sub2ind([in_rows, in_cols], r, c+1);
    in4_ind = sub2ind([in_rows, in_cols], r+1, c+1);       

    %// Now interpolate
    %// Go through each channel for the case of colour
    %// Create output image that is the same class as input
    out = zeros(out_rows, out_cols, size(im, 3));
    out = cast(out, class(im));

    for idx = 1 : size(im, 3)
        chan = double(im(:,:,idx)); %// Get i'th channel
        %// Interpolate the channel
        tmp = chan(in1_ind).*(1 - delta_R).*(1 - delta_C) + ...
                       chan(in2_ind).*(delta_R).*(1 - delta_C) + ...
                       chan(in3_ind).*(1 - delta_R).*(delta_C) + ...
                       chan(in4_ind).*(delta_R).*(delta_C);
        out(:,:,idx) = cast(tmp, class(im));
    end

Weź powyższy kod, skopiuj i wklej do pliku / align = "left" / Upewnij się, że zmieniłeś katalog roboczy, w którym zapisałeś ten plik.


Z Wyjątkiem sub2ind i być może meshgrid, wszystko wydaje się być zgodne z algorytmem. meshgrid jest bardzo łatwy do wyjaśnienia. Wszystko, co robisz, to określanie siatki 2D współrzędnych (x,y), gdzie każda lokalizacja na obrazie ma parę współrzędnych (x,y) lub kolumn i wierszy. Tworzenie siatki przez meshgrid unika żadnych for pętli, ponieważ wygenerujemy wszystkie odpowiednich lokalizacji pikseli z algorytmu, którego potrzebujemy, zanim przejdziemy dalej.

Jak sub2ind działa to, że zajmuje w wierszu i kolumnie lokalizacji w matrycy 2D (dobrze... może to być Dowolna Ilość wymiarów, którą chcesz), i wyświetla pojedynczy indeks liniowy. Jeśli nie wiesz, jak MATLAB indeksuje macierze, istnieją dwa sposoby uzyskania dostępu do elementu w macierzy. Możesz użyć wiersza i kolumny, aby uzyskać to, co chcesz, lub możesz użyć kolumna-główny indeks. Spójrz na poniższy przykład macierzy:

A = 

1  2  3  4  5
6  7  8  9  10
11 12 13 14 15

Jeśli chcemy uzyskać dostęp do liczby 9, możemy zrobić A(2,4) co jest tym, co większość ludzi zwykle domyślnie robi. Istnieje inny sposób dostępu do liczby 9 za pomocą pojedynczej liczby, czyli A(11)... jak to się stało? MATLAB rozkłada pamięć swoich macierzy w formacie column-major. Oznacza to, że jeśli wziąć tę macierz i złożyć wszystkie jej kolumny razem w pojedyncza tablica, wyglądałaby tak:

A = 

1
6
11
2
7
12
3
8
13
4
9
14
5
10
15

Teraz, jeśli chcesz uzyskać dostęp do elementu numer 9, musisz uzyskać dostęp do 11 elementu tej tablicy. Wracając do bitu interpolacji, sub2ind jest kluczowe, jeśli chcesz wektoryzować dostęp do elementów w obrazie, aby wykonać interpolację bez wykonywania pętli for. W związku z tym, jeśli spojrzymy na ostatnią linię pseudokodu, chcemy uzyskać dostęp do elementów w r, c, r+1 i c+1. Zauważ, że wszystkie z nich są 2D tablice , gdzie każdy element w każdej z pasujących lokalizacji we wszystkich tych tablicach mówi nam o czterech pikselach, z których musimy pobrać próbki, aby uzyskać końcowy piksel wyjściowy. Wyjście sub2indbędzie również być tablicami 2D tego samego rozmiaru co obraz wyjściowy. Kluczem jest to, że każdy element tablic 2D z r, c, r+1, i c+1 da namkolumna-główne indeksy do obrazu, do którego chcemy uzyskać dostęp, a przez wrzucenie tego jako wejście do obrazu do indeksowania, będziemy dokładnie uzyskać lokalizacje pikseli, które chcemy.


Jest kilka ważnych subtelności, które chciałbym dodać podczas implementacji algorytmu:

  1. Aby upewnić się, że indeksy, które mają uzyskać dostęp do obrazu podczas interpolacji poza obrazem, są ustawione na 1 lub liczbę wierszy lub kolumn. W rzeczywistości, jeśli rozszerzysz w prawo lub poniżej obrazu, musisz ustawić to na jeden poniżej maksimum, ponieważ interpolacja wymaga dostępu do pikseli do jednego z prawej lub poniżej. To sprawi, że będziesz nadal w granicach.

  2. Musisz również upewnić się, że obraz wyjściowy jest przypisany do tej samej klasy, co obraz wejściowy.

  3. Przebiegłem przez pętlę for, aby interpolować każdy kanał samodzielnie. Można to zrobić inteligentnie za pomocą bsxfun, ale zdecydowałem się użyć pętli for dla prostoty, i tak, że jesteś / align = "left" /


Jako przykład do pokazania tego działania, użyjmy obrazu onion.png, który jest częścią ścieżki systemowej MATLAB. Oryginalne wymiary tego obrazu to 135 x 198. Interpolujmy Ten obraz, zwiększając go do 270 x 396, który jest dwa razy większy od oryginalnego obrazu:

im = imread('onion.png');
out = bilinearInterpolation(im, [270 396]);
figure;
imshow(im);
figure;
imshow(out);

Powyższy kod interpoluje obrazek zwiększając każdy wymiar o dwa razy więcej, a następnie pokazuje rysunek z oryginalnym obrazem i kolejna postać ze skalowanym obrazem. To jest to, co dostaję za oba:

Tutaj wpisz opis obrazka

Tutaj wpisz opis obrazka


Podobnie zmniejsz obraz o połowę mniej:

im = imread('onion.png');
out = bilinearInterpolation(im, [68 99]);
figure;
imshow(im);
figure;
imshow(out);

Zauważ, że połowa 135 to 67,5 dla rzędów, ale zaokrąglam do 68. Oto co dostaję:

Tutaj wpisz opis obrazka

Tutaj wpisz opis obrazka


Jedną z rzeczy, które zauważyłem w praktyce, jest to, że upsampling z dwinearem ma przyzwoitą wydajność w porównaniu z innymi systemami, takimi jak bicubic... lub nawet Lanczos . Jednak gdy zmniejszasz obraz, ponieważ usuwasz szczegóły, najbliższy sąsiad jest bardzo wystarczający. Uważam, że dwuliniowe lub dwuliniowe to przesada. Nie jestem pewien, jaka jest Twoja aplikacja, ale pobaw się różnymi algorytmami interpolacji i zobacz, co lubisz z wyników. Bicubic to inna historia i zostawię to tobie jako ćwiczenie. Te slajdy, do których Cię skierowałem, mają materiał na interpolację bicubic, jeśli jesteś zainteresowany.


Powodzenia!
 50
Author: rayryeng,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-27 13:50:25