Python'da bir görüntünün exif verilerini nasıl okuyabilirim?


Yanıtlar:


183

Bunu dene:

import PIL.Image
img = PIL.Image.open('img.jpg')
exif_data = img._getexif()

Bu size EXIF ​​sayısal etiketleri tarafından indekslenmiş bir sözlük vermelidir. Sözlüğün gerçek EXIF ​​etiket adı dizeleri tarafından indekslenmesini istiyorsanız, aşağıdaki gibi bir şey deneyin:

import PIL.ExifTags
exif = {
    PIL.ExifTags.TAGS[k]: v
    for k, v in img._getexif().items()
    if k in PIL.ExifTags.TAGS
}

10
Herhangi bir Python 3 alternatifi?
Santosh Kumar

2
@ 2rs2ts: Deneyin import ExifTags( PILönek olmadan ).
Florian Brucker

12
Python3 için Pillow'u kullanın. Hala geliştirilmekte olan PIL, bir çatal ve bir python3 uyumlu sürümü vardır
Mzzl

1
Bunu bu Soru üzerinde test edebilir, resimleri indirebilir ve ImageDescription almaya çalışabilir misiniz? stackoverflow.com/questions/22173902/…
AJ


30

ExifRead modülünü de kullanabilirsiniz :

import exifread
# Open image file for reading (binary mode)
f = open(path_name, 'rb')

# Return Exif tags
tags = exifread.process_file(f)

1
Bunu bu Soru üzerinde test edebilir, resimleri indirebilir ve ImageDescription almaya çalışabilir misiniz? stackoverflow.com/questions/22173902/…
AJ

2
@Clayton her iki görüntü için de exifread boş sözlük döndürür. Ama fotoğraflarım üzerinde test ettim ve gayet iyi çalışıyor.
tnq177

Ayrıca bir dizi resim için boş bir sözlük alıyorum. Bunun neden böyle olduğu hakkında yorum yapan var mı? Exifread.process_file () ne tür görüntülerle çalışır?
Momchill

17

Bunu kullanıyorum:

import os,sys
from PIL import Image
from PIL.ExifTags import TAGS

for (k,v) in Image.open(sys.argv[1])._getexif().iteritems():
        print '%s = %s' % (TAGS.get(k), v)

veya belirli bir alanı almak için:

def get_field (exif,field) :
  for (k,v) in exif.iteritems():
     if TAGS.get(k) == field:
        return v

exif = image._getexif()
print get_field(exif,'ExposureTime')

6
Daha iyisi, ETİKETLERİ ile ters çevirebilir name2tagnum = dict((name, num) for num, name in TAGS.iteritems())ve sonra yapabilirsiniz name2tagnum['ExposureTime'].
Ben

7
Python 3 için, değiştirmek exif.iteritems()içinexif.items()
SPRBRN

14

Python3.x ve başlangıç ​​için Pillow==6.0.0, Imagenesneler artık getexif()geri dönen <class 'PIL.Image.Exif'>veya Nonegörüntünün EXIF ​​verisi yoksa bir yöntem sağlar .

Gönderen Yastık 6.0.0 sürüm notları :

getexif()bir Exiförnek döndüren eklendi . Değerler bir sözlük gibi alınabilir ve ayarlanabilir. JPEG, PNG veya WEBP kaydedilirken, örnek exifçıktı görüntüsündeki herhangi bir değişikliği dahil etmek için bir bağımsız değişken olarak geçirilebilir .

ExifÇıkış sadece için dökülebilir dictEXIF verileri daha sonra normal anahtar değeri çiftleri olarak erişilebilir, böylece, dict. Anahtarlar, ExifTags.TAGSmodül kullanılarak dize adlarına eşlenebilen 16 bitlik tam sayılardır .

from PIL import Image, ExifTags

img = Image.open("sample.jpg")
img_exif = img.getexif()
print(type(img_exif))
# <class 'PIL.Image.Exif'>

if img_exif is None:
    print("Sorry, image has no exif data.")
else:
    img_exif_dict = dict(img_exif)
    print(img_exif_dict)
    # { ... 42035: 'FUJIFILM', 42036: 'XF23mmF2 R WR', 42037: '75A14188' ... }
    for key, val in img_exif_dict.items():
        if key in ExifTags.TAGS:
            print(f"{ExifTags.TAGS[key]}:{repr(val)}")
            # ExifVersion:b'0230'
            # ...
            # FocalLength:(2300, 100)
            # ColorSpace:1
            # FocalLengthIn35mmFilm:35
            # ...
            # Model:'X-T2'
            # Make:'FUJIFILM'
            # ...
            # DateTime:'2019:12:01 21:30:07'
            # ...

Python 3.6.8 ve Pillow==6.0.0.


Benim için çalışmıyor, ikili olarak .info yöntemini kullanarak sadece exif verilerini görebiliyorum
GM

12
import sys
import PIL
import PIL.Image as PILimage
from PIL import ImageDraw, ImageFont, ImageEnhance
from PIL.ExifTags import TAGS, GPSTAGS



class Worker(object):
    def __init__(self, img):
        self.img = img
        self.exif_data = self.get_exif_data()
        self.lat = self.get_lat()
        self.lon = self.get_lon()
        self.date =self.get_date_time()
        super(Worker, self).__init__()

    @staticmethod
    def get_if_exist(data, key):
        if key in data:
            return data[key]
        return None

    @staticmethod
    def convert_to_degress(value):
        """Helper function to convert the GPS coordinates
        stored in the EXIF to degress in float format"""
        d0 = value[0][0]
        d1 = value[0][1]
        d = float(d0) / float(d1)
        m0 = value[1][0]
        m1 = value[1][1]
        m = float(m0) / float(m1)

        s0 = value[2][0]
        s1 = value[2][1]
        s = float(s0) / float(s1)

        return d + (m / 60.0) + (s / 3600.0)

    def get_exif_data(self):
        """Returns a dictionary from the exif data of an PIL Image item. Also
        converts the GPS Tags"""
        exif_data = {}
        info = self.img._getexif()
        if info:
            for tag, value in info.items():
                decoded = TAGS.get(tag, tag)
                if decoded == "GPSInfo":
                    gps_data = {}
                    for t in value:
                        sub_decoded = GPSTAGS.get(t, t)
                        gps_data[sub_decoded] = value[t]

                    exif_data[decoded] = gps_data
                else:
                    exif_data[decoded] = value
        return exif_data

    def get_lat(self):
        """Returns the latitude and longitude, if available, from the 
        provided exif_data (obtained through get_exif_data above)"""
        # print(exif_data)
        if 'GPSInfo' in self.exif_data:
            gps_info = self.exif_data["GPSInfo"]
            gps_latitude = self.get_if_exist(gps_info, "GPSLatitude")
            gps_latitude_ref = self.get_if_exist(gps_info, 'GPSLatitudeRef')
            if gps_latitude and gps_latitude_ref:
                lat = self.convert_to_degress(gps_latitude)
                if gps_latitude_ref != "N":
                    lat = 0 - lat
                lat = str(f"{lat:.{5}f}")
                return lat
        else:
            return None

    def get_lon(self):
        """Returns the latitude and longitude, if available, from the 
        provided exif_data (obtained through get_exif_data above)"""
        # print(exif_data)
        if 'GPSInfo' in self.exif_data:
            gps_info = self.exif_data["GPSInfo"]
            gps_longitude = self.get_if_exist(gps_info, 'GPSLongitude')
            gps_longitude_ref = self.get_if_exist(gps_info, 'GPSLongitudeRef')
            if gps_longitude and gps_longitude_ref:
                lon = self.convert_to_degress(gps_longitude)
                if gps_longitude_ref != "E":
                    lon = 0 - lon
                lon = str(f"{lon:.{5}f}")
                return lon
        else:
            return None

    def get_date_time(self):
        if 'DateTime' in self.exif_data:
            date_and_time = self.exif_data['DateTime']
            return date_and_time 

if __name__ == '__main__':
    try:
        img = PILimage.open(sys.argv[1])
        image = Worker(img)
        lat = image.lat
        lon = image.lon
        date = image.date
        print(date, lat, lon)

    except Exception as e:
        print(e)

8

Kullanmanın ._getexifdaha yüksek python sürümlerinde çalışmadığını, ayrıca korumalı bir sınıf olduğunu ve mümkünse kullanmaktan kaçınılması gerektiğini buldum . Hata ayıklayıcıyı araştırdıktan sonra, bir görüntünün EXIF ​​verilerini almanın en iyi yolu olduğunu buldum:

from PIL import Image

def get_exif(path):
    return Image.open(path).info['parsed_exif']

Bu, bir görüntünün tüm EXIF ​​verilerinin sözlüğünü döndürür.

Not: Python3.x için PIL yerine Yastık kullanın


2
info['parsed_exif']Pillow 6.0 veya daha yenisini gerektirir. info['exif']5.4'te mevcuttur, ancak bu ham bir testtir.
Åsmund

1
info['parsed_exif']7.0.0 sürümünde yoktur ; sadece info['exif'].
ZF007

7

İşte okuması biraz daha kolay olabilecek olanı. Umarım bu yardımcı olur.

from PIL import Image
from PIL import ExifTags

exifData = {}
img = Image.open(picture.jpg)
exifDataRaw = img._getexif()
for tag, value in exifDataRaw.items():
    decodedTag = ExifTags.TAGS.get(tag, tag)
    exifData[decodedTag] = value

0

JPG dosyalarındaki exif bilgilerini ayarlamak için genellikle pyexiv2 kullanıyorum, ancak kitaplığı bir komut dosyasına aktardığımda QGIS komut dosyası çöküyor.

Kütüphane exif'i kullanarak bir çözüm buldum:

https://pypi.org/project/exif/

Kullanımı çok kolay ve Qgis ile herhangi bir problemim yok.

Bu kodda, ekranın anlık görüntüsüne GPS koordinatlarını ekliyorum:

from exif import Image
with open(file_name, 'rb') as image_file:
    my_image = Image(image_file)

my_image.make = "Python"
my_image.gps_latitude_ref=exif_lat_ref
my_image.gps_latitude=exif_lat
my_image.gps_longitude_ref= exif_lon_ref
my_image.gps_longitude= exif_lon

with open(file_name, 'wb') as new_image_file:
    new_image_file.write(my_image.get_file())
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.