長方形をピカサの顔のハッシュに逆転させる方法
-
18-09-2019 - |
質問
ピカサがハッシュとして保管しているものの詳細は次のとおりです。このように保存します:
faces=rect64(54391dc9b6a76c2b),4cd643f64b715489
[DSC_2289.jpg]
faces=rect64(1680000a5c26c82),76bc8d8d518750bc
ウェブ上の情報はこれを言っています:
rect64()に包まれた数は、64ビットの16進数です。
- それを4つの16ビット番号に分割します。
- それぞれを最大符号なしの16ビット数(65535)で割ると、0〜1の間に4つの数値があります。
- 残りの4つの数字は、顔の長方形の相対座標を提供します:(左、上、右、下)。
- 絶対座標になりたい場合は、画像幅で左右に複数と画像の高さで上部と下部になります。
したがって、それを長方形に変える私のコードは正常に機能します(相対座標のみを保持します):
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);
}
今、私は長方形を持っています、そして、私はそれを上記のハッシュに戻したいと思っています。私はこれを理解できないようです。 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();
}
解決
現在のコードは、各座標のバイトを交換しています。これは、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");
}
他のヒント
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);
これがうまくいくかどうか教えてください!
アーロン
所属していません StackOverflow