//////////////////////////////////////////////////////////////////////////////////////
 public void PrintHeadInfo(ref CX_HeadInfo hi)
 {
     //Console.WriteLine("*** PrintHeadInfo ***");
     Console.WriteLine("Frame num:" + hi.m_frame_number + " Head ID:" + hi.m_head_id + " size(r,c)=(" + hi.m_rows + "," + hi.m_cols + ")");
     if (!hi.m_head_ok)
     {
         Console.WriteLine("head_ok=false");
     }
     else
     {
         Console.WriteLine("head_ok=true");
         Console.Write("bl(" + hi.m_head_bl_x + "," + hi.m_head_bl_y + ")");
         Console.Write("tr(" + hi.m_head_tr_x + "," + hi.m_head_tr_y + ")");
     }
     Console.Write("\n");
     if (!hi.m_face_ok)
     {
         Console.WriteLine("m_face_ok=false");
     }
     else
     {
         Console.WriteLine("m_face_ok=true");
         Console.Write("bl(" + hi.m_face_bl_x + "," + hi.m_face_bl_y + ")");
         Console.Write("tr(" + hi.m_face_tr_x + "," + hi.m_face_tr_y + ")");
     }
     Console.Write("\n");
     if (hi.m_has_annotation_set)
     {
         Console.WriteLine("conf: " + hi.m_confidence + ", focus: " + hi.m_focus + ", has anns=true");
     }
     else
     {
         Console.WriteLine("has anna = false");
     }
 }
        //////////////////////////////////////////////////////////////////////////////////////

        //////////////////////////////////////////////////////////////////////////////////////
        public void PrintHeadListData(uint frame_number, IntPtr p_head_list, bool details)
        {
            //Console.WriteLine("*** PrintHeadListData ***");
            int n_heads = CX_GetHeadListSize(p_head_list, msg);

            if (n_heads < 0)
            {
                Console.WriteLine("Frame " + frame_number + " Error: " + msg);
            }
            else
            {
                if (details)
                {
                    Console.WriteLine("FRAME " + frame_number + ", Tracking " + n_heads + " HEADS");
                    for (int i = 0; i < n_heads; i++)
                    {
                        IntPtr p_head = CX_GetHead(p_head_list, i, msg);
                        if (p_head == IntPtr.Zero)
                        {
                            Console.WriteLine("Failed to get head " + i + " of " + n_heads + " heads: " + msg);
                        }
                        else
                        {
                            PrintHeadData(frame_number, i, p_head);
                        }
                    }
                }
                else
                {
                    Console.Write("FRAME " + frame_number + ", Tracking " + n_heads + " HEADS ");
                    for (int i = 0; i < n_heads; i++)
                    {
                        IntPtr p_head = CX_GetHead(p_head_list, i, msg);
                        if (p_head == IntPtr.Zero)
                        {
                            Console.Write("Failed to get head " + i + " of " + n_heads + " heads:" + msg);
                        }
                        else
                        {
                            CX_HeadInfo hi = new CX_HeadInfo();
                            if (1 == CX_GetHeadInfo(p_head, ref hi, msg))
                            {
                                Console.Write("Head ID:" + hi.m_head_id);
                            }
                        }
                    }
                    Console.Write("\n");
                }
            }
        }
        //////////////////////////////////////////////////////////////////////////////////////


        //////////////////////////////////////////////////////////////////////////////////////
        public void PrintHeadData(uint frame_number, int head_index, IntPtr p_head)
        {
            //Console.WriteLine("*** PrintHeadData ***");
            CX_HeadInfo hi = new CX_HeadInfo();;

            if (0 == CX_GetHeadInfo(p_head, ref hi, msg))
            {
                Console.WriteLine("Frame " + frame_number + ": Failed to get head " + head_index + " info: " + msg);
            }
            else
            {
                PrintHeadInfo(ref hi);
                PrintHeadFR(p_head);
            }
        }
        //////////////////////////////////////////////////////////////



        //////////////////////////////////////////////////////////////
        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);
 public static extern int CX_GetHeadInfo(IntPtr p_head, ref CX_HeadInfo p_info, [Out] StringBuilder message);