[C#]取用.picasa.ini內存的現有資訊來做臉部偵測
rect64(3f845bcb59418507)
break this number into 4 16-bit numbers by using substrings:
‘3f845bcb59418507’.substring(0,4) //“3f84”
‘3f845bcb59418507’.substring(4,8) //“5bcb”
‘3f845bcb59418507’.substring(8,12) // “5941”
‘3f845bcb59418507’.substring(12,16) // “8507”
convert each obtained substring to an integer and divide it
by the highest 16-bit number (2^16 = 65536), which should give 0 < results < 1.
these are the relative coordinates of the crop rectangle (left,top,right,bottom):
parseInt(“3f84”,16)/65536 //0.24810791015625 - left
parseInt(“5bcb”,16)/65536 //0.3585662841796875 - top
parseInt(“5941”,16)/65536 //0.3486480712890625 - right
parseInt(“8507”,16)/65536 //0.5196380615234375 - bottom
for absolute coordinates, multiply the left/right coordinates with
the image width and the top/bottom coordinates with the image height
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);
}</pre></div>
namespace WindowsFormsApplication27 { public class PicasaMetaDataHelper { #region DllImport [DllImport(“kernel32”)] private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath); #endregion
#region Const
const string PICASA_INI_FILENAME = ".picasa.ini";
const string FACE_HASH_CODE_PATTERN = @"\((\w+)\)";
#endregion
#region Private Static Method
/// <summary>
/// Gets the rectangle from64 hash.
/// </summary>
/// <param name="hash64">The hash64.</param>
/// <param name="size">The size.</param>
/// <returns></returns>
private static RectangleF GetRectangleFrom64Hash(string hash64, Size size)
{
return GetRectangleFrom64Hash(hash64, size.Width, size.Height);
}
/// <summary>
/// Gets the rectangle from64 hash.
/// </summary>
/// <param name="hash64">The hash64.</param>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
/// <returns></returns>
private static RectangleF GetRectangleFrom64Hash(string hash64, int width, int height)
{
UInt64 hash = UInt64.Parse(hash64, 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 * width, top * height, (right - left) * width, (bottom - top) * height);
}
#endregion
#region Public Static Method
/// <summary>
/// Gets the face areas.
/// </summary>
/// <param name="photoFile">The photo file.</param>
/// <returns></returns>
public static IEnumerable<RectangleF> GetFaceAreas(string photoFile)
{
var photo = Bitmap.FromFile(photoFile);
return GetFaceAreas(photoFile, photo);
}
/// <summary>
/// Gets the face areas.
/// </summary>
/// <param name="photoFile">The photo file.</param>
/// <param name="photo">The photo.</param>
/// <returns></returns>
public static IEnumerable<RectangleF> GetFaceAreas(string photoFile, Image photo)
{
var folder = Path.GetDirectoryName(photoFile);
var iniFile = Path.Combine(folder, PICASA_INI_FILENAME);
if (!File.Exists(iniFile))
yield break;
var fileName = Path.GetFileName(photoFile);
var faceDataBuffer = new StringBuilder(512);
GetPrivateProfileString(fileName, "faces", string.Empty, faceDataBuffer, 512, iniFile);
var faceData = faceDataBuffer.ToString();
if (faceData.Length == 0)
yield break;
var ms = Regex.Matches(faceData, FACE_HASH_CODE_PATTERN);
foreach (Match m in ms)
{
var faceHashCode = m.Groups[1].Value;
yield return GetRectangleFrom64Hash(faceHashCode, photo.Size);
}
}
#endregion
}
}
using (var g = Graphics.FromImage(image))
{
g.DrawRectangles(new Pen(Brushes.Red, 5), faceAreas.ToArray());
}
pbxPhoto.Image = image;
}
...</pre></div>