5

別の SO 回答で見つけたコードを使用して pyexiv2 Python モジュールを使用して JPEG にジオタグを付けています (参照: Python を使用して jpeg-images にジオタグを付ける最良の方法は何ですか? )。 GPSTag 値について質問があります。

回答に示されているコードには、次の行があります。

exiv_image["Exif.Image.GPSTag"] = 654
exiv_image["Exif.GPSInfo.GPSMapDatum"] = "WGS-84"
exiv_image["Exif.GPSInfo.GPSVersionID"] = '2 0 0 0'

Exiv2 のドキュメントを調べたところ、GPSTag、GPSMapDatum、および GPSVersionID の説明が見つかりましたが、GPSTag の値についてはまだ混乱しています。

ドキュメントからそれは言う:

GPS 情報 IFD へのポインター。Exif IFD と同様に、GPS Info IFD の Interoperability 構造には画像データがありません。

この説明は、使用する値を決定する方法を実際には説明しておらず、オンラインで GPSTag のより適切な説明を見つけることができませんでした。

だから私の質問は:

  1. 新しい画像が与えられた場合、Exif.Image.GPSTag の値をどのように決定しますか?
  2. コード サンプルで値 654 が使用されているのはなぜですか (これは質問 1 で回答される可能性があります)。

ご協力いただきありがとうございます。

4

2 に答える 2

3

pyexiv2 を使用して写真にジオタグを付ける最良の方法は、間違いなく私のプログラム、GottenGeographyを使用することです;-)

しかし、真剣に、pyexiv2 から GPS データにアクセスしたい場合、そのコードは次のようになります。

    GPS = 'Exif.GPSInfo.GPS'
    try:
        self.latitude = dms_to_decimal(
            *self.exif[GPS + 'Latitude'].value +
            [self.exif[GPS + 'LatitudeRef'].value]
        )
        self.longitude = dms_to_decimal(
            *self.exif[GPS + 'Longitude'].value +
            [self.exif[GPS + 'LongitudeRef'].value]
        )
    except KeyError:
        pass
    try:
        self.altitude = float(self.exif[GPS + 'Altitude'].value)
        if int(self.exif[GPS + 'AltitudeRef'].value) > 0:
            self.altitude *= -1
    except KeyError:
        pass

そして、書き方は次のようになります。

    self.exif[GPS + 'AltitudeRef']  = '0' if self.altitude >= 0 else '1'
    self.exif[GPS + 'Altitude']     = Fraction(self.altitude)
    self.exif[GPS + 'Latitude']     = decimal_to_dms(self.latitude)
    self.exif[GPS + 'LatitudeRef']  = 'N' if self.latitude >= 0 else 'S'
    self.exif[GPS + 'Longitude']    = decimal_to_dms(self.longitude)
    self.exif[GPS + 'LongitudeRef'] = 'E' if self.longitude >= 0 else 'W'
    self.exif[GPS + 'MapDatum']     = 'WGS-84'

これらのサポート機能により:

class Fraction(fractions.Fraction):
    """Only create Fractions from floats.

    >>> Fraction(0.3)
    Fraction(3, 10)
    >>> Fraction(1.1)
    Fraction(11, 10)
    """

    def __new__(cls, value, ignore=None):
        """Should be compatible with Python 2.6, though untested."""
        return fractions.Fraction.from_float(value).limit_denominator(99999)

def dms_to_decimal(degrees, minutes, seconds, sign=' '):
    """Convert degrees, minutes, seconds into decimal degrees.

    >>> dms_to_decimal(10, 10, 10)
    10.169444444444444
    >>> dms_to_decimal(8, 9, 10, 'S')
    -8.152777777777779
    """
    return (-1 if sign[0] in 'SWsw' else 1) * (
        float(degrees)        +
        float(minutes) / 60   +
        float(seconds) / 3600
    )


def decimal_to_dms(decimal):
    """Convert decimal degrees into degrees, minutes, seconds.

    >>> decimal_to_dms(50.445891)
    [Fraction(50, 1), Fraction(26, 1), Fraction(113019, 2500)]
    >>> decimal_to_dms(-125.976893)
    [Fraction(125, 1), Fraction(58, 1), Fraction(92037, 2500)]
    """
    remainder, degrees = math.modf(abs(decimal))
    remainder, minutes = math.modf(remainder * 60)
    return [Fraction(n) for n in (degrees, minutes, remainder * 60)]

私は現在、 GObject イントロスペクションを使用して exiv2 ライブラリに直接アクセスする GExiv2 と呼ばれる pyexiv2 の代替案に取り組んでおり、フィードバックをお待ちしています。gexiv2 と pyexiv2 はどちらも同じ exiv2 ライブラリのラッパーですが、違いは、pyexiv2 は非常に大規模なプロジェクトであり、多くの接着剤が含まれており、Python でのみ動作し、放棄の瀬戸際にあります*。一方、gexiv2 は軽くて機敏で、どのプログラミング言語からでもアクセスでき、Shotwell で使用されているおかげでよく維持されています。

お役に立てれば!

* pyexiv2's author, Olivier Tilloy, has asked me for help with maintainership as he no longer has much time
于 2012-06-29T06:49:48.680 に答える
0

私のバージョン、少し長い...

from fractions import Fraction
import pyexiv2

try:
    metadata = pyexiv2.metadata.ImageMetadata(image_file)
    metadata.read();
    thumb = metadata.exif_thumbnail

    try:
        latitude = metadata.__getitem__("Exif.GPSInfo.GPSLatitude")
        latitudeRef = metadata.__getitem__("Exif.GPSInfo.GPSLatitudeRef")
        longitude = metadata.__getitem__("Exif.GPSInfo.GPSLongitude")
        longitudeRef = metadata.__getitem__("Exif.GPSInfo.GPSLongitudeRef")

        latitude = str(latitude).split("=")[1][1:-1].split(" ");
        latitude = map(lambda f: str(float(Fraction(f))), latitude)
        latitude = latitude[0] + u"\u00b0" + latitude[1] + "'" + latitude[2] + '"' + " " + str(latitudeRef).split("=")[1][1:-1]

        longitude = str(longitude).split("=")[1][1:-1].split(" ");
        longitude = map(lambda f: str(float(Fraction(f))), longitude)
        longitude = longitude[0] + u"\u00b0" + longitude[1] + "'" + longitude[2] + '"' + " " + str(longitudeRef).split("=")[1][1:-1]

        latitude_value = dms_to_decimal(*metadata.__getitem__("Exif.GPSInfo.GPSLatitude").value + [metadata.__getitem__("Exif.GPSInfo.GPSLatitudeRef").value]);
        longitude_value = dms_to_decimal(*metadata.__getitem__("Exif.GPSInfo.GPSLongitude").value + [metadata.__getitem__("Exif.GPSInfo.GPSLongitudeRef").value]);

        print "--- GPS ---"
        print "Coordinates: " + latitude + ", " + longitude
        print "Coordinates: " + str(latitude_value) + ", " + str(longitude_value)
        print "--- GPS ---"
    except Exception, e:
        print "No GPS Information!"
        #print e

    # Check for thumbnail
    if(thumb.data == ""):
        print "No thumbnail!"
except Exception, e:
    print "Error processing image..."
    print e;
于 2012-12-12T11:46:33.513 に答える