如何使用Python調(diào)整圖像大小
作者|Nicholas Ballard
編譯|VK
來源|Towards Data Science
可以說,每一個(gè)“使用計(jì)算機(jī)的人”都需要在某個(gè)時(shí)間點(diǎn)調(diào)整圖像的大小。MacOS的預(yù)覽版可以做到,WindowsPowerToys也可以。
本文使用Python來調(diào)整圖像大小,幸運(yùn)的是,圖像處理和命令行工具是Python的兩個(gè)特長(zhǎng)。
本文旨在向你展示三件事:
- 圖像的基本概念。
- 用于操作圖像的Python庫。
- 你可以在自己的項(xiàng)目中使用本文的代碼。
我們要構(gòu)建的命令行程序可以一次調(diào)整一個(gè)或多個(gè)圖像文件的大小。
創(chuàng)建圖像
在這個(gè)例子中,我們將創(chuàng)建我們自己的圖像,而不是找到一個(gè)真正的圖像來操縱。
為什么?事實(shí)上,創(chuàng)造圖像是一個(gè)很好的方式來說明一個(gè)圖像實(shí)際上是什么。這個(gè)調(diào)整大小的程序在Instagram上也同樣適用。
那么,什么是圖像?在Python數(shù)據(jù)術(shù)語中,圖像是int元組的列表。
image = list[list[tuple[*int, float]]]
NumPy的定義是一個(gè)二維形狀數(shù)組 (h, w, 4),其中h表示高的像素?cái)?shù)(上下),w表示寬的像素?cái)?shù)(從左到右)。
換句話說,圖像是像素列表(行)的列表(整個(gè)圖像)。每個(gè)像素由3個(gè)整數(shù)和1個(gè)可選浮點(diǎn)數(shù)組成:紅色通道、綠色通道、藍(lán)色通道、alpha(浮點(diǎn)可選)。紅色、綠色、藍(lán)色通道(RGB)的值從0到255。
從現(xiàn)在開始,我們將討論沒有alpha通道的彩色圖像,以保持簡(jiǎn)單。Alpha是像素的透明度。圖像也只能有一個(gè)值從0到255的通道。這就是灰度圖像,也就是黑白圖像。在這里我們使用彩色圖像!
import matplotlib as plt pixel: tuple = (200, 100, 150) plt.imshow([[list(pixel)]])
用純Python制作圖像
Python完全能夠創(chuàng)建圖像。要顯示它,我將使用matplotlib庫,你可以使用它安裝:
pip install matplotlib
創(chuàng)建像素:
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)
創(chuàng)建圖像:
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: """ 用可配置的像素塊制作一個(gè)正方形圖像(寬度和高度相同). Args: colors (Pixel): 可迭代的顏色呈現(xiàn)順序的參數(shù)。 blocksize (int, optional): [description]. 默認(rèn)10. squaresize (int, optional): [description]. 默認(rèn)9. Returns: Image: 一幅漂亮的正方形圖片! """ img: list = [] colors = cycle(colors) for row in range(squaresize): row: list = [] for col in range(squaresize): color = next(colors) # 設(shè)置顏色 for _ in range(blocksize): values: list[int] = list(astuple(color)) row.append(values) [img.append(row) for _ in range(squaresize)] # 創(chuàng)建行高 return img if __name__ == '__main__': image = create_image(marigold, red) plt.imshow(image)
這就是渲染的圖像。在背后,數(shù)據(jù)是這樣的:
[[[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中調(diào)整大小
在Python中編寫調(diào)整圖像大小的算法實(shí)際上有很多的工作量。
在圖像處理算法中有很多內(nèi)容,有些人為此貢獻(xiàn)了十分多的工作。例如重采樣——在縮小后的圖像中使用一個(gè)像素來代表周圍的高分辨率像素。圖像處理是一個(gè)巨大的話題。如果你想親眼看看,看看Pillow的Image.py,它在路徑path/to/site-packages/PIL中。
這中間還有一些優(yōu)化,比如抗鋸齒和減少間隙…這里的內(nèi)容非常多。我們是站在巨人的肩膀上,可以用一行代碼來解決我們的問題。
如果你有興趣了解更多有關(guān)處理圖像時(shí)幕后發(fā)生的事情,我鼓勵(lì)你更多地查看“機(jī)器視覺”主題!這絕對(duì)是一個(gè)蓬勃發(fā)展的領(lǐng)域。
做得足夠好,就會(huì)有很多公司愿意為你的計(jì)算機(jī)視覺專業(yè)知識(shí)付出最高的代價(jià)。自動(dòng)駕駛,IOT,監(jiān)視,你命名它;所有基本上依賴于處理圖片(通常在Python或C++)。
一個(gè)很好的起點(diǎn)是查看scikit image。
OpenCV
OpenCV可以用來作圖像處理。他使用C++編寫并移植到了Python
import cv2 def resize(fp: str, scale: Union[float, int]) -> np.ndarray: """ 調(diào)整圖像大小,保持其比例 Args: fp (str): 圖像文件的路徑參數(shù) scale (Union[float, int]): 百分比作為參數(shù)。如: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參數(shù)的選項(xiàng)是cv2包中提供的flags之一:
INTER_NEAREST – 近鄰插值
INTER_LINEAR – 雙線性插值(默認(rèn)使用)
INTER_AREA – 利用像素區(qū)域關(guān)系重新采樣。它可能是圖像抽取的首選方法。但是當(dāng)圖像被縮放時(shí),它類似于INTER_NEAREST方法。
INTER_CUBIC – 一個(gè)大于4×4像素鄰域的雙三次插值
INTER_LANCZOS4 – 一個(gè)大于8×8像素鄰域的Lanczos插值
返回后:
resized = resize("checkers.jpg", 50) print(resized.shape) plt.imshow(resized) # 也可以使用 cv2.imshow("name", image)
它做了我們所期望的。圖像從900像素高,900像素寬,到450×450(仍然有三個(gè)顏色通道)。因?yàn)镴upyter Lab的matplotlib著色,上面的屏幕截圖看起來不太好。
Pillow
pillow庫在Image類上有一個(gè)調(diào)整大小的方法。它的參數(shù)是:
size: (width, height)
resample: 默認(rèn)為BICUBIC. 重采樣算法需要的參數(shù)。
box: 默認(rèn)為None。為一個(gè)4元組,定義了在參數(shù)(0,0,寬度,高度)內(nèi)工作的圖像矩形。
reducing_gap: 默認(rèn)為None。重新采樣優(yōu)化算法,使輸出看起來更好。
以下是函數(shù):
from PIL import Image def resize(fp: str, scale: Union[float, int]) -> np.ndarray: """ 調(diào)整圖像大小,保持其比例 Args: fp (str): 圖像文件的路徑參數(shù) scale (Union[float, int]): 百分比作為參數(shù)。如: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 的函數(shù)與OpenCV非常相似。唯一的區(qū)別是PIL.Image.Image類具有用于訪問圖像(寬度、高度)的屬性大小。
結(jié)果是:
resized = resize("checkers.jpg", 30.5) print(resized.size) resized.show("resized image", resized)
請(qǐng)注意show方法如何打開操作系統(tǒng)的默認(rèn)程序以查看圖像的文件類型。
創(chuàng)建命令行程序
現(xiàn)在我們有了一個(gè)調(diào)整圖像大小的函數(shù),現(xiàn)在是時(shí)候讓它有一個(gè)運(yùn)行調(diào)整大小的用戶界面了。
調(diào)整一個(gè)圖像的大小是可以的。但我們希望能夠批量處理圖像。
我們將要構(gòu)建的接口將是最簡(jiǎn)單的接口:命令行實(shí)用程序。
Pallets項(xiàng)目是Flask背后的天才社區(qū),是一個(gè)Jinja模板引擎:Click(https://click.palletsprojects...。)
pip install click
Click是一個(gè)用于制作命令行程序的庫。這比使用普通的argparse或在if __name__ == '__main__':中啟動(dòng)一些if-then邏輯要好得多。所以,我們將使用Click來裝飾我們的圖像調(diào)整器。
下面是從命令行調(diào)整圖像大小的完整腳本!
""" 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: """ 調(diào)整圖像大小,保持其比例 Args: fp (str): 圖像文件的路徑參數(shù) scale (Union[float, int]): 百分比作為參數(shù)。如: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()
命令行程序從入口點(diǎn)函數(shù)main運(yùn)行。參數(shù)通過傳遞給click.option選項(xiàng):
- pattern采用字符串形式來定位與腳本運(yùn)行的目錄相關(guān)的一個(gè)或多個(gè)圖像。--pattern="../catpics/*.png將向上一級(jí)查找catpics文件夾,并返回該文件夾中具有.png圖像擴(kuò)展名的所有文件。
- scale接受一個(gè)數(shù)字、浮點(diǎn)或整數(shù),并將其傳遞給resize函數(shù)。這個(gè)腳本很簡(jiǎn)單,沒有數(shù)據(jù)驗(yàn)證。如果你添加到代碼中,檢查比例是一個(gè)介于5和99之間的數(shù)字(合理的縮小比例參數(shù))。你可以通過-s "chicken nuggets"進(jìn)行設(shè)置。
- 如果不希望在程序運(yùn)行時(shí)將文本輸出到標(biāo)準(zhǔn)流,則quiet是一個(gè)選項(xiàng)參數(shù)。
從命令行運(yùn)行程序:
python resize.py -s 35 -p "./*jpg"
結(jié)果:
$ 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
不錯(cuò)!所以程序縮小了圖像,給了它一個(gè)描述性的標(biāo)簽,我們可以看到文件大小從362KB到231KB!
為了查看程序同時(shí)處理多個(gè)文件,我們將再次運(yùn)行它:
$ 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.
文件系統(tǒng)輸出:
$ 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
只要匹配到了模式,遞歸可以處理任意數(shù)量的圖像。
Click
Click 是一個(gè)神奇的工具。它可以包裝一個(gè)函數(shù)并在一個(gè)模塊中以“正常的方式”從一個(gè)if __name__ == '__main__'語句運(yùn)行。(實(shí)際上,它甚至不需要這樣做;你只需定義和裝飾要運(yùn)行的函數(shù)即可),但它真正的亮點(diǎn)在于將腳本作為包安裝。
這是通過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 ''' )
使用以下命令生成可執(zhí)行文件/包裝包:
pip install -e .
結(jié)論
本教程進(jìn)行了大量的研究:
- 首先介紹了一些用于圖像處理的第三方Python庫。
- 然后使用Python從頭構(gòu)建一個(gè)圖像,以進(jìn)一步了解圖像的實(shí)際含義。
- 然后,選擇其中一個(gè)選項(xiàng),并構(gòu)建一個(gè)腳本,在保持圖像比例的同時(shí)縮小圖像。
- 最后,把所有這些放在一個(gè)命令行實(shí)用程序中,通過click接受可配置的選項(xiàng)。
請(qǐng)記住,編寫代碼可能需要數(shù)小時(shí)或數(shù)天。但它只需幾毫秒就可以運(yùn)行。你制作的程序不必很大。任何一件能節(jié)省你的時(shí)間或讓你產(chǎn)生更多產(chǎn)出的東西,都有可能為你的余生服務(wù)!
原文鏈接:
https://towardsdatascience.co...
以上就是如何使用Python調(diào)整圖像大小的詳細(xì)內(nèi)容,更多關(guān)于Python調(diào)整圖像大小的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
對(duì)Python中g(shù)ensim庫word2vec的使用詳解
今天小編就為大家分享一篇對(duì)Python中g(shù)ensim庫word2vec的使用詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-05-05linux環(huán)境下的python安裝過程圖解(含setuptools)
這篇文章主要介紹了linux環(huán)境下的python安裝過程圖解(含setuptools),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-11-11Python數(shù)據(jù)分析處理(三)--運(yùn)動(dòng)員信息的分組與聚合
這篇文章主要介紹了Python數(shù)據(jù)清洗與處理?運(yùn)動(dòng)員信息的分組與聚合,根據(jù)Python數(shù)據(jù)清洗與處理?的相關(guān)資料展開運(yùn)動(dòng)員信息的分組與聚合的文章內(nèi)容,需要的朋友可以參考一下2021-12-12python中shell執(zhí)行知識(shí)點(diǎn)
在本篇文章里小編給大家分享的是關(guān)于python中shell執(zhí)行知識(shí)點(diǎn)內(nèi)容,需要的朋友們可以學(xué)習(xí)下。2020-05-05Python的__builtin__模塊中的一些要點(diǎn)知識(shí)
這篇文章主要介紹了Python的__builtin__模塊中的一些要點(diǎn)知識(shí),是Python學(xué)習(xí)中的基礎(chǔ),需要的朋友可以參考下2015-05-05python操作SqlServer獲取特定表的所有列名(推薦)
這篇文章主要介紹了python操作SqlServer獲取特定表的所有列名,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-08-08Python利用Selenium實(shí)現(xiàn)網(wǎng)站自動(dòng)簽到功能
小編了解到了python的selenium庫對(duì)于自動(dòng)化測(cè)試的初學(xué)者很容易上手,今天就借這篇文章給大家介紹Python利用Selenium實(shí)現(xiàn)網(wǎng)站自動(dòng)簽到功能,感興趣的朋友一起看看吧2021-09-09Python中xml.etree.ElementTree的使用示例
ElementTree是Python標(biāo)準(zhǔn)庫中的一個(gè)模塊,專門用于處理XML文件,它提供了解析、創(chuàng)建、修改和遍歷XML文檔的API,非常適合處理配置文件、數(shù)據(jù)交換格式和Web服務(wù)響應(yīng)等場(chǎng)景,本文就來介紹一下,感興趣的可以了解一下2024-09-09