Chciałbym zrobić zdjęcie i zmienić skalę obrazu, podczas gdy jest to tablica numpy.
Na przykład mam ten obraz butelki coca-coli: butelka-1
Co przekłada się na numeryczną tablicę kształtów (528, 203, 3)
i chcę zmienić jej rozmiar, aby powiedzieć rozmiar tego drugiego obrazu:
butelka-2
Który ma kształt (140, 54, 3)
.
Jak zmienić rozmiar obrazu do określonego kształtu, zachowując oryginalny obraz? Inne odpowiedzi sugerują usunięcie co drugiego lub trzeciego wiersza, ale to, co chcę zrobić, to w zasadzie zmniejszyć obraz tak, jak byś to zrobił za pomocą edytora obrazów, ale w kodzie Pythona. Czy są jakieś biblioteki, które mogą to zrobić w numpy / SciPy?
Odpowiedzi:
Tak, możesz zainstalować
opencv
(jest to biblioteka używana do przetwarzania obrazu i wizji komputerowej) i używać tejcv2.resize
funkcji. I na przykład użyj:import cv2 import numpy as np img = cv2.imread('your_image.jpg') res = cv2.resize(img, dsize=(54, 140), interpolation=cv2.INTER_CUBIC)
Oto
img
tablica numpy zawierająca oryginalny obraz, podczas gdyres
tablica numpy zawierająca obraz o zmienionym rozmiarze . Ważnym aspektem jestinterpolation
parametr: istnieje kilka sposobów zmiany rozmiaru obrazu. Zwłaszcza, że zmniejszasz obraz, a rozmiar oryginalnego obrazu nie jest wielokrotnością rozmiaru obrazu o zmienionym rozmiarze. Możliwe schematy interpolacji to:Podobnie jak w przypadku większości opcji, nie ma „najlepszej” opcji w tym sensie, że dla każdego schematu zmiany rozmiaru istnieją scenariusze, w których jedna strategia może być preferowana.
źródło
dsize
powinno byćdsize=(54, 140)
tak, jak ma x, a następnie y, gdzie jako tablica numpy pokazuje kształt jako y, a następnie x (y to liczba wierszy, a x to liczba kolumn)skimage.io.imread('image.jpg')
iskimage.transform.resize(img)
. scikit-image.org/docs/dev/install.htmlChociaż może być możliwe użycie do tego samego numpy, operacja nie jest wbudowana. To powiedziawszy, możesz użyć
scikit-image
(który jest zbudowany na numpy) do wykonania tego rodzaju manipulacji obrazem.Dokumentacja dotycząca skalowania Scikit-Image jest tutaj .
Na przykład możesz wykonać następujące czynności ze swoim obrazem:
from skimage.transform import resize bottle_resized = resize(bottle, (140, 54))
To zajmie się takimi kwestiami, jak interpolacja, wygładzanie krawędzi itp.
źródło
anti_aliasing
flagą, wygląda na to, że została usunięta z najnowszej wersji 0.13.1Dla osób przybywających tutaj z Google, którzy szukają szybkiego sposobu na zmniejszenie próbkowania obrazów w
numpy
tablicach do wykorzystania w aplikacjach uczenia maszynowego, oto super szybka metoda (dostosowana stąd ). Ta metoda działa tylko wtedy, gdy wymiary wejściowe są wielokrotnością wymiarów wyjściowych.Poniższe przykłady zmniejszają rozmiar ze 128x128 do 64x64 (można to łatwo zmienić).
Kanały - ostatnie zamówienie
# large image is shape (128, 128, 3) # small image is shape (64, 64, 3) input_size = 128 output_size = 64 bin_size = input_size // output_size small_image = large_image.reshape((output_size, bin_size, output_size, bin_size, 3)).max(3).max(1)
Kanały w pierwszej kolejności
# large image is shape (3, 128, 128) # small image is shape (3, 64, 64) input_size = 128 output_size = 64 bin_size = input_size // output_size small_image = large_image.reshape((3, output_size, bin_size, output_size, bin_size)).max(4).max(2)
Dla skali szarości tylko zmianę
3
Do1
tak:Kanały w pierwszej kolejności
# large image is shape (1, 128, 128) # small image is shape (1, 64, 64) input_size = 128 output_size = 64 bin_size = input_size // output_size small_image = large_image.reshape((1, output_size, bin_size, output_size, bin_size)).max(4).max(2)
Ta metoda używa odpowiednika maksymalnej puli. To najszybszy sposób, jaki znalazłem.
źródło
np.repeat(np.repeat(a, 2, axis=0), 2, axis=1)
Jeśli ktoś przyszedł tutaj, szukając prostej metody skalowania / zmiany rozmiaru obrazu w Pythonie, bez korzystania z dodatkowych bibliotek, oto bardzo prosta funkcja zmiany rozmiaru obrazu:
#simple image scaling to (nR x nC) size def scale(im, nR, nC): nR0 = len(im) # source number of rows nC0 = len(im[0]) # source number of columns return [[ im[int(nR0 * r / nR)][int(nC0 * c / nC)] for c in range(nC)] for r in range(nR)]
Przykładowe użycie: zmiana rozmiaru obrazu (30 x 30) na (100 x 200):
import matplotlib.pyplot as plt def sqr(x): return x*x def f(r, c, nR, nC): return 1.0 if sqr(c - nC/2) + sqr(r - nR/2) < sqr(nC/4) else 0.0 # a red circle on a canvas of size (nR x nC) def circ(nR, nC): return [[ [f(r, c, nR, nC), 0, 0] for c in range(nC)] for r in range(nR)] plt.imshow(scale(circ(30, 30), 100, 200))
Wynik:
Działa to w celu zmniejszania / skalowania obrazów i działa dobrze z tablicami numpy.
źródło
imresize()
Metoda SciPy była kolejną metodą zmiany rozmiaru, ale zostanie usunięta począwszy od SciPy v 1.3.0. SciPy odnosi się do metody zmiany rozmiaru obrazu PIL :Image.resize(size, resample=0)
rozmiar - żądany rozmiar w pikselach, jako dwie krotki: (szerokość, wysokość).
resample - opcjonalny filtr ponownego próbkowania. Może to być jeden z PIL.Image.NEAREST (użyj najbliższego sąsiada), PIL.Image.BILINEAR (interpolacja liniowa), PIL.Image.BICUBIC (interpolacja sześciennego splajnu) lub PIL.Image.LANCZOS (wysokiej jakości filtr próbkujący ). W przypadku pominięcia lub jeśli obraz ma tryb „1” lub „P”, ustawiany jest PIL.Image.NEAREST.
Link tutaj: https://pillow.readthedocs.io/en/3.1.x/reference/Image.html#PIL.Image.Image.resize
źródło
Pewnie. Możesz to zrobić bez OpenCV, scikit-image lub PIL.
Zmiana rozmiaru obrazu polega w zasadzie na odwzorowaniu współrzędnych każdego piksela z oryginalnego obrazu na jego zmienioną pozycję.
Ponieważ współrzędne obrazu muszą być liczbami całkowitymi (traktuj to jak macierz), jeśli odwzorowana współrzędna ma wartości dziesiętne, należy interpolować wartość piksela, aby przybliżyć ją do pozycji całkowitej (np. Znalezienie najbliższego piksela do tej pozycji jest znane jako interpolacja najbliższego sąsiada ).
Wszystko, czego potrzebujesz, to funkcja, która wykona tę interpolację za Ciebie. SciPy ma
interpolate.interp2d
.Możesz go użyć do zmiany rozmiaru obrazu w tablicy numpy, powiedzmy
arr
w następujący sposób:W, H = arr.shape[:2] new_W, new_H = (600,300) xrange = lambda x: np.linspace(0, 1, x) f = interp2d(xrange(W), xrange(H), arr, kind="linear") new_arr = f(xrange(new_W), xrange(new_H))
Oczywiście, jeśli twój obraz jest RGB, musisz wykonać interpolację dla każdego kanału.
Jeśli chcesz dowiedzieć się więcej, polecam obejrzenie Resize Images - Computerphile .
źródło
import cv2 import numpy as np image_read = cv2.imread('filename.jpg',0) original_image = np.asarray(image_read) width , height = 452,452 resize_image = np.zeros(shape=(width,height)) for W in range(width): for H in range(height): new_width = int( W * original_image.shape[0] / width ) new_height = int( H * original_image.shape[1] / height ) resize_image[W][H] = original_image[new_width][new_height] print("Resized image size : " , resize_image.shape) cv2.imshow(resize_image) cv2.waitKey(0)
źródło
cv2
i używa właściwej funkcji zmiany rozmiaru zamiast ponownego wdrożenia „nieoptymalnej” funkcji zmiany rozmiaru, która działa gorzej niż interpolacja najbliższego sąsiada.