public unsafe Contour AutoCorrelation(bool normalize) { int capacity = this.Count / 2; Contour contour = new Contour(capacity); fixed(Complex *complexRef = contour.array) { Complex *complexPtr = complexRef; double d = 0.0; int shift = 0; while (shift < capacity) { complexPtr[0] = this.Dot(this, shift); double normaSquare = complexPtr->NormaSquare; if (normaSquare > d) { d = normaSquare; } complexPtr++; shift++; } if (normalize) { d = Math.Sqrt(d); complexPtr = complexRef; for (shift = 0; shift < capacity; shift++) { complexPtr[0] = new Complex(complexPtr->a / d, complexPtr->b / d); complexPtr++; } } } return(contour); }
/// <summary> /// Scalar product /// </summary> public Complex Dot(Contour c) { return Dot(c, 0); }
/// <summary> /// Scalar product /// </summary> public unsafe Complex Dot(Contour c, int shift) { var count = Count; double sumA = 0; double sumB = 0; fixed (Complex* ptr1 = &array[0]) fixed (Complex* ptr2 = &c.array[shift]) fixed (Complex* ptr22 = &c.array[0]) fixed (Complex* ptr3 = &c.array[c.Count - 1]) { Complex* p1 = ptr1; Complex* p2 = ptr2; for (int i = 0; i < count; i++) { Complex x1 = *p1; Complex x2 = *p2; sumA += x1.a * x2.a + x1.b * x2.b; sumB += x1.b * x2.a - x1.a * x2.b; p1++; if (p2 == ptr3) p2 = ptr22; else p2++; } } return new Complex(sumA, sumB); }
public double Distance(Contour c) { double n1 = this.Norma; double n2 = c.Norma; return n1 * n1 + n2 * n2 - 2 * (this.Dot(c).a); }
/// <summary> /// Returns R^2 of difference of norms /// </summary> /// <param name="c"></param> /// <returns></returns> public double DiffR2(Contour c) { double max1 = 0; double max2 = 0; double sum = 0; for (int i = 0; i < Count; i++) { double v1 = array[i].Norma; double v2 = c.array[i].Norma; if (v1 > max1) max1 = v1; if (v2 > max2) max2 = v2; double v = v1 - v2; sum += v * v; } double max = Math.Max(max1, max2); return 1 - sum / Count / max / max; }
private List<Contour<Point>> ConvertContours(Contour<Point> contours) { var c = contours; List<Contour<Point>> result = new List<Contour<Point>>(); while (c != null) { result.Add(c); c = c.HNext; } return result; }
public void FindBestContour(ImageProcessor processor, double owerflowContoursRatio) { int secondBiggestContourIndex; processor.ProcessImage(new Image<Bgr, Byte>(new Bitmap(_digit)), true); var biggestContourIndex = SortContour(processor, out secondBiggestContourIndex); if (((biggestContourIndex != secondBiggestContourIndex) && (processor.contours[biggestContourIndex].Area / processor.contours[secondBiggestContourIndex].Area < owerflowContoursRatio)) || (processor.contours.Count < 3)) { _contour = processor.contours[secondBiggestContourIndex]; } else { _contour = processor.contours[biggestContourIndex]; } }
/// <summary> /// Intercorrelcation function (ICF) /// maxShift - max deviation (left+right) /// </summary> public Contour InterCorrelation(Contour c, int maxShift) { Contour result = new Contour(maxShift); int i = 0; int count = Count; while (i < maxShift/2) { result.array[i] = Dot(c, i); result.array[maxShift - i - 1] = Dot(c, c.Count - i - 1); i++; } return result; }
public void Draw(Graphics gr, Rectangle rect) { int num8; int right; gr.DrawRectangle(Pens.SteelBlue, rect); rect = new Rectangle(rect.Left, rect.Top, rect.Width - 0x18, rect.Height); Contour contour = this.contour.Clone(); Contour contour2 = this.autoCorr.Clone(); contour2.Normalize(); Rectangle rectangle = new Rectangle(rect.X, rect.Y, rect.Width / 2, rect.Height); rectangle.Inflate(-20, -20); Point[] points = contour.GetPoints(this.startPoint); Rectangle rectangle2 = Rectangle.Round(contour.GetBoundsRect()); double width = rectangle2.Width; double height = rectangle2.Height; float num3 = (float)Math.Min((double)(((double)rectangle.Width) / width), (double)(((double)rectangle.Height) / height)); int num4 = this.startPoint.X - contour.SourceBoundingRect.Left; int num5 = this.startPoint.Y - contour.SourceBoundingRect.Top; int num6 = -((int)(rectangle2.Left * num3)); int num7 = (int)(rectangle2.Bottom * num3); for (num8 = 0; num8 < points.Length; num8++) { points[num8] = new Point((rectangle.Left + num6) + ((int)(((points[num8].X - contour.SourceBoundingRect.Left) - num4) * num3)), (rectangle.Top + num7) + ((int)(((points[num8].Y - contour.SourceBoundingRect.Top) - num5) * num3))); } gr.DrawPolygon(Pens.Red, points); rectangle = new Rectangle((rect.Width / 2) + rect.X, rect.Y, rect.Width / 2, rect.Height); rectangle.Inflate(-20, -20); List <Point> list = new List <Point>(); for (num8 = 0; num8 < contour2.Count; num8++) { right = (rectangle.X + 5) + (num8 * 3); Complex complex = contour2[num8 % contour2.Count]; int num10 = (int)(complex.Norma * rectangle.Height); gr.FillRectangle(Brushes.Blue, right, rectangle.Bottom - num10, 3, num10); complex = contour2[num8 % contour2.Count]; list.Add(new Point(right, rectangle.Bottom - ((int)(rectangle.Height * (0.5 + ((complex.Angle / 2.0) / 3.1415926535897931)))))); } try { gr.DrawLines(Pens.Red, list.ToArray()); } catch (OverflowException) { } Pen pen = new Pen(Color.FromArgb(100, Color.Black)); for (num8 = 0; num8 <= 10; num8++) { gr.DrawLine(pen, rectangle.X, rectangle.Bottom - ((num8 * rectangle.Height) / 10), rectangle.X + rectangle.Width, rectangle.Bottom - ((num8 * rectangle.Height) / 10)); } right = rect.Right; int num11 = rectangle.Bottom - (rectangle.Height / 2); gr.DrawLine(Pens.Gray, right, num11, right + 0x17, num11); if ((this.autoCorrDescriptor1 < 0x7fffffff) && (this.autoCorrDescriptor1 > -2147483648)) { gr.FillRectangle(Brushes.Red, right, num11 - ((this.autoCorrDescriptor1 < 0) ? 0 : ((this.autoCorrDescriptor1 * rectangle.Height) / 100)), 5, (Math.Abs(this.autoCorrDescriptor1) * rectangle.Height) / 100); gr.FillRectangle(Brushes.Red, right + 6, num11 - ((this.autoCorrDescriptor2 < 0) ? 0 : ((this.autoCorrDescriptor2 * rectangle.Height) / 100)), 5, (Math.Abs(this.autoCorrDescriptor2) * rectangle.Height) / 100); gr.FillRectangle(Brushes.Red, right + 12, num11 - ((this.autoCorrDescriptor3 < 0) ? 0 : ((this.autoCorrDescriptor3 * rectangle.Height) / 100)), 5, (Math.Abs(this.autoCorrDescriptor3) * rectangle.Height) / 100); gr.FillRectangle(Brushes.Red, right + 0x12, num11 - ((this.autoCorrDescriptor4 < 0) ? 0 : ((this.autoCorrDescriptor4 * rectangle.Height) / 100)), 5, (Math.Abs(this.autoCorrDescriptor4) * rectangle.Height) / 100); } }
public Complex Dot(Contour c) => this.Dot(c, 0);
/// <summary> /// Normalized Scalar Product /// </summary> public Complex NotmalizedScalarProduct(Contour otherContour) { var res = ScalarProduct(otherContour) * (1 / (Norma * otherContour.Norma)); return(res); }
public Complex ScalarProduct(Contour c) { return(ScalarProduct(c, 0)); }
/** * отсеивает контуры по длинне контура и площади * */ private List<Contour<Point>> FilterContours(Contour<Point> contours, Image<Gray, byte> cannyFrame, int frameWidth, int frameHeight) { int maxArea = frameWidth * frameHeight / 5; var c = contours; List<Contour<Point>> result = new List<Contour<Point>>(); while (c != null) { if (filterContoursBySize) if (c.Total < minContourLength || c.Area < minContourArea || c.Area > maxArea || c.Area / c.Total <= minFormFactor) goto next; if (noiseFilter) { Point p1 = c[0]; Point p2 = c[(c.Total / 2) % c.Total]; if (cannyFrame[p1].Intensity <= double.Epsilon && cannyFrame[p2].Intensity <= double.Epsilon) goto next; } result.Add(c); next: c = c.HNext; } return result; }
/// <summary> /// Discrete Fourier Transform /// </summary> public Contour Fourier() { int count = Count; Contour result = new Contour(count); for (int m = 0; m < count; m++) { Complex sum = new Complex(0, 0); double k = -2d*Math.PI*m/count; for (int n = 0; n < count; n++) sum += this[n].Rotate(k * n); result.array[m]=sum; } return result; }
/// <summary> /// Scalar product /// </summary> public Complex Dot(Contour c) { return(Dot(c, 0)); }
/// <summary> /// Intercorrelcation function (ICF) /// </summary> public Contour InterCorrelation(Contour c) { int count = Count; Contour result = new Contour(count); for (int i = 0; i < count; i++) result.array[i] = Dot(c, i); return result; }
/// <summary> /// Autocorrelation function (ACF) /// </summary> public unsafe Contour AutoCorrelation(bool normalize) { int count = Count/2; Contour result = new Contour(count); fixed (Complex* ptr = &result.array[0]) { Complex* p = ptr; double maxNormaSq = 0; for (int i = 0; i < count; i++) { *p = Dot(this, i); double normaSq = (*p).NormaSquare; if (normaSq > maxNormaSq) maxNormaSq = normaSq; p++; } if (normalize) { maxNormaSq = Math.Sqrt(maxNormaSq); p = ptr; for (int i = 0; i < count; i++) { *p = new Complex((*p).a / maxNormaSq, (*p).b / maxNormaSq); p++; } } } return result; }
/// <summary> /// Normalized Scalar Product /// </summary> public Complex NormDot(Contour c) { var count = this.Count; double sumA = 0; double sumB = 0; double norm1 = 0; double norm2 = 0; for (int i = 0; i < count; i++) { var x1 = this[i]; var x2 = c[i]; sumA += x1.a * x2.a + x1.b * x2.b; sumB += x1.b * x2.a - x1.a * x2.b; norm1 += x1.NormaSquare; norm2 += x2.NormaSquare; } double k = 1d / Math.Sqrt(norm1*norm2); return new Complex(sumA * k, sumB * k); }
public Contour Clone() { Contour result = new Contour(); result.array = (Complex[])array.Clone(); return result; }
public void FindMaxContour(ImageProcessor processor) { int secondLongestContourIndex; processor.ProcessImage(new Image<Bgr, Byte>(new Bitmap(_digit)), true); _contour = processor.contours[SortContour(processor, out secondLongestContourIndex)]; }
public void ProcessImage(Image <Gray, byte> grayFrame) { Action <Contour <Point> > body = null; if (this.equalizeHist) { grayFrame._EqualizeHist(); } Image <Gray, byte> image = grayFrame.PyrDown().PyrUp(); Image <Gray, byte> image2 = null; if (this.noiseFilter) { image2 = image.Canny(new Gray((double)this.cannyThreshold), new Gray((double)this.cannyThreshold)); } if (this.blur) { grayFrame = image; } CvInvoke.cvAdaptiveThreshold((IntPtr)grayFrame, (IntPtr)grayFrame, 255.0, ADAPTIVE_THRESHOLD_TYPE.CV_ADAPTIVE_THRESH_MEAN_C, THRESH.CV_THRESH_BINARY, (this.adaptiveThresholdBlockSize + (this.adaptiveThresholdBlockSize % 2)) + 1, 1.0); grayFrame._Not(); if (this.addCanny && (image2 != null)) { grayFrame._Or(image2); } this.binarizedFrame = grayFrame; if (image2 != null) { image2 = image2.Dilate(3); } Contour <Point> contours = grayFrame.FindContours(CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_NONE, RETR_TYPE.CV_RETR_LIST); this.contours = this.FilterContours(contours, image2, grayFrame.Width, grayFrame.Height); lock (this.foundTemplates) { this.foundTemplates.Clear(); } this.samples.Clear(); lock (this.templates) { if (body == null) { body = delegate(Contour <Point> contour) { Template item = new Template(contour.ToArray(), contour.Area, this.samples.templateSize); lock (this.samples) { this.samples.Add(item); } if (!this.onlyFindContours) { FoundTemplateDesc desc = this.finder.FindTemplate(this.templates, item); if (desc != null) { lock (this.foundTemplates) { this.foundTemplates.Add(desc); } } } }; } Parallel.ForEach <Contour <Point> >(this.contours, body); } FilterByIntersection(ref this.foundTemplates); }