Znalazłem kilka metod powiększania obrazu, ale nie ma możliwości zmniejszenia obrazu. Obecnie używam metody najbliższego sąsiada. Jak to zrobić z interpolacją dwuliniową bez korzystania z funkcji imresize
w programie MATLAB?Zmienianie rozmiaru obrazu za pomocą interpolacji dwuliniowej bez wymazywania
Odpowiedz
W swoich komentarzach wspomniałeś, że chciałeś zmienić rozmiar obrazu za pomocą interpolacji dwuliniowej. Należy pamiętać, że dwuwymiarowy algorytm interpolacji jest niezależny od rozmiaru. Możesz bardzo dobrze wykorzystać ten sam algorytm do powiększania obrazu i zmniejszania obrazu. Odpowiednie współczynniki skalowania do lokalizacji pikseli zależą od podanych wymiarów wyjściowych. Ten nie zmienia w żaden sposób algorytmu rdzeniowego.
Zanim zacznę od jakiegokolwiek kodu, zamierzam skierować cię do Richard Alan Peters' II digital image processing slides on interpolation, w szczególności slajdu # 59. Ma świetną ilustrację oraz pseudokod na temat interpolacji dwuliniowej, która jest przyjazna dla MATLAB. Aby być samowystarczalny, mam zamiar to jego slajd tu więc możemy podążać i kod go:
Napiszmy funkcję, która zrobi to za nas. Ta funkcja pobiera obraz (odczytany przez imread
), który może mieć kolor lub skalę szarości, a także tablicę złożoną z dwóch elementów - Obraz, który ma zostać zmieniony, oraz wymiary wyjściowe w dwuelementowej tablicy ostateczny obraz, który chcesz zmienić. Pierwszym elementem tej tablicy będą wiersze, a drugim elementem tej tablicy będą kolumny. Będziemy po prostu przejść przez ten algorytm i obliczyć wartości kolorów piksela wyjściowego/w skali szarości przy użyciu tego Pseudokod:
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
Take powyższy kod, skopiuj i wklej go do pliku o nazwie bilinearInterpolation.m
i zapisz go. Upewnij się, że zmieniłeś katalog roboczy, w którym zapisałeś ten plik.
wyjątkiem sub2ind
a może meshgrid
, wszystko wydaje się być zgodne z algorytmem. meshgrid
jest bardzo łatwy do wytłumaczenia. Wszystko, co robisz, to określanie współrzędnych 2D o współrzędnych (x,y)
, gdzie każda lokalizacja na obrazku ma parę (x,y)
lub współrzędnych kolumny i wiersza. Tworzenie siatki przez meshgrid
pozwala uniknąć pętli for
, ponieważ będziemy generować wszystkie właściwe lokalizacje pikseli z algorytmu, który jest nam potrzebny, zanim będziemy kontynuować.
Jak sub2ind
dzieła jest to, że odbywa się w miejscu wiersza i kolumny w matrycy 2D (no ... to może być naprawdę dowolny ilość wymiarów chcesz), a to generuje pojedynczy indeks liniowej. Jeśli nie wiesz, w jaki sposób MATLAB indeksuje do macierzy, 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ć indeksu kolumna-major. Spójrz na ten przykład macierzy Mam poniżej:
A =
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
Jeśli chcemy uzyskać dostęp do numeru 9, możemy zrobić A(2,4)
który jest co większość ludzi zazwyczaj domyślnie. Istnieje inny sposób uzyskania dostępu do numeru 9 za pomocą jednego numeru, który jest A(11)
... jak to się dzieje? MATLAB określa pamięć swoich matryc w formacie kolumna-major.Oznacza to, że jeśli były do podjęcia tej matrycy i stack wszystkich swoich kolumn razem w jednej tablicy, to będzie wyglądać następująco:
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, byś Potrzebuję dostępu do 11 elementu tej tablicy. Powrót do bitu interpolacji, sub2ind
ma kluczowe znaczenie, jeśli chcesz uzyskać dostęp do elementów w obrazie w celu utworzenia interpolacji bez wykonywania pętli for
. W związku z tym, jeśli spojrzysz na ostatni wiersz pseudokodu, chcemy uzyskać dostęp do elementów pod r
, c
, r+1
i c+1
. Zauważ, że wszystkie z nich to tablice 2D, gdzie każdy element w każdej z pasujących lokalizacji we wszystkich tych tablicach informuje nas o czterech pikselach, z których musimy pobrać próbki, aby uzyskać końcowy piksel wyjściowy. Dane wyjściowe z sub2ind
będą również tablicami 2D o tym samym rozmiarze co obraz wyjściowy. Kluczem tutaj jest to, że każdy element 2D tablice r
, c
, r+1
i c+1
da nam kolumny główne indeksy do obrazu, który chcemy uzyskać dostęp, a rzucając to jako wkład do obrazu do indeksowania , otrzymamy dokładnie te lokalizacje pikseli, które chcemy.
Istnieje kilka ważnych subtelności, które chciałbym dodać podczas realizacji algorytmu:
Musisz upewnić się, że wszelkie indeksy dostępu do obrazu podczas interpolacji poza obrazem są albo ustaw na 1 lub liczbę wierszy lub kolumn, aby upewnić się, że nie wyjdziesz poza granice. W rzeczywistości, jeśli rozciągasz się w prawo lub pod obrazem, musisz ustawić tę wartość na jedną poniżej na maksimum, ponieważ interpolacja wymaga dostępu do pikseli do jednego z prawej lub poniżej. Zapewni to, że nadal jesteś w granicach.
Należy również upewnić się, że obraz wyjściowy jest rzutowany na tę samą klasę, co obraz wejściowy.
Przebiegłem pętlę
for
, aby interpolować każdy kanał na własną rękę. Możesz to zrobić inteligentnie, używającbsxfun
, ale zdecydowałem się użyć pętlifor
dla uproszczenia, abyś mógł podążać za algorytmem.
Jako przykład, aby pokazać to działa, użyjmy onion.png
obraz, który jest częścią ścieżki systemowej Matlaba. Oryginalne wymiary tego obrazu to 135 x 198
. Załóżmy interpolacji tego obrazu przez co większe, będzie 270 x 396
który jest dwukrotnie większy od oryginalnego obrazu:
im = imread('onion.png');
out = bilinearInterpolation(im, [270 396]);
figure;
imshow(im);
figure;
imshow(out);
Powyższy kod interpolacji obrazu poprzez zwiększenie każdy wymiar przez dwa razy tyle, a następnie przedstawiają postać z oryginalny obraz i inna postać ze skalowanym obrazem.To, co mam do obu:
Podobnie, niech zmniejszyć obraz w dół o połowę za dużo:
im = imread('onion.png');
out = bilinearInterpolation(im, [68 99]);
figure;
imshow(im);
figure;
imshow(out);
Należy zauważyć, że połowa z 135 67,5 dla wierszy, ale zaokrąglono do 68. Otrzymuję:
Jedno zauważyłem jest to, że w praktyce z Upsampling bilinear ma przyzwoitą wydajność w porównaniu do innych systemów, takich jak bicubic ... lub nawet Lanczos. Jednak podczas zmniejszania obrazu, ponieważ usuwasz szczegóły, najbliższy sąsiad jest bardzo wystarczający. Uważam, że bilinear lub bicubic to przesada. Nie jestem pewien co to jest twoja aplikacja, ale korzystaj z różnych algorytmów interpolacji i zobacz, co ci się podoba w wynikach. Bicubic to kolejna historia, a ja zostawię to jako ćwiczenie. Te slajdy, do których cię poleciłem, mają materiał na temat interpubacji bikubicznej, jeśli jesteś zainteresowany.
Powodzenia!
możesz wyjaśnić sub2ind ([in_rows, in_cols], r, c); ... Dziękuję bardzo! – teardrop
@teardrop - będę edytować mój post, aby dać ci bardziej szczegółowe wyjaśnienie, co robi 'sub2ind'. – rayryeng
Wykłady (Richard Alan Peters II) są świetne. Ten link jednak już nie działa. Znalazłem slajdy [tutaj] (https://archive.org/details/Lectures_on_Image_Processing). Pokazany slajd pojawia się w 15. wykładzie, slajd numer 58. – ADB
- 1. Rozmiar obrazu ImageMagick bez interpolacji
- 2. Zmiana rozmiaru obrazu warunkowego za pomocą Carrierwave
- 3. Zmiana rozmiaru obrazu za pomocą C#
- 4. Automatyczne zmienianie rozmiaru obrazu na podstawie wymiarów okna przeglądarki
- 5. jak wykonać automatyczne zmienianie rozmiaru obrazu w Pythonie3 za pomocą PyGI?
- 6. Zmienianie rozmiaru UIViews
- 7. przeciąganie i zmienianie rozmiaru obrazu na płótnie html5
- 8. Zmienianie rozmiaru wysokości komórki tabeli zgodnie z pobraną wysokością obrazu
- 9. Ręczne zmienianie rozmiaru pliku JPanel
- 10. Niepotrzebne zmienianie rozmiaru okna formularza
- 11. Dynamiczne zmienianie rozmiaru okna JQuery
- 12. Wyłącz Zmienianie rozmiaru okna przeglądarki
- 13. Zmiana rozmiaru obrazu płótno bez rozmycia to
- 14. Wstawianie obrazu do DocX za pomocą OpenXML i ustawianie rozmiaru
- 15. Zmiana rozmiaru obrazu za pomocą PIL zmienia kolory drastycznie
- 16. bash multiline ciąg bez interpolacji
- 17. IOS: Zmniejszenie rozmiaru obrazu bez obniżania jakości obrazu
- 18. Zmienianie rozmiaru okna wpf programowo w C#
- 19. Zastępowanie elementów w wektorze za pomocą wymazywania i wstawiania
- 20. Przesunięcie zawartości obrazu za pomocą OpenCV
- 21. iPhone: Zmienianie CGImageAlphaInfo obrazu CGImage
- 22. Zmienianie przekątnych macierzy za pomocą Mathematica
- 23. Zmienianie koloru zaznaczenia tekstu za pomocą CSS?
- 24. Zmienianie przestrzeni nazw XML za pomocą Scala
- 25. Zmienianie kolorów linii za pomocą ggplot()
- 26. Ukrywanie tekstu Zmienianie rozmiaru uchwytu w Safari
- 27. IFrame Zmiana rozmiaru obrazu
- 28. C# WinForm, bez strzałki zmiany rozmiaru za pomocą GrowAndShrink
- 29. obracanie obrazu za pomocą css
- 30. Facebook - Zmienianie podpisu pod zdjęciem za pomocą wykresu api
trzeba to zrobić bez korzystania z określonej funkcji? twoim najlepszym podejściem byłoby kodowanie interpolacji biliniowej lub bikubicznej, a następnie tworzenie obrazów. W przeciwnym razie można zginąć piramidalny jist, wykonując połowę obrazu: img = img (1: 2: koniec, 1: 2: koniec) –
Jak to zrobić z interpolacją dwu liniową? – teardrop
Interpolacja dwuliniowa jest dość łatwa do zakodowania. Google trochę i możesz wiedzieć, jak to zakodować. Po uzyskaniu interpolacji, po prostu uzyskaj wartości obrazu. –