作者|Nicholas Ballard

编译|VK

来源|Towards Data Science

可以说,每一个“使用计算机的人”都需要在某个时间点调整图像的大小。MacOS的预览版可以做到,WindowsPowerToys也可以。

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

本文旨在向你展示三件事:图像的基本概念。

用于操作图像的Python库。

你可以在自己的项目中使用本文的代码。

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

创建图像

在这个例子中,我们将创建我们自己的图像,而不是找到一个真正的图像来操纵。

为什么?事实上,创造图像是一个很好的方式来说明一个图像实际上是什么。这个调整大小的程序在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++编写并移植到了Pythonimport 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接受可配置的选项。

请记住,编写代码可能需要数小时或数天。但它只需几毫秒就可以运行。你制作的程序不必很大。任何一件能节省你的时间或让你产生更多产出的东西,都有可能为你的余生服务!

资源

python调整图像大小_使用Python调整图像大小相关推荐

  1. python爬网络图片脚步_关于python:如何从本地计算机或网络资源将图像或图片嵌入jupyter笔记本中?...

    我想将图像包括在Jupyter笔记本中. 如果执行以下操作,则可以正常工作: from IPython.display import Image Image("img/picture.png ...

  2. python图像检测_用Python实现通过哈希算法检测图片重复的教程

    Iconfinder 是一个图标搜索引擎,为设计师.开发者和其他创意工作者提供精美图标,目前托管超过 34 万枚图标,是全球最大的付费图标库.用户也可以在 Iconfinder 的交易板块上传出售原创 ...

  3. python tkinter获取屏幕大小_使用Python构建属于自己的Markdown编辑器

    点击上方Linux公社,关注我们 正文Markdown编辑器大家应该都知道,很受程序员喜欢.许多人都在创建一个Markdown编辑器,有些很有创意,有些则很无聊.不过很多开发人员不希望使用Tkinte ...

  4. python图像计数_检测并计数图像中的对象

    我试图用python编写一个脚本来检测和计算图像中的对象,但我失败得很惨.在 这是我第一次对计算机视觉感兴趣并尝试一些东西.我已经尝试过使用cv2模块(opencv),遵循关于特征匹配和模板匹配的教程 ...

  5. python opencv 图像切割_使用Python+OpenCV进行图像处理(二)| 视觉入门

    译者 | 磐石 编辑 | 安可 [前言]图像预处理对于整个图像处理任务来讲特别重要.如果我们没有进行恰当的预处理,无论我们有多么好的数据也很难得到理想的结果. 本篇是视觉入门系列教程的第二篇.整个视觉 ...

  6. python查重算法_用Python实现通过哈希算法检测图片重复的教程

    Iconfinder 是一个图标搜索引擎,为设计师.开发者和其他创意工作者提供精美图标,目前托管超过 34 万枚图标,是全球最大的付费图标库.用户也可以在 Iconfinder 的交易板块上传出售原创 ...

  7. python蟒蛇绘制文字_【Python】蟒蛇绘制

    来画一只你的小蛇吧! 1. 2. 3.了解turtle库 Turtle,也叫海龟渲染器,使用Turtle库画图也叫海龟作图.Turtle库是Python语言中一个很流行的绘制图像的函数库.海龟渲染器, ...

  8. python去干扰线_验证码——python去除干扰线

    [在上一篇文章中,我们使用sklearn对验证码进行了识别,为了提高识别率,今天来进行进一步优化. 观察验证码后,发现还可以对其进行旋转处理,这个验证码旋转角度在-30-30 一.验证码识别的概念 机 ...

  9. python包裹和运费_这个Python库真的太好用了,10行代码就能轻松搞定目标检测

    目标检测是指计算机和软件系统对图像或场景中的目标进行定位和识别的任务. 目标检测已广泛应用于人脸检测.车辆检测.人流量统计.网络图像.安防系统和无人驾驶等多个领域. 早期目标检测的实现基于经典算法,比 ...

最新文章

  1. C# 如何在ComboBox输入文字改变时,触发事件?
  2. RTlinux3.2安装
  3. linux-centerOs6.8安装nginx与配置
  4. java客户端服务器代码_Java Socket通信 客户端服务器端基本代码
  5. MySql 错误 Err [Imp] 1153 - Got a packet bigger than 'max_allowed_packet' bytes
  6. 牛客16438 回文日期
  7. 和平精英有电脑版吗_和平精英电脑版灵敏度调多少 CP端灵敏度设置攻略
  8. Java基础知识点回顾
  9. 孤儿进程与僵尸进程产生及其处理
  10. 原来酷炫的大屏,用Excel就能做
  11. Python进阶-正则表达式
  12. SpringBoot入门第二天
  13. Navicat可视化界面导入SQL文件生成数据库表
  14. Android Studio 基础 之 简单获取手机端所有图片
  15. win10和ubuntu双系统,使用AOMEI分区后启动项损坏,只显示grub>
  16. AxureRP实战(三)Banner轮播图交互(进阶篇)
  17. 美化修复版付费塔罗牌测算源码 (附带搭建教程)
  18. java实现游戏道具购买_基于jsp的虚拟游戏交易-JavaEE实现虚拟游戏交易 - java项目源码...
  19. 利用无线物联网控制器实现无线位移测量
  20. 小米4联通3G_2014215_官方线刷包_救砖包_解账户锁

热门文章

  1. blufr 算法的理解---理解的不对的,欢迎拍砖
  2. 2015年4月1号 的日志
  3. windeployqt.exe 发布windows下qt产生的exe程序
  4. VC创建可隐藏文件夹的方法
  5. html 文字如何和阴影齐平,求助!Html Div齐平无效
  6. python编程(定时器)
  7. linux下的C语言开发(进程创建)
  8. 配置文件默认有项目路劲_SpringBoot 深度调优,让你的项目飞起来!
  9. 动态网站的技术路线_派康大会官方网站建设项目开通上线啦!
  10. linux非root用户搭建docker,linux centos7 非root用户安装源码版docker