Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/360.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 调整图像大小而不失真OpenCV_Python_Image_Python 3.x_Opencv - Fatal编程技术网

Python 调整图像大小而不失真OpenCV

Python 调整图像大小而不失真OpenCV,python,image,python-3.x,opencv,Python,Image,Python 3.x,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')

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

希望这有帮助。

在使用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)
用法: 平方图像=获取平方(图像,大小=(28,28))

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


希望,如果您需要修改图像分辨率并保持纵横比,这将帮助您使用该功能(查看文档)。大概是这样的:

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

希望有帮助,祝你好运

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

由于我创建了方形图像,同时保持了原始图像的纵横比。但有一个问题是,规模越小,丢失的信息就越多

512x25664x64的外观如下:

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

我修改了一点以平滑地缩小图像

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

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

提供的答案过于具体。还包括额外的不必要的填充。我建议的固定代码如下:

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)

与最初的问题并不完全一致,但我来到这里是为了寻找一个类似问题的答案

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\u height
,通过它可以计算
window\u 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方向进行裁剪(每个裁剪取决于纵横比的if比率)

def裁剪和调整大小(img、w、h):
im_h,im_w,通道=img.shape
分辨率纵横比=w/h
输入宽高比=im\u w/im\u h
如果输入纵横比>分辨率纵横比:
im_w_r=int(输入宽高比*h)
im_h_r=h
img=cv2.调整大小(img,(im_w_r,im_h_r))
x1=int((im_w_r-w)/2)
x2=x1+w
img=img[:,x1:x2,:]
如果输入纵横比<分辨率纵横比:
im_w_r=w
im\u h\u r=int(带输入/纵横比)
img=cv2.调整大小(img,(im_w_r,im_h_r))
y1=int((im_h_r-h)/2)
y2=y1+h
img=img[y1:y2,:,:]
如果输入纵横比==分辨率纵横比:
img=cv2。调整大小(img,(w,h))
返回img

所有其他答案都使用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
例如:

img2 = crop_square(img, 300)
原件:

调整大小:


在不失真的情况下,您有两个选项:a)裁剪图像的一部分,使其具有相同的纵横比。b) 将部分图像(例如黑色像素)添加到图像的侧面,使其具有相同的纵横比。如果没有相同的纵横比,你必须确保你传递的新尺寸的纵横比与原始图像相同,并确保使用合适的插值方法。我在原始图像中添加了黑色像素,使其达到640x640,但当我调整其大小时,仍然会得到扭曲的图像。我能做什么?指定插值修复它。谢谢。请确定您看到的是哪种失真。应该没有几何变形。根据调整大小所使用的方法,可能会有插值更改。如果要更改原始图像的纵横比,该怎么办?我想让每幅图像都达到28x28,不管其原始尺寸如何。然后,直接使用
cv2.resize(image,(28,28),interpolation=inter)
@TanmayBhatnagar如果我的答案有助于解决你的问题,你能给我投票吗?你能解释一下什么是插值吗?我知道这有助于减少因调整图像大小而产生的错误,但我们如何决定使用哪种技术?它只是点击和试用吗?@TanmayBhatnagar您可以参考cv2.resize上的本教程。jk没有定义感谢您@Mitali Cyrus的错误报告。我修正了。但是如何修改高度呢?代码修改高度以保持sa的纵横比
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)