void Hu(Image <Gray, byte> img, ref Double[] MomentHu, ref Double[] MomentR) { double r1 = 0, r2 = 0, r3 = 0, r4 = 0, r5 = 0, r6 = 0, r7 = 0, r8 = 0, r9 = 0, r10 = 0; Image <Gray, byte> imgA = new Image <Gray, byte>(img.Size); imgA = img.ThresholdBinary(new Gray(60), new Gray(255)); Contour <Point> contourA = imgA.FindContours(); MCvMoments momentsA = contourA.GetMoments(); MCvHuMoments HuMomentsA = momentsA.GetHuMoment(); MomentHu[0] = HuMomentsA.hu1; MomentHu[1] = HuMomentsA.hu2; MomentHu[2] = HuMomentsA.hu3; MomentHu[3] = HuMomentsA.hu4; MomentHu[4] = HuMomentsA.hu5; MomentHu[5] = HuMomentsA.hu6; Rmoment(HuMomentsA.hu1, HuMomentsA.hu2, HuMomentsA.hu3, HuMomentsA.hu4, HuMomentsA.hu5, HuMomentsA.hu6, ref r1, ref r2, ref r3, ref r4, ref r5, ref r6, ref r7, ref r8, ref r9, ref r10); MomentR[0] = r1; MomentR[1] = r2; MomentR[2] = r3; MomentR[3] = r4; MomentR[4] = r5; MomentR[5] = r6; MomentR[6] = r7; MomentR[7] = r8; MomentR[8] = r9; MomentR[9] = r10; }
public static void PrintHuMoments(MCvHuMoments huMoment) { double[] m = new double[7]; m[0] = huMoment.hu1; m[1] = huMoment.hu2; m[2] = huMoment.hu3; m[3] = huMoment.hu4; m[4] = huMoment.hu5; m[5] = huMoment.hu6; m[6] = huMoment.hu7; for (int i = 0; i < 7; i++) { int sign; double result = Math.Abs(m[i]); if (m[i] > 0) { sign = 1; } else if (m[i] < 0) { sign = -1; } else { sign = 0; } result = sign * Math.Log10(result); Console.WriteLine("hu{0}: {1}", i + 1, result); } }
static void Main(string[] args) { string img1 = "image1.bmp"; string img2 = "image2.bmp"; double dist; MCvHuMoments huMoments = new MCvHuMoments(); /* * IsGetShapeFeature(img1, ref huMoments); * PrintHuMoments(huMoments); * * IsGetShapeFeature(img2, ref huMoments); * PrintHuMoments(huMoments); * * IsGetShapeFeature(img1, ref huMoments); * PrintHuMoments(huMoments); */ //Console.ReadLine(); if ((dist = MatchShapes(img1, img2)) >= 0) { Console.WriteLine("The distance between {0} and {1} is {2}", img1, img2, dist); } else { Console.WriteLine("Fail to compute the distance"); } Console.ReadLine(); }
void Hu(Image <Gray, byte> img, ref Double[] MomentHu) { Image <Gray, byte> imgA = new Image <Gray, byte>(img.Size); imgA = img.ThresholdBinary(new Gray(60), new Gray(255)); Contour <Point> contourA = imgA.FindContours(); MCvMoments momentsA = contourA.GetMoments(); MCvHuMoments HuMomentsA = momentsA.GetHuMoment(); MomentHu[0] = HuMomentsA.hu1; MomentHu[1] = HuMomentsA.hu2; MomentHu[2] = HuMomentsA.hu3; MomentHu[3] = HuMomentsA.hu4; MomentHu[4] = HuMomentsA.hu5; MomentHu[5] = HuMomentsA.hu6; }
public void GetHuMoments(Image <Gray, Byte> img, double[] m_hu) { MCvMoments moments = new MCvMoments(); MCvHuMoments hu = new MCvHuMoments(); CvInvoke.cvMoments(img, ref moments, 0); CvInvoke.cvGetHuMoments(ref moments, ref hu); m_hu[0] = hu.hu1; m_hu[1] = hu.hu2; m_hu[2] = hu.hu3; m_hu[3] = hu.hu4; m_hu[4] = hu.hu5; m_hu[5] = hu.hu6; m_hu[6] = hu.hu7; }
// get the Hu public static bool IsGetShapeFeature(string ImgPath, ref MCvHuMoments huMoments) { IntPtr img = IntPtr.Zero; MCvMoments moments = new MCvMoments(); if ((img = CvInvoke.cvLoadImage(ImgPath, LOAD_IMAGE_TYPE.CV_LOAD_IMAGE_GRAYSCALE)) != IntPtr.Zero) { CvInvoke.cvMoments(img, ref moments, 0); CvInvoke.cvGetHuMoments(ref moments, ref huMoments); CvInvoke.cvReleaseImage(ref img); return(true); } else { return(false); } }
public void ComputeFeatures(Segment s) { //Add the relative size NamedFeature f = new NamedFeature("RelativeSize"); f.values.Add(s.points.Count() / (double)(imageWidth * imageHeight)); s.features.Add(f); // Relative centroid PointF c = NormalizedCentroid(s); s.features.Add(new NamedFeature("RelativeCentroid", new List <double> { c.X, c.Y })); // One interior point PointF np = RandomNormalizedInteriorPoint(s); s.features.Add(new NamedFeature("OneInteriorPoint", new List <double> { np.X, np.Y })); //Radial distance s.features.Add(new NamedFeature("RadialDistance", new List <double> { Math.Sqrt(c.X * c.X + c.Y * c.Y) })); //Normalized Discrete Compactness http://www.m-hikari.com/imf-password2009/25-28-2009/bribiescaIMF25-28-2009.pdf //Find the segment id Point sp = s.points.First(); int sidx = assignments[sp.X, sp.Y]; //count number of perimeter edges int perimeter = 0; foreach (Point p in s.points) { for (int i = -1; i <= 1; i++) { for (int j = -1; j <= 1; j++) { if (Math.Abs(i) == Math.Abs(j)) { continue; } if (Util.InBounds(p.X + i, p.Y + j, imageWidth, imageHeight) && assignments[p.X + i, p.Y + j] != sidx) { perimeter++; } else if (!Util.InBounds(p.X + i, p.Y + j, imageWidth, imageHeight)) //edge pixels should be considered perimeter too { perimeter++; } } } } int n = s.points.Count(); double CD = (4.0 * n - perimeter) / 2; double CDmin = n - 1; double CDmax = (4 * n - 4 * Math.Sqrt(n)) / 2; double CDN = (CD - CDmin) / Math.Max(1, (CDmax - CDmin)); s.features.Add(new NamedFeature("NormalizedDiscreteCompactness", new List <double> { CDN })); //Add elongation (width/length normalized between 0-square to 1-long http://hal.archives-ouvertes.fr/docs/00/44/60/37/PDF/ARS-Journal-SurveyPatternRecognition.pdf PointF[] points = s.points.Select <Point, PointF>(p => new PointF(p.X, p.Y)).ToArray <PointF>(); Emgu.CV.Structure.MCvBox2D box = Emgu.CV.PointCollection.MinAreaRect(points); PointF[] vertices = box.GetVertices(); double elongation = 1 - Math.Min(box.size.Width + 1, box.size.Height + 1) / Math.Max(box.size.Width + 1, box.size.Height + 1); s.features.Add(new NamedFeature("Elongation", new List <double> { elongation })); //Add Hu shape moments, invariant to translation, scale, and rotation (not sure what each measure refers to intuitively though, or if there is an intuitive analog) //They may also do badly on noisy data however. See: http://hal.archives-ouvertes.fr/docs/00/44/60/37/PDF/ARS-Journal-SurveyPatternRecognition.pdf (called Invariant Moments) Bitmap regionBitmap = new Bitmap(imageWidth, imageHeight); Graphics g = Graphics.FromImage(regionBitmap); g.FillRectangle(new SolidBrush(Color.Black), 0, 0, imageWidth, imageHeight); foreach (Point p in s.points) { regionBitmap.SetPixel(p.X, p.Y, Color.White); } Emgu.CV.Image <Gray, byte> region = new Emgu.CV.Image <Gray, byte>(regionBitmap); MCvMoments moment = region.GetMoments(true); MCvHuMoments hu = moment.GetHuMoment(); s.features.Add(new NamedFeature("HuMoments", new List <double> { hu.hu1, hu.hu2, hu.hu3, hu.hu4, hu.hu5, hu.hu6, hu.hu7 })); region.Dispose(); regionBitmap.Dispose(); }
//return the distances between two pics. dist >= 0: func works right, else fail public static double MatchShapes(string ImgPath1, string ImgPath2) { const double eps = 0.000000000000000001; MCvHuMoments huMoment1 = new MCvHuMoments(); MCvHuMoments huMoment2 = new MCvHuMoments(); double[] ma = new double[7]; double[] mb = new double[7]; IsGetShapeFeature(ImgPath1, ref huMoment1); /* Here is a bug. * I still cannot figure out why the first time calling IsGetShapeFeautre() it returns wrong anwser * * Details: * CvInvoke.cvMoments(img, ref moments, 0) cannot work right first time, then CVInvoke.cvGetHuMoments() returns wrong hu * And I find when I use C++ to call this function, it works fine at the first, just for C#, it has this problem * Actual: * moments.m00, moments.m01, moments.02 etc returns NaN * huMoments.hu[i] returns NaN * Excepted: * moments.m00 etc returns double value * huMoments.hu[i] returns double value * * So I call the IsGetShapeFeature() once to pass the wrong anwser, it's really an ugly way to fix it. I will back to fix it when I am free. * * 2009/8/30 */ if (IsGetShapeFeature(ImgPath1, ref huMoment1) && IsGetShapeFeature(ImgPath2, ref huMoment2)) { ma[0] = huMoment1.hu1; ma[1] = huMoment1.hu2; ma[2] = huMoment1.hu3; ma[3] = huMoment1.hu4; ma[4] = huMoment1.hu5; ma[5] = huMoment1.hu6; ma[6] = huMoment1.hu7; mb[0] = huMoment1.hu1; mb[1] = huMoment2.hu2; mb[2] = huMoment2.hu3; mb[3] = huMoment2.hu4; mb[4] = huMoment2.hu5; mb[5] = huMoment2.hu6; mb[6] = huMoment2.hu7; double result = 0; for (int i = 0; i < 7; i++) { double ama = Math.Abs(ma[i]); double amb = Math.Abs(mb[i]); int sma, smb; if (ma[i] > 0) { sma = 1; } else if (ma[i] < 0) { sma = -1; } else { sma = 0; } if (mb[i] > 0) { smb = 1; } else if (mb[i] < 0) { smb = -1; } else { smb = 0; } if (ama > eps && amb > eps) { ama = sma * Math.Log10(ama); amb = smb * Math.Log10(amb); result += (amb - ama) * (amb - ama); } } result = Math.Sqrt(result); return(result); } else { return(-1); } }