//////////////////////////////////////////////////////////////



        //////////////////////////////////////////////////////////////
        public void TestDetectHeads()
        {
            // as an example we are going to load an image from the example sequence
            //string image_file = "C:/CyberExtruder/Aureus/SequentialFrames/Doorway4/M001.jpg";
            //string image_file = "D:/CyberBase/data/Gallery/Tygart/Roby/bounding_box/A.jpg";
            string image_file = "D:/CyberBase/data/Gallery/Tygart/Roby/bounding_box/B.jpg";

            //string image_file = "D:/CyberBase/data/Gallery/Tygart/Roby/bounding_box/C.bmp";
            Console.WriteLine("Detecting heads in image: \n" + image_file);

            // set detection parameters
            float top    = 0.0f;
            float left   = 0.0f;
            float height = 1.0f;
            float width  = 1.0f;
            float minh   = 0.2f;
            float maxh   = 1.0f;

            if (0 == CX_SetDetectionParameters(mp_video, top, left, height, width, minh, maxh, msg))
            {
                Console.WriteLine(msg);
                return;
            }

            // set frame reduction step
            int frame_reduction_step = 1;

            if (0 == CX_SetFrameReductionStep(mp_video, frame_reduction_step, msg))
            {
                Console.WriteLine(msg);
                return;
            }
            frame_reduction_step = CX_GetFrameReductionStep(mp_video, msg);
            Console.WriteLine("Frame Reduction step = " + frame_reduction_step);

            // data to store detected head
            CX_HeadInfo hi = new CX_HeadInfo();

            // load the image
            Bitmap im = new Bitmap(image_file);

            // lock the bits as we are going to pass it into Aureus
            Rectangle  rect    = new Rectangle(0, 0, im.Width, im.Height);
            BitmapData bmpData = im.LockBits(rect, ImageLockMode.ReadWrite, im.PixelFormat);

            // construct a CX_RAM_Image struct
            CX_RAM_Image rim = new CX_RAM_Image();

            rim.mp_pixels = bmpData.Scan0; // the pointer to the first line, hence first pixel
            rim.m_rows    = (uint)im.Height;
            rim.m_cols    = (uint)im.Width;
            rim.m_origin  = 0; // C# loaded Bitmaps usually have a top left origin


            // set the RAM image pixel format (we only use 24 & 32 bit here)
            bool format_ok = true;

            if (im.PixelFormat.Equals(PixelFormat.Format24bppRgb))
            {
                rim.m_type = 3;                                                    // BGR
            }
            else if (im.PixelFormat.Equals(PixelFormat.Format32bppArgb))
            {
                rim.m_type = 4;                                                          // BGRA
            }
            else if (im.PixelFormat.Equals(PixelFormat.Format32bppPArgb))
            {
                rim.m_type = 4;                                                           // BGRA
            }
            else if (im.PixelFormat.Equals(PixelFormat.Format32bppRgb))
            {
                rim.m_type = 4;                                                         // BGRA
            }
            //if (im.PixelFormat.Equals(PixelFormat.Format24bppRgb)) rim.m_type = 0; // RGB
            //else if (im.PixelFormat.Equals(PixelFormat.Format32bppArgb)) rim.m_type = 1; // RGBA
            //else if (im.PixelFormat.Equals(PixelFormat.Format32bppPArgb)) rim.m_type = 1; // RGBA
            //else if (im.PixelFormat.Equals(PixelFormat.Format32bppRgb)) rim.m_type = 1; // RGBA
            else
            {
                format_ok = false;
            }

            if (!format_ok)
            {
                Console.WriteLine("ERROR! can't use this format");
                return;
            }

            // detect the heads
            int use_face_detector = 1;
            int use_fail_safe     = 1;
            int n = CX_DetectHeads(mp_video, ref rim, 1, ref hi, 1, use_face_detector, use_fail_safe, msg);


            string txt = "Detected " + n.ToString() + " Heads";

            Console.WriteLine(txt);



            if (n > 0)
            {
                // here we convert to pixels with origin top left to easily
                // enable us to see where on the image the detection occurs
                if (hi.m_face_ok)
                {
                    // swap origin
                    hi.m_face_bl_y = 1.0f - hi.m_face_bl_y;
                    hi.m_face_tr_y = 1.0f - hi.m_face_tr_y;
                    // convert to pixels
                    hi.m_face_bl_x *= im.Width;
                    hi.m_face_bl_y *= im.Height;
                    hi.m_face_tr_x *= im.Width;
                    hi.m_face_tr_y *= im.Height;
                }
                if (hi.m_head_ok)
                {
                    // swap origin
                    hi.m_head_bl_y = 1.0f - hi.m_head_bl_y;
                    hi.m_head_tr_y = 1.0f - hi.m_head_tr_y;
                    // convert to pixels
                    hi.m_head_bl_x *= im.Width;
                    hi.m_head_bl_y *= im.Height;
                    hi.m_head_tr_x *= im.Width;
                    hi.m_head_tr_y *= im.Height;
                }
                PrintHeadInfo(ref hi);
            }
        }
 public static extern int CX_DetectHeads(IntPtr p_video, ref CX_RAM_Image p_im, int frame_number, ref CX_HeadInfo p_head_info_array, int array_size, int use_face_detector, int fail_safe, [Out] StringBuilder message);
        ////////////////////////////////////////////////////////////////////


        //////////////////////////////////////////////////////////////////////////////////////
        // Simple frame call back
        private void VideoFrameCallBack(IntPtr p_head_list, uint head_list_size, IntPtr p_pixels, uint rows, uint cols, uint frame_num, IntPtr p_object)
        {
            StringBuilder vmsg = new StringBuilder(1024);

            // just print num of heads being tracked
            int n_heads = CX_GetHeadListSize(p_head_list, vmsg);

            if (n_heads < 0)
            {
                Console.WriteLine("Frame " + frame_num + " Error: " + vmsg);
            }
            else
            {
                //Console.WriteLine("FRAME " + frame_num + ", Tracking " + n_heads + " HEADS rows = " + rows + " cols = " + cols);
                // or print more detailed info (including FR if switched on)
                PrintHeadListData(frame_num, p_head_list, true);
            }

            //////////////////////////////////////////////////////////
            // Example of how to save the frame image (or any Aureus Image)
            // The Frame is always returned as a 32bppRGBA with bottom left origin, however
            // when using a C# Bitmap, the Bitmap object assumes that it is stored in
            // memory as BGRA or BGR, with the origin top left, hence we use CX_CopyImage
            // to provide a fast copy to the format we want (fastest will be BGRA as
            // CX_CopyImage can copy whole rows at a time
            //
            // Note: This will dramatically slow down the video processing since we are
            // constructing and saving an image to disk
            //
            bool save_images = false; // change this to save the frames

            if (save_images)
            {
                int    stride = (int)((cols * 4) + ((cols * 4) % 4));
                Bitmap im     = new Bitmap((int)cols, (int)rows, PixelFormat.Format32bppRgb); // 4 bytes per pixel
                //Bitmap im = new Bitmap((int)cols, (int)rows, PixelFormat.Format24bppRgb); // 3 bytes per pixel

                // lock the bits as we are going to allow CX_CopyImage to fill the bitmap
                Rectangle  rect    = new Rectangle(0, 0, im.Width, im.Height);
                BitmapData bmpData = im.LockBits(rect, ImageLockMode.ReadWrite, im.PixelFormat);

                // Get the pointer to the first line, hence first pixel
                IntPtr ptr = bmpData.Scan0;

                // construct a CX_RAM_Image struct
                CX_RAM_Image rim = new CX_RAM_Image();
                rim.mp_pixels = p_pixels; // frame pixels
                rim.m_rows    = rows;
                rim.m_cols    = cols;
                rim.m_origin  = 1; // frames always have bottom left origin
                rim.m_type    = 1; // frames are always RGBA

                // select desired output type
                int dst_type = 4; // BGRA
                //int dst_type = 3; // BGR

                int dst_origin = 0; // we want origin at top left

                if (0 == CX_CopyImage(ref rim, dst_type, dst_origin, ptr, msg))
                {
                    im.UnlockBits(bmpData);
                    Console.WriteLine(msg);
                }
                else
                {
                    im.UnlockBits(bmpData);
                    string odir = "C:/temp/Test"; // obviously change this to something suitable on your machine
                    System.IO.Directory.CreateDirectory(odir);
                    string oname = odir + "/Frame_";
                    oname += frame_num;
                    oname += ".jpg";
                    im.Save(oname);
                }
                //////////////////////////////////////////////////////////
            }
        }
 public static extern int CX_CopyImage(ref CX_RAM_Image p_src_image, int dst_im_type, int dst_origin, IntPtr p_dst_pixels, [Out] StringBuilder message);