/// <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> /// 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); } }
/// <summary> /// check whether the possible plate after clean func is a plate or not by finding the characters in it. /// </summary> /// <param name="suspected_plate"></param> /// <param name="type"></param> /// <returns></returns> public static Tuple <bool, List <Image <Gray, byte> > > check_plate_has_character(Image <Gray, byte> suspected_plate, Plate_feature.type_of_plate type) { List <Image <Gray, byte> > characters_found_on_plate = Plate_segmentation.segment_characters_from_plate(suspected_plate); Tuple <bool, List <Image <Gray, byte> > > output = new Tuple <bool, List <Image <Gray, byte> > >(false, characters_found_on_plate); if (characters_found_on_plate.Count > 5) { output = new Tuple <bool, List <Image <Gray, byte> > >(true, characters_found_on_plate); return(output); } else { return(output); } }
/// <summary> /// /// </summary> /// <param name="input_image"></param> /// <returns></returns> public static Image <Gray, byte> morphology_ex(Image <Gray, byte> input_image, Plate_feature.type_of_plate type) { Mat structure = new Mat(); if (type == Plate_feature.type_of_plate.RECT_PLATE) { structure = CvInvoke.GetStructuringElement(Emgu.CV.CvEnum.ElementShape.Rectangle, new Size(22, 3), new Point(-1, -1)); } else if (type == Plate_feature.type_of_plate.SQUARE_PLATE) { structure = CvInvoke.GetStructuringElement(Emgu.CV.CvEnum.ElementShape.Rectangle, new Size(26, 5), new Point(-1, -1)); } Image <Gray, byte> output_image = input_image.MorphologyEx(MorphOp.Close, structure, new Point(-1, -1), 1, BorderType.Default, new MCvScalar(0)); return(output_image); }