/// <summary> /// A method which builds the expected pattern /// </summary> /// <param name="pos1">The position of the first stripe</param> /// <param name="pos2">The position of the second stripe</param> private kenType[] createpattern(int pos1, int pos2) { kenType[] partsNum = new kenType[3]; // If it matches this then it must be this pattern if ((pos1 == 1 && pos2 == 4) || (pos1 == 2 && pos2 == 5)) { partsNum[0] = kenType.NUMBER; partsNum[1] = kenType.CHAR; partsNum[2] = kenType.NUMBER; return(partsNum); } // If the state ment didn't match then it must be a // pattern with pos1 = 2 and pos2 = 4 // Create a pointer int partNumPlace = 0; // The error of a found pattern double err = double.MaxValue; for (int i = 0; i < chars.Count; i++) { // Check if should move up with the pointer if (i == pos1 || i == pos2) { partNumPlace += 1; // Reset the error value err = double.MaxValue; } // Check if we found an char / digit and the matcher is sure about it // and it is more sure about this one compared to the error found if (chars[i].error <= 0.13 && chars[i].error < err) { // Sure enough about this char to use if to determine if part is num or not // Change error to this error value err = chars[i].error; // Check what we found if (Char.IsNumber(chars[i].character[0])) { partsNum[partNumPlace] = kenType.NUMBER; } else { partsNum[partNumPlace] = kenType.CHAR; } } // End if } // End loop // Return the pattern return(partsNum); }
/// <summary> /// A method which creates the best possible match for a license plate /// </summary> /// <param name="pos1">The position of the first stripe</param> /// <param name="pos2">The posisiton of the second stripe</param> /// <param name="partsNum">The kenType array</param> /// <param name="matcher">The BlobMatcher</param> private void createBestMatch(int pos1, int pos2, kenType[] partsNum, BlobMatcher_Int16 matcher) { // ************************************************************** // ** Creates the best match based on: ** // ** - If there should be a number, but char found: ** // ** - Find a number in the results and change it ** // ** - If there should be a number and number found ** // ** - If the next match is a character then we can ** // ** up the confidence a lot ** // ** - If the then following match is a number we ** // ** can up it a little ** // ** ** // ** - This also aplies for chars ** // ************************************************************** // A pointer which points to the partsNum place where we are at int partNumPlace = 0; const double maxError = 0.20; // Go through all the chars for (int i = 0; i < chars.Count; i++) { // Check if we need to up the pointer if (i == pos1 || i == pos2) partNumPlace += 1; // If there should be a number found if (partsNum[partNumPlace] == kenType.NUMBER && chars[i].error < maxError) { // If it isn't a number if (!Char.IsNumber(chars[i].character[0])) { // Loop through the results and find a number foreach (PatternMatchResult patrn in chars[i].PatternResults) { // if this is a number if (Char.IsNumber(matcher.PatternName(patrn.id)[0])) { // Change the chars value to this number chars[i] = new LicenseCharacter(matcher.PatternName(patrn.id), -0.04, 41); break; } } // End for loop } // End number expected but not found else if (chars[i].error > 0.11) // If there should be a number and a number was found { // Check if the next match is a char if (!Char.IsNumber(matcher.PatternName(chars[i].PatternResults[1].id)[0])) { // If so we can up the confidence chars[i] = new LicenseCharacter(chars[i].character, -0.02, 41); } // If the then following match is a char else if (!Char.IsNumber(matcher.PatternName(chars[i].PatternResults[2].id)[0])) { // Then we up the confidence a little chars[i] = new LicenseCharacter(chars[i].character, -0.01, chars[i].confidence + 0.1); } } } // Check if we should expect a char and the error value isn't to high else if (partsNum[partNumPlace] == kenType.CHAR && chars[i].error < maxError) { // Char expected but number found if (Char.IsNumber(chars[i].character[0])) { // Loop through the matches foreach (PatternMatchResult patrn in chars[i].PatternResults) { if (!Char.IsNumber(matcher.PatternName(patrn.id)[0])) { // If a char was found change the chars[i] value to it chars[i] = new LicenseCharacter(matcher.PatternName(patrn.id), -0.04, 41); break; } } // End for loop } // If we already have a char else if (chars[i].error > 0.11) { // Check if the second match is a number if (Char.IsNumber(matcher.PatternName(chars[i].PatternResults[1].id)[0])) { // If so we can up the confidence a lot chars[i] = new LicenseCharacter(chars[i].character, -0.02, 41); } // Check if the then following match is a number else if (Char.IsNumber(matcher.PatternName(chars[i].PatternResults[2].id)[0])) { // If so then we can up the confidence a little chars[i] = new LicenseCharacter(chars[i].character, -0.01, chars[i].confidence + 0.1); } } // End char expected and char found } // End char expected } // End loop // Done }
/// <summary> /// A method which checks if the kenType array contains a /// DONTKNOW /// </summary> /// <param name="partsNum">The kenType array which need to be checked</param> /// <returns>True if no DONTKNOW was found, /// False otherwise</returns> private bool checkFullMatch(kenType[] partsNum) { // Loop through foreach (kenType abc in partsNum) { // If one is a DONTKNOW if (abc == kenType.DONTKNOW) { return false; } } return true; }
/// <summary> /// If a pattern didn't get matched fully then this method will try to create a full /// pattern. /// </summary> /// <param name="partsNum">The array to check</param> private void tryFullPattern(ref kenType[] partsNum) { // **************************************************************************** // ** Reconstructs based on the fact that a license plate: ** // ** - If we got into this method it always has pos1 = 2 and pos2 = 4 ** // ** and thus: ** // ** - Always has one number (can be on all three places) ** // ** - Always has two char (can also be on all places) ** // ** ** // ** Based on these facts it can be reconstruced ** // ***************************************************************************** // Check if there is a number on some place // Then the other parts must be chars if (partsNum[0] == kenType.NUMBER) { partsNum[1] = kenType.CHAR; partsNum[2] = kenType.CHAR; } else if (partsNum[1] == kenType.NUMBER) { partsNum[0] = kenType.CHAR; partsNum[2] = kenType.CHAR; } else if (partsNum[2] == kenType.NUMBER) { partsNum[0] = kenType.CHAR; partsNum[1] = kenType.CHAR; } // Check if there are two chars on some place, then the other must be a number else if (partsNum[0] == kenType.CHAR && partsNum[1] == kenType.CHAR) partsNum[2] = kenType.NUMBER; else if (partsNum[0] == kenType.CHAR && partsNum[2] == kenType.CHAR) partsNum[1] = kenType.NUMBER; else if (partsNum[1] == kenType.CHAR && partsNum[2] == kenType.CHAR) partsNum[0] = kenType.NUMBER; }
/// <summary> /// A method which builds the expected pattern /// </summary> /// <param name="pos1">The position of the first stripe</param> /// <param name="pos2">The position of the second stripe</param> private kenType[] createpattern(int pos1, int pos2) { kenType[] partsNum = new kenType[3]; // If it matches this then it must be this pattern if ((pos1 == 1 && pos2 == 4) || (pos1 == 2 && pos2 == 5)) { partsNum[0] = kenType.NUMBER; partsNum[1] = kenType.CHAR; partsNum[2] = kenType.NUMBER; return partsNum; } // If the state ment didn't match then it must be a // pattern with pos1 = 2 and pos2 = 4 // Create a pointer int partNumPlace = 0; // The error of a found pattern double err = double.MaxValue; for (int i = 0; i < chars.Count; i++) { // Check if should move up with the pointer if (i == pos1 || i == pos2) { partNumPlace += 1; // Reset the error value err = double.MaxValue; } // Check if we found an char / digit and the matcher is sure about it // and it is more sure about this one compared to the error found if (chars[i].error <= 0.13 && chars[i].error < err) { // Sure enough about this char to use if to determine if part is num or not // Change error to this error value err = chars[i].error; // Check what we found if (Char.IsNumber(chars[i].character[0])) { partsNum[partNumPlace] = kenType.NUMBER; } else { partsNum[partNumPlace] = kenType.CHAR; } } // End if } // End loop // Return the pattern return partsNum; }