public static List <Image <Gray, byte> > test(Image <Gray, byte> plate_after_preprocessing) { VectorOfVectorOfPoint contours = Image_utils.find_all_contours(plate_after_preprocessing); List <VectorOfPoint> hulls = get_convex_hull(plate_after_preprocessing, contours); List <Image <Gray, byte> > order_character_image = ordered_character(plate_after_preprocessing, hulls); return(order_character_image); }
/// <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); }
/// <summary> /// clean the input suspected plate image and decide if that is a possible plate or not by checking ratio condition. /// </summary> /// <param name="suspected_plate"></param> /// <param name="type"></param> /// <returns>a tupple that contains: /// 1: image of the plate, /// 2: the (x,y,w,h) of the actual plate in the image /// </returns> public static Tuple <Image <Gray, byte>, Rectangle> clean_plate(Image <Gray, byte> suspected_plate, Plate_feature.type_of_plate type) { //Image<Gray, byte> threshold_plate = Image_utils.adaptive_threshold(suspected_plate); Image <Gray, byte> threshold_plate = suspected_plate.ThresholdBinary(new Gray(100), new Gray(255)); VectorOfVectorOfPoint contours = Image_utils.find_all_contours(threshold_plate); Rectangle r = new Rectangle(); Tuple <Image <Gray, byte>, Rectangle> output = new Tuple <Image <Gray, byte>, Rectangle>(suspected_plate, r); if (contours != null) { double max_area = 0; VectorOfPoint max_contour = new VectorOfPoint(); for (int i = 0; i < contours.Size; i++) { double temp = CvInvoke.ContourArea(contours[i]); if (temp > max_area) { max_area = temp; max_contour = contours[i]; } } VectorOfVectorOfPoint c = new VectorOfVectorOfPoint(max_contour); CvInvoke.DrawContours(threshold_plate, c, 0, new MCvScalar(0), 2); r = CvInvoke.BoundingRectangle(max_contour); RotatedRect plate_feature = CvInvoke.MinAreaRect(max_contour); Image <Gray, byte> rotated_plate = crop_and_rotated_plate(suspected_plate, plate_feature); output = new Tuple <Image <Gray, byte>, Rectangle>(rotated_plate, r); return(output); } else { return(output); } }