调整图像大小而不失真OpenCV

Tan*_*gar 28 python opencv image python-3.x

我正在使用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')
Run Code Online (Sandbox Code Playgroud)

原始图像为480 x 640(RGB因此我通过0使其变为灰度)

有没有什么方法可以调整大小并避免使用OpenCV或任何其他库的失真?我打算制作一个手写数字识别器,并且我使用MNIST数据训练了我的神经网络,因此我需要图像为28x28.

the*_*ere 60

你可以尝试下面.该功能将保持原始图像的宽高比.

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
Run Code Online (Sandbox Code Playgroud)

这是一个示例用法.

image = image_resize(image, height = 800)
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助.

  • 然后,直接使用`cv2.resize(image,(28,28),interpolation = inter)`。 (6认同)
  • @TanmayBhatnagar如果我的回答有助于解决您的问题,您还可以给我投票吗? (2认同)

Leo*_*iga 11

所有其他答案都使用 pad 来校正纵横比,当您尝试为神经网络创建标准化数据集时,这通常非常糟糕。下面是裁剪和调整大小的简单实现,它保持纵横比并且不创建焊盘。

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
Run Code Online (Sandbox Code Playgroud)

例子:

img2 = crop_square(img, 300)
Run Code Online (Sandbox Code Playgroud)

原来的:

原来的

调整大小:

在此输入图像描述

  • 我用它来将 Stylegan2-ada 调整为方形图像,谢谢它,效果太棒了! (2认同)

小智 10

在使用 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)
Run Code Online (Sandbox Code Playgroud)

用法:squared_image=get_square(image, size=(28,28))

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

希望能帮到你


And*_*tre 8

如果需要修改图像分辨率并保持宽高比,请使用函数imutils(请参阅文档)。像这样的东西:

img = cv2.imread(file , 0)
img = imutils.resize(img, width=1280)
cv2.imshow('image' , img)
Run Code Online (Sandbox Code Playgroud)

希望有帮助,祝你好运!

  • 该代码修改高度以保持纵横比相同。 (2认同)

Ale*_*nko 6

@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)
Run Code Online (Sandbox Code Playgroud)

该代码将调整图像大小,使其变为正方形并同时保持宽高比。该代码也适用于3通道(彩色)图像。用法示例:

resized = resize2SquareKeepingAspectRation(img, size, cv2.INTER_AREA)
Run Code Online (Sandbox Code Playgroud)


Raj*_*aja 5

img = cv2.resize(img, (int(img.shape[1]/2), int(img.shape[0]/2)))
Run Code Online (Sandbox Code Playgroud)

会将图像大小调整为原始大小的一半。您可以将其修改为任何其他比率。请注意,传递给 resize() 的第一个参数是 img.shape[1],而不是 img.shape[0]。这可能是违反直觉的。人们很容易忽视这种逆转并得到非常扭曲的画面。


ora*_*ips 5

与原来的问题不太相符,但我来到这里寻找类似问题的答案。

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
Run Code Online (Sandbox Code Playgroud)