不失真调整图像大小

我使用的是 python3和 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')

原始图像是480x640(RGB,因此我通过0得到它的灰度)

有没有办法我可以调整它的大小,避免失真使用 OpenCV 或任何其他库也许?我打算做一个手写数字识别器,我已经训练了我的神经网络使用 MNIST 的数据,因此我需要的图像是28x28。

160333 次浏览

您可以在下面尝试。该函数将保持原始图像的纵横比率。

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)

希望这个能帮上忙。

在使用 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))

解释: 函数接受任意大小的输入,并创建一个大小图像的高度或宽度的平方形空白图像。 然后将原始图像放在空白图像的中心。然后将正方形图像调整为所需的大小,以保留原始图像内容的形状。

Hope 这个能帮到你

如果需要修改图像分辨率并保持高宽比,可以使用函数 伊莫提斯(检查文档)。像这样:

img = cv2.imread(file , 0)
img = imutils.resize(img, width=1280)
cv2.imshow('image' , img)

希望能有所帮助,祝你好运!

我有一个手绘图的数据集,我需要从非对称绘图创建小方形图像。

enter image description here

由于 @ vijay jha我创建了 正方形图像,同时保持原始图像的纵横比。不过有一个问题是,缩放得越小,丢失的信息就越多。

512x256 对于 64x64来说是这样的:

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

enter image description here

512x256-> 28x28

enter image description here

img = cv2.resize(img, (int(img.shape[1]/2), int(img.shape[0]/2)))

将图像的大小调整为原始大小的一半。您可以修改它为任何其他比率。 请注意,传递给 resize ()的第一个参数是 img.form [1] ,而不是 img.form [0]。这可能有悖常理。很容易忽略这种反转,得到一个非常扭曲的图片。

@ 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)

并不完全符合原来的问题是问,但我降落在这里寻找一个类似问题的答案。

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

该代码给出了一个 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()

我在为神经网络准备数据集时也遇到了同样的问题,为了避免图像失真,我设计了一个函数,可以调整图像的大小,最小限度地裁剪图像以适应目标大小。它首先通过比较输入图像长宽比和目标长宽比来选择是在 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

所有其他的答案使用垫纠正纵横比通常是非常糟糕的,当您试图创建一个神经网络的标准化数据集。下面是一个简单的裁剪和调整大小的实现,它保持了高宽比,并且没有创建补丁。

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)

原文:

Original

调整:

enter image description here

来自 Pillow库的简单而有效的方法
这里,无论是 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')