关于人工智能:使用Python调整图像大小

4次阅读

共计 7923 个字符,预计需要花费 20 分钟才能阅读完成。

作者 |Nicholas Ballard
编译 |VK
起源 |Towards Data Science

能够说,每一个“应用计算机的人”都须要在某个工夫点调整图像的大小。MacOS 的预览版能够做到,WindowsPowerToys 也能够。

本文应用 Python 来调整图像大小,侥幸的是,图像处理和命令行工具是 Python 的两个专长。

本文旨在向你展现三件事:

  1. 图像的基本概念。
  2. 用于操作图像的 Python 库。
  3. 你能够在本人的我的项目中应用本文的代码。

咱们要构建的命令行程序能够一次调整一个或多个图像文件的大小。

创立图像

在这个例子中,咱们将创立咱们本人的图像,而不是找到一个真正的图像来操纵。

为什么?事实上,发明图像是一个很好的形式来阐明一个图像实际上是什么。这个调整大小的程序在 Instagram 上也同样实用。

那么,什么是图像?在 Python 数据术语中,图像是 int 元组的列表。

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

NumPy 的定义是一个二维形态数组 (h, w, 4),其中 h 示意高的像素数(高低),w 示意宽的像素数(从左到右)。

换句话说,图像是像素列表(行)的列表(整个图像)。每个像素由 3 个整数和 1 个可选浮点数组成:红色通道、绿色通道、蓝色通道、alpha(浮点可选)。红色、绿色、蓝色通道(RGB)的值从 0 到 255。

从当初开始,咱们将探讨没有 alpha 通道的彩色图像,以放弃简略。Alpha 是像素的透明度。图像也只能有一个值从 0 到 255 的通道。这就是灰度图像,也就是黑白图像。在这里咱们应用彩色图像!

import matplotlib as plt

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

用纯 Python 制作图像

Python 齐全可能创立图像。要显示它,我将应用 matplotlib 库,你能够应用它装置:

pip install matplotlib

创立像素:

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)

创立图像:

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:
  """ 用可配置的像素块制作一个正方形图像(宽度和高度雷同).
  Args:
      colors (Pixel): 可迭代的色彩出现程序的参数。blocksize (int, optional): [description]. 默认 10.
      squaresize (int, optional): [description]. 默认 9.
  Returns:
      Image: 一幅丑陋的正方形图片!
  """
  img: list = []
  colors = cycle(colors)
  for row in range(squaresize):
    row: list = []
    for col in range(squaresize):
      color = next(colors) # 设置色彩
      for _ in range(blocksize):
        values: list[int] = list(astuple(color))
        row.append(values)
    [img.append(row) for _ in range(squaresize)] # 创立行高
  return img


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

这就是渲染的图像。在背地,数据是这样的:

[[[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],
  ...

当初咱们有了一个图像,让咱们调整它的大小!

在 Python 中调整大小

在 Python 中编写调整图像大小的算法实际上有很多的工作量。

在图像处理算法中有很多内容,有些人为此奉献了非常多的工作。例如重采样——在放大后的图像中应用一个像素来代表四周的高分辨率像素。图像处理是一个微小的话题。如果你想亲眼看看,看看 Pillow 的 Image.py,它在门路 path/to/site-packages/PIL 中。

这两头还有一些优化,比方抗锯齿和缩小间隙…这里的内容十分多。咱们是站在伟人的肩膀上,能够用一行代码来解决咱们的问题。

如果你有趣味理解更多无关解决图像时幕后产生的事件,我激励你更多地查看“机器视觉”主题!这相对是一个蓬勃发展的畛域。

做得足够好,就会有很多公司违心为你的计算机视觉专业知识付出最高的代价。主动驾驶,IOT,监督,你命名它;所有基本上依赖于解决图片(通常在 Python 或 C ++)。

一个很好的终点是查看 scikit image。

OpenCV

OpenCV 能够用来作图像处理。他应用 C ++ 编写并移植到了 Python

import cv2

def resize(fp: str, scale: Union[float, int]) -> np.ndarray:
    """ 调整图像大小,放弃其比例
    Args:
        fp (str): 图像文件的门路参数
        scale (Union[float, int]): 百分比作为参数。如:53
    Returns:
        image (np.ndarray): 按比例放大的图片
    """    
    _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)

interpolation 参数的选项是 cv2 包中提供的 flags 之一:

INTER_NEAREST – 近邻插值
INTER_LINEAR – 双线性插值(默认应用)
INTER_AREA – 利用像素区域关系从新采样。它可能是图像抽取的首选办法。然而当图像被缩放时,它相似于 INTER_NEAREST 办法。INTER_CUBIC – 一个大于 4×4 像素邻域的双三次插值
INTER_LANCZOS4 – 一个大于 8×8 像素邻域的 Lanczos 插值

返回后:

resized = resize("checkers.jpg", 50)
print(resized.shape)
plt.imshow(resized) # 也能够应用 cv2.imshow("name", image)

它做了咱们所冀望的。图像从 900 像素高,900 像素宽,到 450×450(依然有三个色彩通道)。因为 Jupyter Lab 的 matplotlib 着色,下面的屏幕截图看起来不太好。

Pillow

pillow 库在 Image 类上有一个调整大小的办法。它的参数是:

size: (width, height)
resample: 默认为 BICUBIC. 重采样算法须要的参数。box: 默认为 None。为一个 4 元组,定义了在参数 (0,0,宽度,高度) 内工作的图像矩形。reducing_gap: 默认为 None。从新采样优化算法,使输入看起来更好。

以下是函数:

from PIL import Image

def resize(fp: str, scale: Union[float, int]) -> np.ndarray:
    """ 调整图像大小,放弃其比例
    Args:
        fp (str): 图像文件的门路参数
        scale (Union[float, int]): 百分比作为参数。如:53
    Returns:
        image (np.ndarray): 按比例放大的图片
    """
    _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)

应用 Pillow 的函数与 OpenCV 十分类似。惟一的区别是 PIL.Image.Image 类具备用于拜访图像(宽度、高度)的属性大小。

后果是:

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

请留神 show 办法如何关上操作系统的默认程序以查看图像的文件类型。

创立命令行程序

当初咱们有了一个调整图像大小的函数,当初是时候让它有一个运行调整大小的用户界面了。

调整一个图像的大小是能够的。但咱们心愿可能批量解决图像。

咱们将要构建的接口将是最简略的接口:命令行实用程序。

Pallets 我的项目是 Flask 背地的蠢才社区,是一个 Jinja 模板引擎:Click(https://click.palletsprojects…。)

pip install click

Click 是一个用于制作命令行程序的库。这比应用一般的 argparse 或在 if __name__ == '__main__': 中启动一些 if-then 逻辑要好得多。所以,咱们将应用 Click 来装璜咱们的图像调整器。

上面是从命令行调整图像大小的残缺脚本!

"""resize.py"""

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

import click
from PIL import Image


"""
文档:
    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:
    """ 调整图像大小,放弃其比例
    Args:
        fp (str): 图像文件的门路参数
        scale (Union[float, int]): 百分比作为参数。如:53
    Returns:
        image (np.ndarray): 按比例放大的图片
    """
    _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()

命令行程序从入口点函数 main 运行。参数通过传递给 click.option 选项:

  • pattern采纳字符串模式来定位与脚本运行的目录相干的一个或多个图像。--pattern="../catpics/*.png将向上一级查找 catpics 文件夹,并返回该文件夹中具备.png 图像扩展名的所有文件。
  • scale承受一个数字、浮点或整数,并将其传递给 resize 函数。这个脚本很简略,没有数据验证。如果你增加到代码中,查看比例是一个介于 5 和 99 之间的数字(正当的放大比例参数)。你能够通过 -s "chicken nuggets" 进行设置。
  • 如果不心愿在程序运行时将文本输入到规范流,则 quiet 是一个选项参数。

从命令行运行程序:

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

后果:

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

正在查看文件夹:

$ 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

不错!所以程序放大了图像,给了它一个描述性的标签,咱们能够看到文件大小从 362KB 到 231KB!

为了查看程序同时解决多个文件,咱们将再次运行它:

$ 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.

文件系统输入:

$ 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

只有匹配到了模式,递归能够解决任意数量的图像。

Click

Click 是一个神奇的工具。它能够包装一个函数并在一个模块中以“失常的形式”从一个 if __name__ == '__main__' 语句运行。(实际上,它甚至不须要这样做;你只需定义和装璜要运行的函数即可),但它真正的亮点在于将脚本作为包装置。

这是通过 Python 附带的 setuptools 库实现的。

这是我的setup.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
    '''
)

应用以下命令生成可执行文件 / 包装包:

pip install -e .

当初,你能够在不应用 python 命令的状况下调用脚本。另外,如果你将新的可执行文件增加到门路中的文件夹中,你能够从计算机上的任何地位调用此程序,如resize -p *jpg -s 75

论断

本教程进行了大量的钻研:

  • 首先介绍了一些用于图像处理的第三方 Python 库。
  • 而后应用 Python 从头构建一个图像,以进一步理解图像的理论含意。
  • 而后,抉择其中一个选项,并构建一个脚本,在放弃图像比例的同时放大图像。
  • 最初, 把所有这些放在一个命令行实用程序中,通过 click 承受可配置的选项。

请记住,编写代码可能须要数小时或数天。但它只需几毫秒就能够运行。你制作的程序不用很大。任何一件能节俭你的工夫或让你产生更多产出的货色,都有可能为你的余生服务!

资源

  • click(https://click.palletsprojects…
  • matplotlib(https://matplotlib.org/3.2.0/…
  • opencv(https://docs.opencv.org/4.4.0/)
  • pillow(https://pillow.readthedocs.io…
  • scikit-image(https://scikit-image.org/)

原文链接:https://towardsdatascience.co…

欢送关注磐创 AI 博客站:
http://panchuang.net/

sklearn 机器学习中文官网文档:
http://sklearn123.com/

欢送关注磐创博客资源汇总站:
http://docs.panchuang.net/

正文完
 0