/// <summary> /// Release all managed resources associated with this background model. /// </summary> protected override void ReleaseManagedResources() { if (_fgMask != null) { _fgMask.Dispose(); } if (_bgMask != null) { _bgMask.Dispose(); } base.ReleaseManagedResources(); }
void stitch(OneSidePcb oneSidePcb) { double or_hl = 0.23; // lower bound for horizontal overlap ratio double or_hu = 0.24; // upper double or_vl = 0.065; // vertical double or_vu = 0.08; double dr_hu = 0.01; // upper bound for horizontal drift ratio double dr_vu = 0.01; // Bitmap bitmap = oneSidePcb.bitmaps.Dequeue(); Emgu.CV.Image <Bgr, Byte> currentFrame = new Emgu.CV.Image <Bgr, Byte>(bitmap); Mat imgOld = new Mat(); CvInvoke.BitwiseAnd(currentFrame, currentFrame, imgOld); int edge = 3; Mat img = new Mat(imgOld, new Rectangle(new Point(edge, edge), new Size(imgOld.Width - edge * 2, imgOld.Height - edge * 2))); //第一行 if (oneSidePcb.currentRow == 0) { if (oneSidePcb.currentCol == 0) { #region 判断s型还是z字形 if (oneSidePcb.zTrajectory) //Z形 { oneSidePcb.trajectorySide = (int)AoiAi.side.left; int x = Convert.ToInt32(img.Cols * (oneSidePcb.allCols - 1) * dr_hu); int y = Convert.ToInt32(img.Rows * (oneSidePcb.allRows - 1) * dr_vu); int dstRows = Convert.ToInt32(img.Rows * (oneSidePcb.allRows + (oneSidePcb.allRows - 1) * (dr_vu * 2 - or_vl))); int dstCols = Convert.ToInt32(img.Cols * (oneSidePcb.allCols + (oneSidePcb.allCols - 1) * (dr_hu * 2 - or_hl))); oneSidePcb.roi = new Rectangle(x, y, img.Cols, img.Rows); oneSidePcb.dst = new Mat(dstRows, dstCols, img.Depth, 3); // 第一张图不要0,0 最好留一些像素 } else // S型 { oneSidePcb.trajectorySide = (int)AoiAi.side.right; int dstRows = Convert.ToInt32(img.Rows * (oneSidePcb.allRows + (oneSidePcb.allRows - 1) * (dr_vu * 2 - or_vl))); int dstCols = Convert.ToInt32(img.Cols * (oneSidePcb.allCols + (oneSidePcb.allCols - 1) * (dr_hu * 2 - or_hl))); int x = Convert.ToInt32((dstCols - img.Cols) * (1 - dr_hu)); int y = Convert.ToInt32(img.Rows * (oneSidePcb.allRows - 1) * dr_vu); oneSidePcb.roi = new Rectangle(x, y, img.Cols, img.Rows); oneSidePcb.dst = new Mat(dstRows, dstCols, img.Depth, 3); // 第一张图不要0,0 最好留一些像素 } #endregion } else { AoiAi.stitchv2(oneSidePcb.dst.Ptr, oneSidePcb.roi, img.Ptr, ref oneSidePcb.roi, oneSidePcb.trajectorySide, Convert.ToInt32(img.Cols * or_hl), Convert.ToInt32(img.Cols * or_hu), Convert.ToInt32(img.Rows * dr_vu)); } //oneSidePcb.dst.Save(@"C:\Users\Administrator\Desktop\suomi-test-img\" + oneSidePcb.currentRow + "-" + oneSidePcb.currentCol + ".jpg"); AoiAi.copy_to(oneSidePcb.dst.Ptr, img.Ptr, oneSidePcb.roi); //oneSidePcb.dst.Save(@"C:\Users\Administrator\Desktop\suomi-test-img\" + oneSidePcb.currentRow + "-" + oneSidePcb.currentCol + ".jpg"); img.Dispose(); currentFrame.Dispose(); bitmap.Dispose(); oneSidePcb.currentCol++; if (oneSidePcb.currentCol >= oneSidePcb.allCols) { oneSidePcb.currentCol = 0; oneSidePcb.currentRow++; if (oneSidePcb.trajectorySide == (int)AoiAi.side.left) { oneSidePcb.trajectorySide = (int)AoiAi.side.right; } else if (oneSidePcb.trajectorySide == (int)AoiAi.side.right) { oneSidePcb.trajectorySide = (int)AoiAi.side.left; } } //oneSidePcb.dst.Save(@"C:\Users\Administrator\Desktop\suomi-test-img\row1.jpg"); } else // 其他行 { if (Convert.ToBoolean(oneSidePcb.currentRow % 2)) //偶行 { if (oneSidePcb.currentCol == 0) { AoiAi.stitchv2(oneSidePcb.dst.Ptr, oneSidePcb.roi, img.Ptr, ref oneSidePcb.roi, (int)AoiAi.side.up, Convert.ToInt32(img.Cols * or_vl), Convert.ToInt32(img.Cols * or_vu), Convert.ToInt32(img.Rows * dr_hu)); //oneSidePcb.roi = oneSidePcb.roi0; } else { AoiAi.stitchv2(oneSidePcb.dst.Ptr, oneSidePcb.roi, img.Ptr, ref oneSidePcb.roi, oneSidePcb.trajectorySide, Convert.ToInt32(img.Cols * or_hl), Convert.ToInt32(img.Cols * or_hu), Convert.ToInt32(img.Rows * dr_vu), (int)AoiAi.side.up, Convert.ToInt32(img.Rows * or_vl), Convert.ToInt32(img.Rows * or_vu), Convert.ToInt32(img.Cols * dr_hu)); } } else { if (oneSidePcb.currentCol == 0) { AoiAi.stitchv2(oneSidePcb.dst.Ptr, oneSidePcb.roi, img.Ptr, ref oneSidePcb.roi, (int)AoiAi.side.up, Convert.ToInt32(img.Cols * or_vl), Convert.ToInt32(img.Cols * or_vu), Convert.ToInt32(img.Rows * dr_hu)); //oneSidePcb.roi = oneSidePcb.roi0; } else { AoiAi.stitchv2(oneSidePcb.dst.Ptr, oneSidePcb.roi, img.Ptr, ref oneSidePcb.roi, oneSidePcb.trajectorySide, Convert.ToInt32(img.Cols * or_hl), Convert.ToInt32(img.Cols * or_hu), Convert.ToInt32(img.Rows * dr_vu), (int)AoiAi.side.up, Convert.ToInt32(img.Rows * or_vl), Convert.ToInt32(img.Rows * or_vu), Convert.ToInt32(img.Cols * dr_hu)); } } //oneSidePcb.dst.Save(@"C:\Users\Administrator\Desktop\suomi-test-img\" + oneSidePcb.currentRow + "-" + oneSidePcb.currentCol + ".jpg"); AoiAi.copy_to(oneSidePcb.dst.Ptr, img.Ptr, oneSidePcb.roi); img.Dispose(); currentFrame.Dispose(); bitmap.Dispose(); oneSidePcb.currentCol++; if (oneSidePcb.currentRow >= oneSidePcb.allRows - 1 && oneSidePcb.currentCol >= oneSidePcb.allCols) { sw.Stop(); TimeSpan ts = sw.Elapsed; Console.WriteLine("DateTime costed for Shuffle function is: {0}ms", ts.TotalMilliseconds); this.BeginInvoke(done); if (oneSidePcb.zTrajectory) { oneSidePcb.dst.Save(Path.Combine(savePath, "Front.jpg")); } else { oneSidePcb.dst.Save(Path.Combine(savePath, "Back.jpg")); } } else if (oneSidePcb.currentCol >= oneSidePcb.allCols) { oneSidePcb.currentCol = 0; oneSidePcb.currentRow++; if (oneSidePcb.trajectorySide == (int)AoiAi.side.left) { oneSidePcb.trajectorySide = (int)AoiAi.side.right; } else if (oneSidePcb.trajectorySide == (int)AoiAi.side.right) { oneSidePcb.trajectorySide = (int)AoiAi.side.left; } } } }
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(); }
/// <summary> /// 拼图主函数 /// </summary> /// <param name="oneSidePcb"></param> public static void StitchMain(OneStitchSidePcb oneSidePcb, Odin.StitchCallBack stitchCallBack) { bool needSave = false; double or_hl = oneSidePcb.or_hl; double or_hu = oneSidePcb.or_hu; double or_vl = oneSidePcb.or_vl; double or_vu = oneSidePcb.or_vu; double dr_hu = oneSidePcb.dr_hu; double dr_vu = oneSidePcb.dr_vu; BitmapInfo bitmapInfo; lock (oneSidePcb.bitmaps) { bitmapInfo = oneSidePcb.bitmaps.Dequeue(); Emgu.CV.Image <Bgr, Byte> currentFrame = new Emgu.CV.Image <Bgr, Byte>(bitmapInfo.bitmap); Mat imgOld = new Mat(); CvInvoke.BitwiseAnd(currentFrame, currentFrame, imgOld); int edge = 3; Mat img = new Mat(imgOld, new Rectangle(new Point(edge, edge), new Size(imgOld.Width - edge * 2, imgOld.Height - edge * 2))); //第一行 if (oneSidePcb.currentRow == 0) { if (oneSidePcb.currentCol == 0) { #region 判断s型还是z字形 if (oneSidePcb.zTrajectory) //Z形 { oneSidePcb.trajectorySide = (int)side.left; int x = Convert.ToInt32(img.Cols * (oneSidePcb.allCols - 1) * dr_hu); int y = Convert.ToInt32(img.Rows * (oneSidePcb.allRows - 1) * dr_vu); int dstRows = Convert.ToInt32(img.Rows * (oneSidePcb.allRows + (oneSidePcb.allRows - 1) * (dr_vu * 2 - or_vl))); int dstCols = Convert.ToInt32(img.Cols * (oneSidePcb.allCols + (oneSidePcb.allCols - 1) * (dr_hu * 2 - or_hl))); oneSidePcb.roi = new Rectangle(x, y, img.Cols, img.Rows); oneSidePcb.dst = new Mat(dstRows, dstCols, img.Depth, 3); // 第一张图不要0,0 最好留一些像素 } else // S型 { oneSidePcb.trajectorySide = (int)side.right; int dstRows = Convert.ToInt32(img.Rows * (oneSidePcb.allRows + (oneSidePcb.allRows - 1) * (dr_vu * 2 - or_vl))); int dstCols = Convert.ToInt32(img.Cols * (oneSidePcb.allCols + (oneSidePcb.allCols - 1) * (dr_hu * 2 - or_hl))); int x = Convert.ToInt32((dstCols - img.Cols) * (1 - dr_hu)); int y = Convert.ToInt32(img.Rows * (oneSidePcb.allRows - 1) * dr_vu); oneSidePcb.roi = new Rectangle(x, y, img.Cols, img.Rows); oneSidePcb.dst = new Mat(dstRows, dstCols, img.Depth, 3); // 第一张图不要0,0 最好留一些像素 } #endregion } else { stitchv2(oneSidePcb.dst.Ptr, oneSidePcb.roi, img.Ptr, ref oneSidePcb.roi, oneSidePcb.trajectorySide, Convert.ToInt32(img.Cols * or_hl), Convert.ToInt32(img.Cols * or_hu), Convert.ToInt32(img.Rows * dr_vu)); } //oneSidePcb.dst.Save(@"C:\Users\Administrator\Desktop\suomi-test-img\" + oneSidePcb.currentRow + "-" + oneSidePcb.currentCol + ".jpg"); copy_to(oneSidePcb.dst.Ptr, img.Ptr, oneSidePcb.roi); //oneSidePcb.dst.Save(@"C:\Users\Administrator\Desktop\suomi-test-img\" + oneSidePcb.currentRow + "-" + oneSidePcb.currentCol + ".jpg"); oneSidePcb.currentCol++; if (oneSidePcb.currentCol >= oneSidePcb.allCols) { oneSidePcb.currentCol = 0; oneSidePcb.currentRow++; if (oneSidePcb.trajectorySide == (int)side.left) { oneSidePcb.trajectorySide = (int)side.right; } else if (oneSidePcb.trajectorySide == (int)side.right) { oneSidePcb.trajectorySide = (int)side.left; } } //oneSidePcb.dst.Save(@"C:\Users\Administrator\Desktop\suomi-test-img\row1.jpg"); } else // 其他行 { if (Convert.ToBoolean(oneSidePcb.currentRow % 2)) //偶行 { if (oneSidePcb.currentCol == 0) { stitchv2(oneSidePcb.dst.Ptr, oneSidePcb.roi, img.Ptr, ref oneSidePcb.roi, (int)side.up, Convert.ToInt32(img.Cols * or_vl), Convert.ToInt32(img.Cols * or_vu), Convert.ToInt32(img.Rows * dr_hu)); //oneSidePcb.roi = oneSidePcb.roi0; } else { stitchv2(oneSidePcb.dst.Ptr, oneSidePcb.roi, img.Ptr, ref oneSidePcb.roi, oneSidePcb.trajectorySide, Convert.ToInt32(img.Cols * or_hl), Convert.ToInt32(img.Cols * or_hu), Convert.ToInt32(img.Rows * dr_vu), (int)side.up, Convert.ToInt32(img.Rows * or_vl), Convert.ToInt32(img.Rows * or_vu), Convert.ToInt32(img.Cols * dr_hu)); } } else { if (oneSidePcb.currentCol == 0) { stitchv2(oneSidePcb.dst.Ptr, oneSidePcb.roi, img.Ptr, ref oneSidePcb.roi, (int)side.up, Convert.ToInt32(img.Cols * or_vl), Convert.ToInt32(img.Cols * or_vu), Convert.ToInt32(img.Rows * dr_hu)); //oneSidePcb.roi = oneSidePcb.roi0; } else { stitchv2(oneSidePcb.dst.Ptr, oneSidePcb.roi, img.Ptr, ref oneSidePcb.roi, oneSidePcb.trajectorySide, Convert.ToInt32(img.Cols * or_hl), Convert.ToInt32(img.Cols * or_hu), Convert.ToInt32(img.Rows * dr_vu), (int)side.up, Convert.ToInt32(img.Rows * or_vl), Convert.ToInt32(img.Rows * or_vu), Convert.ToInt32(img.Cols * dr_hu)); } } //oneSidePcb.dst.Save(@"C:\Users\Administrator\Desktop\suomi-test-img\" + oneSidePcb.currentRow + "-" + oneSidePcb.currentCol + ".jpg"); copy_to(oneSidePcb.dst.Ptr, img.Ptr, oneSidePcb.roi); //oneSidePcb.dst.Save(@"C:\Users\Administrator\Desktop\suomi-test-img\" + oneSidePcb.currentRow + "-" + oneSidePcb.currentCol + ".jpg"); oneSidePcb.currentCol++; if (oneSidePcb.currentRow >= oneSidePcb.allRows - 1 && oneSidePcb.currentCol >= oneSidePcb.allCols) { needSave = true; } else if (oneSidePcb.currentCol >= oneSidePcb.allCols) { oneSidePcb.currentCol = 0; oneSidePcb.currentRow++; if (oneSidePcb.trajectorySide == (int)side.left) { oneSidePcb.trajectorySide = (int)side.right; } else if (oneSidePcb.trajectorySide == (int)side.right) { oneSidePcb.trajectorySide = (int)side.left; } } } #region 实时更新采集框 stitchCallBack(false, oneSidePcb, bitmapInfo, new RectangleF((float)(oneSidePcb.roi.Location.X * 0.25), (float)(oneSidePcb.roi.Location.Y * 0.25), (float)(oneSidePcb.roi.Size.Width * 0.25), (float)(oneSidePcb.roi.Size.Height * 0.25))); #endregion #region 释放资源 img.Dispose(); currentFrame.Dispose(); //bitmap.Dispose(); #endregion if (needSave) // 加这里主要是为了优化workingForm.imgBoxWorking最后一个框的显示问题 { stitchCallBack(true, oneSidePcb, bitmapInfo, new RectangleF()); Mat smallmat = new Mat(); CvInvoke.Resize(oneSidePcb.dst, smallmat, new Size(Convert.ToInt32(oneSidePcb.dst.Cols * oneSidePcb.scale), Convert.ToInt32(oneSidePcb.dst.Rows * oneSidePcb.scale))); if (oneSidePcb.zTrajectory) { string saveFile = Path.Combine(oneSidePcb.savePath, "front.jpg"); smallmat.Save(saveFile); //oneSidePcb.dst.Save(saveFile + "big.jpg"); Ftp.UpLoadFile(saveFile, Ftp.ftpPath + oneSidePcb.pcbId + "/front.jpg"); } else { string saveFile = Path.Combine(oneSidePcb.savePath, "back.jpg"); smallmat.Save(saveFile); //oneSidePcb.dst.Save(saveFile + "big.jpg"); Ftp.UpLoadFile(saveFile, Ftp.ftpPath + oneSidePcb.pcbId + "/back.jpg"); } smallmat.Dispose(); oneSidePcb.dst.Dispose(); } } }
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(); }