Numpy Resize/Rescale Image

后端 未结 7 2052
轻奢々
轻奢々 2020-12-02 06:38

I would like to take an image and change the scale of the image, while it is a numpy array.

For example I have this image of a coca-cola bottle: bottle-1

Whi

相关标签:
7条回答
  • 2020-12-02 06:46

    Are there any libraries to do this in numpy/SciPy

    Sure. You can do this without OpenCV, scikit-image or PIL.

    Image resizing is basically mapping the coordinates of each pixel from the original image to its resized position.

    Since the coordinates of an image must be integers (think of it as a matrix), if the mapped coordinate has decimal values, you should interpolate the pixel value to approximate it to the integer position (e.g. getting the nearest pixel to that position is known as Nearest neighbor interpolation).

    All you need is a function that does this interpolation for you. SciPy has interpolate.interp2d.

    You can use it to resize an image in numpy array, say arr, as follows:

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

    Of course, if your image is RGB, you have to perform the interpolation for each channel.

    If you would like to understand more, I suggest watching Resizing Images - Computerphile.

    0 讨论(0)
  • 2020-12-02 06:55

    For people coming here from Google looking for a fast way to downsample images in numpy arrays for use in Machine Learning applications, here's a super fast method (adapted from here ). This method only works when the input dimensions are a multiple of the output dimensions.

    The following examples downsample from 128x128 to 64x64 (this can be easily changed).

    Channels last ordering

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

    Channels first ordering

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

    For grayscale images just change the 3 to a 1 like this:

    Channels first ordering

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

    This method uses the equivalent of max pooling. It's the fastest way to do this that I've found.

    0 讨论(0)
  • 2020-12-02 06:56

    If anyone came here looking for a simple method to scale/resize an image in Python, without using additional libraries, here's a very simple image resize function:

    #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)]
    

    Example usage: resizing a (30 x 30) image to (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))
    

    Output:

    This works to shrink/scale images, and works fine with numpy arrays.

    0 讨论(0)
  • 2020-12-02 07:00

    While it might be possible to use numpy alone to do this, the operation is not built-in. That said, you can use scikit-image (which is built on numpy) to do this kind of image manipulation.

    Scikit-Image rescaling documentation is here.

    For example, you could do the following with your image:

    from skimage.transform import resize
    bottle_resized = resize(bottle, (140, 54))
    

    This will take care of things like interpolation, anti-aliasing, etc. for you.

    0 讨论(0)
  • 2020-12-02 07:04
    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)
    
    0 讨论(0)
  • 2020-12-02 07:05

    Yeah, you can install opencv (this is a library used for image processing, and computer vision), and use the cv2.resize function. And for instance use:

    import cv2
    import numpy as np
    
    img = cv2.imread('your_image.jpg')
    res = cv2.resize(img, dsize=(54, 140), interpolation=cv2.INTER_CUBIC)

    Here img is thus a numpy array containing the original image, whereas res is a numpy array containing the resized image. An important aspect is the interpolation parameter: there are several ways how to resize an image. Especially since you scale down the image, and the size of the original image is not a multiple of the size of the resized image. Possible interpolation schemas are:

    • INTER_NEAREST - a nearest-neighbor interpolation
    • INTER_LINEAR - a bilinear interpolation (used by default)
    • INTER_AREA - resampling using pixel area relation. It may be a preferred method for image decimation, as it gives moire’-free results. But when the image is zoomed, it is similar to the INTER_NEAREST method.
    • INTER_CUBIC - a bicubic interpolation over 4x4 pixel neighborhood
    • INTER_LANCZOS4 - a Lanczos interpolation over 8x8 pixel neighborhood

    Like with most options, there is no "best" option in the sense that for every resize schema, there are scenarios where one strategy can be preferred over another.

    0 讨论(0)
提交回复
热议问题