做者|Nicholas Ballard
编译|VK
来源|Towards Data Sciencehtml
能够说,每个“使用计算机的人”都须要在某个时间点调整图像的大小。MacOS的预览版能够作到,WindowsPowerToys也能够。python
本文使用Python来调整图像大小,幸运的是,图像处理和命令行工具是Python的两个特长。算法
本文旨在向你展现三件事:数组
咱们要构建的命令行程序能够一次调整一个或多个图像文件的大小。bash
在这个例子中,咱们将建立咱们本身的图像,而不是找到一个真正的图像来操纵。app
为何?事实上,创造图像是一个很好的方式来讲明一个图像其实是什么。这个调整大小的程序在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彻底可以建立图像。要显示它,我将使用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中编写调整图像大小的算法实际上有不少的工做量。
在图像处理算法中有不少内容,有些人为此贡献了十分多的工做。例如重采样——在缩小后的图像中使用一个像素来表明周围的高分辨率像素。图像处理是一个巨大的话题。若是你想亲眼看看,看看Pillow的Image.py,它在路径path/to/site-packages/PIL中。
这中间还有一些优化,好比抗锯齿和减小间隙…这里的内容很是多。咱们是站在巨人的肩膀上,能够用一行代码来解决咱们的问题。
若是你有兴趣了解更多有关处理图像时幕后发生的事情,我鼓励你更多地查看“机器视觉”主题!这绝对是一个蓬勃发展的领域。作得足够好,就会有不少公司愿意为你的计算机视觉专业知识付出最高的代价。自动驾驶,IOT,监视,你命名它;全部基本上依赖于处理图片(一般在Python或C++)。
一个很好的起点是查看scikit image。
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库在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 是一个神奇的工具。它能够包装一个函数并在一个模块中以“正常的方式”从一个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
本教程进行了大量的研究:
请记住,编写代码可能须要数小时或数天。但它只需几毫秒就能够运行。你制做的程序没必要很大。任何一件能节省你的时间或让你产生更多产出的东西,都有可能为你的余生服务!
原文连接:https://towardsdatascience.co...
欢迎关注磐创AI博客站:
http://panchuang.net/
sklearn机器学习中文官方文档:
http://sklearn123.com/
欢迎关注磐创博客资源汇总站:
http://docs.panchuang.net/