Resizing images using Python

Time:2021-9-27

By Nicholas Ballard
Compile VK
Source: towards Data Science

It can be said that every “computer user” needs to adjust the size of the image at a certain point in time. The preview version of Mac OS can do this, and so can windows PowerToys.

This article uses Python to resize images. Fortunately, image processing and command-line tools are two of Python’s strengths.

This article aims to show you three things:

  1. Basic concept of image.

  2. Python library for manipulating images.

  3. You can use the code in this article in your own projects.

The command line program we want to build can resize one or more image files at a time.

Create image

In this example, we will create our own image instead of finding a real image to manipulate.

Why? In fact, creating images is a good way to explain what an image is actually. This resizing program also works on instagram.

So, what is an image? In Python data terminology, an image is a list of int tuples.

image = list[list[tuple[*int, float]]]

Numpy is defined as a two-dimensional shape array (h, W, 4), where h represents the number of high pixels (up and down) and W represents the number of wide pixels (from left to right).

In other words, an image is a list of pixels (rows) (the entire image). Each pixel consists of 3 integers and 1 optional floating-point number: red channel, green channel, blue channel and alpha (floating-point optional). The red, green, and blue channels (RGB) have values from 0 to 255.

From now on, we will discuss color images without alpha channels to keep it simple. Alpha is the transparency of the pixel. Images can also have only one channel with a value from 0 to 255. This is a grayscale image, that is, a black-and-white image. Here we use color images!

import matplotlib as plt

pixel: tuple = (200, 100, 150)
plt.imshow([[list(pixel)]])

Making images in pure Python

Python is fully capable of creating images. To display it, I’ll use the Matplotlib library, which you can use to install:

pip install matplotlib

Create pixels:

from dataclasses import dataclass

@dataclass
class Pixel:
  red: int
  green: int
  blue: int
  # alpha: float = 1
	
pixel = Pixel(255,0,0)
pixel
# returns: 
# Pixel(red=255, green=0, blue=0, alpha=1)

Create image:

from __future__ import annotations

from dataclasses import dataclass, astuple
from itertools import cycle
from typing import List

import matplotlib.pyplot as plt
import matplotlib.image as mpimg


@dataclass
class Pixel:
  red: int
  green: int
  blue: int
  # alpha: float = 1


pixel = Pixel(255,0,0)
pixel

marigold: Pixel = Pixel(234,162,33)
red: Pixel = Pixel(255,0,0)

Image = List[List[Pixel]]


def create_image(*colors: Pixel, blocksize: int = 10, squaresize: int = 9) -> Image:
  "" "make a square image (the same width and height) with configurable pixel blocks."
  Args:
      Colors (pixel): parameters of iterative color rendering order.
      Blocksize (int, optional): [description]. Default: 10
      Squaresize (int, optional): [description]. Default 9
  Returns:
      Image: a beautiful square picture!
  """
  img: list = []
  colors = cycle(colors)
  for row in range(squaresize):
    row: list = []
    for col in range(squaresize):
      Color = next (colors) # set color
      for _ in range(blocksize):
        values: list[int] = list(astuple(color))
        row.append(values)
    [img. Append (row) for in range (squaresize)] # create row height
  return img


if __name__ == '__main__':
  image = create_image(marigold, red)
  plt.imshow(image)

This is the rendered image. Behind this, the data is as follows:

[[[234, 162, 33],
  [234, 162, 33],
  [234, 162, 33],
  [234, 162, 33],
  [234, 162, 33],
  [234, 162, 33],
  [234, 162, 33],
  [234, 162, 33],
  [234, 162, 33],
  [234, 162, 33],
  [255, 0, 0],
  [255, 0, 0],
  [255, 0, 0],
  [255, 0, 0],
  [255, 0, 0],
  [255, 0, 0],
  [255, 0, 0],
  [255, 0, 0],
  [255, 0, 0],
  [255, 0, 0],
  [234, 162, 33],
  ...

Now that we have an image, let’s resize it!

Adjust the size in Python

Writing an image resizing algorithm in Python actually has a lot of work.

There are many contents in image processing algorithms, and some people have contributed a lot to this. For example, resampling – a pixel is used in the reduced image to represent the surrounding high-resolution pixels. Image processing is a huge topic. If you want to see it for yourself, take a look at the image.py of pilot, which is in the path path / to / site packages / PIL.

There are also some optimizations, such as anti aliasing and reducing gap… There is a lot of content here. We stand on the shoulders of giants and can solve our problems with one line of code.

If you are interested in learning more about what happens behind the scenes when processing images, I encourage you to check out the topic of “machine vision” more! This is definitely a booming field.

If you do well enough, many companies will be willing to pay the highest price for your computer vision expertise. Autopilot, IOT, surveillance, you name it; All basically depend on processing pictures (usually in Python or C + +).

A good starting point is to view the scikit image.

OpenCV

Opencv can be used for image processing. He wrote it in C + + and ported it to python

import cv2

def resize(fp: str, scale: Union[float, int]) -> np.ndarray:
    "" "resize the image to maintain its scale"
    Args:
        FP (STR): path parameter of image file
        Scale (Union [float, int]): percentage as a parameter. For example: 53
    Returns:
        Image (NP. Ndarray): a scaled down picture
    """    
    _scale = lambda dim, s: int(dim * s / 100)
    im: np.ndarray = cv2.imread(fp)
    width, height, channels = im.shape
    new_width: int = _scale(width, scale)
    new_height: int = _scale(height, scale)
    new_dim: tuple = (new_width, new_height)
    return cv2.resize(src=im, dsize=new_dim, interpolation=cv2.INTER_LINEAR)

The options for the interpolation parameter are one of the flags provided in the CV2 package:

INTER_ Nearest – nearest neighbor interpolation
INTER_ Linear – bilinear interpolation (default)
INTER_ Area – resampling using pixel area relationships. It may be the preferred method of image extraction. But when the image is scaled, it is similar to Inter_ Nearest method.
INTER_ Cubic – one greater than 4 × Bicubic interpolation of 4-pixel neighborhood
INTER_ Lanczos4 – one greater than 8 × Lanczos interpolation in 8-pixel neighborhood

After return:

resized = resize("checkers.jpg", 50)
print(resized.shape)
Plt.imshow (resized) # or cv2.imshow ("name", image)

It did what we expected. Images range from 900 pixels high and 900 pixels wide to 450 × 450 (there are still three color channels). The screenshot above doesn’t look very good because of the mattlotlib coloring of jupyter lab.

Pillow

The pilot library has a resizing method on the image class. Its parameters are:

size: (width, height)
Resample: the default is the parameter required by bicubic. Resampling algorithm.
Box: the default is none. For a 4-tuple, the image rectangle working within the parameters (0,0, width, height) is defined.
reducing_ Gap: the default is none. Resampling optimization algorithm to make the output look better.

Here are the functions:

from PIL import Image

def resize(fp: str, scale: Union[float, int]) -> np.ndarray:
    "" "resize the image to maintain its scale"
    Args:
        FP (STR): path parameter of image file
        Scale (Union [float, int]): percentage as a parameter. For example: 53
    Returns:
        Image (NP. Ndarray): a scaled down picture
    """
    _scale = lambda dim, s: int(dim * s / 100)
    im = Image.open(fp)
    width, height = im.size
    new_width: int = _scale(width, scale)
    new_height: int = _scale(height, scale)
    new_dim: tuple = (new_width, new_height)
    return im.resize(new_dim)

The function using pilot is very similar to OpenCV. The only difference is that the pil.image.image class has an attribute size for accessing the image (width, height).

The result is:

resized = resize("checkers.jpg", 30.5)
print(resized.size)
resized.show("resized image", resized)

Notice how the show method opens the default program of the operating system to view the file type of the image.

Create command line program

Now that we have an image resizing function, it’s time to have a user interface to run resizing.

It is possible to resize an image. But we want to be able to process images in batches.

The interface we’re going to build will be the simplest: the command line utility.

Pallets project is the genius community behind flash. It is a Jinja template engine: click(https://click.palletsprojects.com/en/7.x/。)

pip install click

Click is a library for making command line programs. This is better than using normal argparse orif __name__ == '__main__':It’s much better to start some if then logic in. Therefore, we will use click to decorate our image adjuster.

The following is a complete script for resizing images from the command line!

""" resize.py
"""

from __future__ import annotations
import os
import glob
from pathlib import Path
import sys

import click
from PIL import Image


"""
file:
    https://pillow.readthedocs.io/en/5.1.x/handbook/image-file-formats.html
"""
SUPPORTED_FILE_TYPES: list[str] = [".jpg", ".png"]


def name_file(fp: Path, suffix) -> str:
    return f"{fp.stem}{suffix}{fp.suffix}"


def resize(fp: str, scale: Union[float, int]) -> Image:
    "" "resize the image to maintain its scale"
    Args:
        FP (STR): path parameter of image file
        Scale (Union [float, int]): percentage as a parameter. For example: 53
    Returns:
        Image (NP. Ndarray): a scaled down picture
    """
    _scale = lambda dim, s: int(dim * s / 100)
    im: PIL.Image.Image = Image.open(fp)
    width, height = im.size
    new_width: int = _scale(width, scale)
    new_height: int = _scale(height, scale)
    new_dim: tuple = (new_width, new_height)
    return im.resize(new_dim)


@click.command()
@click.option("-p", "--pattern")
@click.option("-s", "--scale", default=50, help="Percent as whole number to scale. eg. 40")
@click.option("-q", "--quiet", default=False, is_flag=True, help="Suppresses stdout.")
def main(pattern: str, scale: int, quiet: bool):
    for image in (images := Path().glob(pattern)):
        if image.suffix not in SUPPORTED_FILE_TYPES:
            continue
        im = resize(image, scale)
        nw, nh = im.size
        suffix: str = f"_{scale}_{nw}x{nh}"
        resize_name: str = name_file(image, suffix)
        _dir: Path = image.absolute().parent
        im.save(_dir / resize_name)
        if not quiet:
            print(
                f"resized image saved to {resize_name}.")
    if images == []:
        print(f"No images found at search pattern '{pattern}'.")
        return


if __name__ == '__main__':
    main()

The command line program runs from the entry point function main. Parameters are passed to the click.option option:

  • patternUse string form to locate one or more images related to the directory in which the script runs.--pattern="../catpics/*.pngLooks up the catpics folder one level and returns all the files in the folder with the. PNG image extension.
  • scaleAccepts a number, floating point, or integer and passes it to the resize function. This script is very simple without data validation. If you add it to the code, the check scale is a number between 5 and 99 (reasonable reduction scale parameter). You can pass-s "chicken nuggets"Make settings.
  • If you do not want to output text to the standard stream while the program is running, thenquietIs an option parameter.

Run the program from the command line:

python resize.py -s 35 -p "./*jpg"

result:

$ py resize.py -p "checkers.jpg" -s 90
resized image saved to checkers_90_810x810.jpg.

Checking folder:

$ ls -lh checkers*
-rw-r--r-- 1 nicho 197609 362K Aug 15 13:13 checkers.jpg
-rw-r--r-- 1 nicho 197609 231K Aug 15 23:56 checkers_90_810x810.jpg

not bad So the program shrinks the image and gives it a descriptive label. We can see that the file size ranges from 362KB to 231kb!

In order to see that the program processes multiple files at the same time, we will run it again:

$ py resize.py --pattern="checkers*" --scale=20
resized image saved to checkers_20_180x180.jpg.
resized image saved to checkers_90_810x810_20_162x162.jpg.

File system output:

$ ll -h checkers*
-rw-r--r-- 1 nicho 197609 362K Aug 15 13:13 checkers.jpg
-rw-r--r-- 1 nicho 197609 1.8K Aug 16 00:23 checkers_20_180x180.jpg
-rw-r--r-- 1 nicho 197609 231K Aug 15 23:56 checkers_90_810x810.jpg
-rw-r--r-- 1 nicho 197609 1.8K Aug 16 00:23 checkers_90_810x810_20_162x162.jpg

As long as the pattern is matched, recursion can process any number of images.

Click

ClickIs a magical tool. It can wrap a function and extract it from a module in a “normal way”if __name__ == '__main__'Statement run. (in fact, it doesn’t even need to do this; you just need to define and decorate the functions to run), but its real highlight is to install the script as a package.

This comes with PythonsetuptoolsLibrary completed.

This is minesetup.py.

from setuptools import setup

setup(
    name='resize',
    version='0.0.1',
    py_modules=['resize'],
    install_requires=[
        'click',
        'pillow',
    ],
    entry_points='''
        [console_scripts]
        resize=resize:main
    '''
)

Generate an executable / wrapper using the following command:

pip install -e .

Now you can call the script without using Python commands. In addition, if you add a new executable to a folder in the path, you can call this program from anywhere on your computer, such asresize -p *jpg -s 75

conclusion

This tutorial has done a lot of research:

  • Firstly, some third-party Python libraries for image processing are introduced.
  • Then build an image from scratch using Python to further understand the actual meaning of the image.
  • Then, select one of the options and build a script to reduce the image while maintaining the image scale.
  • Finally, put all this in a command-line utility and accept configurable options through click.

Keep in mind that writing code can take hours or days. But it only takes a few milliseconds to run. The program you make doesn’t have to be big. Anything that can save you time or make you produce more output may serve the rest of your life!

resources

Original link:https://towardsdatascience.com/how-to-resize-images-using-python-8aaba74602ed

Welcome to panchuang AI blog:
http://panchuang.net/

Official Chinese document of sklearn machine learning:
http://sklearn123.com/

Welcome to panchuang blog resources summary station:
http://docs.panchuang.net/