/// <summary> /// Use camshift to track the feature /// </summary> /// <param name="observedFeatures">The feature found from the observed image</param> /// <param name="initRegion">The predicted location of the model in the observed image. If not known, use MCvBox2D.Empty as default</param> /// <param name="priorMask">The mask that should be the same size as the observed image. Contains a priori value of the probability a match can be found. If you are not sure, pass an image fills with 1.0s</param> /// <returns>If a match is found, the homography projection matrix is returned. Otherwise null is returned</returns> public HomographyMatrix CamShiftTrack(SURFFeature[] observedFeatures, MCvBox2D initRegion, Image <Gray, Single> priorMask) { using (Image <Gray, Single> matchMask = new Image <Gray, Single>(priorMask.Size)) { #region get the list of matched point on the observed image Single[, ,] matchMaskData = matchMask.Data; //Compute the matched features MatchedSURFFeature[] matchedFeature = _matcher.MatchFeature(observedFeatures, 2, 20); matchedFeature = VoteForUniqueness(matchedFeature, 0.8); foreach (MatchedSURFFeature f in matchedFeature) { PointF p = f.ObservedFeature.Point.pt; matchMaskData[(int)p.Y, (int)p.X, 0] = 1.0f / (float)f.SimilarFeatures[0].Distance; } #endregion Rectangle startRegion; if (initRegion.Equals(MCvBox2D.Empty)) { startRegion = matchMask.ROI; } else { startRegion = PointCollection.BoundingRectangle(initRegion.GetVertices()); if (startRegion.IntersectsWith(matchMask.ROI)) { startRegion.Intersect(matchMask.ROI); } } CvInvoke.cvMul(matchMask.Ptr, priorMask.Ptr, matchMask.Ptr, 1.0); MCvConnectedComp comp; MCvBox2D currentRegion; //Updates the current location CvInvoke.cvCamShift(matchMask.Ptr, startRegion, new MCvTermCriteria(10, 1.0e-8), out comp, out currentRegion); #region find the SURF features that belongs to the current Region MatchedSURFFeature[] featuesInCurrentRegion; using (MemStorage stor = new MemStorage()) { Contour <System.Drawing.PointF> contour = new Contour <PointF>(stor); contour.PushMulti(currentRegion.GetVertices(), Emgu.CV.CvEnum.BACK_OR_FRONT.BACK); CvInvoke.cvBoundingRect(contour.Ptr, 1); //this is required before calling the InContour function featuesInCurrentRegion = Array.FindAll(matchedFeature, delegate(MatchedSURFFeature f) { return(contour.InContour(f.ObservedFeature.Point.pt) >= 0); }); } #endregion return(GetHomographyMatrixFromMatchedFeatures(VoteForSizeAndOrientation(featuesInCurrentRegion, 1.5, 20))); } }
// Create rectangle bounding box with specific aspect ratio starting from a set of landarmarks points. // Border padding is used for expand the bounding box mantaining same aspect ratio. public Rectangle GetBoundingBox(PointF[] componentPoints, double ratio, int borderPadding) { var rect = PointCollection.BoundingRectangle(componentPoints); var height = (int)Math.Ceiling(rect.Width * ratio); var diff = Math.Ceiling((height - rect.Height) / 2d); rect.Inflate(0, (int)diff); rect.Inflate(borderPadding, borderPadding); return(rect); }
private static void DrawAllRectangles() { Image <Gray, Byte> edgeImage = new Image <Gray, byte>(show_img); #region Find rectangles boxList = new List <RotatedRect>(); //a box is a rotated rectangle using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint()) { CvInvoke.FindContours(edgeImage, contours, null, RetrType.List, ChainApproxMethod.ChainApproxSimple); for (int i = 0; i < contours.Size; i++) { Image <Rgb, Byte> img = new Image <Rgb, byte>(ori_img); double rate = img.Width * img.Height / 3864714.0; using (VectorOfPoint contour = contours[i]) using (VectorOfPoint approxContour = new VectorOfPoint()) { CvInvoke.ApproxPolyDP(contour, approxContour, CvInvoke.ArcLength(contour, true) * 0.05, true); double area = CvInvoke.ContourArea(contour, false); if (area > 40000) { Point[] pts = contour.ToArray(); PointF[] ptfs = new PointF[pts.Length]; for (int pi = 0; pi < pts.Length; pi++) { ptfs[pi] = new PointF(pts[pi].X, pts[pi].Y); } Rectangle rec = PointCollection.BoundingRectangle(ptfs); img.Draw(rec, new Rgb(Color.DarkOrange), 2); // Create string to draw. String drawString = "Area : " + area; // Draw string to image. img.Draw(drawString, rec.Location, FontFace.HersheyTriplex, 1, new Rgb(Color.Black), 2); #region draw rectangle pre_img = show_img; show_img = img.Bitmap; rform.UpdateImage(show_img); img.Save("rect_" + i + ".png"); #endregion } } } } #endregion }
private void getRectangles() { count = 0; foreach (System.Drawing.Point[] point in Points) { if (count % 2 == 0) { System.Drawing.PointF[] pointF = Array.ConvertAll(point, new Converter <System.Drawing.Point, System.Drawing.PointF>(PointToPointF)); rect[count] = PointCollection.BoundingRectangle(pointF); getInfo(count); } count++; } }
// Hair component is a particular component not identified by landmarks // This methods extract hair component starting from the bounding box of face and // from the bounding box of shape identified by landmarks. public Image <Gray, byte> GetHairComponent(Image <Gray, byte> image, PointF[] face, PointF[] shape, BoundingBoxParam hairParam) { var shapeBox = PointCollection.BoundingRectangle(shape); var faceBox = Rectangle.Ceiling(new RectangleF(face[0].X, face[0].Y, face[1].X - face[0].X, face[1].Y - face[0].Y)); // calculate height from shape box and top border of image var height = image.Size.Height - (image.Size.Height - shapeBox.Top); // calculate the normalized height using the desidered aspect ratio var normHeight = (int)Math.Floor(faceBox.Width * hairParam.AspectRatio); // calculate if the normalized height go out of image border var extra = height - normHeight; // create the right bounding box, adding on bottom of bounding box the extra height var hairBox = (extra < 0) ? new Rectangle(faceBox.X, 0, faceBox.Width, height - extra) : new Rectangle(faceBox.X, extra, faceBox.Width, normHeight); var cropHeight = (int)Math.Floor(hairParam.CropWidth * hairParam.AspectRatio); return(image.GetSubRect(hairBox).Resize(hairParam.CropWidth, cropHeight, Inter.Area)); }
/// <summary> /// Находит объект /// </summary> /// <returns>Возвращает координаты объекта. Если оюъект не найден возвращает null.</returns> public POIData detectObj() { var frame = sc.PrintWindow(winDiscript); var processedFrameSt = ProcessImage(frame); var processedFrame = processedFrameSt.Canny(180, 120); List <PointF> pList = new List <PointF>(); using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint()) { CvInvoke.FindContours(processedFrame, contours, null, RetrType.External, ChainApproxMethod.ChainApproxSimple); int count = contours.Size; for (int i = 0; i < count; i++) { using (VectorOfPoint contour = contours[i]) using (VectorOfPoint approxContour = new VectorOfPoint()) { CvInvoke.ApproxPolyDP(contour, approxContour, CvInvoke.ArcLength(contour, true) * 0.05, true); double area = CvInvoke.ContourArea(approxContour, false); for (int k = 0; k < approxContour.Size; k++) { pList.Add(approxContour[k]); } } } } var rec = PointCollection.BoundingRectangle(pList.ToArray()); if (recWhenBigDist.IsEmpty) { recWhenBigDist = rec; } if (recWhenBigDist.Width - rec.Width > 3) { distLess100 = true; } else { distLess100 = false; } if (rec.Width > 0) { if (++distReqest > 20) { filtDist = recognizeSpeed(rec, processedFrameSt); if (filtDist > 1) { distReqest = 0; if (prevDist - filtDist >= 15) { situation = 1; } if (Math.Abs(prevDist - filtDist) > 1 && Math.Abs(prevDist - filtDist) < 15) { situation = 2; } prevDist = filtDist; } else { if (distLess40) { situation = 3; } } } var pd = new POIData(rec.Location, filtDist); distLess40 = filtDist < 40; pd.noFiltDist = noFiltDist; pd.situation = situation; return(pd); } return(null); }
private Dictionary <int, KeyValuePair <decimal, decimal> > _FindContoursAndCalculate(Emgu.CV.Image <Bgr, Byte> colorImage, out Emgu.CV.Image <Gray, Byte> processedImage) { int circles = 0; VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint(); Mat hierarchy = new Mat(); /// Detect edges using Threshold Image <Gray, Byte> Img_Source_Gray = colorImage.Convert <Gray, Byte>(); Img_Source_Gray = Img_Source_Gray.SmoothBlur(3, 3); Image <Gray, Byte> threshold_output = Img_Source_Gray.ThresholdBinary(new Gray(90), new Gray(255)); /// Find contours CvInvoke.FindContours(threshold_output, contours, hierarchy, RetrType.Tree, ChainApproxMethod.ChainApproxSimple); /// Approximate contours to polygons + get bounding rects and circles VectorOfVectorOfPoint contours_poly = new VectorOfVectorOfPoint(contours.Size); Point[][] con = contours.ToArrayOfArray(); PointF[][] conf = new PointF[con.GetLength(0)][]; for (int i = 0; i < con.GetLength(0); i++) { conf[i] = new PointF[con[i].Length]; for (int j = 0; j < con[i].Length; j++) { conf[i][j] = new PointF(con[i][j].X, con[i][j].Y); } } for (int i = 0; i < contours.Size; i++) { double a = CvInvoke.ContourArea(contours[i], false); if (a > 30000) { CvInvoke.ApproxPolyDP(contours[i], contours_poly[circles], 3, true); circles++; } } /// Draw polygonal contour + bonding rects + circles Image <Gray, byte> filteredImage = new Image <Gray, byte>(Img_Source_Gray.Width, Img_Source_Gray.Height); for (int i = 0; i < circles; i++) { CvInvoke.DrawContours(filteredImage, contours_poly, i, new MCvScalar(255, 255, 255), -1); } filteredImage = colorImage.Convert <Gray, Byte>().And(filteredImage); Image <Gray, Byte> whiteAreas = new Image <Gray, byte>(filteredImage.Width, filteredImage.Height); List <DetectedCircle> detectedCircles = new List <DetectedCircle>(); for (int i = 0; i < circles; i++) { PointF[] pointfs = Array.ConvertAll(contours_poly[i].ToArray(), input => new PointF(input.X, input.Y)); Rectangle boundingRect = PointCollection.BoundingRectangle(pointfs); DetectedCircle detectedCircle = new DetectedCircle() { contour = contours_poly[i], boundingRect = boundingRect, center = new Point(boundingRect.X + (boundingRect.Width / 2), boundingRect.Y + (boundingRect.Height / 2)) }; detectedCircles.Add(detectedCircle); filteredImage.ROI = boundingRect; int threshold = _ComputeThreshold(filteredImage, detectedCircle); filteredImage.ROI = Rectangle.Empty; Image <Gray, Byte> mask = new Image <Gray, byte>(filteredImage.Width, filteredImage.Height); mask.Draw(boundingRect, new Gray(255), -1); mask = filteredImage.And(mask); /* Extract white are solely based on the Blue channel */ mask = mask.ThresholdBinary(new Gray(threshold), new Gray(255)); whiteAreas = whiteAreas.Or(mask.Convert <Gray, Byte>().ThresholdBinary(new Gray(10), new Gray(255))); CvInvoke.DrawContours(whiteAreas, contours_poly, i, new MCvScalar(255, 255, 255), 3); } detectedCircles = detectedCircles.OrderBy(c => c.center.X).ToList(); processedImage = whiteAreas; return(_ComputeMetrics(whiteAreas, detectedCircles, circles)); }
public void Rotation() { //Bitmap src = new Bitmap(@"C:\Users\nhonarva\Documents\strabo-command-line-master\strabo-command-line-master\Strabo.CommandLine\data\intermediate\136_p_4_559_1292_s_0_525_1280_72_24.png"); //Rectangle rect = new Rectangle(0, 0, 100, 50); //Bitmap cropped = CropRotatedRect(src, rect, -30.5f, true); //cropped.Save(@"C:\Users\nhonarva\Documents\sample.png"); List <PointF> points = new List <PointF>(); PointF[] pts; //PointF[] pts=new PointF[4]; //pts[0] = new PointF(40.5f, 60.5f); //pts[1] = new PointF(34f, 44f); //pts[2] = new PointF(39f, 70f); //pts[3] = new PointF(14f, 45f); Bitmap sourceImage = new Bitmap(@"C:\Users\ronaldiscool\Documents\GitHub\strabo-command-line\Strabo.CommandLine\data\intermediate\138_p_6_1482_1009_s_0_1469_965_28_84.png"); /// this image belongs to map 1920-4 intermediate result Image <Bgr, byte> source = new Image <Bgr, byte>(@"C:\Users\ronaldiscool\Documents\GitHub\strabo-command-line\Strabo.CommandLine\data\intermediate\138_p_6_1482_1009_s_0_1469_965_28_84.png"); Image <Bgr, byte> source1 = new Image <Bgr, byte>(@"C:\Users\ronaldiscool\Documents\GitHub\strabo-command-line\Strabo.CommandLine\data\intermediate\SourceMapImage_ms.png"); Bitmap sourceImage1 = new Bitmap(@"C:\Users\ronaldiscool\Documents\GitHub\strabo-command-line\Strabo.CommandLine\data\intermediate\BinaryOutput.png"); Image <Bgr, byte> img = new Image <Bgr, byte>(400, 400, new Bgr(Color.White)); for (int i = 0; i < sourceImage.Width; i++) { for (int j = 0; j < sourceImage.Height; j++) { Color color = sourceImage.GetPixel(i, j); if (!sourceImage.GetPixel(i, j).Name.Equals("ffffffff")) { PointF point = new PointF(i, j); points.Add(point); } } } string filename = Path.GetFileNameWithoutExtension((@"C:\Users\ronaldiscool\Documents\GitHub\strabo-command-line\Strabo.CommandLine\data\intermediate\138_p_6_1482_1009_s_0_1469_965_28_84.png")); // string filename = Path.GetFileNameWithoutExtension(filePaths[i]); String[] splitTokens = filename.Split('_'); int numberOfLetters = 5; //if (splitTokens[6].Equals("0")) //{ int x = Convert.ToInt32(splitTokens[7]); int y = Convert.ToInt32(splitTokens[8]); // int width=Convert.ToInt32(splitTokens[9]); // int height=Convert.ToInt32(splitTokens[10]); // int estimatedSizeOfOneLetter = width/numberOfLetters; // double pixelToSizeRatio = (double)points.Count / (double)(width * height); // Point left = new Point(); // int leftPixelCount = 0; // double leftPixelToSizeRatio = 0; // left.X = x - estimatedSizeOfOneLetter; // left.Y = y; // Point right = new Point(); // int rightPixelCount = 0; // double rightPixelToSizeRatio = 0; // right.X = x + width; // right.Y = y; // do // { // for (int i = left.X; i < left.X+estimatedSizeOfOneLetter; i++) // { // for (int j = left.Y; j < left.Y+height; j++) // { // Color color = sourceImage1.GetPixel(i, j); // if (!sourceImage1.GetPixel(i, j).Name.Equals("ffffffff")) // { // leftPixelCount++; // // sourceImage1.SetPixel(i, j, Color.Green); // } // sourceImage1.SetPixel(i, j, Color.Green); // } // } // leftPixelToSizeRatio = (double)leftPixelCount / (double)(estimatedSizeOfOneLetter * height); // left.X -= estimatedSizeOfOneLetter; // leftPixelCount = 0; // } while (leftPixelToSizeRatio > 0.1); // do // { // for (int i = right.X; i < right.X + estimatedSizeOfOneLetter; i++) // { // for (int j = right.Y; j < right.Y + height; j++) // { // Color color = sourceImage1.GetPixel(i, j); // if (!sourceImage1.GetPixel(i, j).Name.Equals("ffffffff")) // { // rightPixelCount++; // // sourceImage1.SetPixel(i, j, Color.Green); // } // sourceImage1.SetPixel(i, j, Color.Green); // } // } // rightPixelToSizeRatio = (double)(rightPixelCount) / (double)(estimatedSizeOfOneLetter * height); // right.X += estimatedSizeOfOneLetter; // rightPixelCount = 0; // } while (rightPixelToSizeRatio > 0.2); //} // else // { pts = points.ToArray(); Emgu.CV.Structure.MCvBox2D box = PointCollection.MinAreaRect(pts); Rectangle boundingbox = PointCollection.BoundingRectangle(pts); img.Draw(box, new Bgr(Color.Red), 1); img.Draw(boundingbox, new Bgr(Color.Green), 2); source.Draw(box, new Bgr(Color.Red), 1); source.Draw(boundingbox, new Bgr(Color.Green), 2); Emgu.CV.Structure.MCvBox2D boxinoriginalImage = box; boxinoriginalImage.center.X += x - boundingbox.X; /// 63=originalboundingbox.x(1069)(I used result of intermediate image)-boundingbox.x(21) boxinoriginalImage.center.Y += y - boundingbox.Y; //// 175=originalboundingbox.x(1211)(I used result of intermediate image)-boundingbox.x(21) double angleInRadius = (((-1) * box.angle) * Math.PI) / 180; // double height = (box.size.Height) / Math.Sin(angleInRadius); // double width = (box.size.Width) / Math.Sin(angleInRadius); double addToX = (((box.size.Width) * 3) / 4) * Math.Cos(angleInRadius); // I have multiplied height to 3/4 because we have four letter in recognized image and I want to find the center of added part for boundingbox double addToY = (((box.size.Width) * 3) / 4) * Math.Sin(angleInRadius); double OriginalpixelToSizeRatio = points.Count() / (box.size.Height * box.size.Width); Emgu.CV.Structure.MCvBox2D addedArea = box; addedArea.center.X += x - boundingbox.X + (float)addToX; addedArea.center.Y += y - boundingbox.Y - (float)addToY; addedArea.size.Width = (float)((box.size.Width) / 2); source1.Draw(boxinoriginalImage, new Bgr(Color.Green), 2); source1.Draw(addedArea, new Bgr(Color.Red), 2); // PointF[] vertices = boxinoriginalImage.GetVertices(); PointF[] AddedAreaVertices = addedArea.GetVertices(); int AddedAreaPixelNumber = 0; double[] slope = new double[4]; double[] b = new double[4]; for (int i = 0; i < AddedAreaVertices.Length; i++) { if (i < AddedAreaVertices.Length - 1) { slope[i] = (AddedAreaVertices[i].Y - AddedAreaVertices[i + 1].Y) / (AddedAreaVertices[i].X - AddedAreaVertices[i + 1].X); } else { slope[i] = (AddedAreaVertices[i].Y - AddedAreaVertices[0].Y) / (AddedAreaVertices[i].X - AddedAreaVertices[0].X); } b[i] = -(AddedAreaVertices[i].Y - slope[i] * AddedAreaVertices[i].X); } for (int i = 0; i < sourceImage1.Width; i++) { for (int j = 0; j < sourceImage1.Height; j++) { Color color = sourceImage1.GetPixel(i, j); double[] result = new double[4]; for (int k = 0; k < result.Length; k++) { result[k] = j - slope[k] * i + b[k]; } if (result[0] < 0 && result[1] > 0 && result[2] > 0 && result[3] < 0) /// explore if pixel is in bounding box of Min Area Rectangle { // sourceImage1.SetPixel(i, j, Color.Green); if (!sourceImage1.GetPixel(i, j).Name.Equals("ffffffff")) { AddedAreaPixelNumber++; } sourceImage1.SetPixel(i, j, Color.Green); } } } double addedAreaSize = addedArea.size.Height * addedArea.size.Width; double AddedAreaPixelToSizeRatio = (double)(AddedAreaPixelNumber) / (addedArea.size.Height * addedArea.size.Width); // PointF[] vertices = boxinoriginalImage.GetVertices(); //// PointF[] otherVertices = addedArea.GetVertices(); // double[] slope = new double[4]; // double[] b=new double[4]; // for (int i = 0; i < vertices.Length;i++) // { // if (i < vertices.Length - 1) // slope[i] = (vertices[i].Y - vertices[i + 1].Y) / (vertices[i].X - vertices[i + 1].X); // else // slope[i] = (vertices[i].Y - vertices[0].Y) / (vertices[i].X - vertices[0].X); // b[i] = -(vertices[i].Y - slope[i] * vertices[i].X); // } // for (int i = 0; i < sourceImage.Width; i++) // { // for (int j = 0; j < sourceImage.Height; j++) // { // Color color = sourceImage.GetPixel(i, j); // double[] result = new double[4]; // for (int k = 0; k < result.Length;k++) // result[k] = j - slope[k] * i + b[k]; // if (result[0] < 0 && result[1] > 0 && result[2] > 0 && result[3] < 0) /// explore if pixel is in bounding box of Min Area Rectangle // { // sourceImage.SetPixel(i, j, Color.Green); // } // } // } foreach (PointF p in pts) { img.Draw(new CircleF(p, 2), new Bgr(Color.Green), 1); } // } sourceImage.Save(@"C:\Users\ronaldiscool\Documents\separationResult.png"); img.Save(@"C:\Users\ronaldiscool\Documents\sample.png"); source.Save(@"C:\Users\ronaldiscool\Documents\sample1.png"); source1.Save(@"C:\Users\ronaldiscool\Documents\sample2.png"); sourceImage1.Save(@"C:\Users\ronaldiscool\Documents\sample3.png"); }
private static void FindRectangle(int min, int max) { Image <Rgb, Byte> img = new Image <Rgb, byte>(ori_img); Image <Gray, Byte> edgeImage = new Image <Gray, byte>(show_img); #region Find rectangles boxList = new List <RotatedRect>(); //a box is a rotated rectangle double rate = img.Width * img.Height / 3864714.0; bool isIDPExist = false, isUseExist = false, isAddressExist = false; using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint()) { CvInvoke.FindContours(edgeImage, contours, null, RetrType.List, ChainApproxMethod.ChainApproxSimple); int count = contours.Size; for (int i = 0; i < count; i++) { using (VectorOfPoint contour = contours[i]) using (VectorOfPoint approxContour = new VectorOfPoint()) { CvInvoke.ApproxPolyDP(contour, approxContour, CvInvoke.ArcLength(contour, true) * 0.05, true); double area = CvInvoke.ContourArea(contour, false); if (area > 100000 * rate && area < 142000 * rate && !isIDPExist) { // eid, date, price Point[] pts = contour.ToArray(); PointF[] ptfs = new PointF[pts.Length]; for (int pi = 0; pi < pts.Length; pi++) { ptfs[pi] = new PointF(pts[pi].X, pts[pi].Y); } Rectangle rec = PointCollection.BoundingRectangle(ptfs); img.Draw(rec, new Rgb(Color.DarkOrange), 2); rects.Add(rec); isIDPExist = true; } else if (area > 350000 * rate && area < 450000 * rate) { // use Point[] pts = contour.ToArray(); PointF[] ptfs = new PointF[4]; int minx = int.MaxValue, miny = int.MaxValue, maxx = 0, maxy = 0; for (int pi = 0; pi < pts.Length; pi++) { if (pts[pi].X < minx) { minx = pts[pi].X; } if (pts[pi].Y < miny) { miny = pts[pi].Y; } if (pts[pi].X > maxx) { maxx = pts[pi].X; } if (pts[pi].Y > maxy) { maxy = pts[pi].Y; } } ptfs[0] = new PointF(minx, miny); ptfs[1] = new PointF(minx, (miny + maxy) / 2); ptfs[2] = new PointF(maxx, miny); ptfs[3] = new PointF(maxx, (miny + maxy) / 2); Rectangle rec = PointCollection.BoundingRectangle(ptfs); img.Draw(PointCollection.BoundingRectangle(ptfs), new Rgb(Color.DarkOrange), 2); if (!isUseExist) { rects.Add(rec); isUseExist = true; } PointF[] ptfks = new PointF[4]; ptfks[0] = new PointF(maxx * 1.5f, maxy); ptfks[1] = new PointF(maxx * 1.5f, (float)(maxy + 32 * rate)); ptfks[2] = new PointF(minx, maxy); ptfks[3] = new PointF(minx, (float)(maxy + 32 * rate)); Rectangle rec2 = PointCollection.BoundingRectangle(ptfks); img.Draw(PointCollection.BoundingRectangle(ptfks), new Rgb(Color.DarkOrange), 2); if (!isAddressExist) { rects.Add(rec2); isAddressExist = true; } } else if (area > min * rate && area < max * rate) { Point[] pts = contour.ToArray(); PointF[] ptfs = new PointF[pts.Length]; for (int pi = 0; pi < pts.Length; pi++) { ptfs[pi] = new PointF(pts[pi].X, pts[pi].Y); } Rectangle rec = PointCollection.BoundingRectangle(ptfs); img.Draw(rec, new Rgb(Color.DarkOrange), 2); rects.Add(rec); } } } } #endregion #region draw rectangles foreach (RotatedRect box in boxList) { img.Draw(box, new Rgb(Color.DarkOrange), 2); } pre_img = show_img; show_img = img.Bitmap; rform.UpdateImage(show_img); //img.Save("rect_" + this.count + ".png"); #endregion }
public void AddNeighbor(List <TessResult> tessOcrResultList, string inputpath) { string file_name = ""; List <PointF> points = new List <PointF>(); Boolean Continue = true; int Counter = 0; SVM SVMForClassification = new SVM(@"C:\Users\nhonarva\Documents\MachineLearning\sampleTraintData\"); for (int k = 0; k < tessOcrResultList.Count; k++) /// add neighbors of each bounding box { points = new List <PointF>(); string TotalPixelToSizeRatio = ""; file_name = tessOcrResultList[k].fileName; Bitmap ResultOfTextDetection; string[] split = file_name.Split('_'); if (split[6].Equals("0")) { ResultOfTextDetection = new Bitmap(inputpath + file_name + ".png"); } else { string newFileName = ""; split[6] = "0"; for (int j = 0; j < split.Length; j++) { if (j < split.Length - 1) { newFileName += split[j] + "_"; } else { newFileName += split[j]; } } ResultOfTextDetection = new Bitmap(inputpath + newFileName + ".png"); } Bitmap OriginalBinaryImage = new Bitmap(inputpath + "BinaryOutput.png"); for (int i = 0; i < ResultOfTextDetection.Width; i++) //// scan image to find foreground pixels { for (int j = 0; j < ResultOfTextDetection.Height; j++) { Color color = ResultOfTextDetection.GetPixel(i, j); if (!ResultOfTextDetection.GetPixel(i, j).Name.Equals("ffffffff")) { PointF point = new PointF(i, j); points.Add(point); } } } String[] splitTokens = file_name.Split('_'); int numberOfRecognizedLetters = tessOcrResultList[k].tess_word3.Length - 2; /// -2 because we have \n\n at the end of word int x = Convert.ToInt32(tessOcrResultList[k].x); int y = Convert.ToInt32(tessOcrResultList[k].y); int width = Convert.ToInt32(tessOcrResultList[k].w); int height = Convert.ToInt32(tessOcrResultList[k].h); if (splitTokens[6].Equals("0")) /// bounding box with slope 0 (horizental) { int estimatedSizeOfOneLetter = width / numberOfRecognizedLetters; double pixelToSizeRatio = (double)(points.Count) / (double)(width * height); TotalPixelToSizeRatio = Convert.ToString(Math.Round((decimal)pixelToSizeRatio, 2)); Point left = new Point(); /// left coordinate for box at left hand side of blob int leftPixelCount = 0; double leftPixelToSizeRatio = 0; left.X = x - estimatedSizeOfOneLetter; left.Y = y; Point right = new Point(); //// right coordinate for box at right hand side of blob int rightPixelCount = 0; double rightPixelToSizeRatio = 0; right.X = x + width; right.Y = y; Continue = true; if (char.IsUpper(tessOcrResultList[k].tess_word3.ToCharArray()[0])) { Continue = false; } if (left.X < 0) { Continue = false; } // continue; int AddedAreaWidth = estimatedSizeOfOneLetter; Counter = 0; while (Continue) { if ((left.X - estimatedSizeOfOneLetter) < 0) { AddedAreaWidth = left.X; } int[,] AddedAreaPoints = new int[AddedAreaWidth, height]; for (int i = left.X; i < left.X + AddedAreaWidth; i++) { for (int j = left.Y; j < left.Y + height; j++) { if ((!OriginalBinaryImage.GetPixel(i, j).Name.Equals("ffffffff"))) { leftPixelCount++; AddedAreaPoints[i - left.X, j - left.Y] = 1; } else { AddedAreaPoints[i - left.X, j - left.Y] = 0; } } } Counter++; leftPixelToSizeRatio = (double)(leftPixelCount) / (double)(AddedAreaWidth * height); QGISJsonNeighbothood.AddFeature(left.X, left.Y, left.X + AddedAreaWidth, left.Y, left.X + AddedAreaWidth, left.Y + tessOcrResultList[k].h, left.X, left.Y + tessOcrResultList[k].h, tessOcrResultList[k].id + "-" + Convert.ToString(Counter), Convert.ToString(Math.Round((decimal)leftPixelToSizeRatio, 2)), -1); left.X -= estimatedSizeOfOneLetter; leftPixelCount = 0; if (left.X < 0) { Continue = false; } if (leftPixelToSizeRatio < 0.2) { Continue = false; } if (leftPixelToSizeRatio > 0.2) { SVMForClassification.Classification(AddedAreaPoints, tessOcrResultList[k].id + "-" + Convert.ToString(Counter)); } } Continue = true; if (right.X > OriginalBinaryImage.Width) { Continue = false; } AddedAreaWidth = estimatedSizeOfOneLetter; Counter = 0; while (Continue) { if ((right.X + estimatedSizeOfOneLetter) > OriginalBinaryImage.Width) { AddedAreaWidth = OriginalBinaryImage.Width - right.X; } int[,] AddedAreaPoints = new int[AddedAreaWidth, height]; for (int i = right.X; i < right.X + AddedAreaWidth; i++) { for (int j = right.Y; j < right.Y + height; j++) { if (!OriginalBinaryImage.GetPixel(i, j).Name.Equals("ffffffff")) { rightPixelCount++; AddedAreaPoints[i - right.X, j - right.Y] = 1; } else { AddedAreaPoints[i - right.X, j - right.Y] = 0; } } } Counter++; rightPixelToSizeRatio = (double)(rightPixelCount) / (double)(AddedAreaWidth * height); QGISJsonNeighbothood.AddFeature(right.X, right.Y, right.X + AddedAreaWidth, right.Y, right.X + AddedAreaWidth, right.Y + tessOcrResultList[k].h, right.X, right.Y + tessOcrResultList[k].h, tessOcrResultList[k].id + "-" + Convert.ToString(Counter), Convert.ToString(Math.Round((decimal)rightPixelToSizeRatio, 2)), -1); right.X += estimatedSizeOfOneLetter; rightPixelCount = 0; if (right.X > OriginalBinaryImage.Width) { Continue = false; } if (rightPixelToSizeRatio < 0.2) { Continue = false; } if (rightPixelToSizeRatio > 0.2) { SVMForClassification.Classification(AddedAreaPoints, tessOcrResultList[k].id + "-" + Convert.ToString(Counter)); } } // } QGISJsonNeighbothood.AddFeature(x, y, x + width, y, x + width, y + height, x, y + height, tessOcrResultList[k].id, TotalPixelToSizeRatio, -1); } else { PointF[] pts; pts = points.ToArray(); Emgu.CV.Structure.MCvBox2D box = PointCollection.MinAreaRect(pts); Rectangle boundingbox = PointCollection.BoundingRectangle(pts); Emgu.CV.Structure.MCvBox2D boxinoriginalImage = box; boxinoriginalImage.center.X += x - boundingbox.X; /// 63=originalboundingbox.x(1069)(I used result of intermediate image)-boundingbox.x(21) boxinoriginalImage.center.Y += y - boundingbox.Y; PointF[] vertices = boxinoriginalImage.GetVertices(); double pixelToSizeRatio = (double)(points.Count) / (double)(box.size.Width * box.size.Height); TotalPixelToSizeRatio = Convert.ToString(Math.Round((decimal)pixelToSizeRatio, 2)); QGISJsonNeighbothood.AddFeature(vertices[0].X, vertices[0].Y, vertices[1].X, vertices[1].Y, vertices[2].X, vertices[2].Y, vertices[3].X, vertices[3].Y, tessOcrResultList[k].id, TotalPixelToSizeRatio, -1); for (int m = 1; m < 4; m++) { Emgu.CV.Structure.MCvBox2D addedArea = box; if (box.size.Height > box.size.Width) ///Non horizental bounding boxes that slope of bounding box is less than zero { double angleInRadius = ((90 + box.angle) * Math.PI) / 180; double addToX = (((box.size.Height) * ((m - 1) * 2 + numberOfRecognizedLetters + 1)) / (numberOfRecognizedLetters * 2)) * Math.Cos(angleInRadius); // I have multiplied height to 3/4 because we have four letter in recognized image and I want to find the center of added part for boundingbox double addToY = (((box.size.Height) * ((m - 1) * 2 + numberOfRecognizedLetters + 1)) / (numberOfRecognizedLetters * 2)) * Math.Sin(angleInRadius); addedArea.center.X += (x - boundingbox.X) + (float)addToX; addedArea.center.Y += (y - boundingbox.Y) + (float)addToY; addedArea.size.Height = (float)((box.size.Height) / numberOfRecognizedLetters); } else ///Non horizental bounding boxes that slope of bounding box is greater than zero { double angleInRadius = (((-1) * box.angle) * Math.PI) / 180; double addToX = (((box.size.Width) * ((m - 1) * 2 + numberOfRecognizedLetters + 1)) / (numberOfRecognizedLetters * 2)) * Math.Cos(angleInRadius); // I have multiplied height to 3/4 because we have four letter in recognized image and I want to find the center of added part for boundingbox double addToY = (((box.size.Width) * ((m - 1) * 2 + numberOfRecognizedLetters + 1)) / (numberOfRecognizedLetters * 2)) * Math.Sin(angleInRadius); addedArea.center.X += (x - boundingbox.X) - (float)addToX; addedArea.center.Y += (y - boundingbox.Y) + (float)addToY; addedArea.size.Width = (float)((box.size.Width) / numberOfRecognizedLetters); } PointF[] AddedAreaVertices = addedArea.GetVertices(); PointF ExploreAddedArea_MinPoint = AddedAreaVertices[0]; PointF ExploreAddedArea_MaxPoint = AddedAreaVertices[0]; for (int i = 1; i < AddedAreaVertices.Length; i++) { if (AddedAreaVertices[i].X < ExploreAddedArea_MinPoint.X) { ExploreAddedArea_MinPoint.X = AddedAreaVertices[i].X; } if (AddedAreaVertices[i].Y < ExploreAddedArea_MinPoint.Y) { ExploreAddedArea_MinPoint.Y = AddedAreaVertices[i].Y; } if (AddedAreaVertices[i].X > ExploreAddedArea_MaxPoint.X) { ExploreAddedArea_MaxPoint.X = AddedAreaVertices[i].X; } if (AddedAreaVertices[i].Y > ExploreAddedArea_MaxPoint.Y) { ExploreAddedArea_MaxPoint.Y = AddedAreaVertices[i].Y; } } int AddedAreaPixelNumber = 0; double[] slope = new double[4]; double[] b = new double[4]; for (int i = 0; i < AddedAreaVertices.Length; i++) //// find four lines that create min area rectangle bounding box { if (i < AddedAreaVertices.Length - 1) { slope[i] = (AddedAreaVertices[i].Y - AddedAreaVertices[i + 1].Y) / (AddedAreaVertices[i].X - AddedAreaVertices[i + 1].X); } else { slope[i] = (AddedAreaVertices[i].Y - AddedAreaVertices[0].Y) / (AddedAreaVertices[i].X - AddedAreaVertices[0].X); } b[i] = -(AddedAreaVertices[i].Y - slope[i] * AddedAreaVertices[i].X); } for (int i = Convert.ToInt32(ExploreAddedArea_MinPoint.X); i < Convert.ToInt32(ExploreAddedArea_MaxPoint.X) + 1; i++) { for (int j = Convert.ToInt32(ExploreAddedArea_MinPoint.Y); j < Convert.ToInt32(ExploreAddedArea_MaxPoint.Y) + 1; j++) { if ((i < OriginalBinaryImage.Width) && (j < OriginalBinaryImage.Width) && (i > 0) && (j > 0)) { Color color = OriginalBinaryImage.GetPixel(i, j); double[] result = new double[4]; for (int l = 0; l < result.Length; l++) { result[l] = j - slope[l] * i + b[l]; } if (result[0] < 0 && result[1] > 0 && result[2] > 0 && result[3] < 0) /// explore if pixel is in bounding box of Min Area Rectangle { // sourceImage1.SetPixel(i, j, Color.Green); if (!OriginalBinaryImage.GetPixel(i, j).Name.Equals("ffffffff")) { AddedAreaPixelNumber++; } } } else { break; } } } double addedAreaSize = addedArea.size.Height * addedArea.size.Width; double AddedAreaPixelToSizeRatio = (double)(AddedAreaPixelNumber) / (addedArea.size.Height * addedArea.size.Width); QGISJsonNeighbothood.AddFeature(AddedAreaVertices[0].X, AddedAreaVertices[0].Y, AddedAreaVertices[1].X, AddedAreaVertices[1].Y, AddedAreaVertices[2].X, AddedAreaVertices[2].Y, AddedAreaVertices[3].X, AddedAreaVertices[3].Y, tessOcrResultList[k].id, Convert.ToString(Math.Round((decimal)AddedAreaPixelToSizeRatio, 2)), -1); } for (int m = 1; m < 4; m++) { Emgu.CV.Structure.MCvBox2D addedArea = box; if (box.size.Height > box.size.Width) ///Non horizental bounding boxes that slope of bounding box is less than zero { double angleInRadius = ((90 + box.angle) * Math.PI) / 180; double addToX = (((box.size.Height) * ((m - 1) * 2 + numberOfRecognizedLetters + 1)) / (numberOfRecognizedLetters * 2)) * Math.Cos(angleInRadius); // I have multiplied height to 3/4 because we have four letter in recognized image and I want to find the center of added part for boundingbox double addToY = (((box.size.Height) * ((m - 1) * 2 + numberOfRecognizedLetters + 1)) / (numberOfRecognizedLetters * 2)) * Math.Sin(angleInRadius); addedArea.center.X += (x - boundingbox.X) - (float)addToX; addedArea.center.Y += (y - boundingbox.Y) - (float)addToY; addedArea.size.Height = (float)((box.size.Height) / numberOfRecognizedLetters); } else ///Non horizental bounding boxes that slope of bounding box is greater than zero { double angleInRadius = (((-1) * box.angle) * Math.PI) / 180; double addToX = (((box.size.Width) * ((m - 1) * 2 + numberOfRecognizedLetters + 1)) / (numberOfRecognizedLetters * 2)) * Math.Cos(angleInRadius); // I have multiplied height to 3/4 because we have four letter in recognized image and I want to find the center of added part for boundingbox double addToY = (((box.size.Width) * ((m - 1) * 2 + numberOfRecognizedLetters + 1)) / (numberOfRecognizedLetters * 2)) * Math.Sin(angleInRadius); addedArea.center.X += (x - boundingbox.X) + (float)addToX; addedArea.center.Y += (y - boundingbox.Y) - (float)addToY; addedArea.size.Width = (float)((box.size.Width) / numberOfRecognizedLetters); } PointF[] AddedAreaVertices = addedArea.GetVertices(); PointF ExploreAddedArea_MinPoint = AddedAreaVertices[0]; PointF ExploreAddedArea_MaxPoint = AddedAreaVertices[0]; for (int i = 1; i < AddedAreaVertices.Length; i++) { if (AddedAreaVertices[i].X < ExploreAddedArea_MinPoint.X) { ExploreAddedArea_MinPoint.X = AddedAreaVertices[i].X; } if (AddedAreaVertices[i].Y < ExploreAddedArea_MinPoint.Y) { ExploreAddedArea_MinPoint.Y = AddedAreaVertices[i].Y; } if (AddedAreaVertices[i].X > ExploreAddedArea_MaxPoint.X) { ExploreAddedArea_MaxPoint.X = AddedAreaVertices[i].X; } if (AddedAreaVertices[i].Y > ExploreAddedArea_MaxPoint.Y) { ExploreAddedArea_MaxPoint.Y = AddedAreaVertices[i].Y; } } int AddedAreaPixelNumber = 0; double[] slope = new double[4]; double[] b = new double[4]; for (int i = 0; i < AddedAreaVertices.Length; i++) //// find four lines that create min area rectangle bounding box { if (i < AddedAreaVertices.Length - 1) { slope[i] = (AddedAreaVertices[i].Y - AddedAreaVertices[i + 1].Y) / (AddedAreaVertices[i].X - AddedAreaVertices[i + 1].X); } else { slope[i] = (AddedAreaVertices[i].Y - AddedAreaVertices[0].Y) / (AddedAreaVertices[i].X - AddedAreaVertices[0].X); } b[i] = -(AddedAreaVertices[i].Y - slope[i] * AddedAreaVertices[i].X); } for (int i = Convert.ToInt32(ExploreAddedArea_MinPoint.X); i < Convert.ToInt32(ExploreAddedArea_MaxPoint.X) + 1; i++) { for (int j = Convert.ToInt32(ExploreAddedArea_MinPoint.Y); j < Convert.ToInt32(ExploreAddedArea_MaxPoint.Y) + 1; j++) { if ((i < OriginalBinaryImage.Width) && (j < OriginalBinaryImage.Width) && (i > 0) && (j > 0)) { Color color = OriginalBinaryImage.GetPixel(i, j); double[] result = new double[4]; for (int l = 0; l < result.Length; l++) { result[l] = j - slope[l] * i + b[l]; } if (result[0] < 0 && result[1] > 0 && result[2] > 0 && result[3] < 0) /// explore if pixel is in bounding box of Min Area Rectangle { // sourceImage1.SetPixel(i, j, Color.Green); if (!OriginalBinaryImage.GetPixel(i, j).Name.Equals("ffffffff")) { AddedAreaPixelNumber++; } } } else { break; } } } double addedAreaSize = addedArea.size.Height * addedArea.size.Width; double AddedAreaPixelToSizeRatio = (double)(AddedAreaPixelNumber) / (addedArea.size.Height * addedArea.size.Width); QGISJsonNeighbothood.AddFeature(AddedAreaVertices[0].X, AddedAreaVertices[0].Y, AddedAreaVertices[1].X, AddedAreaVertices[1].Y, AddedAreaVertices[2].X, AddedAreaVertices[2].Y, AddedAreaVertices[3].X, AddedAreaVertices[3].Y, tessOcrResultList[k].id, Convert.ToString(Math.Round((decimal)AddedAreaPixelToSizeRatio, 2)), -1); } } } QGISJsonNeighbothood.WriteGeojsonFileByPixels(); }