/*
         *  Description:
         *      Locates the characters of the license plate
         *      - Warp image (Rectify)
         *      - Segment characters
         *      - Remove blobs which are to small (Lines between characters)
         *  Input:
         *      //Original image
         *      RGB888Image plateImage
         *      //Segmented license plate
         *      Int32Image binaryPlateImage
         *      Output:
         *      //Image containing binary six characters
         *      ref Int32Image binaryCharacterImage
         *  Return:
         *      //Function executed successfully
         *      bool
         */
        public static bool FindCharacters(RGB888Image plateImage, Int32Image binaryPlateImage, ref Int32Image binaryCharacterImage)
        {
            try
            {
                //Constants
                const int c_height           = 100;
                const int c_width            = 470;
                const int c_remove_blobs_min = 1;
                const int c_remove_blobs_max = 450;

                XYCoord leftTop     = new XYCoord();
                XYCoord rightTop    = new XYCoord();
                XYCoord leftBottom  = new XYCoord();
                XYCoord rightBottom = new XYCoord();


                //Find licenseplate
                VisionLab.FindCornersRectangle(binaryPlateImage, Connected.EightConnected, 0.5, Orientation.Landscape, leftTop, rightTop, leftBottom, rightBottom);
                if (!VisionLab.WarpCoordsValid(new Coord2D(leftTop), new Coord2D(rightTop), new Coord2D(leftBottom), new Coord2D(rightBottom)))
                {
                    VisionLab.FindCornersRectangleSq(binaryPlateImage, Connected.EightConnected, leftTop, rightTop, leftBottom, rightBottom);
                    if (!VisionLab.WarpCoordsValid(new Coord2D(leftTop), new Coord2D(rightTop), new Coord2D(leftBottom), new Coord2D(rightBottom)))
                    {
                        return(false);
                    }
                }

                Int32Image plateImageGray = new Int32Image();
                VisionLab.Convert(plateImage, plateImageGray);

                //Rectify plate
                VisionLab.Warp(plateImageGray, binaryCharacterImage, TransformDirection.ForwardT, new Coord2D(leftTop), new Coord2D(rightTop), new Coord2D(leftBottom), new Coord2D(rightBottom), c_height, c_width, 0);


                plateImageGray.Dispose();

                //*******************************//
                //** Exercise:                 **//
                //**   adjust licenseplate     **//
                //**   segmentation            **//
                //*******************************//


                //Find dark text on bright licenseplate using ThresholdISOData
                VisionLab.ThresholdIsoData(binaryCharacterImage, ObjectBrightness.DarkObject);

                //Remove small blobs and noise
                Int32Image binaryCharacterImageCopy = new Int32Image(binaryCharacterImage);
                VisionLab.Opening(binaryCharacterImageCopy, binaryCharacterImage, new Mask_Int32(5, 1, 1));

                //Remove blobs connected to the border
                VisionLab.RemoveBorderBlobs(binaryCharacterImage, Connected.EightConnected, Border.AllBorders);
                //Remove small blobs
                VisionLab.RemoveBlobs(binaryCharacterImage, Connected.EightConnected, BlobAnalyse.BA_Area, c_remove_blobs_min, c_remove_blobs_max);

                leftTop.Dispose();
                rightTop.Dispose();
                leftBottom.Dispose();
                rightBottom.Dispose();

                return(true);
            }
            catch (System.Exception ex)
            {
                throw new Exception("FindCharacters: " + ex.Message);
            }
        }