【问题标题】:Convert hex to latitude longitude from dashcam .MOV file从dashcam .MOV文件将十六进制转换为纬度经度
【发布时间】:2018-01-10 09:49:08
【问题描述】:

我有一个以 .MOV 格式保存视频的 OEM 行车记录仪。我想以编程方式从视频文件中提取嵌入的 gps 数据。在十六进制编辑器中打开 .mov 文件后,我发现了带有 freeGPS 标头的数据包,我可以确认对于我的 7 秒示例视频有 7 个数据包,所以我知道 gps 数据的来源。

我已经找到了日期和时间,但在将十六进制值转换为纬度经度时遇到了困难。以下是使用 Registrator Viewer 提取时的十六进制值及其等效坐标。

273108AC1C7996404E,0D022B873EA3C74045 - 14.637967,121.041475 516B9A771C7996404E,0D022B873EA3C74045 - 14.637963,121.041475 B9FC87F41B7996404E,52499D803EA3C74045 - 14.637955,121.041472 B9FC87F41B7996404E,52499D803EA3C74045 - 14.637955,121.041472 B459F5B91A7996404E,C442AD693EA3C74045 - 14.637935,121.041460 1DEBE2361A7996404E,ACAD85F3EA3C74045 - 14.637927,121.041455 08CE19511A7996404E,4FD1915C3EA3C74045 - 14.637928,121.041453

加粗的字节直接转换为@N 和@E,所以我认为它们不是转换的一部分。我已经尝试了以下答案,但没有成功获得正确的坐标。

How to convert GPS Longitude and latitude from hex

How to convert my binary (hex) data to latitude and longitude?

我已经向行车记录仪提供商发送了一封电子邮件,要求他们提供协议文档,但看起来他们没有,因为当我要求他们自己的视频播放器时,他们发送了 Registrator Viewer。

我还将包含第一个 freeGPS 数据包,以防我看错了地方。

00 00 80 00 66 72 65 65 47 50 53 20 98 00 00 00 78 2E 78 78 00 00 00 00 00 00 00 00 00 00 00 00 30 30 30 30 30 00 00 0 00 00 00 00 00 00 00 00 03 00 00 00 03 00 00 00 27 00 00 00 41 00 00 00 27 31 08 AC 1C 79 96 40 4E 00 00 00 00 00 00 00 0D 02 2B 87 3E A3 C7 40 45 00 00 00 00 00 00 00 8F C2 F5 28 5C 8F E2 3F 48 E1 7A 14 AE 07 68 40 11 00 00 00 06 00 00 00 14 00 00 00 76 00 00 00 88 00 00 00 DE 00 00 00 4D 00 00 00 49 00 00 00 4F 00 00 00 2D 00 00 00 2B 00 00 00 00 0 p>

粗体数据按顺序提取:freeGPS、时间、纬度@N?、经度@E?、日期

我可以确认时间和日期是正确的。速度应该是 1 公里/小时,但我也找不到。

提前感谢那些可以提供帮助的人。

编辑: 这是测试视频的链接。 Test Video

【问题讨论】:

标签: gps hex latitude-longitude


【解决方案1】:

找到this GPS 数据格式的解释,对我有用。

        public static ViofoGpsPoint Parse(uint offset, uint size, byte[] file)
    {
        byte[] data = new byte[size];
        Array.Copy(file, offset, data, 0, size);

        uint pos = 0;

        uint size1 = Box.ReadUintBE(data, pos); pos += 4;
        string type = Encoding.ASCII.GetString(data, (int)pos, 4); pos += 4;
        string magic = Encoding.ASCII.GetString(data, (int)pos, 4); pos += 4;

        if (size != size1 || type != "free" || magic != "GPS ")
            return null;

        ViofoGpsPoint gps = new ViofoGpsPoint();

        //# checking for weird Azdome 0xAA XOR "encrypted" GPS data. 
        //This portion is a quick fix.
        uint payload_size = 254;
        if (data[pos] == 0x05)
        {
            if (size < 254)
                payload_size = size;

            byte[] payload = new byte[payload_size];

            pos += 6; //???
            for (int i = 0; i < payload_size; i++)
            {
                payload[i] = (byte)(file[pos + i] ^ 0xAA);
            }
        }
        else if ((char)data[pos] == 'L')
        {
            const uint OFFSET_V2 = 48, OFFSET_V1 = 16; 
            pos = OFFSET_V2;

            //# Datetime data
            int hour = (int)Box.ReadUintLE(data, pos); pos += 4;
            int minute = (int)Box.ReadUintLE(data, pos); pos += 4;
            int second = (int)Box.ReadUintLE(data, pos); pos += 4;
            int year = (int)Box.ReadUintLE(data, pos); pos += 4;
            int month = (int)Box.ReadUintLE(data, pos); pos += 4;
            int day = (int)Box.ReadUintLE(data, pos); pos += 4;

            try { gps.Date = new DateTime(2000 + year, month, day, hour, minute, second); }
            catch (Exception err) { Debug.WriteLine(err.ToString()); return null; }

            //# Coordinate data
            char active = (char)data[pos]; pos++;
            gps.IsActive = (active == 'A');

            gps.Latitude_hemisphere = (char)data[pos]; pos++;
            gps.Longtitude_hemisphere = (char)data[pos]; pos++;
            gps.Unknown = data[pos]; pos++;

            float lat = Box.ReadFloatLE(data, pos); pos += 4;
            gps.Latitude = FixCoordinate(lat, gps.Latitude_hemisphere);

            float lon = Box.ReadFloatLE(data, pos); pos += 4;
            gps.Longtitude = FixCoordinate(lon, gps.Longtitude_hemisphere);

            gps.Speed = Box.ReadFloatLE(data, pos); pos += 4;
            gps.Bearing = Box.ReadFloatLE(data, pos); pos += 4;

            return gps;
        }

        return null;
    }

    /// <summary>
    /// # Novatek stores coordinates in odd DDDmm.mmmm format
    /// </summary>
    /// <param name="coord"></param>
    /// <param name="hemisphere"></param>
    /// <returns></returns>
    private static double FixCoordinate(double coord, char hemisphere)
    {
        double minutes = coord % 100.0;
        double degrees = coord - minutes;

        double coordinate = degrees / 100.0 + (minutes / 60.0);
        if (hemisphere == 'S' || hemisphere == 'W')
            return -1 * (coordinate);
        else
            return (coordinate);
    }

【讨论】:

  • 'FixCoordinate'函数的定义是什么?
  • 添加了“FixCoordinate”功能 - 它将格式从奇数 DDDmm.mmmm 调整为标准“双” 整个项目在:link
【解决方案2】:

不确定这有多大帮助,但如果您将十六进制字符串(包括末尾的 0x40)转换为小端 IEEE-754 双精度实数,那么您将获得大约 100 倍的纬度/经度。

在 C 中,我做了类似的事情

printf( "%f\n", *(double*)"\x27\x31\x08\xAC\x1C\x79\x96\x40" );
printf( "%f\n", *(double*)"\x0D\x02\x2B\x87\x3E\xA3\xC7\x40" );

然后出去

1438.278000
12102.488500

感谢@TDG更新

如果 1438.278 被解释为 14 度 38.278 分钟,那么您将得到一个十进制值 14.6379666666666667。如果 12102.4885 被解释为 121 度和 2.4885 分钟,则十进制等效值为 121.041475

执行此操作的一些示例 C 代码

#include<stdio.h>
double convert( double input ) {
  int i = input/100;
  return ( input - i*100 ) / 60 + i;
}
int main(){
  printf( "%f\n", convert( *(double*)"\x27\x31\x08\xAC\x1C\x79\x96\x40" ) );
  printf( "%f\n", convert( *(double*)"\x0D\x02\x2B\x87\x3E\xA3\xC7\x40" ) );
}

【讨论】:

  • 实际经度与使用此方法计算的经度之间的差异非常大。
  • 我认为@ceilingcat 是对的 - 将 1438.278 读作 14 度 38 分 27.8 秒。
  • 谢谢@ceilingcat 和@TDG! PS:我还需要帮助在这个十六进制数据中找到速度和方位,它应该是 1km/h 和 192。
  • 我认为速度的单位是 m/s - 米每秒,而不是 kmh。不知道标题。
  • @RioMarieA.Callos 我从真北得到了大约 209.43 度的方位,但我可能选择了与你不同的点。 209.43 ~ 90+atan2( second_latitude-first_latitude, second_longitude-first_longitude ) * 180/pi 要估计速度,至少需要两个时间戳和两个航路点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-26
  • 2013-01-05
  • 2019-08-04
  • 2010-11-11
  • 2014-09-12
相关资源
最近更新 更多