[英]Resize an image without distortion OpenCV
我正在使用 python 3 和最新版本的 openCV。 我正在嘗試使用提供的調整大小功能調整圖像大小,但調整大小后圖像非常失真。 代碼 :
import cv2
file = "/home/tanmay/Desktop/test_image.png"
img = cv2.imread(file , 0)
print(img.shape)
cv2.imshow('img' , img)
k = cv2.waitKey(0)
if k == 27:
cv2.destroyWindow('img')
resize_img = cv2.resize(img , (28 , 28))
cv2.imshow('img' , resize_img)
x = cv2.waitKey(0)
if x == 27:
cv2.destroyWindow('img')
原始圖像為 480 x 640(RGB 因此我通過 0 使其變為灰度)
有什么辦法可以調整它的大小並避免使用 OpenCV 或任何其他庫的失真? 我打算制作一個手寫數字識別器,並且我已經使用 MNIST 數據訓練了我的神經網絡,因此我需要圖像為 28x28。
你可以試試下面。 該功能將保持原始圖像的縱橫比。
def image_resize(image, width = None, height = None, inter = cv2.INTER_AREA):
# initialize the dimensions of the image to be resized and
# grab the image size
dim = None
(h, w) = image.shape[:2]
# if both the width and height are None, then return the
# original image
if width is None and height is None:
return image
# check to see if the width is None
if width is None:
# calculate the ratio of the height and construct the
# dimensions
r = height / float(h)
dim = (int(w * r), height)
# otherwise, the height is None
else:
# calculate the ratio of the width and construct the
# dimensions
r = width / float(w)
dim = (width, int(h * r))
# resize the image
resized = cv2.resize(image, dim, interpolation = inter)
# return the resized image
return resized
這是一個示例用法。
image = image_resize(image, height = 800)
希望這可以幫助。
如果您需要修改圖像分辨率並保持寬高比,請使用函數imutils (查看文檔)。 像這樣的東西:
img = cv2.imread(file , 0)
img = imutils.resize(img, width=1280)
cv2.imshow('image' , img)
希望有幫助,祝你好運!
在使用 OpenCV 的 python 中嘗試這個簡單的函數。 只需傳遞圖像並提及您想要的正方形大小。
def resize_image(img, size=(28,28)):
h, w = img.shape[:2]
c = img.shape[2] if len(img.shape)>2 else 1
if h == w:
return cv2.resize(img, size, cv2.INTER_AREA)
dif = h if h > w else w
interpolation = cv2.INTER_AREA if dif > (size[0]+size[1])//2 else
cv2.INTER_CUBIC
x_pos = (dif - w)//2
y_pos = (dif - h)//2
if len(img.shape) == 2:
mask = np.zeros((dif, dif), dtype=img.dtype)
mask[y_pos:y_pos+h, x_pos:x_pos+w] = img[:h, :w]
else:
mask = np.zeros((dif, dif, c), dtype=img.dtype)
mask[y_pos:y_pos+h, x_pos:x_pos+w, :] = img[:h, :w, :]
return cv2.resize(mask, size, interpolation)
用法:squared_image=get_square(image, size=(28,28))
解釋:函數接受任何大小的輸入,並創建一個正方形的空白圖像,大小為圖像的高度或寬度,以較大者為准。 然后它將原始圖像放置在空白圖像的中心。 然后它將這個方形圖像調整為所需的大小,以便保留原始圖像內容的形狀。
希望對你有幫助
@vijay jha提供的答案過於具體。 還包括額外的不必要的填充。 我建議下面的固定代碼:
def resize2SquareKeepingAspectRation(img, size, interpolation):
h, w = img.shape[:2]
c = None if len(img.shape) < 3 else img.shape[2]
if h == w: return cv2.resize(img, (size, size), interpolation)
if h > w: dif = h
else: dif = w
x_pos = int((dif - w)/2.)
y_pos = int((dif - h)/2.)
if c is None:
mask = np.zeros((dif, dif), dtype=img.dtype)
mask[y_pos:y_pos+h, x_pos:x_pos+w] = img[:h, :w]
else:
mask = np.zeros((dif, dif, c), dtype=img.dtype)
mask[y_pos:y_pos+h, x_pos:x_pos+w, :] = img[:h, :w, :]
return cv2.resize(mask, (size, size), interpolation)
該代碼調整圖像的大小,使其成為正方形並同時保持縱橫比。 該代碼也適用於 3 通道(彩色)圖像。 使用示例:
resized = resize2SquareKeepingAspectRation(img, size, cv2.INTER_AREA)
所有其他答案都使用填充來糾正縱橫比,當您嘗試為神經網絡創建標准化數據集時,這通常是非常糟糕的。 下面是一個簡單的裁剪和調整大小的實現,它保持縱橫比並且不創建填充。
def crop_square(img, size, interpolation=cv2.INTER_AREA):
h, w = img.shape[:2]
min_size = np.amin([h,w])
# Centralize and crop
crop_img = img[int(h/2-min_size/2):int(h/2+min_size/2), int(w/2-min_size/2):int(w/2+min_size/2)]
resized = cv2.resize(crop_img, (size, size), interpolation=interpolation)
return resized
例子:
img2 = crop_square(img, 300)
原來的:
調整大小:
與原始問題的要求不太一致,但我來到這里尋找類似問題的答案。
import cv2
def resize_and_letter_box(image, rows, cols):
"""
Letter box (black bars) a color image (think pan & scan movie shown
on widescreen) if not same aspect ratio as specified rows and cols.
:param image: numpy.ndarray((image_rows, image_cols, channels), dtype=numpy.uint8)
:param rows: int rows of letter boxed image returned
:param cols: int cols of letter boxed image returned
:return: numpy.ndarray((rows, cols, channels), dtype=numpy.uint8)
"""
image_rows, image_cols = image.shape[:2]
row_ratio = rows / float(image_rows)
col_ratio = cols / float(image_cols)
ratio = min(row_ratio, col_ratio)
image_resized = cv2.resize(image, dsize=(0, 0), fx=ratio, fy=ratio)
letter_box = np.zeros((int(rows), int(cols), 3))
row_start = int((letter_box.shape[0] - image_resized.shape[0]) / 2)
col_start = int((letter_box.shape[1] - image_resized.shape[1]) / 2)
letter_box[row_start:row_start + image_resized.shape[0], col_start:col_start + image_resized.shape[1]] = image_resized
return letter_box
img = cv2.resize(img, (int(img.shape[1]/2), int(img.shape[0]/2)))
將圖像大小調整為原始大小的一半。 您可以將其修改為任何其他比率。 請注意,傳遞給 resize() 的第一個參數是 img.shape[1],而不是 img.shape[0]。 這可能違反直覺。 很容易忽略這種反轉並得到非常扭曲的畫面。
我在為神經網絡准備數據集時遇到了同樣的問題,為了避免扭曲圖像,我制作了一個函數,可以最小化調整和裁剪圖像以適應目標大小。 它首先通過比較輸入圖像的縱橫比與目標縱橫比來選擇是在 y 還是在 x 中裁剪。 然后它將輸入圖像的大小調整為目標寬度或高度,然后在 x 或 y 中裁剪(每個取決於縱橫比的比例)。
def crop_and_resize(img, w, h):
im_h, im_w, channels = img.shape
res_aspect_ratio = w/h
input_aspect_ratio = im_w/im_h
if input_aspect_ratio > res_aspect_ratio:
im_w_r = int(input_aspect_ratio*h)
im_h_r = h
img = cv2.resize(img, (im_w_r , im_h_r))
x1 = int((im_w_r - w)/2)
x2 = x1 + w
img = img[:, x1:x2, :]
if input_aspect_ratio < res_aspect_ratio:
im_w_r = w
im_h_r = int(w/input_aspect_ratio)
img = cv2.resize(img, (im_w_r , im_h_r))
y1 = int((im_h_r - h)/2)
y2 = y1 + h
img = img[y1:y2, :, :]
if input_aspect_ratio == res_aspect_ratio:
img = cv2.resize(img, (w, h))
return img
我有一個手繪數據集,我需要從不對稱的圖紙中創建小方形圖像。
感謝@vijay jha ,我在保持原始圖像縱橫比的同時創建了方形圖像。 一個問題是,你縮小的越多,丟失的信息就越多。
512x256到64x64看起來像這樣:
我修改了一些原始代碼以平滑縮小圖像。
from skimage.transform import resize, pyramid_reduce
def get_square(image, square_size):
height, width = image.shape
if(height > width):
differ = height
else:
differ = width
differ += 4
# square filler
mask = np.zeros((differ, differ), dtype = "uint8")
x_pos = int((differ - width) / 2)
y_pos = int((differ - height) / 2)
# center image inside the square
mask[y_pos: y_pos + height, x_pos: x_pos + width] = image[0: height, 0: width]
# downscale if needed
if differ / square_size > 1:
mask = pyramid_reduce(mask, differ / square_size)
else:
mask = cv2.resize(mask, (square_size, square_size), interpolation = cv2.INTER_AREA)
return mask
512x256 -> 64x64
512x256 -> 28x28
代碼被賦予一個window_height
,通過它計算window_width
變量,同時保持圖像的縱橫比。 為了防止它發生任何扭曲。
import cv2
def resize(self,image,window_height = 500):
aspect_ratio = float(image.shape[1])/float(image.shape[0])
window_width = window_height/aspect_ratio
image = cv2.resize(image, (int(window_height),int(window_width)))
return image
img = cv2.imread(img_source) #image location
img_resized = resize(img,window_height = 800)
cv2.imshow("Resized",img_resized)
cv2.waitKey(0)
cv2.destroyAllWindows()
來自Pillow
lib 的簡單和最有效的方法
這里的width
或height
將是400
from PIL import Image
imgPath = './forest.jpg'
img = Image.open(imgPath)
print('The size of img is: ', img.size)
print('After applying thumbnail() function')
img.thumbnail((400, 400))
img.save('image_thumbnail.jpg')
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.