Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Text.RegularExpressions;
- /* Hidde Westerhof & Yannick Strobl
- * L2A
- * Datum: 21 10 2014
- * Laatste Score: 175 (Treshold 30) (min moet 200 zijn)
- *
- */
- namespace LicPlate
- {
- public class LicensePlateMatcher
- {
- /// <summary>
- /// Deze lijst staat vol met reguliere expressies die grammatica's van nummerborden voorstellen.
- /// </summary>
- private static readonly Regex[] regexes = new Regex[] { new Regex(@"^[a-zA-Z]{2}[\d]{2}[\d]{2}$"),
- new Regex(@"^[\d]{2}[\d]{2}[a-zA-Z]{2}$"),
- new Regex(@"^[\d]{2}[a-zA-Z]{2}[\d]{2}$"),
- new Regex(@"^[a-zA-Z]{2}[\d]{2}[a-zA-Z]{2}$"),
- new Regex(@"^[a-zA-Z]{2}[a-zA-Z]{2}[\d]{2}$"),
- new Regex(@"^[\d]{2}[a-zA-Z]{2}[a-zA-Z]{2}$"),
- new Regex(@"^[\d]{2}[a-zA-Z]{3}[\d]{1}$"),
- new Regex(@"^[\d]{1}[a-zA-Z]{3}[\d]{2}$"),
- new Regex(@"^[a-zA-Z]{2}[\d]{3}[a-zA-Z]{1}$"),
- new Regex(@"^[a-zA-Z]{1}[\d]{3}[a-zA-Z]{2}$"),
- new Regex(@"^[a-zA-Z]{3}[\d]{2}[a-zA-Z]{1}$"),
- new Regex(@"^[a-zA-Z]{1}[\d]{2}[a-zA-Z]{3}$"),
- new Regex(@"^[\d]{1}[a-zA-Z]{2}[\d]{3}$"),
- new Regex(@"^[\d]{3}[a-zA-Z]{2}[\d]{1}$")
- };
- private class TresHolds
- {
- public static readonly TresHolds H_NORM = new TresHolds(11, 80);
- public static readonly TresHolds S_NORM = new TresHolds(100, 255);
- public static readonly TresHolds V_NORM = new TresHolds(100, 255);
- public static readonly TresHolds H_ONDER = new TresHolds(11, 85);
- public static readonly TresHolds S_ONDER = new TresHolds(20, 160);
- public static readonly TresHolds V_ONDER = new TresHolds(30, 175);
- public static readonly TresHolds H_OVER = new TresHolds(20, 240);
- public static readonly TresHolds S_OVER = new TresHolds(30, 150);
- public static readonly TresHolds V_OVER = new TresHolds(250, 255);
- public static readonly TresHolds BLOBS = new TresHolds(1, 1000);
- public int min { get; set; }
- public int max { get; set; }
- private TresHolds(int min, int max)
- {
- this.min = min;
- this.max = max;
- }
- }
- /*
- * Description:
- * Find the largest license plate in the image
- * - Segment using ThresholdHSVchannels
- * - Remove blobs which are not license plates
- * Input:
- * //Original image
- * RGB888Image plateImage
- * Output:
- * //Segmented license plate
- * ref Int32Image binaryPlateImage
- * Return:
- * //License plate found?
- * bool
- */
- public static bool FindPlate(RGB888Image plateImage, ref Int32Image binaryPlateImage)
- {
- try
- {
- //*******************************//
- //** Exercise: **//
- //** adjust licenseplate **//
- //** segmentation **//
- //*******************************//
- //Find licenseplate
- Func<RGB888Image, TresHolds, Int32Image>[] methods = new Func<RGB888Image, TresHolds, Int32Image>[] {
- new Func<RGB888Image, TresHolds, Int32Image>((a, b) => FindPlateOnTres(a, b, TresHolds.H_NORM, TresHolds.S_NORM, TresHolds.V_NORM)),
- new Func<RGB888Image, TresHolds, Int32Image>((a, b) => FindPlateOnTres(a, b, TresHolds.H_ONDER, TresHolds.S_ONDER, TresHolds.V_ONDER)),
- new Func<RGB888Image, TresHolds, Int32Image>((a, b) => FindPlateOnTres(a, b, TresHolds.H_OVER, TresHolds.S_OVER, TresHolds.V_OVER)),
- FindPlateOnHSV};
- Int32Image binaryImage;
- foreach (var method in methods)
- {
- if ((VisionLab.SumIntPixels(binaryImage = method(plateImage, TresHolds.BLOBS)) > 0))
- {
- binaryPlateImage = binaryImage;
- return true;
- }
- }
- return false;
- }
- catch (System.Exception ex)
- {
- throw new Exception("FindPlate: " + ex.Message);
- }
- }
- private static Int32Image FindPlateOnTres(RGB888Image plateImage, TresHolds blob, TresHolds h, TresHolds s, TresHolds v)
- {
- Int32Image binaryPlateImage = new Int32Image(plateImage.GetWidth(), plateImage.GetHeight());
- HSV888Image plateImageHSV = new HSV888Image();
- VisionLab.FastRGBToHSV(plateImage, plateImageHSV);
- VisionLab.Threshold3Channels(plateImageHSV, binaryPlateImage, h.min, h.max, s.min, s.max, v.min, v.max);
- removeBlobs(binaryPlateImage, plateImageHSV, blob.min, blob.max);
- return binaryPlateImage;
- }
- private static Int32Image FindPlateOnHSV(RGB888Image plateImage, TresHolds blob)
- {
- HSV888Image plateImageHSV = new HSV888Image();
- VisionLab.FastRGBToHSV(plateImage, plateImageHSV);
- Int32Image h = new Int32Image();
- Int32Image s = new Int32Image();
- Int32Image v = new Int32Image();
- VisionLab.Extract1Channel(plateImageHSV, HSVColor.Hue, h);
- VisionLab.Extract1Channel(plateImageHSV, HSVColor.Saturation, s);
- VisionLab.Threshold(h, 18, 55);
- VisionLab.Threshold(s, 140, 230);
- VisionLab.Add(h, s);
- removeBlobs(h, plateImageHSV, blob.min, blob.max);
- plateImageHSV.Dispose();
- return h;
- }
- private static void removeBlobs(Int32Image binaryPlateImage, HSV888Image plateImageHSV, int c_remove_blobs_min, int c_remove_blobs_max)
- {
- //Remove blobs with small areas
- VisionLab.RemoveBlobs(binaryPlateImage, Connected.EightConnected, BlobAnalyse.BA_Area, c_remove_blobs_min, c_remove_blobs_max);
- VisionLab.RemoveBorderBlobs(binaryPlateImage, Connected.EightConnected, Border.AllBorders);
- VisionLab.RemoveBlobs(binaryPlateImage, Connected.EightConnected, BlobAnalyse.BA_LengthBreadthRatio, 0, 2.5);
- //VisionLab.RemoveBlobs(binaryPlateImage, Connected.EightConnected, BlobAnalyse.BA_NrOfHoles, 0, 5);
- //Fill up characters
- VisionLab.FillHoles(binaryPlateImage, Connected.FourConnected);
- }
- /*
- * 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 = 400;
- XYCoord leftTop = new XYCoord();
- XYCoord rightTop = new XYCoord();
- XYCoord leftBottom = new XYCoord();
- XYCoord rightBottom = new XYCoord();
- //Find licenseplate
- if (!VisionLab.FindCornersRectangle(binaryPlateImage, Connected.EightConnected, 0.5, Orientation.Landscape, leftTop, rightTop, leftBottom, rightBottom))
- {
- VisionLab.FindCornersRectangleSq(binaryPlateImage, Connected.EightConnected, leftTop, rightTop, leftBottom, rightBottom);
- }
- Int32Image plateImageGray = new Int32Image();
- VisionLab.Convert(plateImage, plateImageGray);
- 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)
- {
- //Warp, 3 coords on one line
- return false;
- }
- plateImageGray.Dispose();
- //*******************************//
- //** Exercise: **//
- //** adjust licenseplate **//
- //** segmentation **//
- //*******************************//
- //Find dark text on bright licenseplate using ThresholdISOData
- if (VisionLab.ThresholdIsoData(binaryCharacterImage, ObjectBrightness.DarkObject) != 1)
- {
- VisionLab.ThresholdIsoData(binaryCharacterImage, ObjectBrightness.BrightObject);
- }
- //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);
- }
- }
- /*
- * Description:
- * Read the license plate
- * Input:
- * //Rectified license plate image containing six characters
- * Int32Image labeledRectifiedPlateImage
- * Output:
- * //Result by the blob matcher
- * ref LicensePlate result
- * Return:
- * //six characters found
- * bool
- */
- public static bool MatchPlate(Int32Image binaryCharacterImage, BlobMatcher_Int32 matcher, ClassLexicon lexicon, ref LicensePlate result, ref LicensePlate lexiconResult)
- {
- try
- {
- //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();
- //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();
- 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);
- //letter veranderen
- //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();
- returnBlobs.Dispose();
- match.Dispose();
- bestWord.Dispose();
- return numchecker(result.getLicensePlateString());
- }
- catch (System.Exception ex)
- {
- throw new Exception("MatchPlate: " + ex.Message);
- }
- }
- /// <summary>
- /// Methode kijkt of het kenteken een valide grammatica heeft.
- /// </summary>
- /// <param name="numbord">string van de gehele nummerbord</param>
- /// <returns>Methode returnt true als et een goede kentekenplaat is. </returns>
- private static bool numchecker(string numbord)
- {
- foreach (Regex s in regexes)
- {
- if (s.IsMatch(numbord))
- {
- return true;
- }
- }
- return false;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement