/// <summary> /// /// </summary> /// <param name="input_img">original image</param> /// <param name="type"></param> /// <returns></returns> public static List <Image <Gray, byte> > find_all_possible_plates(Image <Gray, byte> input_img, Plate_feature.type_of_plate type) { Image <Gray, byte> blur = Image_utils.gaussian_blur(input_img); Image <Gray, byte> sobelx = Image_utils.sobel_X(blur).Convert <Gray, byte>(); Image <Gray, byte> adaptive = Image_utils.adaptive_threshold(sobelx); Image <Gray, byte> morp = Image_utils.morphology_ex(adaptive, Plate_feature.type_of_plate.RECT_PLATE); VectorOfVectorOfPoint contours = Image_utils.find_all_contours(morp); List <Image <Gray, byte> > approved_plates = new List <Image <Gray, byte> >(); for (int i = 0; i < contours.Size; i++) { double area = CvInvoke.ContourArea(contours[i]); Rectangle r = CvInvoke.BoundingRectangle(contours[i]); RotatedRect rr = CvInvoke.MinAreaRect(contours[i]); Image <Gray, byte> suspected_plate = input_img.Copy(r); Tuple <Image <Gray, byte>, Rectangle> after_clean_plate_tuple; Tuple <bool, List <Image <Gray, byte> > > after_check_plate_has_characters_tuple; if (!Plate_feature.ratio_check(type, area, r.Width, r.Height)) { continue; } else { if (!Plate_feature.validate_rotation_and_ratio(type, rr)) { continue; } else { after_clean_plate_tuple = clean_plate(suspected_plate, type); after_check_plate_has_characters_tuple = check_plate_has_character(after_clean_plate_tuple.Item1, type); if (!after_check_plate_has_characters_tuple.Item1) { continue; } else { approved_plates = after_check_plate_has_characters_tuple.Item2; } } } } return(approved_plates); }
/// <summary> /// /// </summary> /// <param name="plate">plate cropped from original image</param> /// <returns>List of images of characters</returns> public static List <Image <Gray, byte> > segment_characters_from_plate(Image <Gray, byte> plate) { List <Image <Gray, byte> > segmented_characters = new List <Image <Gray, byte> >(); //Image<Gray, byte> blur_plate = Image_utils.gaussian_blur(plate); Image <Gray, byte> threshold_plate = Image_utils.adaptive_threshold(plate); //Image<Gray, byte> threshold_plate = plate.ThresholdBinary(new Gray(100), new Gray(255)); //CvInvoke.Imshow("plate", threshold_plate); VectorOfVectorOfPoint contours = Image_utils.find_all_contours(threshold_plate); List <VectorOfPoint> hulls = get_convex_hull(plate, contours); Image <Gray, byte> hull_img = new Image <Gray, byte>(plate.Width, plate.Height, new Gray(0)); foreach (VectorOfPoint hull in hulls) { CvInvoke.FillConvexPoly(hull_img, hull, new MCvScalar(255)); } //CvInvoke.Imshow("hull", hull_img); VectorOfVectorOfPoint final_contours = Image_utils.find_all_contours(hull_img); if (final_contours == null) { return(segmented_characters); } Dictionary <Rectangle, VectorOfPoint> dict_to_order = new Dictionary <Rectangle, VectorOfPoint>(); for (int i = 0; i < final_contours.Size; i++) { Rectangle r = CvInvoke.BoundingRectangle(final_contours[i]); dict_to_order.Add(r, final_contours[i]); } List <VectorOfPoint> ordered_contours = new List <VectorOfPoint>(); var ordered_result = dict_to_order.OrderByDescending(i => i.Key.X); foreach (KeyValuePair <Rectangle, VectorOfPoint> kvp in ordered_result) { ordered_contours.Add(kvp.Value); Image <Gray, byte> character = plate.Copy(kvp.Key); segmented_characters.Add(character); } //CvInvoke.WaitKey(); //CvInvoke.DestroyAllWindows(); return(segmented_characters); }