如何扭转的RectangleF到Picasa脸哈希 [英] How to reverse a RectangleF to a Picasa face hash

查看:251
本文介绍了如何扭转的RectangleF到Picasa脸哈希的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面是什么的Picasa商店作为散列的细节。它存储他们是这样的:

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

信息在网络上这样说:



在rect64包裹()的数目是一个64位的十六进制数。




  • 打破,最多成4个16位的数字。

  • 将每个由最大无符号16位号码(65535),你就会有0和1之间的四个数字。

  • 剩下的给你脸矩形相对坐标四个数字:(左,上,右,下)

  • 如果你想用绝对坐标结束了,多了。左和右的图像的宽度和顶部和底部由图像高度。



因此,我的代码,以将其转换成一个的RectangleF作品就好(只保留相对坐标):

 公共静态的RectangleF GetRectangle(字符串hashstr)
{
UINT64哈希= UInt64.Parse(hashstr,System.Globalization.NumberStyles.HexNumber);
字节[]字节= BitConverter.GetBytes(散);

UINT16 L16 = BitConverter.ToUInt16(字节,6);
UINT16 T16 = BitConverter.ToUInt16(字节,4);
UINT16 R16 = BitConverter.ToUInt16(字节,2);
UINT16 B16 = BitConverter.ToUInt16(字节,0);

浮动左= L16 / 65535.0F;
浮顶= T16 / 65535.0F;
浮动权= R16 / 65535.0F;
浮筒底部= B16 / 65535.0F;

返回新的RectangleF(左,上,右 - 左,下 - 上);
}

现在我有一个的RectangleF,我希望把它放回提到的散列以上。我似乎无法想出解决办法。它看起来像Picasa中使用2个字节,包括精度,但在C#中的浮点为8字节,甚至BitConverter.ToSingle为4个字节。



感谢任何帮助。



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

 公共静态字符串HashFromRectangle( RectangleCoordinates RECT)
{
Console.WriteLine({0} {1} {2} {3},rect.Left,rect.Top,rect.Right,rect.Bottom);
UINT16左= Convert.ToUInt16((浮点)rect.Left * 65535.0F);
UINT16顶部= Convert.ToUInt16((浮点)rect.Top * 65535.0F);
UINT16右= Convert.ToUInt16((浮点)rect.Right * 65535.0F);
UINT16底= Convert.ToUInt16((浮点)rect.Bottom * 65535.0F);

字节[] =磅BitConverter.GetBytes(左);
的byte [] TB = BitConverter.GetBytes(顶部);
字节[] = RB BitConverter.GetBytes(右);
字节[] = BB BitConverter.GetBytes(底部);

字节[] = barray新的字节[8];
barray [0] =磅[0];
barray [1] =磅[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];

返回BitConverter.ToString(barray).Replace( - ,).ToLower();
}


解决方案

您当前的代码被调换每个字节的坐标。这是因为BitConverter给你在小端序(即,阵列中的第一个字节是至少显著字节)的字节。在你的任务交换如下使得解码和重新编码还给原来的哈希值。

  barray [0] =磅[1 ]; 
barray [1] =磅[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 和减/分的哈希字符串解码。例如对于编码:

 公共静态USHORT ToUShort(双坐标)
{
双比=数学。 MAX(0,Math.Min(Math.Round(坐标* 65535),65535));
回报(USHORT)的比例;
}

公共静态字符串HashFromRectangle(矩形RECT)
{
ULONG左= ToUShort(rect.Left);
ULONG顶部= ToUShort(rect.Top);
ULONG右= ToUShort(rect.Right);
ULONG底= ToUShort(rect.Bottom);

ULONG哈希=(((左* 65536)+顶部)* 65536 +右)* 65536 +底部;
返回hash.ToString(×);
}


Here are the details for what Picasa stores as a hash. It stores them like this:

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

Info on the web says this:

The number encased in rect64() is a 64-bit hexadecimal number.

  • Break that up into four 16-bit numbers.
  • Divide each by the maximum unsigned 16-bit number (65535) and you'll have four numbers between 0 and 1.
  • The four numbers remaining give you relative coordinates for the face rectangle: (left, top, right, bottom).
  • If you want to end up with absolute coordinates, multiple the left and right by the image width and the top and bottom by the image height.

So my code to turn that into a RectangleF works just fine (only keeping relative coordinates):

    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);
    }

Now I have a RectangleF and I want to turn it back into the hash mentioned above. I can't seem to figure this out. It looks like picasa uses 2 bytes including precision, however a float in C# is 8 bytes, and even BitConverter.ToSingle is 4 bytes.

Any help appreciated.

EDIT: Here is what I have right now

    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();
    }

解决方案

Your current code is swapping the bytes of each coordinate. This is because BitConverter gives you the bytes in little endian order (i.e. the first byte in the array is the least significant byte). Swapping around your assignments as follows makes decoding and re-encoding give back the original hash.

        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];

That said, I think it's clearer to do the conversion using simple multiplies and adds. You can do a similar thing with the decoding of the hash string if you read it in as a single ulong and subtract/divide. e.g. for the encoding:

    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");
    }

这篇关于如何扭转的RectangleF到Picasa脸哈希的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆