Saya ingin mengambil gambar dan mengubah skala gambar, sementara itu adalah larik numpy.
Misalnya saya punya gambar botol coca-cola: botol-1
Yang diterjemahkan menjadi array bentuk numpy (528, 203, 3)
dan saya ingin mengubah ukurannya untuk mengatakan ukuran gambar kedua ini:
bottle-2
Yang memiliki bentuk (140, 54, 3)
.
Bagaimana cara mengubah ukuran gambar ke bentuk tertentu dengan tetap mempertahankan gambar aslinya? Jawaban lain menyarankan untuk menghapus setiap baris lain atau ketiga, tetapi yang ingin saya lakukan pada dasarnya adalah mengecilkan gambar seperti yang Anda lakukan melalui editor gambar tetapi dalam kode python. Apakah ada perpustakaan untuk melakukan ini di numpy / SciPy?
Jawaban:
Ya, Anda dapat menginstal
opencv
(ini adalah pustaka yang digunakan untuk pemrosesan gambar, dan computer vision), dan menggunakancv2.resize
fungsinya. Dan misalnya penggunaan:import cv2 import numpy as np img = cv2.imread('your_image.jpg') res = cv2.resize(img, dsize=(54, 140), interpolation=cv2.INTER_CUBIC)
Berikut
img
adalah larik numpy yang berisi gambar asli, sedangkanres
larik numpy berisi gambar yang diubah ukurannya . Aspek penting adalahinterpolation
parameter: ada beberapa cara bagaimana mengubah ukuran gambar. Terutama karena Anda memperkecil gambar, dan ukuran gambar asli bukanlah kelipatan dari ukuran gambar yang diubah ukurannya. Skema interpolasi yang mungkin adalah:Seperti kebanyakan opsi, tidak ada opsi "terbaik" dalam arti bahwa untuk setiap skema pengubahan ukuran, terdapat skenario di mana satu strategi dapat lebih disukai daripada yang lain.
sumber
dsize
harus dilakukandsize=(54, 140)
dengan x lalu y, di mana array numpy menunjukkan bentuk sebagai y lalu x (y adalah jumlah baris dan x adalah jumlah kolom)skimage.io.imread('image.jpg')
danskimage.transform.resize(img)
. scikit-image.org/docs/dev/install.htmlMeskipun dimungkinkan untuk menggunakan numpy sendiri untuk melakukan ini, operasinya tidak built-in. Meskipun demikian, Anda dapat menggunakan
scikit-image
(yang dibangun di atas numpy) untuk melakukan manipulasi gambar semacam ini.Dokumentasi penskalaan Scikit-Image ada di sini .
Misalnya, Anda dapat melakukan hal berikut dengan gambar Anda:
from skimage.transform import resize bottle_resized = resize(bottle, (140, 54))
Ini akan menangani hal-hal seperti interpolasi, anti-aliasing, dll. Untuk Anda.
sumber
anti_aliasing
benderanya, sepertinya itu telah dihapus dari versi terbaru 0.13.1Bagi orang yang datang ke sini dari Google mencari cara cepat untuk menurunkan sampel gambar dalam
numpy
array untuk digunakan dalam aplikasi Machine Learning, berikut adalah metode super cepat (diadaptasi dari sini ). Metode ini hanya berfungsi jika dimensi masukan adalah kelipatan dari dimensi keluaran.Contoh berikut menurunkan sampel dari 128x128 menjadi 64x64 (ini dapat dengan mudah diubah).
Saluran pemesanan terakhir
# 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)
Saluran pemesanan pertama
# 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)
Untuk gambar grayscale ubah saja
3
menjadi1
seperti ini:Saluran pemesanan pertama
# 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)
Metode ini menggunakan penggabungan maksimal yang setara. Ini cara tercepat untuk melakukan ini yang saya temukan.
sumber
np.repeat(np.repeat(a, 2, axis=0), 2, axis=1)
Jika ada yang datang ke sini mencari metode sederhana untuk menskalakan / mengubah ukuran gambar dengan Python, tanpa menggunakan pustaka tambahan, berikut adalah fungsi pengubahan ukuran gambar yang sangat sederhana:
#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)]
Contoh penggunaan: mengubah ukuran gambar (30 x 30) menjadi (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))
Keluaran:
Ini berfungsi untuk mengecilkan / menskalakan gambar, dan berfungsi dengan baik dengan array numpy.
sumber
imresize()
Metode SciPy adalah metode pengubahan ukuran lainnya, tetapi akan dihapus mulai dengan SciPy v 1.3.0. SciPy mengacu pada metode pengubahan ukuran gambar PIL :Image.resize(size, resample=0)
size - Ukuran yang diminta dalam piksel, sebagai 2-tuple: (lebar, tinggi).
resample - Filter resampling opsional. Ini dapat berupa salah satu PIL.Image.NEAREST (gunakan tetangga terdekat), PIL.Image.BILINEAR (interpolasi linier), PIL.Image.BICUBIC (interpolasi spline kubik), atau PIL.Image.LANCZOS (filter downsampling berkualitas tinggi ). Jika dihilangkan, atau jika gambar memiliki mode "1" atau "P", ini disetel PIL.Image.NEAREST.
Tautkan di sini: https://pillow.readthedocs.io/en/3.1.x/reference/Image.html#PIL.Image.Image.resize
sumber
Tentu. Anda dapat melakukan ini tanpa OpenCV, scikit-image atau PIL.
Pengubahan ukuran gambar pada dasarnya memetakan koordinat setiap piksel dari gambar asli ke posisinya yang diubah ukurannya.
Karena koordinat gambar harus berupa bilangan bulat (anggap saja sebagai matriks), jika koordinat yang dipetakan memiliki nilai desimal, Anda harus menginterpolasi nilai piksel untuk memperkirakannya ke posisi bilangan bulat (misalnya mendapatkan piksel terdekat ke posisi itu diketahui sebagai interpolasi tetangga terdekat ).
Yang Anda butuhkan hanyalah fungsi yang melakukan interpolasi ini untuk Anda. SciPy memiliki
interpolate.interp2d
.Anda dapat menggunakannya untuk mengubah ukuran gambar dalam larik numpy, katakanlah
arr
, sebagai berikut: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))
Tentu saja, jika gambar Anda RGB, Anda harus melakukan interpolasi untuk setiap saluran.
Jika Anda ingin memahami lebih lanjut, saya sarankan menonton Resizing Images - Computerphile .
sumber
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)
sumber
cv2
dan menggunakan fungsi pengubahan ukuran yang tepat alih-alih menerapkan ulang fungsi pengubahan ukuran "sub-optimal" yang lebih buruk daripada interpolasi tetangga terdekat.