141

次の方法でPILを使用して画像サイズを取得できることを理解しています

from PIL import Image
im = Image.open(image_filename)
width, height = im.size

ただし、画像をメモリにロードすることなく、画像の幅と高さを取得したいと考えています。それは可能ですか?私は画像サイズの統計のみを行っており、画像の内容は気にしません。処理を高速化したいだけです。

4

7 に答える 7

3

OPは「より高速な」ソリューションに興味を持っていました。私は最速のソリューションに興味があり、実際のベンチマークでそれに答えようとしています。

私は比較しています:

202897 ほとんどが 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: 2m00s
  • opsdroid/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)))

そして、そうではありません。

于 2021-11-04T16:48:00.423 に答える
2

Unix システムでそれを行う別の簡単な方法。fileそれは、すべてのシステムで標準化されているかどうかわからない出力に依存します。これは、おそらく製品コードでは使用しないでください。さらに、ほとんどの JPEG は画像サイズを報告しません。

import subprocess, re
image_size = list(map(int, re.findall('(\d+)x(\d+)', subprocess.getoutput("file " + filename))[-1]))
于 2017-06-13T09:08:38.737 に答える