0

I was able to follow the csharp-sample-apps from the github repo for Affectiva. I ran the demo using my webcam and the processing and performance was great.I am not getting the same processing speed from the PhotoDetector when I try to run it over images in filesystem. Any help or improvement would be appreciated.

namespace Logical.EmocaoFace
{
    public class AnaliseEmocao : Affdex.ImageListener, Affdex.ProcessStatusListener
    {
        private Bitmap img { get; set; }
        private Dictionary<int, Affdex.Face> faces { get; set; }
        private Affdex.Detector detector { get; set; }
        private ReaderWriterLock rwLock { get; set; }

        public void processaEmocaoImagem()
        {

            for (int i = 0; i < resultado.count; i++){

                RetornaEmocaoFace();

                if (faceAffdex != null)
                {

                }
            }
        }


        public void RetornaEmocaoFace(string caminhoImagem)
        {
            Affdex.Detector detector = new Affdex.PhotoDetector(1, Affdex.FaceDetectorMode.LARGE_FACES);
            detector.setImageListener(this);
            detector.setProcessStatusListener(this);

            if (detector != null)
            {
                //ProcessVideo videoForm = new ProcessVideo(detector);
                detector.setClassifierPath(@"D:\Desenvolvimento\Componentes\Afectiva\data");
                detector.setDetectAllEmotions(true);
                detector.setDetectAllExpressions(false);
                detector.setDetectAllEmojis(false);
                detector.setDetectAllAppearances(false);
                detector.start();

                ((Affdex.PhotoDetector)detector).process(LoadFrameFromFile(caminhoImagem));

                detector.stop();
            }
        }

        static Affdex.Frame LoadFrameFromFile(string fileName)
        {
            Bitmap bitmap = new Bitmap(fileName);

            // Lock the bitmap's bits.
            Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
            BitmapData bmpData = bitmap.LockBits(rect, ImageLockMode.ReadWrite, bitmap.PixelFormat);

            // Get the address of the first line.
            IntPtr ptr = bmpData.Scan0;

            // Declare an array to hold the bytes of the bitmap. 
            int numBytes = bitmap.Width * bitmap.Height * 3;
            byte[] rgbValues = new byte[numBytes];

            int data_x = 0;
            int ptr_x = 0;
            int row_bytes = bitmap.Width * 3;

            // The bitmap requires bitmap data to be byte aligned.
            // http://stackoverflow.com/questions/20743134/converting-opencv-image-to-gdi-bitmap-doesnt-work-depends-on-image-size

            for (int y = 0; y < bitmap.Height; y++)
            {
                Marshal.Copy(ptr + ptr_x, rgbValues, data_x, row_bytes);//(pixels, data_x, ptr + ptr_x, row_bytes);
                data_x += row_bytes;
                ptr_x += bmpData.Stride;
            }

            bitmap.UnlockBits(bmpData);

            //Affdex.Frame retorno = new Affdex.Frame(bitmap.Width, bitmap.Height, rgbValues, Affdex.Frame.COLOR_FORMAT.BGR);

            //bitmap.Dispose();

            //return retorno;

           return new Affdex.Frame(bitmap.Width, bitmap.Height, rgbValues, Affdex.Frame.COLOR_FORMAT.BGR);
        }

        public void onImageCapture(Affdex.Frame frame)
        {
            frame.Dispose();

        }

        public void onImageResults(Dictionary<int, Affdex.Face> faces, Affdex.Frame frame)
        {
            byte[] pixels = frame.getBGRByteArray();
            this.img = new Bitmap(frame.getWidth(), frame.getHeight(), PixelFormat.Format24bppRgb);
            var bounds = new Rectangle(0, 0, frame.getWidth(), frame.getHeight());
            BitmapData bmpData = img.LockBits(bounds, ImageLockMode.WriteOnly, img.PixelFormat);
            IntPtr ptr = bmpData.Scan0;

            int data_x = 0;
            int ptr_x = 0;
            int row_bytes = frame.getWidth() * 3;

            // The bitmap requires bitmap data to be byte aligned.
            // http://stackoverflow.com/questions/20743134/converting-opencv-image-to-gdi-bitmap-doesnt-work-depends-on-image-size

            for (int y = 0; y < frame.getHeight(); y++)
            {
                Marshal.Copy(pixels, data_x, ptr + ptr_x, row_bytes);
                data_x += row_bytes;
                ptr_x += bmpData.Stride;
            }
            img.UnlockBits(bmpData);

            this.faces = faces;

            frame.Dispose();
        }

        public void onProcessingException(Affdex.AffdexException A_0)
        {
            throw new NotImplementedException("Encountered an exception while processing " + A_0.ToString());
        }

        public void onProcessingFinished()
        {
            string idArquivo = CodEspaco + "," + System.Guid.NewGuid().ToString();

            for(int i = 0; i  < faces.Count; i++)
            {
            }
        }



    }

    public static class GraphicsExtensions
    {
        public static void DrawCircle(this Graphics g, Pen pen,
                                      float centerX, float centerY, float radius)
        {
            g.DrawEllipse(pen, centerX - radius, centerY - radius,
                          radius + radius, radius + radius);
        }
    }
}

1 Answers1

0

Found the answer to my own question:

Using PhotoDetector is not ideal in this case since it is expensive to use the Face Detector configuration on subsequent frame calls.

The best option to improve the performance would be to use an instance of the FrameDetector Class.

Here is a getting started guide to analyze-frames.