Пример #1
0
        public void DisplayImage(Image img, PictureBox pb, bool stretch, bool invert)
        {
            Bitmap bm;

            if (img is Int16Image)
            {
                Int16Image disp = new Int16Image((Int16Image)img);
                if (invert)
                {
                    VisionLab.Not((Int16Image)disp);
                }
                if (stretch)
                {
                    VisionLab.Multiply((Int16Image)disp, 255);
                }

                bm = VisionLabEx.JLToBitmap(disp);
                disp.Dispose();
            }
            else
            {
                bm = VisionLabEx.JLToBitmap(img);
            }

            if (pb.Image != null)
            {
                pb.Image.Dispose();
            }
            pb.Image = bm;
        }
Пример #2
0
        private void MatchImage(String Filename, bool add)
        {
            ErrorTB.Text = "";
            lblExpected.Text = Filename.Substring(0, 6);

            //*************************************//
            //** load and display original image **//
            //*************************************//
            Bitmap bm;
            bm = new Bitmap(Filename);
            RGB888Image plateImage = VisionLabEx.BitmapToJL(bm);
            DisplayImage(plateImage, imgOrig);            

            //****************//
            //** Find plate **//
            //****************//
            Int16Image binaryPlateImage = new Int16Image();

            if (!LicensePlateMatcher.FindPlate(plateImage, ref binaryPlateImage, TresholdConditions.NORMAAL) 
                && !LicensePlateMatcher.FindPlate(plateImage, ref binaryPlateImage, TresholdConditions.OVERBELICHT)
                && !LicensePlateMatcher.FindPlate(plateImage, ref binaryPlateImage, TresholdConditions.ONDERBELICHT))
            {
                DisplayImage(binaryPlateImage, imgPlateBin, true, true);
                lblLexiconResult.Text = "";
                if (add)
                {
                    lstFindPlateErr.Items.Add(Filename);
                    lblFindPlateErrCount.Text = lstFindPlateErr.Items.Count.ToString();
                }
                ClearResultLabels();
                return;
            }           
            DisplayImage(binaryPlateImage, imgPlateBin, true, true);
            
            //*******************//
            //** Rectify plate **//
            //*******************//                       
            Int16Image binaryRectifiedImage = new Int16Image();

            do
            {
                // Check if we can find the plate
                if (LicensePlateMatcher.FindCharacters(plateImage, binaryPlateImage, ref binaryRectifiedImage))
                {
                    // if so we are done
                    break;
                }
                else
                {
                    // ************************************
                    // **  Find the biggest blob in the  **
                    // **  image and remove that one     **
                    // ************************************
                    VisionLab.LabelBlobs(binaryPlateImage, Connected.EightConnected);
                    vector_BlobAnalyse ba_vec = new vector_BlobAnalyse();
                    ba_vec.Add(BlobAnalyse.BA_Area);
                    vector_Blob blobs = new vector_Blob();
                    VisionLab.BlobAnalysis(binaryPlateImage, VisionLab.VectorToSet_BlobAnalyse(ba_vec), VisionLab.MaxPixel(binaryPlateImage), blobs);
                    int biggestArea = 0;
                    foreach (Blob ba in blobs)
                    {
                        if (ba.Area() > biggestArea)
                        {
                            biggestArea = ba.Area();
                        }
                    }
                    VisionLab.RemoveBlobs(binaryPlateImage, Connected.EightConnected, BlobAnalyse.BA_Area, biggestArea - 1, biggestArea + 1);
                }
            } // Repeat this until there is nothing left
            while (VisionLab.SumIntPixels(binaryPlateImage) > 0);

            // If that is so it wasn't found
            if (VisionLab.SumIntPixels(binaryPlateImage) == 0)
            {
                // So do all this
                if (imgRectifiedPlate.Image != null)
                    imgRectifiedPlate.Image.Dispose();
                imgRectifiedPlate.Image = null;
                lblLexiconResult.Text = "";
                if (add)
                {
                    lstRectifyPlateErr.Items.Add(Filename);
                    lblRectfyPlateErrCount.Text = lstRectifyPlateErr.Items.Count.ToString();
                }
                ClearResultLabels();
                return;
            }

            DisplayImage(binaryRectifiedImage, imgRectifiedPlate, true, true);
            

            //*****************//
            //** Match Plate **//
            //*****************//
            LicensePlate result = new LicensePlate();
            LicensePlate lexiconResult = new LicensePlate();
            if (!LicensePlateMatcher.MatchPlate(binaryRectifiedImage, blobMatcher, lexicon, ref result, ref lexiconResult, false))
            {
                lblLexiconResult.Text = "";
                if (add)
                {
                    lstMatchPlateErr.Items.Add(Filename);
                    lblMatchPlateErrCount.Text = lstMatchPlateErr.Items.Count.ToString();
                }
                ClearResultLabels();
                return;
            }            
            // Extra way to up confidence perhaps
            if(result.characters != null && result.confidence < (double)nupConfidence.Value / 100)
            {
                LicensePlateMatcher.MatchPlate(binaryRectifiedImage, blobMatcher, lexicon, ref result, ref lexiconResult, true);
            }

            //*********************//
            //** Process results **//
            //*********************//            
            ProcessResults(result, lexiconResult, Filename, (double) nupConfidence.Value / 100, add);
            
            bm.Dispose();
            plateImage.Dispose();
            binaryPlateImage.Dispose();
            binaryRectifiedImage.Dispose();

            //Force a garbage collect to prevens malloc errors from unmanaged code.
            GC.Collect();
        }
Пример #3
0
        public void DisplayImage(Image img, PictureBox pb, bool stretch, bool invert)
        {          
            Bitmap bm;
            if (img is Int16Image)
            {
                Int16Image disp = new Int16Image((Int16Image)img);
                if (invert)
                    VisionLab.Not((Int16Image)disp);                
                if (stretch)                
                    VisionLab.Multiply((Int16Image)disp, 255);
                
                bm = VisionLabEx.JLToBitmap(disp);
                disp.Dispose();
            } else
                bm = VisionLabEx.JLToBitmap(img);

            if (pb.Image != null)
            {
                pb.Image.Dispose();
            }
            pb.Image = bm;            
        }
Пример #4
0
        /*
         *  Description:
         *      Read the license plate
         *  Input:
         *          //Rectified license plate image containing six characters
         *          Int32Image labeledRectifiedPlateImage
         *          BlobMatcher_Int16 matcher	//initialized blobmatcher
         *          ClassLexicon lexicon		//initialized lexicon
         *  Output:
         *          //Result by the blob matcher
         *          ref LicensePlate result
         *          //Result by the lexicon
         *          ref LicensePlate lexiconResult
         *  Return:
         *          //six characters found
         *      bool
         */
        public static bool MatchPlate(Int32Image binaryCharacterImage, BlobMatcher_Int16 matcher, ClassLexicon lexicon, ref LicensePlate result, ref LicensePlate lexiconResult)
        {
            //Check if 6 characters/blobs have been found and label image.
            if (VisionLab.LabelBlobs(binaryCharacterImage, Connected.EightConnected) != 6)
            {
                return(false);
            }

            //Calculate dimensions and locations of all characters/blobs.
            vector_BlobAnalyse ba_vec = new vector_BlobAnalyse();

            ba_vec.Add(BlobAnalyse.BA_TopLeft);
            ba_vec.Add(BlobAnalyse.BA_Height);
            ba_vec.Add(BlobAnalyse.BA_Width);
            vector_Blob returnBlobs = new vector_Blob();

            VisionLab.BlobAnalysis(binaryCharacterImage, VisionLab.VectorToSet_BlobAnalyse(ba_vec), VisionLab.MaxPixel(binaryCharacterImage), returnBlobs, SortOrder.SortDown, BlobAnalyse.BA_TopLeft, UseXOrY.UseX);
            ba_vec.Dispose();
            Int32Image binaryCharacter   = new Int32Image();
            Int16Image binaryCharacter16 = new Int16Image();

            //Create data structure for lexicon.
            vector_vector_LetterMatch match = new vector_vector_LetterMatch();

            //Process each character/blob.
            foreach (Blob b in returnBlobs)
            {
                //Cut out character
                VisionLab.ROI(binaryCharacterImage, binaryCharacter, b.TopLeft(), new HeightWidth(b.Height(), b.Width()));
                //Convert ROI result to binary
                VisionLab.ClipPixelValue(binaryCharacter, 0, 1);
                //Calculate character's classification for all classes.
                vector_PatternMatchResult returnMatches = new vector_PatternMatchResult();
                VisionLab.Convert(binaryCharacter, binaryCharacter16);
                float  conf = matcher.AllMatches(binaryCharacter16, (float)-0.5, (float)0.5, returnMatches);
                float  err  = returnMatches[0].error;
                int    id   = returnMatches[0].id;
                string chr  = matcher.PatternName(id);

                //Fill datastructure for lexicon.
                match.Add(VisionLabEx.PatternMatchResultToLetterMatch(returnMatches));

                //Store best match in result
                result.characters.Add(new LicenseCharacter(chr, err, conf));
            }

            //Validate match with lexicon.
            vector_int bestWord = new vector_int();

            lexiconResult.confidence = lexicon.FindBestWord(match, bestWord, Optimize.OptimizeForMinimum);
            for (int i = 0; i < bestWord.Count; i++)
            {
                string character = matcher.PatternName(bestWord[i]);
                //Store lexicon result
                lexiconResult.characters.Add(new LicenseCharacter(character));
            }

            binaryCharacter.Dispose();
            binaryCharacter16.Dispose();
            returnBlobs.Dispose();
            match.Dispose();
            bestWord.Dispose();
            //GC.Collect();
            return(true);
        }
Пример #5
0
        private void MatchImage(String Filename, bool add)
        {
            ErrorTB.Text     = "";
            lblExpected.Text = Filename.Substring(0, 6);

            //*************************************//
            //** load and display original image **//
            //*************************************//
            Bitmap bm;

            bm = new Bitmap(Filename);
            RGB888Image plateImage = VisionLabEx.BitmapToJL(bm);

            DisplayImage(plateImage, imgOrig);

            //****************//
            //** Find plate **//
            //****************//
            Int16Image binaryPlateImage = new Int16Image();

            if (!LicensePlateMatcher.FindPlate(plateImage, ref binaryPlateImage, TresholdConditions.NORMAAL) &&
                !LicensePlateMatcher.FindPlate(plateImage, ref binaryPlateImage, TresholdConditions.OVERBELICHT) &&
                !LicensePlateMatcher.FindPlate(plateImage, ref binaryPlateImage, TresholdConditions.ONDERBELICHT))
            {
                DisplayImage(binaryPlateImage, imgPlateBin, true, true);
                lblLexiconResult.Text = "";
                if (add)
                {
                    lstFindPlateErr.Items.Add(Filename);
                    lblFindPlateErrCount.Text = lstFindPlateErr.Items.Count.ToString();
                }
                ClearResultLabels();
                return;
            }
            DisplayImage(binaryPlateImage, imgPlateBin, true, true);

            //*******************//
            //** Rectify plate **//
            //*******************//
            Int16Image binaryRectifiedImage = new Int16Image();

            do
            {
                // Check if we can find the plate
                if (LicensePlateMatcher.FindCharacters(plateImage, binaryPlateImage, ref binaryRectifiedImage))
                {
                    // if so we are done
                    break;
                }
                else
                {
                    // ************************************
                    // **  Find the biggest blob in the  **
                    // **  image and remove that one     **
                    // ************************************
                    VisionLab.LabelBlobs(binaryPlateImage, Connected.EightConnected);
                    vector_BlobAnalyse ba_vec = new vector_BlobAnalyse();
                    ba_vec.Add(BlobAnalyse.BA_Area);
                    vector_Blob blobs = new vector_Blob();
                    VisionLab.BlobAnalysis(binaryPlateImage, VisionLab.VectorToSet_BlobAnalyse(ba_vec), VisionLab.MaxPixel(binaryPlateImage), blobs);
                    int biggestArea = 0;
                    foreach (Blob ba in blobs)
                    {
                        if (ba.Area() > biggestArea)
                        {
                            biggestArea = ba.Area();
                        }
                    }
                    VisionLab.RemoveBlobs(binaryPlateImage, Connected.EightConnected, BlobAnalyse.BA_Area, biggestArea - 1, biggestArea + 1);
                }
            } // Repeat this until there is nothing left
            while (VisionLab.SumIntPixels(binaryPlateImage) > 0);

            // If that is so it wasn't found
            if (VisionLab.SumIntPixels(binaryPlateImage) == 0)
            {
                // So do all this
                if (imgRectifiedPlate.Image != null)
                {
                    imgRectifiedPlate.Image.Dispose();
                }
                imgRectifiedPlate.Image = null;
                lblLexiconResult.Text   = "";
                if (add)
                {
                    lstRectifyPlateErr.Items.Add(Filename);
                    lblRectfyPlateErrCount.Text = lstRectifyPlateErr.Items.Count.ToString();
                }
                ClearResultLabels();
                return;
            }

            DisplayImage(binaryRectifiedImage, imgRectifiedPlate, true, true);


            //*****************//
            //** Match Plate **//
            //*****************//
            LicensePlate result        = new LicensePlate();
            LicensePlate lexiconResult = new LicensePlate();

            if (!LicensePlateMatcher.MatchPlate(binaryRectifiedImage, blobMatcher, lexicon, ref result, ref lexiconResult, false))
            {
                lblLexiconResult.Text = "";
                if (add)
                {
                    lstMatchPlateErr.Items.Add(Filename);
                    lblMatchPlateErrCount.Text = lstMatchPlateErr.Items.Count.ToString();
                }
                ClearResultLabels();
                return;
            }
            // Extra way to up confidence perhaps
            if (result.characters != null && result.confidence < (double)nupConfidence.Value / 100)
            {
                LicensePlateMatcher.MatchPlate(binaryRectifiedImage, blobMatcher, lexicon, ref result, ref lexiconResult, true);
            }

            //*********************//
            //** Process results **//
            //*********************//
            ProcessResults(result, lexiconResult, Filename, (double)nupConfidence.Value / 100, add);

            bm.Dispose();
            plateImage.Dispose();
            binaryPlateImage.Dispose();
            binaryRectifiedImage.Dispose();

            //Force a garbage collect to prevens malloc errors from unmanaged code.
            GC.Collect();
        }
        /*
            Description:
                Read the license plate
            Input:
	            //Rectified license plate image containing six characters	
	            Int16Image labeledRectifiedPlateImage
	            BlobMatcher_Int16 matcher	//initialized blobmatcher
	            ClassLexicon lexicon		//initialized lexicon
            Output:
	            //Result by the blob matcher
	            ref LicensePlate result
	            //Result by the lexicon
	            ref LicensePlate lexiconResult
            Return:
	            //six characters found
	        bool 
        */
        public static bool MatchPlate(Int16Image binaryCharacterImage, BlobMatcher_Int16 matcher, 
            ClassLexicon lexicon, ref LicensePlate result, ref LicensePlate lexiconResult, bool dilate)
        {
            // NIEUW
            // 2de optie voor aanroep als eerste low confidence levert
            if (dilate)
            {
                Int16Image temp = new Int16Image();
                VisionLab.Dilation(binaryCharacterImage, temp, new Mask_Int32(3, 3, 1));
                binaryCharacterImage = new Int16Image(temp);
                temp.Dispose();
            }
            if (VisionLab.LabelBlobs(binaryCharacterImage, Connected.EightConnected) != 6)
                return false;

            //Calculate dimensions and locations of all characters/blobs.
            vector_BlobAnalyse ba_vec = new vector_BlobAnalyse();
            ba_vec.Add(BlobAnalyse.BA_TopLeft);
            ba_vec.Add(BlobAnalyse.BA_Height);
            ba_vec.Add(BlobAnalyse.BA_Width);
            vector_Blob returnBlobs = new vector_Blob();
            VisionLab.BlobAnalysis(binaryCharacterImage, VisionLab.VectorToSet_BlobAnalyse(ba_vec), VisionLab.MaxPixel(binaryCharacterImage), returnBlobs, SortOrder.SortDown, BlobAnalyse.BA_TopLeft, UseXOrY.UseX);
            ba_vec.Dispose();
            Int16Image binaryCharacter = new Int16Image();

            //Create data structure for lexicon.
            vector_vector_LetterMatch match = new vector_vector_LetterMatch();
            
            // NIEUW
            // Change the matcher params
            matcher.ChangeParams(60, 10, 64, 0);
            //Process each character/blob.
            foreach (Blob b in returnBlobs)
            {
                //Cut out character
                VisionLab.ROI(binaryCharacterImage, binaryCharacter, b.TopLeft(), new HeightWidth(b.Height(), b.Width()));
                //Convert ROI result to binary
                VisionLab.ClipPixelValue(binaryCharacter, 0, 1);
                //Calculate character's classification for all classes.
                vector_PatternMatchResult returnMatches = new vector_PatternMatchResult();
                float conf = matcher.AllMatches(binaryCharacter, (float)-0.5, (float)0.5, returnMatches);
                float err = returnMatches[0].error;
                int id = returnMatches[0].id;
                string chr = matcher.PatternName(id);
                // NIEUW
                // If error to big decrease the confidence
                if(err > 0.20f)
                    conf -= 0.2f;
                //Fill datastructure for lexicon.
                match.Add(VisionLabEx.PatternMatchResultToLetterMatch(returnMatches));
                
                //Store best match in result
                result.characters.Add(
                    new LicenseCharacter(
                        chr, 
                        err, 
                        conf,

                        // NIEUW
                        // Extra param: The middle of a character
                        // (used for matching patterns)
                        b.TopLeft().x + ((b.TopRight().x - b.TopLeft().x)/2) ,

                        // NIEUW
                        // All other results that we're found
                        // So we can switch between em
                        returnMatches
                        ));
            }

            //Validate match with lexicon.
            vector_int bestWord = new vector_int();
            lexiconResult.confidence = lexicon.FindBestWord(match, bestWord, Optimize.OptimizeForMinimum);
            for (int i = 0; i < bestWord.Count; i++)
            {
                string character = matcher.PatternName(bestWord[i]);
                //Store lexicon result
                lexiconResult.characters.Add(new LicenseCharacter(character));
            }

            // NIEUW
            // Create the best match with the aid of the pattern matcher
            result.CalculateBestMatch(matcher);
            
            binaryCharacter.Dispose();
            returnBlobs.Dispose();
            match.Dispose();
            bestWord.Dispose();
            GC.Collect();
            return true;
        }
        /*  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
	            Int16Image binaryPlateImage
            Output:
	            //Image containing binary six characters	
	            ref Int16Image binaryCharacterImage 
            Return:
	            //Function executed successfully
	            bool
        */
        public static bool FindCharacters(RGB888Image plateImage, Int16Image binaryPlateImage, ref Int16Image binaryCharacterImage)
        {
            //Constants
            const int c_height = 100;
            const int c_width = 470;
            const int c_remove_blobs_min = 0;
            const int c_remove_blobs_max = 400;

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

            // 2de set coordinaten:
            // NIEUW
            XYCoord leftTop2 = new XYCoord();
            XYCoord rightTop2 = new XYCoord();
            XYCoord leftBottom2 = new XYCoord();
            XYCoord rightBottom2 = new XYCoord();

            //Find licenseplate
            Int32Image binaryPlateImage32 = new Int32Image();
            VisionLab.Convert(binaryPlateImage, binaryPlateImage32);
            
            VisionLab.FindCornersRectangle(
                binaryPlateImage32, 
                Connected.EightConnected, 
                0.5, 
                Orientation.Landscape, 
                leftTop, 
                rightTop, 
                leftBottom, 
                rightBottom
            );

            // NIEUW
            // Coordinaten bepalen voor deze functie
            VisionLab.FindCornersRectangleSq(
                    binaryPlateImage32,
                    Connected.EightConnected,
                    leftTop2,
                    rightTop2,
                    leftBottom2,
                    rightBottom2
                );

            binaryPlateImage32.Dispose();

            Int16Image plateImageGray = new Int16Image();

            VisionLab.Convert(plateImage, plateImageGray);
            binaryCharacterImage.Assign_Op(plateImageGray);
            
            // Eerst de standaard wrap proberen
            try
            {
                //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
                );
            }
            catch (Exception )
            {
                // NIEUW
                // Als dat mislukt dan de andere gebruiken
                try
                {
                    VisionLab.Warp(plateImageGray,
                        binaryCharacterImage,
                        TransformDirection.ForwardT,
                        new Coord2D(leftTop2),
                        new Coord2D(rightTop2),
                        new Coord2D(leftBottom2),
                        new Coord2D(rightBottom2),
                        c_height,
                        c_width,
                        0
                    );
                }
                catch (Exception)
                {
                    return false;
                }                
            }

            plateImageGray.Dispose();

            //*******************************//
            //** Exercise:                 **//
            //**   adjust licenseplate     **//
            //**   segmentation            **//
            //*******************************//
            // NIEUW
            Int16Image MaxMin = new Int16Image();
            Int16Image MaxMin2 = new Int16Image();

            // NIEUW
            //2 x max rondje ding
            //dan 2 x min rondje ding
            //dan van elkaar aftrekken
            //(zoeken op heldere object)
            Mask_Int32 mask = new Mask_Int32(11, 11, 5, 5);
            VisionLab.MaximumFilter(binaryCharacterImage, MaxMin, FixEdge.EdgeExtend, mask);
            VisionLab.MaximumFilter(MaxMin, MaxMin2, FixEdge.EdgeExtend, mask);

            VisionLab.MinimumFilter(MaxMin2, MaxMin, FixEdge.EdgeExtend, mask);
            VisionLab.MinimumFilter(MaxMin, MaxMin2, FixEdge.EdgeExtend, mask);
            // Maxmin2 holds the result now of the filter oparations
            // Get the difference between both
            VisionLab.Subtract(binaryCharacterImage, MaxMin2);

            MaxMin2.Dispose();
            MaxMin.Dispose();

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

            Int16Image bin = new Int16Image();
            
            // NIEUW
            // Recreate images that are corralated / deformed
            VisionLab.Opening(binaryCharacterImage, bin, new Mask_Int32(2, 2, 1));
            
            
            // Convert to a 32 bit format 
            Int32Image binaryCharacterImage32 = new Int32Image();
            // Int32Image binCharImg32 = new Int32Image();
            VisionLab.Convert(bin, binaryCharacterImage32);
            bin.Dispose();
            // Remove blobs connected to the border
            VisionLab.RemoveBorderBlobs(binaryCharacterImage32, Connected.EightConnected, Border.AllBorders);
            // Remove small blobs
            VisionLab.RemoveBlobs(binaryCharacterImage32, Connected.EightConnected, BlobAnalyse.BA_Area, c_remove_blobs_min, c_remove_blobs_max);

            //Convert to a 16 bit format             
            VisionLab.Convert(binaryCharacterImage32, binaryCharacterImage);

            binaryCharacterImage32.Dispose();
            leftTop.Dispose();
            rightTop.Dispose();
            leftBottom.Dispose();
            rightBottom.Dispose();
            GC.Collect();
            // NIEUW
            // Check if 6 characters/blobs have been found and label image.
            if (VisionLab.LabelBlobs(binaryCharacterImage, Connected.EightConnected) != 6)
                return false;
            return true;
        }
        /*
         *  Description:
         *      Read the license plate
         *  Input:
         *          //Rectified license plate image containing six characters
         *          Int16Image labeledRectifiedPlateImage
         *          BlobMatcher_Int16 matcher	//initialized blobmatcher
         *          ClassLexicon lexicon		//initialized lexicon
         *  Output:
         *          //Result by the blob matcher
         *          ref LicensePlate result
         *          //Result by the lexicon
         *          ref LicensePlate lexiconResult
         *  Return:
         *          //six characters found
         *      bool
         */
        public static bool MatchPlate(Int16Image binaryCharacterImage, BlobMatcher_Int16 matcher,
                                      ClassLexicon lexicon, ref LicensePlate result, ref LicensePlate lexiconResult, bool dilate)
        {
            // NIEUW
            // 2de optie voor aanroep als eerste low confidence levert
            if (dilate)
            {
                Int16Image temp = new Int16Image();
                VisionLab.Dilation(binaryCharacterImage, temp, new Mask_Int32(3, 3, 1));
                binaryCharacterImage = new Int16Image(temp);
                temp.Dispose();
            }
            if (VisionLab.LabelBlobs(binaryCharacterImage, Connected.EightConnected) != 6)
            {
                return(false);
            }

            //Calculate dimensions and locations of all characters/blobs.
            vector_BlobAnalyse ba_vec = new vector_BlobAnalyse();

            ba_vec.Add(BlobAnalyse.BA_TopLeft);
            ba_vec.Add(BlobAnalyse.BA_Height);
            ba_vec.Add(BlobAnalyse.BA_Width);
            vector_Blob returnBlobs = new vector_Blob();

            VisionLab.BlobAnalysis(binaryCharacterImage, VisionLab.VectorToSet_BlobAnalyse(ba_vec), VisionLab.MaxPixel(binaryCharacterImage), returnBlobs, SortOrder.SortDown, BlobAnalyse.BA_TopLeft, UseXOrY.UseX);
            ba_vec.Dispose();
            Int16Image binaryCharacter = new Int16Image();

            //Create data structure for lexicon.
            vector_vector_LetterMatch match = new vector_vector_LetterMatch();

            // NIEUW
            // Change the matcher params
            matcher.ChangeParams(60, 10, 64, 0);
            //Process each character/blob.
            foreach (Blob b in returnBlobs)
            {
                //Cut out character
                VisionLab.ROI(binaryCharacterImage, binaryCharacter, b.TopLeft(), new HeightWidth(b.Height(), b.Width()));
                //Convert ROI result to binary
                VisionLab.ClipPixelValue(binaryCharacter, 0, 1);
                //Calculate character's classification for all classes.
                vector_PatternMatchResult returnMatches = new vector_PatternMatchResult();
                float  conf = matcher.AllMatches(binaryCharacter, (float)-0.5, (float)0.5, returnMatches);
                float  err  = returnMatches[0].error;
                int    id   = returnMatches[0].id;
                string chr  = matcher.PatternName(id);
                // NIEUW
                // If error to big decrease the confidence
                if (err > 0.20f)
                {
                    conf -= 0.2f;
                }
                //Fill datastructure for lexicon.
                match.Add(VisionLabEx.PatternMatchResultToLetterMatch(returnMatches));

                //Store best match in result
                result.characters.Add(
                    new LicenseCharacter(
                        chr,
                        err,
                        conf,

                        // NIEUW
                        // Extra param: The middle of a character
                        // (used for matching patterns)
                        b.TopLeft().x + ((b.TopRight().x - b.TopLeft().x) / 2),

                        // NIEUW
                        // All other results that we're found
                        // So we can switch between em
                        returnMatches
                        ));
            }

            //Validate match with lexicon.
            vector_int bestWord = new vector_int();

            lexiconResult.confidence = lexicon.FindBestWord(match, bestWord, Optimize.OptimizeForMinimum);
            for (int i = 0; i < bestWord.Count; i++)
            {
                string character = matcher.PatternName(bestWord[i]);
                //Store lexicon result
                lexiconResult.characters.Add(new LicenseCharacter(character));
            }

            // NIEUW
            // Create the best match with the aid of the pattern matcher
            result.CalculateBestMatch(matcher);

            binaryCharacter.Dispose();
            returnBlobs.Dispose();
            match.Dispose();
            bestWord.Dispose();
            GC.Collect();
            return(true);
        }
        /*  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
         *          Int16Image binaryPlateImage
         *  Output:
         *          //Image containing binary six characters
         *          ref Int16Image binaryCharacterImage
         *  Return:
         *          //Function executed successfully
         *          bool
         */
        public static bool FindCharacters(RGB888Image plateImage, Int16Image binaryPlateImage, ref Int16Image binaryCharacterImage)
        {
            //Constants
            const int c_height           = 100;
            const int c_width            = 470;
            const int c_remove_blobs_min = 0;
            const int c_remove_blobs_max = 400;

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

            // 2de set coordinaten:
            // NIEUW
            XYCoord leftTop2     = new XYCoord();
            XYCoord rightTop2    = new XYCoord();
            XYCoord leftBottom2  = new XYCoord();
            XYCoord rightBottom2 = new XYCoord();

            //Find licenseplate
            Int32Image binaryPlateImage32 = new Int32Image();

            VisionLab.Convert(binaryPlateImage, binaryPlateImage32);

            VisionLab.FindCornersRectangle(
                binaryPlateImage32,
                Connected.EightConnected,
                0.5,
                Orientation.Landscape,
                leftTop,
                rightTop,
                leftBottom,
                rightBottom
                );

            // NIEUW
            // Coordinaten bepalen voor deze functie
            VisionLab.FindCornersRectangleSq(
                binaryPlateImage32,
                Connected.EightConnected,
                leftTop2,
                rightTop2,
                leftBottom2,
                rightBottom2
                );

            binaryPlateImage32.Dispose();

            Int16Image plateImageGray = new Int16Image();

            VisionLab.Convert(plateImage, plateImageGray);
            binaryCharacterImage.Assign_Op(plateImageGray);

            // Eerst de standaard wrap proberen
            try
            {
                //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
                    );
            }
            catch (Exception)
            {
                // NIEUW
                // Als dat mislukt dan de andere gebruiken
                try
                {
                    VisionLab.Warp(plateImageGray,
                                   binaryCharacterImage,
                                   TransformDirection.ForwardT,
                                   new Coord2D(leftTop2),
                                   new Coord2D(rightTop2),
                                   new Coord2D(leftBottom2),
                                   new Coord2D(rightBottom2),
                                   c_height,
                                   c_width,
                                   0
                                   );
                }
                catch (Exception)
                {
                    return(false);
                }
            }

            plateImageGray.Dispose();

            //*******************************//
            //** Exercise:                 **//
            //**   adjust licenseplate     **//
            //**   segmentation            **//
            //*******************************//
            // NIEUW
            Int16Image MaxMin  = new Int16Image();
            Int16Image MaxMin2 = new Int16Image();

            // NIEUW
            //2 x max rondje ding
            //dan 2 x min rondje ding
            //dan van elkaar aftrekken
            //(zoeken op heldere object)
            Mask_Int32 mask = new Mask_Int32(11, 11, 5, 5);

            VisionLab.MaximumFilter(binaryCharacterImage, MaxMin, FixEdge.EdgeExtend, mask);
            VisionLab.MaximumFilter(MaxMin, MaxMin2, FixEdge.EdgeExtend, mask);

            VisionLab.MinimumFilter(MaxMin2, MaxMin, FixEdge.EdgeExtend, mask);
            VisionLab.MinimumFilter(MaxMin, MaxMin2, FixEdge.EdgeExtend, mask);
            // Maxmin2 holds the result now of the filter oparations
            // Get the difference between both
            VisionLab.Subtract(binaryCharacterImage, MaxMin2);

            MaxMin2.Dispose();
            MaxMin.Dispose();

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

            Int16Image bin = new Int16Image();

            // NIEUW
            // Recreate images that are corralated / deformed
            VisionLab.Opening(binaryCharacterImage, bin, new Mask_Int32(2, 2, 1));


            // Convert to a 32 bit format
            Int32Image binaryCharacterImage32 = new Int32Image();

            // Int32Image binCharImg32 = new Int32Image();
            VisionLab.Convert(bin, binaryCharacterImage32);
            bin.Dispose();
            // Remove blobs connected to the border
            VisionLab.RemoveBorderBlobs(binaryCharacterImage32, Connected.EightConnected, Border.AllBorders);
            // Remove small blobs
            VisionLab.RemoveBlobs(binaryCharacterImage32, Connected.EightConnected, BlobAnalyse.BA_Area, c_remove_blobs_min, c_remove_blobs_max);

            //Convert to a 16 bit format
            VisionLab.Convert(binaryCharacterImage32, binaryCharacterImage);

            binaryCharacterImage32.Dispose();
            leftTop.Dispose();
            rightTop.Dispose();
            leftBottom.Dispose();
            rightBottom.Dispose();
            GC.Collect();
            // NIEUW
            // Check if 6 characters/blobs have been found and label image.
            if (VisionLab.LabelBlobs(binaryCharacterImage, Connected.EightConnected) != 6)
            {
                return(false);
            }
            return(true);
        }