【问题标题】:How to reverse a RectangleF to a Picasa face hash如何将 RectangleF 反转为 Picasa 面部哈希
【发布时间】:2011-01-13 04:05:12
【问题描述】:

以下是 Picasa 存储为哈希的详细信息。它像这样存储它们:

faces=rect64(54391dc9b6a76c2b),4cd643f64b715489
[DSC_2289.jpg]
faces=rect64(1680000a5c26c82),76bc8d8d518750bc

网上的信息是这样说的:

rect64() 中包含的数字是一个 64 位的十六进制数字。

  • 将其分成四个 16 位数字。
  • 将每个数字除以最大无符号 16 位数 (65535),您将得到 0 到 1 之间的四个数字。
  • 剩下的四个数字为您提供面部矩形的相对坐标:(左、上、右、下)。
  • 如果您想以绝对坐标结束,请将左右乘以图像宽度,将顶部和底部乘以图像高度。

所以我将其转换为 RectangleF 的代码可以正常工作(仅保留相对坐标):

    public static RectangleF GetRectangle(string hashstr)
    {
        UInt64 hash = UInt64.Parse(hashstr, System.Globalization.NumberStyles.HexNumber);
        byte[] bytes = BitConverter.GetBytes(hash);

        UInt16 l16 = BitConverter.ToUInt16(bytes, 6);
        UInt16 t16 = BitConverter.ToUInt16(bytes, 4);
        UInt16 r16 = BitConverter.ToUInt16(bytes, 2);
        UInt16 b16 = BitConverter.ToUInt16(bytes, 0);

        float left = l16 / 65535.0F;
        float top = t16 / 65535.0F;
        float right = r16 / 65535.0F;
        float bottom = b16 / 65535.0F;

        return new RectangleF(left, top, right - left, bottom - top);
    }

现在我有一个 RectangleF,我想把它变回上面提到的哈希值。我似乎无法弄清楚这一点。看起来 picasa 使用 2 个字节,包括精度,但是 C# 中的浮点数是 8 个字节,甚至 BitConverter.ToSingle 也是 4 个字节。

任何帮助表示赞赏。

编辑:这是我现在所拥有的

    public static string HashFromRectangle(RectangleCoordinates rect)
    {
        Console.WriteLine("{0} {1} {2} {3}", rect.Left, rect.Top, rect.Right, rect.Bottom);
        UInt16 left = Convert.ToUInt16((float)rect.Left * 65535.0F);
        UInt16 top = Convert.ToUInt16((float)rect.Top * 65535.0F);
        UInt16 right = Convert.ToUInt16((float)rect.Right * 65535.0F);
        UInt16 bottom = Convert.ToUInt16((float)rect.Bottom * 65535.0F);            

        byte[] lb = BitConverter.GetBytes(left);
        byte[] tb = BitConverter.GetBytes(top);
        byte[] rb = BitConverter.GetBytes(right);
        byte[] bb = BitConverter.GetBytes(bottom);

        byte[] barray = new byte[8];
        barray[0] = lb[0];
        barray[1] = lb[1];
        barray[2] = tb[0];
        barray[3] = tb[1];
        barray[4] = rb[0];
        barray[5] = rb[1];
        barray[6] = bb[0];
        barray[7] = bb[1];

        return BitConverter.ToString(barray).Replace("-", "").ToLower();
    }

【问题讨论】:

标签: c# picasa bitconverter


【解决方案1】:

看起来你需要像这样从 HashFromRectangle(rect) 中取出浮点类型:

    UInt16 left = (UInt16)( rect.Left * 65535.0F);
    UInt16 top =(UInt16) (rect.Top * 65535.0F);
    UInt16 right = (UInt16) (rect.Right * 65535.0F);
    UInt16 bottom = (UInt16) (rect.Bottom * 65535.0F);

此外,使用它来填充数组可能更具可读性:

    Array.Copy(lb, 0, barray, 0, 2);
    Array.Copy(tb, 0, barray, 2, 2);
    Array.Copy(rb, 0, barray, 4, 2);
    Array.Copy(bb, 0, barray, 6, 2);

让我知道这是否有效!

亚伦

【讨论】:

  • 很遗憾没有。我在已知的哈希值 1cf0102160008916 上对此进行了测试。结果是哈希 ff2983393f520976 并反转到错误的坐标。
【解决方案2】:

您当前的代码正在交换每个坐标的字节。这是因为 BitConverter 以小端顺序为您提供字节(即数组中的第一个字节是最低有效字节)。如下交换您的分配,使解码和重新编码返回原始哈希。

        barray[0] = lb[1];
        barray[1] = lb[0];
        barray[2] = tb[1];
        barray[3] = tb[0];
        barray[4] = rb[1];
        barray[5] = rb[0];
        barray[6] = bb[1];
        barray[7] = bb[0];

也就是说,我认为使用简单的乘法和加法进行转换更清楚。如果您将哈希字符串作为单个 ulong 读入并进行减法/除法,则可以对哈希字符串进行类似的解码。例如对于编码:

    public static ushort ToUShort(double coordinate)
    {
        double ratio = Math.Max(0, Math.Min(Math.Round(coordinate * 65535), 65535));
        return (ushort)ratio;
    }

    public static string HashFromRectangle(Rect rect)
    {
        ulong left = ToUShort(rect.Left);
        ulong top = ToUShort(rect.Top);
        ulong right = ToUShort(rect.Right);
        ulong bottom = ToUShort(rect.Bottom);

        ulong hash = (((left * 65536) + top) * 65536 + right) * 65536 + bottom;
        return hash.ToString("x");
    }

【讨论】:

  • 谢谢,它似乎失去了一点精度,但这样做是正确的。
猜你喜欢
  • 2010-11-23
  • 2012-11-11
  • 1970-01-01
  • 2015-11-26
  • 1970-01-01
  • 2019-10-27
  • 2019-05-23
  • 1970-01-01
  • 2015-07-03
相关资源
最近更新 更多