/// <summary> /// Construct from values. /// </summary> /// <param name="contour"></param> /// <param name="ellipse"></param> /// <param name="rating"></param> public DetectedEllipse( Emgu.CV.Contour<System.Drawing.Point> contour, Emgu.CV.Structure.Ellipse ellipse, double rating) { _contour = contour; _ellipse = ellipse; _rating = rating; }
/// <summary> /// Construct from values. /// </summary> /// <param name="contour"></param> /// <param name="ellipse"></param> /// <param name="rating"></param> public DetectedEllipse( Emgu.CV.Contour <System.Drawing.Point> contour, Emgu.CV.Structure.Ellipse ellipse, double rating) { _contour = contour; _ellipse = ellipse; _rating = rating; }
/// <summary> /// this function used to perform the " Initialization step " in Hand Tracking Algorithm /// </summary> /// <param name="h">a contour point used to determine the bounding recatnagle around the hand</param> internal void ExtractFeatures(Emgu.CV.Contour <System.Drawing.Point> h) { GetImages(); contour_rect = h.BoundingRectangle; temp_Image.ROI = contour_rect; current_image.ROI = contour_rect; foundFeaturesInChannels = current_image.GoodFeaturesToTrack(tracking_features_number, quality, min_distance, block_size); int founded_features = foundFeaturesInChannels[0].Length; for (int i = 0; i < founded_features; i++) { foundFeaturesInChannels[0][i].X += current_image.ROI.X; foundFeaturesInChannels[0][i].Y += current_image.ROI.Y; good_features.Add(foundFeaturesInChannels[0][i]); } temp_Image.ROI = Rectangle.Empty; current_image.ROI = Rectangle.Empty; int ptt = tracking_features_number - founded_features; if (ptt > 0) { AddNewFeatures(ptt, foundFeaturesInChannels[0]); } previous_features = good_features.ToArray(); for (int i = 0; i < previous_features.Length; i++) { feature_speeds[i] = 1; lost_feature[i] = false; } good_features.Clear(); bad_features.Clear(); previous_image = current_image; Form1.NewImage = colored_temp_image; }
/// <summary> /// Fit ellipse through contour points in a least square sense. /// </summary> /// <param name="c">Contour</param> /// <returns>Ellipse</returns> private Emgu.CV.Structure.Ellipse FitByContour(Emgu.CV.Contour <System.Drawing.Point> c) { System.Drawing.PointF[] mypoints = Array.ConvertAll( c.ToArray <System.Drawing.Point>(), value => new System.Drawing.PointF(value.X, value.Y) ); Emgu.CV.Structure.Ellipse e = Emgu.CV.PointCollection.EllipseLeastSquareFitting(mypoints); Emgu.CV.Structure.MCvBox2D box = e.MCvBox2D; // Modify ellipse to have width = a, height = b in the ellipse equation. box.size.Height *= 0.5f; box.size.Width *= 0.5f; return(new Emgu.CV.Structure.Ellipse(box)); }
/// <summary> /// Detect ellipses in image /// </summary> /// <param name="image">Binary image with white foreground</param> /// <returns>List of ellipses found</returns> public DetectedEllipse[] DetectEllipses(Emgu.CV.Image <Emgu.CV.Structure.Gray, byte> image) { List <DetectedEllipse> ellipses = new List <DetectedEllipse>(); Emgu.CV.Contour <System.Drawing.Point> c = image.FindContours(); while (c != null) { if (c.Count() >= _min_contour_count) { Emgu.CV.Structure.Ellipse e = FitByContour(c); double rating = GoodnessOfFit(e, c); ellipses.Add(new DetectedEllipse(c, e, rating)); } c = c.HNext; } return(ellipses.ToArray()); }
/// <summary> /// Evaluate goodness of fit. /// </summary> /// <remarks> /// Calculates the average distance of all contour points to the ellipse. The distance of point to /// an ellipse is given by calculating the point on the ellipse that is closest to the query. This calculation /// is performed by transforming the point into a coordinate system where the ellipse is in main-pose /// (x-axis points toward a, y-axis points toward b, the origin is the center of the ellipse). Additionally, /// the coordinate system is crafted in such a way (non-uniform scaling) that the ellipse becomes a circle. /// Then, the closest point is simply the closest point on the circle. This point is transformed back into /// the world coordinate system where the distance between the query and the returned point is computed. /// </remarks> /// <param name="e">Ellipse</param> /// <param name="c">Contour points</param> /// <returns>Goodness of fit</returns> private double GoodnessOfFit(Emgu.CV.Structure.Ellipse e, Emgu.CV.Contour <System.Drawing.Point> c) { Matrix m = EllipseDetector.GetAffineFrame(e); Matrix inv = m.Inverse(); List <double> distances = new List <double>(); double avg_distance = 0.0; foreach (System.Drawing.Point p in c) { // Bring the point into the ellipse coordinate frame Vector x = p.ToParsley().ToHomogeneous(1.0); Vector r = (inv.Multiply(x.ToColumnMatrix())).GetColumnVector(0); // Find the closest point on the circle to r // From the above scaling construction the resulting circle has radius b Vector closest = r.ToNonHomogeneous().Normalize().Scale(e.MCvBox2D.size.Height); // Transform the closest point back Vector closest_in_world = (m.Multiply(closest.ToHomogeneous(1.0).ToColumnMatrix())).GetColumnVector(0); // Calculate the squared distance between the query and the point. avg_distance += (closest_in_world - x).ToNonHomogeneous().SquaredNorm(); } return(Math.Sqrt(avg_distance / c.Count())); }
public void Horizontal() { System.Diagnostics.Stopwatch stop = new System.Diagnostics.Stopwatch(); stop.Start(); u = Horiz(SobelGray); stop.Stop(); u = Proizvodnij1(u); u = Proizvodnij2(u); float max = MAX(u); DrawLine(u, max, Sobel); float sum = DrawMiddleLineHoriz(u, max, Sobel); List <int> maximum = SearchMaximums(u, sum, max, Sobel, false); Greenze(maximum, u); for (int i = 0; i < Horizont.Count; i++) { //Sobel.Draw(new CircleF(new System.Drawing.PointF(Convert.ToSingle(Sobel.Width * u[Horizont[i].k1] / max), Horizont[i].k1), 3), new Bgr(System.Drawing.Color.Red), 3); //Sobel.Draw(new CircleF(new System.Drawing.PointF(Convert.ToSingle(Sobel.Width * u[Horizont[i].k2] / max), Horizont[i].k2), 3), new Bgr(System.Drawing.Color.Red), 3); Horizont[i].original = Original.Copy(new System.Drawing.Rectangle(0, Horizont[i].k1, Original.Width, Horizont[i].k2 - Horizont[i].k1)); Horizont[i].sobel = Horizont[i].original.Convert <Gray, byte>(); Horizont[i].sobel1 = Horizont[i].original.Convert <Bgr, byte>(); Vertical(i); Horizont[i].p = Proizvodnij1(Horizont[i].p); Horizont[i].p = Proizvodnij2(Horizont[i].p); Horizont[i].p = Proizvodnij2(Horizont[i].p); float max1 = MAX(Horizont[i].p); float sum1 = DrawMiddleLineVertical(i, max1); float h = Horizont[i].sobel1.Height * sum1 / max1; Horizont[i].sobel1.Draw(new LineSegment2DF(new System.Drawing.PointF(0, h), new System.Drawing.PointF(Horizont[i].sobel1.Width, h)), new Bgr(System.Drawing.Color.Blue), 2); GetPlate(i, sum1, max1); } stop.Stop(); System.Diagnostics.Stopwatch st = new System.Diagnostics.Stopwatch(); st.Start(); Int32 ret = 0; for (int i = 0; i < Plate.Count; i++) { Ugol(Plate[i]); Plate[i].rotate2 = Plate[i].rotate.Resize(260, 56, Emgu.CV.CvEnum.INTER.CV_INTER_AREA); // Plate[i].rotate1 = Plate[i].rotate2.Convert <Gray, byte>(); CvInvoke.cvCLAHE(Plate[i].rotate1, 5, new System.Drawing.Size(8, 8), Plate[i].rotate1); //Plate[i].rotate1 = Threshold.GrayHCH(Plate[i].rotate1); CvInvoke.cvNormalize(Plate[i].rotate1, Plate[i].rotate1, 0, 255, Emgu.CV.CvEnum.NORM_TYPE.CV_MINMAX, Plate[i].rotate1); CvInvoke.cvAdaptiveThreshold(Plate[i].rotate1, Plate[i].rotate1, 255, Emgu.CV.CvEnum.ADAPTIVE_THRESHOLD_TYPE.CV_ADAPTIVE_THRESH_GAUSSIAN_C, Emgu.CV.CvEnum.THRESH.CV_THRESH_BINARY_INV, 15, 13); List <System.Drawing.Rectangle> rec = new List <System.Drawing.Rectangle>(); // Plate[i].rotate1 = Plate[i].rotate1.MorphologyEx(new StructuringElementEx(5, 5, 3, 3, Emgu.CV.CvEnum.CV_ELEMENT_SHAPE.CV_SHAPE_RECT), Emgu.CV.CvEnum.CV_MORPH_OP.CV_MOP_CLOSE, 1); using (Emgu.CV.MemStorage storage = new MemStorage()) { int il = 0; for (Emgu.CV.Contour <System.Drawing.Point> contours = Plate[i].rotate1.Convert <Gray, byte>().FindContours(Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_CCOMP); contours != null; contours = contours.HNext) { Emgu.CV.Contour <System.Drawing.Point> currentContour = contours; if (currentContour.BoundingRectangle.X > 3 && currentContour.BoundingRectangle.Width > 10 && currentContour.BoundingRectangle.Height > 10 && currentContour.BoundingRectangle.Height < 200 && currentContour.BoundingRectangle.Width < 50 && currentContour.BoundingRectangle.Height / currentContour.BoundingRectangle.Width < 1.5) { il++; Plate[i].rotate2.Draw(currentContour.BoundingRectangle, new Bgr(System.Drawing.Color.Red), 2); rec.Add(currentContour.BoundingRectangle); } } /*if (il < 1) * { * Plate.Remove(Plate[i]); * i--; * continue; * }*/ } for (int io = rec.Count - 1; io >= 0; io--) { for (int ip = 0; ip < io; ip++) { if (rec[ip].X > rec[ip + 1].X) { System.Drawing.Rectangle r = rec[ip]; rec[ip] = rec[ip + 1]; rec[ip + 1] = r; } } } GetRect(i, rec); if (!IsPlate(i, rec)) { Plate.Remove(Plate[i]); i--; continue; } for (int ih = 0; ih < rec.Count; ih++) { LetterDigit l = new LetterDigit(); l.LD = Plate[i].rotate1.Copy(rec[ih]); ret++; Plate[i].digit.Add(l); } Plate[i].px = new float[Plate[i].rotate1.Width]; for (int kl = 0; kl < Plate[i].rotate1.Width; kl++) { for (int kp = 0; kp < Plate[i].rotate1.Height; kp++) { if (Convert.ToInt32(Plate[i].rotate1[kp, kl].Intensity) == 255) { Plate[i].px[kl]++; } } } Plate[i].px = Proizvodnij1(Plate[i].px); Plate[i].px = Proizvodnij2(Plate[i].px); float maxpx = MAX(Plate[i].px); for (int h1 = 0, x = 0; h1 < Plate[i].px.Length - 1; h1++, x++) { float j = Plate[i].rotate2.Height * Plate[i].px[h1] / (maxpx); float j1 = Plate[i].rotate2.Height * Plate[i].px[h1 + 1] / (maxpx); Plate[i].rotate2.Draw(new LineSegment2DF(new System.Drawing.PointF(x, j), new System.Drawing.PointF(x, j1)), new Bgr(System.Drawing.Color.Red), 2); } List <int> min1 = SearchMininum(Plate[i].px, i, maxpx); /* double sumraz = Plate[i].rotate1.Width / min1.Count - 10; * for (int il = 0; il < min1.Count-1; il++) * { * double ggg= Math.Abs( min1[il+1] - min1[il]); * if (ggg < sumraz) * { * min1.Remove(min1[il + 1]); * il--; * continue; * } * /* if (il % 2 == 0) * Plate[i].rotate2.Draw(new LineSegment2DF(new System.Drawing.PointF(min1[il], 10), new System.Drawing.PointF(Convert.ToSingle(min1[il+1]), 10)), new Bgr(System.Drawing.Color.Aqua), 2); * if (il % 2 == 1) * Plate[i].rotate2.Draw(new LineSegment2DF(new System.Drawing.PointF(min1[il], 15), new System.Drawing.PointF(Convert.ToSingle(min1[il+1]), 15)), new Bgr(System.Drawing.Color.Orange), 2); * }*/ for (int il = 0; il < Plate[i].digit.Count; il++) { for (int gh = 0; gh < images.Length; gh++) { Image <Gray, byte> res = Plate[i].digit[il].LD.Resize(10, 18, Emgu.CV.CvEnum.INTER.CV_INTER_CUBIC).Sub(images[gh]); Plate[i].digit[il]._list.Add(Value2(images[gh], res)); } } //xOOOxxOOO Plate[i].text = TextLetter(i, 0) + TextDigit(i, 1) + TextDigit(i, 2) + TextDigit(i, 3) + TextLetter(i, 4) + TextLetter(i, 5) + TextDigit(i, 6) + TextDigit(i, 7) + TextDigit(i, 8); Original.Draw(new System.Drawing.Rectangle(Plate[i].x1, Plate[i].y1, Plate[i].x2 - Plate[i].x1, Plate[i].y2 - Plate[i].y1), new Bgr(System.Drawing.Color.Red), 2); } st.Stop(); }
public void ProcessImage(Emgu.CV.Image <Emgu.CV.Structure.Bgr, byte> image) { Emgu.CV.Image <Gray, byte> gray = image.Convert <Gray, byte>(); Emgu.CV.Image <Gray, byte> binary = new Image <Gray, byte>(image.Size); CvInvoke.cvThreshold(gray, binary, 40, 255, THRESH.CV_THRESH_BINARY | THRESH.CV_THRESH_OTSU); binary._Not(); Emgu.CV.Contour <System.Drawing.Point> contour_points = binary.FindContours(); MemStorage storage = new MemStorage(); Matrix <double> warp = new Matrix <double>(3, 3); while (contour_points != null) { Contour <Point> c = contour_points.ApproxPoly(contour_points.Perimeter * 0.05, storage); double p = c.Perimeter; if (c.Total == 4 && p > 300) { PointF[] src = new PointF[] { new PointF(c[0].X, c[0].Y), new PointF(c[1].X, c[1].Y), new PointF(c[2].X, c[2].Y), new PointF(c[3].X, c[3].Y) }; CvInvoke.cvGetPerspectiveTransform(src, _dest, warp); int flags = (int)INTER.CV_INTER_LINEAR + (int)WARP.CV_WARP_FILL_OUTLIERS; CvInvoke.cvWarpPerspective(gray, _roi, warp, flags, new MCvScalar(0)); double min_error; Orientation orient; FindBestOrientation(out min_error, out orient); if (min_error < 0.4) { image.DrawPolyline(c.ToArray(), true, new Bgr(Color.Green), 2); System.Console.WriteLine(min_error + " " + orient); switch (orient) { case Orientation.Degrees0: image.Draw(new LineSegment2D(c[0], c[3]), new Bgr(System.Drawing.Color.Red), 2); break; case Orientation.Degrees90: image.Draw(new LineSegment2D(c[1], c[0]), new Bgr(System.Drawing.Color.Red), 2); break; case Orientation.Degrees180: image.Draw(new LineSegment2D(c[2], c[1]), new Bgr(System.Drawing.Color.Red), 2); break; case Orientation.Degrees270: image.Draw(new LineSegment2D(c[3], c[2]), new Bgr(System.Drawing.Color.Red), 2); break; } } // 0 degrees } contour_points = contour_points.HNext; } }