使用PowerShell从图像文件中提取GPS纬度等(属性>详细信息

0wi1tuuw  于 2023-02-04  发布在  Shell
关注(0)|答案(4)|浏览(205)

我正在寻找一种方法来提取GPS纬度和经度值从大量的.jpg文件。
我知道Exiftool可以做到这一点,但由于我所寻找的值在Windows 10资源管理器中可见(属性〉详细信息〉GPS标题〉纬度)...我可以使用PS直接获取它们吗?我想这样会更快。
我知道如何提取$img.FullName等,但无法通过这种方式到达Latitude。

flvtvl50

flvtvl501#

要在不使用外部工具的情况下访问Windows资源管理器中的元数据(不同于文件系统元数据),必须使用Windows Image Acquisition (WIA) Automation Layer

# Create an ImageFile object and load an image file
$image = New-Object -ComObject Wia.ImageFile
$image.LoadFile("C:\Absolute\path\to\my.jpg")

# Read your desirered metadata
$image.Properties.Item('GpsLatitude').Value
$image.Properties.Item('GpsLongitude').Value

请注意,与ExifToolexiv2等外部工具相比,WIA的解析功能非常有限,但足以获取您所需的数据。
你可以阅读更多关于ImageFile对象的信息,以及它们在here中的作用。

xdnvmnnf

xdnvmnnf2#

感谢大家,尤其是@stackprotector。我学到了很多,并且设法找到了如何提取我的精确值,包括重要的N,S,E,W。
为了帮助别人,我发现了:

# Based on answer from @stackprotector (above)
# Create an ImageFile object and load an image file
$image = New-Object -ComObject Wia.ImageFile
$image.LoadFile("D:\temp\toNAS\temp\PXL_20210830_004210948.jpg")
$image.Properties.Item('GpsLatitudeRef').Value
# S
$image.Properties.Item('GpsLatitude').Value 
<#
Value Numerator Denominator
----- --------- -----------
   37        37           1
   51        51           1
43.92      4392         100
>#
# Can rinse and repeat for GpsLongitude

现在提取我想要的。这是一个子集;容易复制在gps经度为另一个:-)

$image.Properties.Item('GpsLatitude').Value[1].Value
# 37

 $image.Properties.Item('GpsLatitude').Value[2].Value
# 51

$image.Properties.Item('GpsLatitude').Value[3].Value
# 43.92

$image.Properties.Item('GpsLatitudeRef').Value 
# S

$image.Properties.Item('DateTime').Value
# 2021:08:30 10:42:10
# This is local not UTC

# So final latitude is 37 deg  51 min 43.92 sec S 
# Taken on 2021:08:30 10:42:10 local time

相机内的值显示为**-37.8622**,拍摄于2021年8月30日当地时间10:42:10,非常满意,包括“-”代表南部
我会试试Exiftool @丹尼尔,看看是否更容易,我以前用过,非常好。

***更新(2022-02-13)。***我最终选择了Exiftool。随着我对JSON越来越有信心,这个工具集对我来说也变得越来越明显。下面是关键代码片段(见下文)。还有一点:这个exiftool选项集在运行时不给“反馈”。2只有在最后才给出一个总结:

# $photoYear is the root folder with the images
$data = (exiftool -if '$gpsdatetime' -s -s -s -json -ext jpg -filename -FileTypeExtension -Directory -CreateDate -GPSDateTime -GPSLatitude -GPSLongitude -n -r $photoYear ) | ConvertFrom-Json
# ...
[int]$n = 0
foreach ($photo in $data){
    Write-host $n, "  " $photo.CreateDate,  $photo.GPSLatitude, $photo.GPSLongitude
    $n++
    }
ocebsuys

ocebsuys3#

使用@dwids和@stackprotector的答案,我得到了下面的代码来遍历一个文件夹中的所有文件,它不是最整洁的,但它是不言自明的:

cls

$FolderPath = "c:\MyFolder"

Get-ChildItem $FolderPath -Filter *.* | where { ! $_.PSIsContainer } | 
Foreach-Object {
    # Get the file name and path, write it out to screen
    $FileName = $_.FullName
    Write-Host "$FileName"

    # Create an ImageFile object and load an image file
    $image = New-Object -ComObject Wia.ImageFile
    $image.LoadFile($FileName)

    # Read your desirered metadata, if it doesn't contain any, say NONE
    try
    {
        #Clear variables for Lat and Lon
        Clear-Variable Lat*
        Clear-Variable Lon*
        $LatDEG = $image.Properties.Item('GpsLatitude').Value[1].Value
        $LatMIN = $image.Properties.Item('GpsLatitude').Value[2].Value
        $LatSEC = $image.Properties.Item('GpsLatitude').Value[3].Value 
        $LatREF = $image.Properties.Item('GpsLatitudeRef').Value
        $LonDEG = $image.Properties.Item('GpsLongitude').Value[1].Value
        $LonMIN = $image.Properties.Item('GpsLongitude').Value[2].Value
        $LonSEC = $image.Properties.Item('GpsLongitude').Value[3].Value 
        $LonREF = $image.Properties.Item('GpsLongitudeRef').Value

        # Convert them to Degrees Minutes Seconds Ref
        $LatSTR = "$LatDEG$([char]176) $LatMIN$([char]39) $LatSEC$([char]34) $LatREF"
        $LonSTR = "$LonDEG$([char]176) $LonMIN$([char]39) $LonSEC$([char]34) $LonREF"

        # Write the full coordinates out
        Write-Host "$LatSTR $LonSTR"
    }
    catch
    {
        Write-Host "NONE"
    }
}

显然,如果只需要坐标列表,可以删除Write-Host "$FileName"(文件路径和名称),或者如果只需要文件名,可以将其更改为Write-Host "$_"
您可以将-Recurse添加到Get-ChildItem $FolderPath -Filter *.* |,这样就可以使用Get-ChildItem $FolderPath -Filter *.* -Recurse |查看所有子文件夹中的所有文件。

omjgkv6w

omjgkv6w4#

@dwids-要显示进度,您可以使用exiftool 'pod' www.example.com中记录的exiftool的"进度"功能https://exiftool.org/exiftool_pod.html#Advanced-formatting-feature

  • progress [:[TITLE]]显示处理文件时的进度。如果不使用冒号,-progress选项会在每个已处理文件的名称后添加一个进度计数(用括号括起来),以提供当前文件号和要处理的文件总数。隐含-v0选项,导致在写入时也打印已处理文件的名称。与-if选项结合使用时,总数包括应用条件之前的所有文件,但不符合条件的文件将不会打印其名称。
    如果后跟冒号(即-progress:),则根据指定的TITLE字符串设置控制台窗口标题。如果未给定TITLE,则假定默认TITLE字符串为"ExifTool % p %%"。在该字符串中,% f表示文件名,% p表示进度百分比,% r表示进度比率,%##b表示宽度为"##"(如果省略"##",则为20个字符)的进度条,%%表示%字符。可以与normal-progress选项结合使用,以便在控制台消息中显示进度计数。(注意:要使此功能在Mac/Linux上正常运行,必须将stderr转到控制台。)
    下面的代码是从工作代码中摘录的,而不是重新编写您的示例:
$sourcedir = 'fewphotos'
$exifargs = 'exiftool -json -d %Y%m%dT%H%M%S%z -Model -DateTimeOriginal -ext jpg -progress:%50b -r ' + $sourcedir
$exifdata = invoke-expression $exifargs | ConvertFrom-Json

进度条将出现在exiftool运行窗口的框架中。%50b将为exiftool处理的每2%的文件创建一个新标记。
这个例子还展示了exiftool命令如何包含变量,例如源目录的变量。这个例子在Linux和Windows下都可以使用。
希望这个有用。
应该是一个评论,但我没有足够的代表。

相关问题