次の方法でPILを使用して画像サイズを取得できることを理解しています
from PIL import Image
im = Image.open(image_filename)
width, height = im.size
ただし、画像をメモリにロードすることなく、画像の幅と高さを取得したいと考えています。それは可能ですか?私は画像サイズの統計のみを行っており、画像の内容は気にしません。処理を高速化したいだけです。
次の方法でPILを使用して画像サイズを取得できることを理解しています
from PIL import Image
im = Image.open(image_filename)
width, height = im.size
ただし、画像をメモリにロードすることなく、画像の幅と高さを取得したいと考えています。それは可能ですか?私は画像サイズの統計のみを行っており、画像の内容は気にしません。処理を高速化したいだけです。
OPは「より高速な」ソリューションに興味を持っていました。私は最速のソリューションに興味があり、実際のベンチマークでそれに答えようとしています。
私は比較しています:
cv2.imread
: https://www.kite.com/python/docs/cv2.imreadPIL.open
: https://pillow.readthedocs.io/en/stable/reference/Image.htmlopsdroid/image_size
: https://github.com/opsdroid/image_size ( https://raw.githubusercontent.com/scardine/image_size/master/get_image_size.pyのパッケージ版)shibukawa/imagesize_py
:https ://github.com/shibukawa/imagesize_pykobaltcore/pymage_size
: https://github.com/kobaltcore/pymage_size202897 ほとんどが JPG ファイルで次のコードを実行しています。
"""
pip install opsdroid-get-image-size --user
pip install pymage_size
pip install imagesize
"""
import concurrent.futures
from pathlib import Path
import cv2
import numpy as np
import pandas as pd
from tqdm import tqdm
from PIL import Image
import get_image_size
import imagesize
import pymage_size
files = [str(p.resolve())
for p in Path("/data/").glob("**/*")
if p.suffix in {".jpg", ".jpeg", ".JPEG", ".JPG", ".png", ".PNG"}]
def get_shape_cv2(fname):
img = cv2.imread(fname)
return (img.shape[0], img.shape[1])
with concurrent.futures.ProcessPoolExecutor(8) as executor:
results = list(tqdm(executor.map(get_shape_cv2, files), total=len(files)))
def get_shape_pil(fname):
img=Image.open(fname)
return (img.size[0], img.size[1])
with concurrent.futures.ProcessPoolExecutor(8) as executor:
results = list(tqdm(executor.map(get_shape_pil, files), total=len(files)))
def get_shape_scardine_size(fname):
try:
width, height = get_image_size.get_image_size(fname)
except get_image_size.UnknownImageFormat:
width, height = -1, -1
return (width, height)
with concurrent.futures.ProcessPoolExecutor(8) as executor:
results = list(tqdm(executor.map(get_shape_scardine_size, files), total=len(files)))
def get_shape_shibukawa(fname):
width, height = imagesize.get(fname)
return (width, height)
with concurrent.futures.ProcessPoolExecutor(8) as executor:
results = list(tqdm(executor.map(get_shape_shibukawa, files), total=len(files)))
def get_shape_pymage_size(fname):
img_format = pymage_size.get_image_size(fname)
width, height = img_format.get_dimensions()
return (width, height)
with concurrent.futures.ProcessPoolExecutor(8) as executor:
results = list(tqdm(executor.map(get_shape_pymage_size, files), total=len(files)))
結果:
cv2.imread
: 8分23秒PIL.open
: 2m00sopsdroid/image_size
: 29秒shibukawa/imagesize_py
: 29秒kobaltcore/pymage_size
: 29秒したがって、opsdroid、シブカワ、kobaltcore は同じ速度で実行されます。私にとってもう 1 つの興味深い点は、どのライブラリが最適な形式をサポートしているかをよりよく理解することです。
[編集] そこで、高速ライブラリが異なる結果を提供するかどうかをテストしました。
# test if the libs provide the same results
def show_size_differences(fname):
w1, h1 = get_shape_scardine_size(fname)
w2, h2 = get_shape_pymage_size(fname)
w3, h3 = get_shape_shibukawa(fname)
if w1 != w2 or w2 != w3 or h1 != h2 or h2 != h3:
print(f"scardine: {w1}x{h1}, pymage: {w2}x{h2}, shibukawa: {w3}x{h3}")
with concurrent.futures.ProcessPoolExecutor(8) as executor:
results = list(tqdm(executor.map(show_size_differences, files), total=len(files)))
そして、そうではありません。
Unix システムでそれを行う別の簡単な方法。file
それは、すべてのシステムで標準化されているかどうかわからない出力に依存します。これは、おそらく製品コードでは使用しないでください。さらに、ほとんどの JPEG は画像サイズを報告しません。
import subprocess, re
image_size = list(map(int, re.findall('(\d+)x(\d+)', subprocess.getoutput("file " + filename))[-1]))