public static PadSegmentInfo[] GetPadSegmentInfo(Image <Gray, byte> image, Rectangle ROI) { List <PadSegmentInfo> padinfo = new List <PadSegmentInfo>(); using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint()) { CvInvoke.FindContours(image, contours, null, Emgu.CV.CvEnum.RetrType.External, Emgu.CV.CvEnum.ChainApproxMethod.ChainApproxSimple); for (int i = 0; i < contours.Size; i++) { Moments mm = CvInvoke.Moments(contours[i]); if (mm.M00 == 0) { continue; } Point ctCnt = new Point(Convert.ToInt32(mm.M10 / mm.M00), Convert.ToInt32(mm.M01 / mm.M00)); ctCnt.X += ROI.X; ctCnt.Y += ROI.Y; Rectangle bound = CvInvoke.BoundingRectangle(contours[i]); bound.X += ROI.X; bound.Y += ROI.Y; double s = CvInvoke.ContourArea(contours[i]); PadSegmentInfo pad = new PadSegmentInfo(); pad.Contours = contours[i].ToArray(); for (int j = 0; j < pad.Contours.Length; j++) { pad.Contours[j] = new Point(pad.Contours[j].X + ROI.X, pad.Contours[j].Y + ROI.Y); } pad.Bouding = bound; pad.Area = s; pad.Center = ctCnt; padinfo.Add(pad); } } return(padinfo.ToArray()); }
private static PadErrorDetail CheckPad(Models.PadItem padItem, PadSegmentInfo[] padSegment, double umPPixel, bool Inflate = false) { Rectangle boundPadRef = padItem.BoudingAdjust; if (Inflate) { boundPadRef.Inflate(3, 3); } double sPadRef = padItem.Area; List <int> idPadSegOverlap = new List <int>(); for (int j = 0; j < padSegment.Length; j++) { //if (boundPadRef.IntersectsWith(padSegment[j].Bouding)) //{ // idPadSegOverlap.Add(j); //} if (IntersectsContour(padItem.ContourAdjust, padSegment[j].Contours, boundPadRef)) { idPadSegOverlap.Add(j); } } boundPadRef = padItem.Bouding; PadErrorDetail padEr = new PadErrorDetail(); double scaleArea = 0; double scaleAreaAddperimeter = 0; double shiftx = 0; double shifty = 0; int inflate = 40; padEr.AreaStdHight = padItem.AreaThresh.UM_USL; padEr.AreaStdLow = padItem.AreaThresh.PERCENT_LSL; padEr.ShiftXStduM = padItem.ShiftXThresh.UM_USL; padEr.ShiftYStduM = padItem.ShiftYThresh.UM_USL; padEr.ShiftXStdArea = padItem.ShiftXThresh.PERCENT_LSL; padEr.ShiftYStdArea = padItem.ShiftYThresh.PERCENT_LSL; padEr.ROI = Rectangle.Inflate(boundPadRef, inflate, inflate); padEr.Pad = padItem; if (padItem.FOVs.Count > 0) { padEr.FOVNo = padItem.FOVs[0]; } if (idPadSegOverlap.Count > 0) { double areaAllPadSeg = 0; double perimeter = 0; Rectangle boundAllPadSeg = new Rectangle(); for (int j = 0; j < idPadSegOverlap.Count; j++) { PadSegmentInfo padSeg = padSegment[idPadSegOverlap[j]]; areaAllPadSeg += padSeg.Area; using (VectorOfPoint cnt = new VectorOfPoint(padSeg.Contours)) { perimeter += CvInvoke.ArcLength(cnt, true) / 2; } if (j == 0) { boundAllPadSeg = padSeg.Bouding; continue; } if (padSeg.Bouding.X < boundAllPadSeg.X) { boundAllPadSeg.X = padSeg.Bouding.X; } if (padSeg.Bouding.Y < boundAllPadSeg.Y) { boundAllPadSeg.Y = padSeg.Bouding.Y; } if (padSeg.Bouding.X + padSeg.Bouding.Width > boundAllPadSeg.X + boundAllPadSeg.Width) { boundAllPadSeg.Width = padSeg.Bouding.X + padSeg.Bouding.Width - boundAllPadSeg.X; } if (padSeg.Bouding.Y + padSeg.Bouding.Height > boundAllPadSeg.Y + boundAllPadSeg.Height) { boundAllPadSeg.Height = padSeg.Bouding.Y + padSeg.Bouding.Height - boundAllPadSeg.Y; } } padEr.Center = new Point(boundAllPadSeg.X + boundAllPadSeg.Width / 2, boundAllPadSeg.Y + boundAllPadSeg.Height / 2); scaleArea = areaAllPadSeg * 100 / sPadRef; scaleAreaAddperimeter = (areaAllPadSeg + perimeter) * 100 / sPadRef; shiftx = (Math.Max(Math.Abs(boundPadRef.X - boundAllPadSeg.X), Math.Abs((boundPadRef.X + boundPadRef.Width) - (boundAllPadSeg.X + boundAllPadSeg.Width))) * umPPixel); shifty = (Math.Max(Math.Abs(boundPadRef.Y - boundAllPadSeg.Y), Math.Abs((boundPadRef.Y + boundPadRef.Height) - (boundAllPadSeg.Y + boundAllPadSeg.Height))) * umPPixel); bool insert = false; double deviation = (100 - (sPadRef / umPPixel)) / 2; deviation = deviation < 0 ? 0 : deviation; if (scaleAreaAddperimeter < padItem.AreaThresh.PERCENT_LSL - deviation) { //if (sPadRef > 100 || (sPadRef < 100 && scaleArea < 5)) { insert = true; } } if (scaleArea > padItem.AreaThresh.UM_USL) { insert = true; } if (shiftx > padItem.ShiftXThresh.UM_USL) { insert = true; } if (shifty > padItem.ShiftXThresh.UM_USL) { insert = true; } if (insert) { padEr.Area = scaleArea; padEr.ShiftX = shiftx; padEr.ShiftY = shifty; return(padEr); } else { // pad pass return(null); } } else { // not found solder paste return(padEr); } }