takuya-takeuchi / FaceRecognitionDotNet

The world's simplest facial recognition api for .NET on Windows, MacOS and Linux
MIT License
1.27k stars 308 forks source link

FaceRecognition.LoadImage usage. #36

Closed MiyamuraMiyako closed 5 years ago

MiyamuraMiyako commented 5 years ago

I use Aforge to capture camera frame. On NewFrame arrive, I invoke FaceRecognition.LoadImage to prepare EncodingFace, but I don't know how to convert System.Drawing.Bitmap to byte array and get row,s cols.

takuya-takeuchi commented 5 years ago

Sample code. I can not guarantee it works.

private static byte[] ToManaged(Bitmap bitmap)
{
    var format = bitmap.PixelFormat;
    var width = bitmap.Width;
    var height = bitmap.Height;
    var array = new byte[width * height * 3]; // bitmap is treated as rgb

    BitmapData bitmapData = null;
    try
    {
        bitmapData = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, width, height),
            ImageLockMode.WriteOnly,
            format);

        var stride = bitmapData.Stride;
        var scan0 = bitmapData.Scan0;
        for (var y = 0; y < height; y++)
    {
        Marshal.Copy(new IntPtr(scan0 + y * stride), array, y * width * 3, width * 3)
    }
    }
    finally
    {
        if (bitmapData != null)
            bitmap.UnlockBits(bitmapData);
    }

    return array;
}
MiyamuraMiyako commented 5 years ago

Thanks, Referring to your code, I succeeded.

        private void VideoCapDev_NewFrame(object sender, AForge.Video.NewFrameEventArgs e)
        {
            System.Drawing.Rectangle rect = new System.Drawing.Rectangle(0, 0, e.Frame.Width, e.Frame.Height);
            e.Frame.Clone(rect, PixelFormat.Format24bppRgb);
            var array = new byte[e.Frame.Width * e.Frame.Height * 3];
            BitmapData data = e.Frame.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
            Marshal.Copy(data.Scan0, array, 0, array.Length);
            e.Frame.UnlockBits(data);
            using (var img = FaceRecognition.LoadImage(array, e.Frame.Height, e.Frame.Width, 3))
            {
                var arr = FR.FaceEncodings(img).ToArray();
                if (arr.Length > 0)
                {
                    Invoke((MethodInvoker)(() => { label1.Text = FaceRecognition.CompareFace(feSample, arr[0], 0.5).ToString(); }));
                }
                else
                {
                    Invoke((MethodInvoker)(() => { label1.Text = "False"; }));
                }
            }
            return;
        }
takuya-takeuchi commented 5 years ago

it's my pleasure

atabora1 commented 4 years ago

Hi @takuya-takeuchi Any suggestions on how to efficiently rotate an image then perform the facial recognition?

This is a snippet of what I'm using. While this is great at detecting Faces from images that have a normal orientation, it doesn't detect them if the image is flipped.

            using (var image1 = FaceRecognition.LoadImageFile(strfullpath))
            {

                var faceEncodings = _FaceRecognition1.FaceEncodings(image1).ToArray();
          }
atabora1 commented 4 years ago

I've also tried this without success. Your feedback would be appreciated.

DlibDotNet.Dlib.FlipImageLeftRight(array2D, array2D_Output); var bytes = array2D_Output.ToBytes();

            using (var image = FaceRecognition.LoadImage(bytes, array2D_Output.Rows, array2D_Output.Columns, 3))//strFilePath using the smaller file size to optimize facial search
            {

                var faceEncodings = _FaceRecognition1.FaceEncodings(image).ToArray();

                }
takuya-takeuchi commented 4 years ago

You can use DlibDotNeyt.Dlib.RotateImage. And you can get binary data from Array2d. Then you can pass it to LoadImage.

atabora1 commented 4 years ago

Thanks @takuya-takeuchi I'll give it a shot. On a different topic, could you suggest a model or algorithm for side face detection? Thanks, always appreciate the feedback.

atabora1 commented 4 years ago

Thanks that worked. I was using the Dlib.RotateImage method however I was confused because I provided a 800x600 pixel image and when I attempted to rotate it 90 degrees by providing "DlibDotNet.Dlib.RotateImage(array2D, array2D_Output1, 90)" the Width and Height changed to 895x984.

takuya-takeuchi commented 4 years ago

Angle is radian. So you Should pass 1.57 instead of 90. However, argument name confuse user. I will change arg name to radian.

atabora1 commented 4 years ago

Hi @takuya-takeuchi I used "1.57" as suggested to rotate an image that was 800 Width by 600 Height and the image didn't rotate 90 degrees. So then I created a for loop and found that the value of 11 worked.

DlibDotNet.Dlib.RotateImage(array2D, array2D_Output1,1.57); var win2 = new ImageWindow(array2D_Output1);

takuya-takeuchi commented 4 years ago

@atabora1 please discuss about this issue in https://github.com/takuya-takeuchi/DlibDotNet/issues/180