使用 python 获取图像的大小(NEF 和 jpeg)
use python to get the size of an image (NEF and jpeg)
用我的 NIKON D5100 拍照时,我用 raw (.NEF) 和 jpeg 格式拍摄。大多数时候我不使用原始图像,但有时我会这样做。
为了简化图像的标记和选择,我想自动将原始图像移动到不同的位置。作为检查 python 脚本以移动原始图像,我想将 jpeg 的图像分辨率与原始分辨率进行比较。到目前为止,我还没有找到 returns 原始图像和 jpeg 图像大小相同的方法。
这是我尝试使用的方法的总结 Python:
from PIL import Image as PIL_Image
from wand.image import Image as wand_Image
import imageio
from PIL.ExifTags import TAGS
import exifread
from collections import namedtuple
def get_exif(fname):
# http://www.blog.pythonlibrary.org/2010/03/28/getting-photo-metadata-exif-using-python/
ret = {}
i = PIL_Image.open(fname)
info = i._getexif()
for tag, value in info.items():
decoded = TAGS.get(tag, tag)
ret[decoded] = value
return ret
def get_imagesize_PIL(fname):
with PIL_Image.open(fname) as im:
return im.size
def get_imagesize_PIL2(fname):
exif = get_exif(fname)
return exif['ExifImageHeight'], exif['ExifImageWidth']
def get_imagesize_PIL3(fname):
with PIL_Image.open(fname) as im:
return im.info
def get_imagesize_imageioraw(fname):
return imageio.imread(fname, "raw").shape[:-1]
def get_imagesize_imageio(fname):
return imageio.imread(fname).shape[:-1]
def get_imagesize_exifread(fname): #
exif = exifread.process_file(open(fname, 'rb'), strict=True)
return exif['Image XResolution'], exif['Image YResolution']
def get_imagesize_exifread2(fname):
exif = exifread.process_file(open(fname, 'rb'), strict=True)
return exif['Image ImageLength'], exif['Image ImageWidth']
def get_imagesize_exifread3(fname):
exif = exifread.process_file(open(fname, 'rb'), strict=True)
return exif['MakerNote CropHiSpeed']
def get_imagesize_exifread4(fname):
exif = exifread.process_file(open(fname, 'rb'), strict=True)
return exif['EXIF ExifImageLength'], exif['EXIF ExifImageWidth']
def get_imagesize_wand(fname):
with wand_Image(filename=fname) as img:
return img.size
def get_imagesize_wand2(fname):
with wand_Image(filename=fname) as img:
return img.page
# def get_imagesize_wand3(fname):
# with wand_Image(filename=fname) as img:
# return img.info
def get_imagesize_libraw(fname):
with rawkit_Raw(filename=fname) as raw:
print(raw.Metadata.height, raw.Metadata.width)
def create_eval(fmethod, fname):
try:
eval_str = "get_imagesize_%s('%s')" % (fmethod, fname)
# print(eval_str)
return eval(eval_str)
except BaseException as e:
return str(e)
if __name__ == '__main__':
file_nt = namedtuple("image_file", "filename tag")
filetypes = list()
filetypes.append(file_nt("20120917_131155 DSC_0159.JPG", "jpeg"))
filetypes.append(file_nt("20120917_131155 DSC_0159.NEF", "nef"))
# filetypes.append(file_nt("20120917_131155 DSC_0159.xmp", "xmp"))
# @TODO: add method to check into xmp?
methods = [
"PIL",
"PIL2",
"PIL3",
"imageioraw",
"imageio",
"exifread",
"exifread2",
"exifread3",
"exifread4",
"wand",
"wand2",
"libraw",
]
for method in methods:
for filetype in filetypes:
print("%s %s: %s" % (filetype.tag, method, repr(create_eval(method, filetype.filename))))
# @TODO: add timers to check the fastest method
这个结果
jpeg PIL: (4928, 3264)
nef PIL: (160, 120)
jpeg PIL2: (3264, 4928)
nef PIL2: "'TiffImageFile' object has no attribute '_getexif'"
jpeg PIL3: {'exif': b'Exif\x00\x00MM\x00*\x00\x00\x00\x08\x00\x0b\x01\x0f\x00\x02\x00\x00\x00\x12\x00\x00\x00\x94\x01\x10\x00\x02\x00\x00\x00\x0c\x00\x00\x00\xa8\x01\x12\x00...'}
nef PIL3: {'compression': 'raw', 'dpi': (300.0, 300.0)}
jpeg imageioraw: 'Could not load bitmap "C:\Users\maarten\PycharmProjects\fotosize\20120917_131155 DSC_0159.JPG": LibRaw : failed to open input stream (unknown format)'
nef imageioraw: (3280, 4948)
jpeg imageio: (3264, 4928)
nef imageio: (120, 160)
jpeg exifread: ((0x011A) Ratio=300 @ 180, (0x011B) Ratio=300 @ 188)
nef exifread: ((0x011A) Ratio=300 @ 356, (0x011B) Ratio=300 @ 364)
jpeg exifread2: "'Image ImageLength'"
nef exifread2: ((0x0101) Long=120 @ 42, (0x0100) Long=160 @ 30)
jpeg exifread3: (0x001B) Short=[0, 4992, 3280, 4992, 3280, 0, 0] @ 1676
nef exifread3: (0x001B) Short=[0, 4992, 3280, 4992, 3280, 0, 0] @ 1852
jpeg exifread4: ((0xA003) Short=3264 @ 526, (0xA002) Short=4928 @ 514)
nef exifread4: "'EXIF ExifImageLength'"
jpeg wand: (4928, 3264)
nef wand: (4948, 3280)
jpeg wand2: (4928, 3264, 0, 0)
nef wand2: (4948, 3280, 0, 0)
jpeg libraw: 'Cannot find LibRaw on your system!'
nef libraw: 'Cannot find LibRaw on your system!'
返回 160x120 的可能是嵌入预览图像
Windows 资源管理器似乎确实找到了正确的维度
screenshot
我也试过rawkit,但是好像找不到libraw。我没有找到关于如何 'install' libraw 的明确说明,但我尝试将其命名为 libraw.dll 或 Raw.dll 复制到 "C:\Anaconda3\Library\bin" 中,当我尝试
In[3]: ctypes.util.find_library("libraw")
Out[3]:
'C:\Anaconda3\Library\bin\libraw.dll'
In[4]: ctypes.util.find_library("Raw")
Out[4]:
'C:\Anaconda3\Library\bin\Raw.dll'
它似乎确实找到了。
有谁知道我可以用什么方法吗? jpeg 和 NEF 图像不必使用相同的方法,但欢迎这样做。
目前性能不是关键问题,但越快越好
可以在 my github repo
中找到代码和示例图像
ImageMagick 将它们标识如下:
identify sign.jpg
输出
sign.jpg JPEG 4928x3264 4928x3264+0+0 8-bit sRGB 4.401MB 0.000u 0:00.009
对于 NEF:
identify ~/Desktop/*NEF
输出
/Users/... NEF 4948x3280 4948x3280+0+0 16-bit sRGB 75.99MB 0.010u 0:00.009
,我找到了一个使用 win32com 的不同解决方案
from pprint import pprint
import win32com.client
import os
import re
from pathlib import Path
# https://bytes.com/topic/python/answers/802917-finding-file-details
def _get_dimensions_subdir(folder_name):
sh = win32com.client.Dispatch('Shell.Application')
ns = sh.NameSpace(folder_name)
results = {}
for c in range(0, 255):
colname = ns.GetDetailsOf(None, c)
if colname == 'Dimensions':
for i in ns.Items():
dimensions = ns.GetDetailsOf(i, c)
if dimensions:
results[ns.GetDetailsOf(i, 0)] = _parse_dimensions(dimensions)
return results
dim_pat = re.compile("(\d+) x (\d+)")
def _parse_dimensions(dim):
x, y = dim_pat.findall(dim)[0]
return int(x), int(y)
def get_combined_results(subdirs, src_path):
for subdir in subdirs:
dim = _get_dimensions_subdir(str(subdir))
if dim:
yield str(subdir.relative_to(src_path)), dim
if __name__ == '__main__':
DATA_DIR = Path(".")
subdirs = DATA_DIR.glob("**")
results = get_combined_results(subdirs, DATA_DIR)
pprint(dict(results))
用我的 NIKON D5100 拍照时,我用 raw (.NEF) 和 jpeg 格式拍摄。大多数时候我不使用原始图像,但有时我会这样做。
为了简化图像的标记和选择,我想自动将原始图像移动到不同的位置。作为检查 python 脚本以移动原始图像,我想将 jpeg 的图像分辨率与原始分辨率进行比较。到目前为止,我还没有找到 returns 原始图像和 jpeg 图像大小相同的方法。
这是我尝试使用的方法的总结 Python:
from PIL import Image as PIL_Image
from wand.image import Image as wand_Image
import imageio
from PIL.ExifTags import TAGS
import exifread
from collections import namedtuple
def get_exif(fname):
# http://www.blog.pythonlibrary.org/2010/03/28/getting-photo-metadata-exif-using-python/
ret = {}
i = PIL_Image.open(fname)
info = i._getexif()
for tag, value in info.items():
decoded = TAGS.get(tag, tag)
ret[decoded] = value
return ret
def get_imagesize_PIL(fname):
with PIL_Image.open(fname) as im:
return im.size
def get_imagesize_PIL2(fname):
exif = get_exif(fname)
return exif['ExifImageHeight'], exif['ExifImageWidth']
def get_imagesize_PIL3(fname):
with PIL_Image.open(fname) as im:
return im.info
def get_imagesize_imageioraw(fname):
return imageio.imread(fname, "raw").shape[:-1]
def get_imagesize_imageio(fname):
return imageio.imread(fname).shape[:-1]
def get_imagesize_exifread(fname): #
exif = exifread.process_file(open(fname, 'rb'), strict=True)
return exif['Image XResolution'], exif['Image YResolution']
def get_imagesize_exifread2(fname):
exif = exifread.process_file(open(fname, 'rb'), strict=True)
return exif['Image ImageLength'], exif['Image ImageWidth']
def get_imagesize_exifread3(fname):
exif = exifread.process_file(open(fname, 'rb'), strict=True)
return exif['MakerNote CropHiSpeed']
def get_imagesize_exifread4(fname):
exif = exifread.process_file(open(fname, 'rb'), strict=True)
return exif['EXIF ExifImageLength'], exif['EXIF ExifImageWidth']
def get_imagesize_wand(fname):
with wand_Image(filename=fname) as img:
return img.size
def get_imagesize_wand2(fname):
with wand_Image(filename=fname) as img:
return img.page
# def get_imagesize_wand3(fname):
# with wand_Image(filename=fname) as img:
# return img.info
def get_imagesize_libraw(fname):
with rawkit_Raw(filename=fname) as raw:
print(raw.Metadata.height, raw.Metadata.width)
def create_eval(fmethod, fname):
try:
eval_str = "get_imagesize_%s('%s')" % (fmethod, fname)
# print(eval_str)
return eval(eval_str)
except BaseException as e:
return str(e)
if __name__ == '__main__':
file_nt = namedtuple("image_file", "filename tag")
filetypes = list()
filetypes.append(file_nt("20120917_131155 DSC_0159.JPG", "jpeg"))
filetypes.append(file_nt("20120917_131155 DSC_0159.NEF", "nef"))
# filetypes.append(file_nt("20120917_131155 DSC_0159.xmp", "xmp"))
# @TODO: add method to check into xmp?
methods = [
"PIL",
"PIL2",
"PIL3",
"imageioraw",
"imageio",
"exifread",
"exifread2",
"exifread3",
"exifread4",
"wand",
"wand2",
"libraw",
]
for method in methods:
for filetype in filetypes:
print("%s %s: %s" % (filetype.tag, method, repr(create_eval(method, filetype.filename))))
# @TODO: add timers to check the fastest method
这个结果
jpeg PIL: (4928, 3264)
nef PIL: (160, 120)
jpeg PIL2: (3264, 4928)
nef PIL2: "'TiffImageFile' object has no attribute '_getexif'"
jpeg PIL3: {'exif': b'Exif\x00\x00MM\x00*\x00\x00\x00\x08\x00\x0b\x01\x0f\x00\x02\x00\x00\x00\x12\x00\x00\x00\x94\x01\x10\x00\x02\x00\x00\x00\x0c\x00\x00\x00\xa8\x01\x12\x00...'}
nef PIL3: {'compression': 'raw', 'dpi': (300.0, 300.0)}
jpeg imageioraw: 'Could not load bitmap "C:\Users\maarten\PycharmProjects\fotosize\20120917_131155 DSC_0159.JPG": LibRaw : failed to open input stream (unknown format)'
nef imageioraw: (3280, 4948)
jpeg imageio: (3264, 4928)
nef imageio: (120, 160)
jpeg exifread: ((0x011A) Ratio=300 @ 180, (0x011B) Ratio=300 @ 188)
nef exifread: ((0x011A) Ratio=300 @ 356, (0x011B) Ratio=300 @ 364)
jpeg exifread2: "'Image ImageLength'"
nef exifread2: ((0x0101) Long=120 @ 42, (0x0100) Long=160 @ 30)
jpeg exifread3: (0x001B) Short=[0, 4992, 3280, 4992, 3280, 0, 0] @ 1676
nef exifread3: (0x001B) Short=[0, 4992, 3280, 4992, 3280, 0, 0] @ 1852
jpeg exifread4: ((0xA003) Short=3264 @ 526, (0xA002) Short=4928 @ 514)
nef exifread4: "'EXIF ExifImageLength'"
jpeg wand: (4928, 3264)
nef wand: (4948, 3280)
jpeg wand2: (4928, 3264, 0, 0)
nef wand2: (4948, 3280, 0, 0)
jpeg libraw: 'Cannot find LibRaw on your system!'
nef libraw: 'Cannot find LibRaw on your system!'
返回 160x120 的可能是嵌入预览图像
Windows 资源管理器似乎确实找到了正确的维度 screenshot
我也试过rawkit,但是好像找不到libraw。我没有找到关于如何 'install' libraw 的明确说明,但我尝试将其命名为 libraw.dll 或 Raw.dll 复制到 "C:\Anaconda3\Library\bin" 中,当我尝试
In[3]: ctypes.util.find_library("libraw")
Out[3]:
'C:\Anaconda3\Library\bin\libraw.dll'
In[4]: ctypes.util.find_library("Raw")
Out[4]:
'C:\Anaconda3\Library\bin\Raw.dll'
它似乎确实找到了。
有谁知道我可以用什么方法吗? jpeg 和 NEF 图像不必使用相同的方法,但欢迎这样做。
目前性能不是关键问题,但越快越好
可以在 my github repo
中找到代码和示例图像ImageMagick 将它们标识如下:
identify sign.jpg
输出
sign.jpg JPEG 4928x3264 4928x3264+0+0 8-bit sRGB 4.401MB 0.000u 0:00.009
对于 NEF:
identify ~/Desktop/*NEF
输出
/Users/... NEF 4948x3280 4948x3280+0+0 16-bit sRGB 75.99MB 0.010u 0:00.009
from pprint import pprint
import win32com.client
import os
import re
from pathlib import Path
# https://bytes.com/topic/python/answers/802917-finding-file-details
def _get_dimensions_subdir(folder_name):
sh = win32com.client.Dispatch('Shell.Application')
ns = sh.NameSpace(folder_name)
results = {}
for c in range(0, 255):
colname = ns.GetDetailsOf(None, c)
if colname == 'Dimensions':
for i in ns.Items():
dimensions = ns.GetDetailsOf(i, c)
if dimensions:
results[ns.GetDetailsOf(i, 0)] = _parse_dimensions(dimensions)
return results
dim_pat = re.compile("(\d+) x (\d+)")
def _parse_dimensions(dim):
x, y = dim_pat.findall(dim)[0]
return int(x), int(y)
def get_combined_results(subdirs, src_path):
for subdir in subdirs:
dim = _get_dimensions_subdir(str(subdir))
if dim:
yield str(subdir.relative_to(src_path)), dim
if __name__ == '__main__':
DATA_DIR = Path(".")
subdirs = DATA_DIR.glob("**")
results = get_combined_results(subdirs, DATA_DIR)
pprint(dict(results))