/// <summary> /// Autocropping of image /// - Adapative threshold /// - Border following /// - Check if size of components matches size of a number /// </summary> /// <param name="img"></param> /// <returns></returns> private Image <Gray, Byte> preprocessMaterialID(Image <Gray, Byte> img) { Image <Gray, Byte> preprocessed = img.Convert <Gray, Byte>(); Image <Gray, Byte> found_contours = new Image <Gray, Byte>(img.Size); imgMaterialID = null; preprocessed = preprocessed.ThresholdAdaptive(new Gray(255), ADAPTIVE_THRESHOLD_TYPE.CV_ADAPTIVE_THRESH_MEAN_C, THRESH.CV_THRESH_BINARY, 33, new Gray(15)); using (MemStorage storage = new MemStorage()) { for (Contour <Point> contours = preprocessed.FindContours(); contours != null; contours = contours.HNext) { Rectangle rect = contours.BoundingRectangle; // Check if size is ok for a number if ( rect.Width > 15 && rect.Width < 40 && rect.Height > 10 && rect.Height < 35) { found_contours.Draw(rect, new Gray(255), 3); } } } MCvBox2D box = minAreaRect(found_contours); if (box.size.Width > 0 && box.size.Height > 0) { imgMaterialID = preprocessed.Copy(box); } return(imgMaterialID); }
private static LineSegment2D GetLineH(int count, int n, MCvBox2D box) { //egy vízszintes vonalat ad vissza, a megfelőle pocízióra téve //temporary LineSegment2D result = new LineSegment2D(); Point lineBeg; Point lineEnd; double doloesszog = box.angle; double atfogoC = box.size.Height; //cosinus tétellel először ezt tudom kiszámolni legegyszerűbben //cos(dőlésszög) = (szög melletti befogó)/(átfogó) ebből a befogó kell, átfogó és szög ismert double befogoA = Math.Cos(toRadian(doloesszog)) * atfogoC; double befogoB = Math.Sqrt(Math.Pow(atfogoC, 2) - Math.Pow(befogoA, 2)); double offX = befogoA / count; double offY = befogoB / count; int cx = (int)(box.center.X - (((count - 2) / 2.0) - n) * offY); int cy = (int)(box.center.Y - (((count - 2) / 2.0) - n) * offX); double leptekX = (Math.Cos(toRadian(doloesszog)) * box.size.Width); double leptekY = Math.Sqrt(Math.Pow(box.size.Width, 2) - Math.Pow(leptekX, 2)); lineBeg = new Point((int)(cx + leptekX / 2.0), (int)(cy - leptekY / 2.0)); lineEnd = new Point((int)(cx - leptekX / 2.0), (int)(cy + leptekY / 2.0)); result = new LineSegment2D(lineBeg, lineEnd); return(result); }
/// <summary> /// A paraméterként kapott kameraképre rárajzolja a detektált négyzethálót a megfelelő dőlésszöggel. /// </summary> /// <param name="img">Az adott kép, amire rajzol a metódus.</param> /// <param name="bigBox">A négyzetháló kerete.</param> /// <param name="avgSmallSize">A tábla mezőinek nagysága.</param> /// <param name="color">A szín, amilyen színű legyen a kirajzolt négyzetháló.</param> /// <returns>A kapott képet ad vissza, a rárajzolt négyzethálóval.</returns> public static Image <Bgr, Byte> DrawCage(Image <Bgr, Byte> img, MCvBox2D bigBox, float avgSmallSize, Bgr color) { Image <Bgr, Byte> result = img.Copy(); float cageWidth = bigBox.size.Width + 10; //Négyzetháló szélessége. float cageHeight = bigBox.size.Height + 10; //Négyzetháló magassága. int colNumber = (int)(cageWidth / avgSmallSize); //Oszlopok száma. int rowNumber = (int)(cageHeight / avgSmallSize); //Sorok száma. result.Draw(bigBox, color, 2); //Először csak maga a négyzetháló kerete kerül a képre. if (colNumber > 0 && rowNumber > 0) //Ezt követően a vízszintes és függőleges vonalak is felkerülnek. { for (int i = 0; i < colNumber - 1; i++) //Függőleges vonalak kirajzolása. { result.Draw(GetLine(colNumber, i, false, bigBox), color, 2); } for (int i = 0; i < rowNumber - 1; i++) //Vízszintes vonalak kirajzolása. { result.Draw(GetLine(rowNumber, i, true, bigBox), color, 2); } } return(result); }
public bool updateBoundingBox(MCvBox2D box) { // this is for determining orientation of square objects // we'll get this done in M5 or later this.boundingBox = box; return(true); }
public HandGeastureWindows() { InitializeComponent(); InitializeComponent(); //grabber = new Emgu.CV.Capture(@".\..\..\..\M2U00253.MPG"); grabber = new Emgu.CV.Capture(); grabber.QueryFrame(); frameWidth = grabber.Width; frameHeight = grabber.Height; detector = new AdaptiveSkinDetector(1, AdaptiveSkinDetector.MorphingMethod.NONE); hsv_min = new Hsv(0, 45, 0); hsv_max = new Hsv(20, 255, 255); YCrCb_min = new Ycc(0, 131, 80); YCrCb_max = new Ycc(255, 185, 135); box = new MCvBox2D(); ellip = new Emgu.CV.Structure.Ellipse(); //Application.Idle += new EventHandler(FrameGrabber); worker = new BackgroundWorker(); worker.DoWork += FrameGrabber; worker.RunWorkerAsync(); worker.RunWorkerCompleted += (object sender, RunWorkerCompletedEventArgs e) => { worker.RunWorkerAsync(); }; }
/// <summary> /// Fit an ellipse to the points collection /// </summary> /// <param name="points">The points to be fitted</param> /// <returns>An ellipse</returns> public static Ellipse EllipseLeastSquareFitting(PointF[] points) { IntPtr seq = Marshal.AllocHGlobal(StructSize.MCvSeq); IntPtr block = Marshal.AllocHGlobal(StructSize.MCvSeqBlock); GCHandle handle = GCHandle.Alloc(points, GCHandleType.Pinned); CvInvoke.cvMakeSeqHeaderForArray( CvInvoke.CV_MAKETYPE((int)CvEnum.MAT_DEPTH.CV_32F, 2), StructSize.MCvSeq, StructSize.PointF, handle.AddrOfPinnedObject(), points.Length, seq, block); Ellipse e = new Ellipse(CvInvoke.cvFitEllipse2(seq)); //The angle returned by cvFitEllipse2 has the wrong sign. //Returned angle is clock wise rotation, what we need for the definition of MCvBox is the counter clockwise rotation. //For this, we needs to change the sign of the angle MCvBox2D b = e.MCvBox2D; b.angle = -b.angle; if (b.angle < 0) { b.angle += 360; } e.MCvBox2D = b; handle.Free(); Marshal.FreeHGlobal(seq); Marshal.FreeHGlobal(block); return(e); }
private void sensor_AllFramesReady(object sender, AllFramesReadyEventArgs e) { using (ColorImageFrame colorFrame = e.OpenColorImageFrame()) { if (colorFrame != null) { colorFrame.CopyPixelDataTo(this.colorPixels); this.colorBitmap.WritePixels( new Int32Rect(0, 0, this.colorBitmap.PixelWidth, this.colorBitmap.PixelHeight), this.colorPixels, this.colorBitmap.PixelWidth * sizeof(int), 0); int sx = (int)this.sld_c1_sX.Value; int sy = (int)this.sld_c1_sY.Value; int dx = (int)this.sld_c1_dX.Value; int dy = (int)this.sld_c1_dY.Value; int w = 0; int h = 0; if (dx >= sx) { w = (dx - sx); } if (dy >= sy) { h = (dy - sy); } float cx = (float)sx + ((float)w) / 2; float cy = (float)sy + ((float)h) / 2; Image <Bgr, Byte> openCVImg = new Image <Bgr, byte>(colorBitmap.ToBitmap()); box = new MCvBox2D(new PointF(cx, cy), new SizeF(new PointF((float)w, (float)h)), 0); openCVImg.Draw(box, new Bgr(System.Drawing.Color.Green), 4); this.cimg_cage4.Source = ImageHelpers.ToBitmapSource(openCVImg); } } }
/// <summary>交換McvBox2D的寬高</summary> public static void SwapMcvBox2DHeightWidth(ref MCvBox2D box) { float temp = box.size.Height; box.size.Height = box.size.Width; box.size.Width = temp; }
private PointF avgCenter; //Mezők alkotta pálya középpontja. /// <summary> /// A kapott képen található négyzetháló keretét keresi. /// </summary> /// <param name="img">A kép, amin keressük a tábla keretét.</param> /// <returns>A detektált négyzetháló keretét adja vissza.</returns> public DetectedField GeneralField(Image <Bgr, Byte> img) { List <MCvBox2D> allBoxes = RealBoxes(Boxes(img), 400); List <MCvBox2D> uniqueBoxes = UniqueBoxes(allBoxes); List <MCvBox2D> relevantBoxes = RelevantBoxes(uniqueBoxes); //Beállítunk néhány táblára jellenző értéket, melyet később felhasználunk. avgCenter = AvgCenter(relevantBoxes); avgAngle = AvgAngle(relevantBoxes); avgSize = AvgSize(relevantBoxes); MCvBox2D frameBox = new MCvBox2D(); //Ha megfelelő szögben áll a pálya, akkor egy egyszerűbb metódus fut le. if (Math.Abs(avgAngle) < 3 || Math.Abs(avgAngle) > 87) { frameBox = StraightFrame(avgSize, relevantBoxes); } else //Ferde négyzethálót kell keresni. { frameBox = CrossFrame(avgSize, relevantBoxes); } return(new DetectedField(frameBox, avgSize)); }
public void ProcessImage(Emgu.CV.Image<Emgu.CV.Structure.Bgr, byte> image) { MCvBox2D mybox = new MCvBox2D(new System.Drawing.PointF(100, 100), new System.Drawing.Size(50, 30), 110); MCvBox2D mybox2 = new MCvBox2D(new System.Drawing.PointF(100, 100), new System.Drawing.Size(50, 30), 0); image.Draw(new Ellipse(mybox), new Bgr(0,0,255), 2); image.Draw(new Ellipse(mybox2), new Bgr(0, 255, 0), 2); }
public Form1() { InitializeComponent(); grabber = new Emgu.CV.Capture("C:/Users/L33549.CITI/Desktop/a.avi"); grabber.QueryFrame(); frameWidth = grabber.Width; frameHeight = grabber.Height; //detector = new AdaptiveSkinDetector(1, AdaptiveSkinDetector.MorphingMethod.NONE); hsv_min = new Hsv(0, 45, 0); hsv_max = new Hsv(20, 255, 255); YCrCb_min = new Ycc(0, 129, 40); YCrCb_max = new Ycc(255, 185, 135); box = new MCvBox2D(); ellip = new Ellipse(); contourStorage = new MemStorage(); approxStorage = new MemStorage(); hullStorage = new MemStorage(); defectsStorage = new MemStorage(); tipPts = new Point[MAX_POINTS]; // coords of the finger tips foldPts = new Point[MAX_POINTS]; // coords of the skin folds between fingers depths = new float[MAX_POINTS]; // distances from tips to folds cogPt = new Point(); fingerTips = new List<Point>(); face = new CascadeClassifier("C:/Users/L33549.CITI/Desktop/AbuseAnalysis/HandGestureRecognition/HandGestureRecognition/HandGestureRecognition/haar/Original/haarcascade_hand.xml"); Application.Idle += new EventHandler(FrameGrabber); /*foreach (var potentialSensor in KinectSensor.KinectSensors) { if (potentialSensor.Status == KinectStatus.Connected) { this.sensor = potentialSensor; break; } } if (null != this.sensor) { // Turn on the color stream to receive color frames this.sensor.ColorStream.Enable(ColorImageFormat.RgbResolution640x480Fps30); // Allocate space to put the pixels we'll receive this.colorPixels = new byte[this.sensor.ColorStream.FramePixelDataLength]; // This is the bitmap we'll display on-screen this.colorBitmap = new WriteableBitmap(this.sensor.ColorStream.FrameWidth, this.sensor.ColorStream.FrameHeight, 96.0, 96.0, PixelFormats.Bgr32, null); // Set the image we display to point to the bitmap where we'll put the image data //this.Image.Source = this.colorBitmap; // Add an event handler to be called whenever there is new color frame data this.sensor.ColorFrameReady += this.SensorColorFrameReady; // Start the sensor! this.sensor.Start(); }*/ }
//1. 畫面上選取要追蹤的區域這裡我稱為 物件 (Object),也就是要被追蹤的東東 //2. 計算出物件的 直方圖 (Histogram) //3. 將物件的直方圖與輸入畫面進行 反向投影(Backproject) 計算 //4. 透過 物件追蹤演算法(Camshift) 快速地框出反向投影計算出的結果 //5. 回傳追蹤區域 //於是一直重複 3~5 的過程,我們的物件追蹤程式就大功告成了! public ObjectTracking(Image <Bgr, Byte> image, Rectangle ROI) { // Initialize parameters //A boundary box trackbox = new MCvBox2D(); //連通物件 trackcomp = new MCvConnectedComp(); //Hue圖? hue = new Image <Gray, byte>(image.Width, image.Height); //*待理解 hue._EqualizeHist(); //遮罩 mask = new Image <Gray, byte>(image.Width, image.Height); //直方圖 hist = new DenseHistogram(30, new RangeF(0, 180)); //一張普通的灰階圖 backproject = new Image <Gray, byte>(image.Width, image.Height); // Assign Object's ROI from source image. // Region of Interest 只針對特定區域進行處理 trackingWindow = ROI; // Producing Object's hist //產生物件直方圖 CalObjectHist(image); }
public static Image <Bgr, Byte> DrawCage(Image <Bgr, Byte> img, MCvBox2D bigBox, float avgSmallSize, Bgr color) { //It draws to camera picture the field Image <Bgr, Byte> result = img.Copy(); float cageWidth = bigBox.size.Width + 10; float cageHeight = bigBox.size.Height + 10; int colNumber = (int)(cageWidth / avgSmallSize); int rowNumber = (int)(cageHeight / avgSmallSize); result.Draw(bigBox, color, 2); //Draw cage if (colNumber > 0 && rowNumber > 0) { for (int i = 0; i < colNumber - 1; i++) { result.Draw(GetLineV(colNumber, i, bigBox), color, 2); } for (int i = 0; i < rowNumber - 1; i++) { result.Draw(GetLineH(rowNumber, i, bigBox), color, 2); } } return(result); }
public static Image <Bgr, byte> DrawBorder(this Image <Bgr, byte> image, int offset, Color color, int tickness = 5) { MCvBox2D box = new MCvBox2D(new PointF(image.Width / 2, image.Height / 2), new SizeF(image.Width - offset, image.Height - offset), 0); image.Draw(box, new Bgr(color), tickness); return(image); }
public DetectedField GeneralField(Image <Bgr, Byte> img) { //Detect all possible boxes by opencv List <MCvBox2D> allBoxes = RealBoxes(Boxes(img)); //Opencv can recognise redundant boxes at the same place so I have to remove some of them List <MCvBox2D> uniqueBoxes = UniqueBoxes(allBoxes); //There can be more boxes out of the field but we need only the boxes on field //List<MCvBox2D> relevantBoxes = Coherent(RelevantBoxes(uniqueBoxes)); List <MCvBox2D> relevantBoxes = RelevantBoxes(uniqueBoxes); //Some avarage properties avgCenter = AvgCenter(relevantBoxes); avgAngle = AvgAngle(relevantBoxes); avgSize = AvgSize(relevantBoxes); //csinálok egy pályakeretet MCvBox2D frameBox = new MCvBox2D(); //ha megfelelő szögben áll if (Math.Abs(avgAngle) < 3 || Math.Abs(avgAngle) > 87) { frameBox = StraightFrame(avgSize, relevantBoxes); } else { frameBox = CrossFrame(avgSize, relevantBoxes); } return(new DetectedField(frameBox, avgSize)); }
/*ROI检测*/ void Region_Detection(int id) { using (MemStorage storage = new MemStorage()) //allocate storage for contour(轮廓) approximation for ( Contour <Point> contours = slide_gray_img[id].FindContours( Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_LIST, storage); contours != null; contours = contours.HNext) { Contour <Point> currentContour = contours.ApproxPoly(contours.Perimeter * 0.05, storage); //逼近多边形曲线 if (currentContour.Area < size_of_roi) //only consider contours with area greater than 250 { tempbox = currentContour.GetMinAreaRect(); //保证roi在中心位置 if (tempbox.size.Height >= 10 && tempbox.size.Width >= 10 && tempbox.center.X > slide[id].Width * 0.17 && tempbox.center.X < slide[id].Width * 0.83) { roi[id] = tempbox.MinAreaRect(); Rectangle absRoi = ConvertToAbsolute(roi[id], slide[id]); Image <Bgr, Byte> RectangleImage = frame; RectangleImage.Draw(absRoi, new Bgr(Color.Blue), 2); imageBox3.Image = RectangleImage; if (id == maxNum) { scanDone = true; } break; } } } }
public static BitmapSource DetectObject(DepthImageFrame depthFrame, double firstGray, double secGray, double sliderMinSize, double sliderMaxSize) { BitmapSource depthBmp = depthFrame.SliceDepthImage(300, 1100); Image <Bgr, Byte> openCVImg = new Image <Bgr, byte>(depthBmp.ToBitmap()); Image <Gray, byte> gray_image = openCVImg.Convert <Gray, byte>().PyrDown().PyrUp(); Image <Gray, Byte> cannyEdges = gray_image.Canny(firstGray, secGray); using (MemStorage stor = new MemStorage()) { //Find contours with no holes try CV_RETR_EXTERNAL to find holes Contour <System.Drawing.Point> contours = cannyEdges.FindContours( Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_EXTERNAL, stor); for (int i = 0; contours != null; contours = contours.HNext) { i++; if (contours.Area > sliderMinSize && contours.Area < sliderMaxSize) { MCvBox2D box = contours.GetMinAreaRect(); openCVImg.Draw(box, new Bgr(System.Drawing.Color.Red), 2); } } } return(ToBitmapSource(openCVImg)); }
public HandRecognition() { InitializeComponent(); // grabber = new Emgu.CV.Capture(@"E:\HandGestureRecognition\M2U00253.mpg"); try { grabber = new Emgu.CV.Capture(); } catch (Exception e) { grabber = new Emgu.CV.Capture(@"E:\HandGestureRecognition\M2U00253.mpg"); } grabber.QuerySmallFrame(); frameWidth = grabber.Width; frameHeight = grabber.Height; detector = new AdaptiveSkinDetector(1, AdaptiveSkinDetector.MorphingMethod.NONE); hsv_min = new Hsv(0, 45, 0); hsv_max = new Hsv(20, 255, 255); YCrCb_min = new Ycc(0, 131, 80); YCrCb_max = new Ycc(255, 185, 135); box = new MCvBox2D(); ellip = new Ellipse(); Application.Idle += new EventHandler(FrameGrabber); }
// chiết xuất ra đường viền bao bọc bàn tay private void ExtractContourAndHull(Image <Gray, byte> skin) { { // tìm đường viền bao bọc bàn tay Contour <Point> contours = skin.FindContours(Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_LIST, storage); // biggest contour chính là đường biểu thị đường bao bọc bàn tay Contour <Point> biggestContour = null; // class contour() đê taọ đường viền, sử dụng bộ nhớ storage Double Result1 = 0; Double Result2 = 0; while (contours != null) { Result1 = contours.Area; if (Result1 > Result2) { Result2 = Result1; biggestContour = contours; } contours = contours.HNext; } if (biggestContour != null) { // class ApproxPoly(Double, MemStorage) xấp xỉ 1 đường cong và trả về kết quả xấp xỉ Contour <Point> currentContour = biggestContour.ApproxPoly(biggestContour.Perimeter * 0.0025, storage); // dung màu xanh là cây để biểu diễn đường viền bao tay currentFrame.Draw(currentContour, new Bgr(Color.LimeGreen), 2); biggestContour = currentContour; hull = biggestContour.GetConvexHull(Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE); box = biggestContour.GetMinAreaRect(); PointF[] points = box.GetVertices(); Point[] ps = new Point[points.Length]; for (int i = 0; i < points.Length; i++) { ps[i] = new Point((int)points[i].X, (int)points[i].Y); } currentFrame.DrawPolyline(hull.ToArray(), true, new Bgr(200, 125, 75), 2); currentFrame.Draw(new CircleF(new PointF(box.center.X, box.center.Y), 3), new Bgr(200, 125, 75), 2); filteredHull = new Seq <Point>(storage); for (int i = 0; i < hull.Total; i++) { if (Math.Sqrt(Math.Pow(hull[i].X - hull[i + 1].X, 2) + Math.Pow(hull[i].Y - hull[i + 1].Y, 2)) > box.size.Width / 10) { filteredHull.Push(hull[i]); } } defects = biggestContour.GetConvexityDefacts(storage, Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE); defectArray = defects.ToArray(); } } }
public void ProcessImage(Emgu.CV.Image <Emgu.CV.Structure.Bgr, byte> image) { MCvBox2D mybox = new MCvBox2D(new System.Drawing.PointF(100, 100), new System.Drawing.Size(50, 30), 110); MCvBox2D mybox2 = new MCvBox2D(new System.Drawing.PointF(100, 100), new System.Drawing.Size(50, 30), 0); image.Draw(new Ellipse(mybox), new Bgr(0, 0, 255), 2); image.Draw(new Ellipse(mybox2), new Bgr(0, 255, 0), 2); }
/// <summary> /// Default constructor /// </summary> public CardDetector() { //Setting the pot default position potRegion = new MCvBox2D(new PointF(515, 246), new SizeF(150, 22), 0); loadPositions(); //load the templates from disk to memory loadTemplates(); }
public static Image <Bgr, Byte> GameImage(int[,] matrix) { //It draws the game view Image <Bgr, Byte> result = new Image <Bgr, byte>(640, 480); int col = matrix.GetLength(0); int row = matrix.GetLength(1); //Boxes size int size = 80; MCvBox2D bigBox = new MCvBox2D(new PointF(50 + (int)((size * col) / 2), 240), new SizeF(size * col, size * row), 0); result.Draw(bigBox, new Bgr(0, 255, 0), 2); //Horizontal, Vertical lines int line_u = (int)(bigBox.center.Y - bigBox.size.Height / 2); int line_d = (int)(bigBox.center.Y + bigBox.size.Height / 2); int line_l = (int)(bigBox.center.X - bigBox.size.Width / 2); int line_r = (int)(bigBox.center.X + bigBox.size.Width / 2); for (int i = 1; i < col; i++) { LineSegment2D horLine; horLine = new LineSegment2D(new Point(line_l + i * size, line_u), new Point(line_l + i * size, line_d)); result.Draw(horLine, new Bgr(0, 255, 0), 2); } for (int i = 1; i < row; i++) { LineSegment2D verLine; verLine = new LineSegment2D(new Point(line_l, line_u + i * size), new Point(line_r, line_u + i * size)); result.Draw(verLine, new Bgr(0, 255, 0), 2); } for (int i = 0; i < col; i++) { for (int j = 0; j < row; j++) { if (matrix[i, j] == 1) { //Draw X List <LineSegment2D> x = GameX(new PointF((float)(line_l + (i + 0.5) * size), (float)(line_u + (j + 0.5) * size)), size); foreach (LineSegment2D line in x) { result.Draw(line, new Bgr(255, 0, 0), 2); } } else if (matrix[i, j] == 0) { //Draw O result.Draw(GameO(new PointF((float)(line_l + (i + 0.5) * size), (float)(line_u + (j + 0.5) * size)), size), new Bgr(0, 0, 255), 2); } } //newnewnew } return(result); }
private void GetContour_Hull(Image <Gray, byte> skin) { using (MemStorage Mem = new MemStorage()) { Contour <Point> Contours = skin.FindContours(Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_LIST, Mem); Contour <Point> Maxium = null; Double area_cur = 0, area_max = 0; while (Contours != null) { area_cur = Contours.Area; if (area_cur > area_max) { area_max = area_cur; Maxium = Contours; } Contours = Contours.HNext; } if (Maxium != null) { Contour <Point> CurrentContour = Maxium.ApproxPoly(Maxium.Perimeter * 0.0025, Mem); Cam_Income.Draw(CurrentContour, new Bgr(Color.LimeGreen), 2); Maxium = CurrentContour; hull = Maxium.GetConvexHull(Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE); box = Maxium.GetMinAreaRect(); PointF[] points = box.GetVertices(); //box.center.Y += 30; judge.X = (float)(box.center.X - (box.size.Width - box.center.X) * 0.20); judge.Y = (float)(box.center.Y + (box.size.Height - box.center.Y) * 0.40); //dif = box.center.Y + (box.size.Height - box.center.Y) * 0.30; Point[] P_To_int = new Point[points.Length]; for (int i = 0; i < points.Length; i++) { P_To_int[i] = new Point((int)points[i].X, (int)points[i].Y); } Cam_Income.DrawPolyline(hull.ToArray(), true, new Bgr(Color.Pink), 2); Cam_Income.Draw(new CircleF(new PointF(box.center.X, box.center.Y), 3), new Bgr(Color.DarkOrchid), 5); Cam_Income.Draw(new CircleF(new PointF(judge.X, judge.Y), 3), new Bgr(Color.Cyan), 5); FilterHull = new Seq <Point>(Mem); for (int i = 0; i < hull.Total - 1; i++) { if (Math.Sqrt(Math.Pow(hull[i].X - hull[i + 1].X, 2) + Math.Pow(hull[i].Y - hull[i + 1].Y, 2)) > box.size.Width / 10) { FilterHull.Push(hull[i]); } } Defects = Maxium.GetConvexityDefacts(Mem, Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE); DefectArray = Defects.ToArray(); Get_Result(); //MessageBox.Show(DefectArray.Count().ToString()); } } }
internal void InitializeBoxes(MCvBox2D outerBox, List<MCvBox2D> allFoundRectangles, int startIndex) { m_OuterBox = outerBox; List<MCvBox2D> insideBoxes = GetOrderedInsideBoxes(allFoundRectangles, startIndex); for (int i = 0; i < m_CellInfos.Length; i++) { m_CellInfos[i].Box = insideBoxes[i]; } }
/// <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))); } }
public static MCvBox2D ToCvBox2D(this Rectangle r) { var box = new MCvBox2D(); box.center = new PointF(r.GetXCenter(), r.GetYCenter()); box.size = new SizeF(r.Width, r.Height); box.angle = 0; return(box); }
private void sensor_AllFramesReady(object sender, AllFramesReadyEventArgs e) { BitmapSource depthBmp = null; blobCount = 0; using (ColorImageFrame colorFrame = e.OpenColorImageFrame()) { using (DepthImageFrame depthFrame = e.OpenDepthImageFrame()) { if (depthFrame != null) { blobCount = 0; depthBmp = depthFrame.SliceDepthImage((int)sliderMin.Value, (int)sliderMax.Value); Image <Bgr, Byte> openCVImg = new Image <Bgr, byte>(depthBmp.ToBitmap()); Image <Gray, byte> gray_image = openCVImg.Convert <Gray, byte>(); using (MemStorage stor = new MemStorage()) { //Find contours with no holes try CV_RETR_EXTERNAL to find holes Contour <System.Drawing.Point> contours = gray_image.FindContours( Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_EXTERNAL, stor); for (int i = 0; contours != null; contours = contours.HNext) { i++; if ((contours.Area > Math.Pow(sliderMinSize.Value, 2)) && (contours.Area < Math.Pow(sliderMaxSize.Value, 2))) { MCvBox2D box = contours.GetMinAreaRect(); openCVImg.Draw(box, new Bgr(System.Drawing.Color.Red), 2); blobCount++; } } } this.outImg.Source = ImageHelpers.ToBitmapSource(openCVImg); txtBlobCount.Text = blobCount.ToString(); } } if (colorFrame != null) { colorFrame.CopyPixelDataTo(this.colorPixels); this.colorBitmap.WritePixels( new Int32Rect(0, 0, this.colorBitmap.PixelWidth, this.colorBitmap.PixelHeight), this.colorPixels, this.colorBitmap.PixelWidth * sizeof(int), 0); } } }
/// <summary>將1D的磁磚陣列轉為2D陣列</summary> public static MCvBox2D[,] TileArrayToTile2DArray(Point theGridRD, Point theGridLT, List <MCvBox2D> BaseMcvBox2DList) { #region 定位磁磚 MCvBox2D[,] tiles = new MCvBox2D[SquareGrids.COLUMN_COUNT, SquareGrids.ROW_COUNT]; bool[,] PositionOccupied = new bool[SquareGrids.ROW_COUNT, SquareGrids.COLUMN_COUNT]; for (int rowIndex = 0; rowIndex < SquareGrids.ROW_COUNT; rowIndex++) { for (int columnIndex = 0; columnIndex < SquareGrids.COLUMN_COUNT; columnIndex++) { PositionOccupied[columnIndex, rowIndex] = false; } } PointF LeftTop = PointF.Empty; double minDis = double.MaxValue; PointF RightDown = PointF.Empty; double maxDis = double.MinValue; foreach (var item in BaseMcvBox2DList) { if (myMath.GetDistance(item.center, new PointF(0, 0)) < minDis) { minDis = myMath.GetDistance(item.center, new PointF(0, 0)); LeftTop = item.center; } if (myMath.GetDistance(item.center, new PointF(0, 0)) > maxDis) { maxDis = myMath.GetDistance(item.center, new PointF(0, 0)); RightDown = item.center; } } double avgGridSpacingH_Pixel = (RightDown.X - LeftTop.X) / (SquareGrids.COLUMN_COUNT - 1); double avgGridSpacingV_Pixel = (RightDown.Y - LeftTop.Y) / (SquareGrids.ROW_COUNT - 1); for (int index = 0; index < BaseMcvBox2DList.Count; index++) { //int columnOfBox = (int)((BaseMcvBox2DList[index].center.X - myGrid.get_GridsLT.X) / myGrid.get_gridSpacingInPixel); int columnOfBox = (int)((BaseMcvBox2DList[index].center.X - theGridLT.X) / avgGridSpacingH_Pixel); //int rowOfBox = (int)((BaseMcvBox2DList[index].center.Y - myGrid.get_GridsLT.Y) / myGrid.get_gridSpacingInPixel); int rowOfBox = (int)((BaseMcvBox2DList[index].center.Y - theGridLT.Y) / avgGridSpacingV_Pixel); if (PositionOccupied[columnOfBox, rowOfBox] == false) { tiles[columnOfBox, rowOfBox] = BaseMcvBox2DList[index]; PositionOccupied[columnOfBox, rowOfBox] = true; } else { throw new Exception("tile" + index + "位置與其他tile重複"); } } return(tiles); #endregion 定位磁磚 }
internal void InitializeBoxes(MCvBox2D outerBox, List <MCvBox2D> allFoundRectangles, int startIndex) { m_OuterBox = outerBox; List <MCvBox2D> insideBoxes = GetOrderedInsideBoxes(allFoundRectangles, startIndex); for (int i = 0; i < m_CellInfos.Length; i++) { m_CellInfos[i].Box = insideBoxes[i]; } }
public bool callButtonVisible(Image <Bgr, byte> img) { //Using optical character recognition VirtualMouse1 vr = new VirtualMouse1(); Rectangle[] buttons = vr.getButtonsRectangles(); Rectangle callButton = buttons[1]; PointF center = new PointF(callButton.X + callButton.Width / 2, callButton.Y + callButton.Height / 2); SizeF size = new SizeF(callButton.Width, callButton.Height); Image <Bgr, byte> image = cropImage(img, new MCvBox2D(center, size, 0)); if (image != null) { image = image.Resize(3.0, INTER.CV_INTER_CUBIC); string[] recong = OCR(image); image.Dispose(); if (recong[0].Contains("Pago") || recong[0].Contains("Passo")) { return(true); } } //If it does not work, using template matching Image <Bgr, Byte> region; double[] min1, max1; Point[] pointMin1, pointMax1; MCvBox2D box = new MCvBox2D(new PointF(653, 646), new SizeF(311, 106), 0); region = cropImage(img, box); if (region != null) { Image <Bgr, Byte> buttonTemplate1 = new Image <Bgr, Byte>("ButtonsTemplate/call.png"); Image <Bgr, Byte> buttonTemplate2 = new Image <Bgr, Byte>("ButtonsTemplate/call2.png"); //Template match the template with the region containing the comunitary cards Image <Gray, float> comparationImage1 = region.MatchTemplate(buttonTemplate1, Emgu.CV.CvEnum.TM_TYPE.CV_TM_CCOEFF_NORMED); Image <Gray, float> comparationImage2 = region.MatchTemplate(buttonTemplate2, Emgu.CV.CvEnum.TM_TYPE.CV_TM_CCOEFF_NORMED); comparationImage1.MinMax(out min1, out max1, out pointMin1, out pointMax1); //If the max correlation exceds some minimum value comparationImage1.Dispose(); if (max1[0] > MIN_TMPLT_MATCHING_DEALER) { return(true); } double[] min2, max2; Point[] pointMin2, pointMax2; comparationImage2.MinMax(out min2, out max2, out pointMin2, out pointMax2); //If the max correlation exceds some minimum value comparationImage2.Dispose(); if (max2[0] > MIN_TMPLT_MATCHING_DEALER) { return(true); } } return(false); }
public bool IsFilled(int x, int y, Image <Gray, Byte> image) { MCvBox2D box = this.InsideRectangles[x, y]; using (Image <Gray, Byte> cellImage = image.Copy(box)) { int nonZeroCount = cellImage.CountNonzero()[0]; //Debug.WriteLine(nonZeroCount); return(nonZeroCount > 60); } }
public static MCvBox2D AvgBox(MCvBox2D box1, MCvBox2D box2) { float Width = (box1.size.Width + box2.size.Width) / 2; float Height = (box1.size.Height + box2.size.Height) / 2; float X = (box1.center.X + box2.center.X) / 2; float Y = (box1.center.Y + box2.center.Y) / 2; float A = (box1.angle + box2.angle) / 2; return(new MCvBox2D(new System.Drawing.PointF(X, Y), new System.Drawing.SizeF(Width, Height), A)); }
/// <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 )); } }
void ExtractContourAndHull(Image <Gray, Byte> skin) { Contour <Point> contours = skin.FindContours(Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_LIST); Contour <Point> biggestContour = null; Double result1 = 0; Double result2 = 0; while (contours != null) { result1 = contours.Area; if (result1 > result2) { result2 = result1; biggestContour = contours; } contours = contours.HNext; } if (biggestContour != null) { Contour <Point> currentContour = biggestContour.ApproxPoly(biggestContour.Perimeter * 0.0025, storage); currentFrame.Draw(currentContour, new Bgr(Color.LimeGreen), 2); biggestContour = currentContour; hull = biggestContour.GetConvexHull(Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE); box = biggestContour.GetMinAreaRect(); PointF[] points = box.GetVertices(); Point[] ps = new Point[points.Length]; for (int i = 0; i < points.Length; i++) { ps[i] = new Point((int)points[i].X, (int)points[i].Y); } currentFrame.DrawPolyline(hull.ToArray(), true, new Bgr(200, 125, 75), 2); currentFrame.Draw(new CircleF(new PointF(box.center.X, box.center.Y), 3), new Bgr(200, 125, 75), 2); PointF center; float radius; filterredHull = new Seq <Point>(storage); for (int i = 0; i < hull.Total; i++) { if (Math.Sqrt(Math.Pow(hull[i].X - hull[i + 1].X, 2) + Math.Pow(hull[i].Y - hull[i + 1].Y, 2)) > box.size.Width / 10) { filterredHull.Push(hull[i]); } } defects = biggestContour.GetConvexityDefacts(storage, Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE); defectArray = defects.ToArray(); } }
//:::::::::::::::::fin variables:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: //:::::::::::::Method for make the image binary:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: //the binarization is inspired in NiBlanck banarization, but in this case, we use just the average of the image. //openinOperation() remove the noise of the binarized image, using morphological operation, we use opening. private Image<Gray, Byte> binaryNiBlack(Image<Gray, Byte> handFrame) { int widthFrame = handFrame.Width; int heigthFrame = handFrame.Height; int sizeSW = 4; int sizeSW_w = sizeSW; //Size of the slinding window int sizeSW_h = sizeSW; //Size of the slinding window int halfWidth = (int)(Math.Floor((double)sizeSW / 2)); int halfHeigth = (int)(Math.Floor((double)sizeSW / 2)); int binaryWidth = widthFrame + halfWidth * 2; int binaryHeigth = heigthFrame + halfHeigth * 2; double k = .6; Image<Gray, Byte> binaryFrameCalculation = new Image<Gray, Byte>(binaryWidth, binaryHeigth); binaryFrameCalculation.SetZero(); Rectangle roiHand = new Rectangle(halfWidth, halfHeigth, widthFrame, heigthFrame); binaryFrameCalculation.ROI = roiHand; handFrame.CopyTo(binaryFrameCalculation); binaryFrameCalculation.ROI = Rectangle.Empty; byte[, ,] byteData = handFrame.Data; for (int i = halfHeigth; i < heigthFrame + halfHeigth; i++) { for (int j = halfWidth; j < widthFrame + halfWidth; j++) { Gray media; MCvScalar desest; MCvScalar mediaValue; double threshold; MCvBox2D roi; Image<Gray, Byte> imageCalculate = new Image<Gray, Byte>(sizeSW_w, sizeSW_h); roi = new MCvBox2D(new System.Drawing.Point(j, i), new System.Drawing.Size(sizeSW_w, sizeSW_h), 0); imageCalculate = binaryFrameCalculation.Copy(roi); binaryFrameCalculation.ROI = Rectangle.Empty; imageCalculate.AvgSdv(out media, out desest); mediaValue = media.MCvScalar; threshold = mediaValue.v0 + (k * desest.v0); if (byteData[i - halfHeigth, j - halfWidth, 0] < threshold) byteData[i - halfHeigth, j - halfWidth, 0] = 255; else byteData[i - halfHeigth, j - halfWidth, 0] = 0; } } handFrame.Data = byteData; return handFrame; }
public Form1() { InitializeComponent(); grabber = new Emgu.CV.Capture(@".\..\..\..\M2U00253.MPG"); grabber.QueryFrame(); frameWidth = grabber.Width; frameHeight = grabber.Height; detector = new AdaptiveSkinDetector(1, AdaptiveSkinDetector.MorphingMethod.NONE); hsv_min = new Hsv(0, 45, 0); hsv_max = new Hsv(20, 255, 255); YCrCb_min = new Ycc(0, 131, 80); YCrCb_max = new Ycc(255, 185, 135); box = new MCvBox2D(); ellip = new Ellipse(); Application.Idle += new EventHandler(FrameGrabber); }
public ObjectTracking(Image<Bgr, Byte> image, Rectangle ROI) { // Initialize parameters trackbox = new MCvBox2D(); trackcomp = new MCvConnectedComp(); hue = new Image<Gray, byte>(image.Width, image.Height); hue._EqualizeHist(); mask = new Image<Gray, byte>(image.Width, image.Height); hist = new DenseHistogram(30, new RangeF(0, 180)); backproject = new Image<Gray, byte>(image.Width, image.Height); // Assign Object's ROI from source image. trackingWindow = ROI; // Producing Object's hist CalObjectHist(image); }
public MainWindow() { InitializeComponent(); box = new MCvBox2D(); mouse = new MouseDriver(); touchPoints = new ArrayList(); thickness = 100; cropWidth = 480; cropHeight = 360; recalibrate = true; // show status for each sensor that is found now. foreach (KinectSensor kinect in KinectSensor.KinectSensors) { kinect.DepthStream.Enable(DepthImageFormat.Resolution640x480Fps30); kinect.DepthStream.Range = (DepthRange)1; kinect.Start(); kinect.DepthFrameReady += new EventHandler<DepthImageFrameReadyEventArgs>(DepthImageReady); } }
public Form1() { InitializeComponent(); grabber = new Emgu.CV.Capture(); grabber.QueryFrame(); frameWidth = grabber.Width; frameHeight = grabber.Height; detector = new AdaptiveSkinDetector(1, AdaptiveSkinDetector.MorphingMethod.NONE); hsv_min = new Hsv(0, 45, 0); hsv_max = new Hsv(20, 255, 255); YCrCb_min = new Ycc(0, 131, 80); YCrCb_max = new Ycc(255, 185, 135); box = new MCvBox2D(); // ellip = new Ellipse(); _face = new HaarCascade("haarcascade_frontalface_alt_tree.xml"); eyes = new HaarCascade("haarcascade_mcs_eyepair_big.xml"); reye = new HaarCascade("haarcascade_mcs_lefteye.xml"); leye = new HaarCascade("haarcascade_mcs_righteye.xml"); label1.Hide(); }
public void DetectRect(Image<Bgr, byte> img, List<Image<Gray, Byte>> stopSignList, List<Rectangle> boxList, List<Contour<Point>> contourSignFound) { imagecolor = img; joinContour.Clear(); Image<Bgr, Byte> smoothImg = img.SmoothGaussian(5, 5, 1.5, 1.5); Image<Gray, Byte> smoothedBlackMask = GetColorPixelMask(smoothImg, 0, 180, 0, 94, 0, 100); imageGray = smoothedBlackMask; //Use Dilate followed by Erode to eliminate small gaps in some countour. smoothedBlackMask._Dilate(1); smoothedBlackMask._Erode(1); using (Image<Gray, Byte> canny = smoothedBlackMask.Canny(new Gray(100), new Gray(50)))//Canny(100,50)) using (MemStorage stor = new MemStorage()) { Contour<Point> contours = canny.FindContours( Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_TREE, stor); FindRect(img, stopSignList, boxList, contours, 5); } CvInvoke.cvAnd(imageGray, imageSelector, imageGray, IntPtr.Zero); using (Image<Gray, Byte> cannySelector = imageSelector.Canny(new Gray(100), new Gray(50)))//Canny(100,50)) using (MemStorage stor = new MemStorage()) { Contour<Point> contours = cannySelector.FindContours( Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_TREE, stor); imageGray.Draw(contours, new Gray(255), 1); } //imageGray.Draw(joinContour.GetMinAreaRect(),new Gray(180),1); CvInvoke.cvShowImage("Image Black", imageGray); PointF temp = new PointF(); MCvBox2D tempbox = new MCvBox2D(); bool swapped = false; //bubble sort for making following sorting // 0 // 1 2 // 4 do { swapped = false; for (int i = 0; i < 3; i++) { if (pointBlack[i].Y > pointBlack[i + 1].Y) { temp = pointBlack[i]; tempbox= minBoxesBlack[i]; pointBlack[i] = pointBlack[i + 1]; minBoxesBlack[i] = minBoxesBlack[i + 1]; pointBlack[i + 1] = temp; minBoxesBlack[i + 1] = tempbox; swapped = true; } } } while (swapped); if (pointBlack[1].X > pointBlack[2].X) { temp = pointBlack[1]; tempbox = minBoxesBlack[1]; pointBlack[1] = pointBlack[2]; minBoxesBlack[1] = minBoxesBlack[2]; pointBlack[2] = temp; minBoxesBlack[2] = tempbox; } MCvFont f = new MCvFont(Emgu.CV.CvEnum.FONT.CV_FONT_HERSHEY_PLAIN, 0.8, 0.8); //for (int i=0; i < 4; i++) //{ // imageGray.Draw(" " + i, ref f, new Point((int)pointBlack[i].X, (int)pointBlack[i].Y), new Gray(200)); // imageGray.Draw(minBoxesBlack[i], new Gray(100), 2); //} LineSegment2DF[]lines = new LineSegment2DF[9]; lines[0] = new LineSegment2DF(pointBlack[0], pointBlack[3]); lines[1] = new LineSegment2DF(pointBlack[1], pointBlack[2]); lines[2] = translatationLineXNeg(lines[0], lines[1]); lines[3] = translatationLineXPos(lines[0], lines[1]); imageGray.Draw(lines[0], new Gray(100), 2); imageGray.Draw(lines[1], new Gray(100), 2); imageGray.Draw(lines[2], new Gray(100), 2); imageGray.Draw(lines[3], new Gray(100), 2); //areas.Clear(); Image<Gray, Byte> smoothedWhiteMask = GetColorPixelMask(smoothImg, 0, 180, 0, 94, 92, 255); imageGray = smoothedWhiteMask; //Use Dilate followed by Erode to eliminate small gaps in some countour. smoothedWhiteMask._Dilate(1); smoothedWhiteMask._Erode(1); CvInvoke.cvAnd(smoothedWhiteMask, imageSelector, smoothedWhiteMask, IntPtr.Zero); using (Image<Gray, Byte> canny = smoothedWhiteMask.Canny(new Gray(100), new Gray(50)))//Canny(100,50)) using (MemStorage stor = new MemStorage()) { Contour<Point> contours = canny.FindContours( Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_TREE, stor); FindRect(img, stopSignList, boxList, contours,6); } CvInvoke.cvShowImage("Image White", smoothedWhiteMask); }
public void TestGetBox2DPoints() { MCvBox2D box = new MCvBox2D( new PointF(3.0f, 2.0f), new SizeF(4.0f, 6.0f), 0.0f); PointF[] vertices = box.GetVertices(); Assert.IsTrue(vertices[0].Equals(new PointF(0.0f, 0.0f))); Assert.IsTrue(vertices[1].Equals(new PointF(6.0f, 0.0f))); }
private void FindContourAndConvexHull(Image<Gray, byte> skin, Image<Bgr, byte> imageFrame) { using (MemStorage cacheStorage = new MemStorage()) { //getting the countours by simplest algorithm and list in retourn (tree isn't necessary) Contour<Point> contours = skin.FindContours( Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_LIST, cacheStorage ); //this variable will contain the biggest countour (if any avaiable) Contour<Point> largestContour = null; //searching for biggest countour Double CurrArea = 0, MaxArea = 0; while (contours != null) { CurrArea = contours.Area; if (CurrArea > MaxArea) { MaxArea = CurrArea; largestContour = contours; } contours = contours.HNext; } if (largestContour != null) { //drawing oryginal countour on image: imageFrame.Draw(largestContour, new Bgr(Color.DarkViolet), 2); //smoothing a bit the countour to make less amout of defects + draw: Contour<Point> currentContour = largestContour.ApproxPoly(largestContour.Perimeter * 0.0025, cacheStorage); imageFrame.Draw(currentContour, new Bgr(Color.LimeGreen), 2); largestContour = currentContour; //computing and drawing convex hull (smallest polygon that covers whole hand): hull = largestContour.GetConvexHull(Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE); imageFrame.DrawPolyline(hull.ToArray(), true, new Bgr(200, 125, 75), 2); //computing smallest box (with angle), that covers the hull, and drawing without angle: box = largestContour.GetMinAreaRect(); handRect = box.MinAreaRect(); imageFrame.Draw(handRect, new Bgr(200, 0, 0), 1); //drawing the center of the box iwth hull: imageFrame.Draw(new CircleF(new PointF(box.center.X, box.center.Y), 3), new Bgr(200, 125, 75), 2); //drawing ellipse ("E") that containts most of the foun pixels: if (largestContour.Count() >= 5) { ellip.MCvBox2D = CvInvoke.cvFitEllipse2(largestContour.Ptr); imageFrame.Draw(new Ellipse(ellip.MCvBox2D), new Bgr(Color.LavenderBlush), 3); } //computing and drawing minimal enclosing circle, that contains whole contour: PointF center; float radius; CvInvoke.cvMinEnclosingCircle(largestContour.Ptr, out center, out radius); imageFrame.Draw(new CircleF(center, radius), new Bgr(Color.Gold), 2); //drawing center of ellipse "E": imageFrame.Draw(new CircleF(new PointF(ellip.MCvBox2D.center.X, ellip.MCvBox2D.center.Y), 3), new Bgr(100, 25, 55), 2); imageFrame.Draw(ellip, new Bgr(Color.DeepPink), 2); //computing and drawing ellipse ("F") that shows the direction of hand: CvInvoke.cvEllipse(imageFrame, new Point((int)ellip.MCvBox2D.center.X, (int)ellip.MCvBox2D.center.Y), new Size((int)ellip.MCvBox2D.size.Width, (int)ellip.MCvBox2D.size.Height), ellip.MCvBox2D.angle, 0, 360, new MCvScalar(120, 233, 88), 1, Emgu.CV.CvEnum.LINE_TYPE.EIGHT_CONNECTED, 0); //drawing ellipse, that's small, but also shows the direction of hand: imageFrame.Draw( new Ellipse( new PointF(box.center.X, box.center.Y), new SizeF(box.size.Height, box.size.Width), box.angle), new Bgr(0, 0, 0), 2); //algorithm that fiters convex hull. It saves only those points, that have distance //between next point bigger than 1/10th of the box size. Small ones are removed. filteredHull = new Seq<Point>(cacheStorage); for (int i = 0; i < hull.Total; i++) { if (Math.Sqrt(Math.Pow(hull[i].X - hull[i + 1].X, 2) + Math.Pow(hull[i].Y - hull[i + 1].Y, 2)) > box.size.Width / 10) { filteredHull.Push(hull[i]); } } //finding convex hull defects: defects = largestContour.GetConvexityDefacts(cacheStorage, Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE); defectsArr = defects.ToArray(); } } }
private void sensor_AllFramesReady(object sender, AllFramesReadyEventArgs e) { using (ColorImageFrame colorFrame = e.OpenColorImageFrame()) { if (colorFrame != null) { colorFrame.CopyPixelDataTo(this.colorPixels); this.colorBitmap.WritePixels( new Int32Rect(0, 0, this.colorBitmap.PixelWidth, this.colorBitmap.PixelHeight), this.colorPixels, this.colorBitmap.PixelWidth * sizeof(int), 0); int sx = (int)this.sld_c1_sX.Value; int sy = (int)this.sld_c1_sY.Value; int dx = (int)this.sld_c1_dX.Value; int dy = (int)this.sld_c1_dY.Value; int w = 0; int h = 0; if (dx >= sx) w = (dx - sx); if (dy >= sy) h = (dy - sy); float cx = (float)sx + ((float)w) / 2; float cy = (float)sy + ((float)h) / 2; Image<Bgr, Byte> openCVImg = new Image<Bgr, byte>(colorBitmap.ToBitmap()); box = new MCvBox2D(new PointF(cx, cy), new SizeF(new PointF((float)w, (float)h)), 0); openCVImg.Draw(box, new Bgr(System.Drawing.Color.Green), 4); this.cimg_cage4.Source = ImageHelpers.ToBitmapSource(openCVImg); } } }
private void ExtractContourAndHull(Image<Gray, byte> skin) { using (MemStorage storage = new MemStorage()) { Contour<Point> contours = skin.FindContours(Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_LIST, storage); Contour<Point> biggestContour = null; Double Result1 = 0; Double Result2 = 0; while (contours != null) { Result1 = contours.Area; if (Result1 > Result2) { Result2 = Result1; biggestContour = contours; } contours = contours.HNext; } if (biggestContour != null) { //currentFrame.Draw(biggestContour, new Bgr(Color.DarkViolet), 2); Contour<Point> currentContour = biggestContour.ApproxPoly(biggestContour.Perimeter * 0.0025, storage); currentFrame.Draw(currentContour, new Bgr(Color.LimeGreen), 2); biggestContour = currentContour; hull = biggestContour.GetConvexHull(Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE); box = biggestContour.GetMinAreaRect(); PointF[] points = box.GetVertices(); mv = biggestContour.GetMoments(); CvInvoke.cvMoments(biggestContour,ref mv, 1); double m00 = CvInvoke.cvGetSpatialMoment(ref mv, 0, 0) ; double m10 = CvInvoke.cvGetSpatialMoment(ref mv, 1, 0) ; double m01 = CvInvoke.cvGetSpatialMoment(ref mv, 0, 1) ; if (m00 != 0) { // calculate center int xCenter = (int) Math.Round(m10/m00)*2; //scale = 2 int yCenter = (int) Math.Round(m01/m00)*2; cogPt.X =xCenter; cogPt.Y =yCenter; } double m11 = CvInvoke.cvGetCentralMoment(ref mv, 1, 1); double m20 = CvInvoke.cvGetCentralMoment(ref mv, 2, 0); double m02 = CvInvoke.cvGetCentralMoment(ref mv, 0, 2); contourAxisAngle = calculateTilt(m11, m20, m02); Point[] ps = new Point[points.Length]; for (int i = 0; i < points.Length; i++) ps[i] = new Point((int)points[i].X, (int)points[i].Y); currentFrame.DrawPolyline(hull.ToArray(), true, new Bgr(200, 125, 75), 2); currentFrame.Draw(new CircleF(new PointF(box.center.X, box.center.Y), 3), new Bgr(200, 125, 75), 2); filteredHull = new Seq<Point>(storage); for (int i = 0; i < hull.Total; i++) { if (Math.Sqrt(Math.Pow(hull[i].X - hull[i + 1].X, 2) + Math.Pow(hull[i].Y - hull[i + 1].Y, 2)) > box.size.Width / 10) { filteredHull.Push(hull[i]); } } defects = biggestContour.GetConvexityDefacts(storage, Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE); defectArray = defects.ToArray(); } } }
private Image<Gray, Byte> CalculateConvexityDefacts(Image<Gray, Byte> image) { Gray cannyThreshold = new Gray(80); Gray cannyThresholdLinking = new Gray(80); //image = image.Canny(cannyThreshold, cannyThresholdLinking); image = image.ThresholdBinary(cannyThreshold, cannyThresholdLinking); //image = image.Erode(1); //image = image.SmoothBilatral(1, 1, 1); //image = image.SmoothMedian(5); //image = image.SmoothBlur(1,1); using (MemStorage storage = new MemStorage()) { Contour<Point> contours = image.FindContours(Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_LIST, storage); Contour<Point> biggestContour = null; Double Result1 = 0; Double Result2 = 0; //takes the biggest contour to track (not really relevant if u paint only the hand.) while (contours != null) { Result1 = contours.Area; if (Result1 > Result2) { Result2 = Result1; biggestContour = contours; } contours = contours.HNext; } double contourArea = biggestContour.Area; if (biggestContour != null) { //Drawing the contour of the hand Contour<Point> currentContour = biggestContour.ApproxPoly(biggestContour.Perimeter * 0.0025, storage); image.Draw(currentContour, new Gray(250), 1); biggestContour = currentContour; hull = biggestContour.GetConvexHull(Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE); box = biggestContour.GetMinAreaRect(); PointF[] points = box.GetVertices(); Point[] ps = new Point[points.Length]; for (int i = 0; i < points.Length; i++) { ps[i] = new Point((int)points[i].X, (int)points[i].Y); } image.DrawPolyline(hull.ToArray(), true, new Gray(255), 1); image.Draw(new CircleF(new PointF(box.center.X, box.center.Y), 2), new Gray(255), 1); filteredHull = new Seq<Point>(storage); for (int i = 0; i < hull.Total; i++) { if (Math.Sqrt(Math.Pow(hull[i].X - hull[i + 1].X, 2) + Math.Pow(hull[i].Y - hull[i + 1].Y, 2)) > box.size.Width / 10) { filteredHull.Push(hull[i]); } } defects = biggestContour.GetConvexityDefacts(storage, Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE); defectArray = defects.ToArray(); } } return image; }
public static extern void cvBoxPoints( MCvBox2D box, [Out] PointF[] pt);
private static MCvBox2D GetLargest(List<MCvBox2D> boxes) { MCvBox2D ret = new MCvBox2D(); int i = 0; foreach(MCvBox2D b in boxes) { if (i == 0) { ret = b; } if ((b.size.Height * b.size.Width) > (ret.size.Height * ret.size.Width)) { ret = b; } i++; } return ret; }
/// <summary> /// Returns the end points of the major and minor axes of an ellipse. /// </summary> /// <param name="ellipse"></param> /// <returns></returns> public static PointF[] EllipseAxes(MCvBox2D ellipse) { var vertices = ellipse.GetVertices(); var midPoints = new PointF[vertices.Length]; for (int i = 0; i < midPoints.Length; i++) { var p1 = vertices[i]; var p2 = vertices[(i + 1) % vertices.Length]; var mid = new PointF((p1.X + p2.X) / 2, (p1.Y + p2.Y) / 2); // Correct the bug in the angle of the ellipse in OpenCV. midPoints[i] = Rotate(mid, ellipse.center, Math.PI / 2); } return midPoints; }
private List<Contour<Point>> findDiffContour(Image<Gray, Byte> imgThreshed) { List<Contour<Point>> contourList = new List<Contour<Point>>(); Contour<Point> bigContour = null; Contour<Point> secondContour = null; Contour<Point> thirdContour = null; float maxArea = 500.0f; float nxtMaxArea = 300.0f; float lastMaxArea = 250.0f; MCvBox2D box = new MCvBox2D(); // generate all the contours in the threshold image as a list for (Contour<Point> contours = imgThreshed.FindContours(CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, RETR_TYPE.CV_RETR_LIST, contourStorage); contours != null; contours = contours.HNext) { // find the largest contour in the list based on bounded box size if (contours.MCvSeq.elem_size > 0) { box = CvInvoke.cvMinAreaRect2(contours, contourStorage); SizeF size = box.size; float area = size.ToPointF().X * size.ToPointF().Y; if (area > maxArea) { contourList.Remove(bigContour); maxArea = area; bigContour = contours; contourList.Add(bigContour); } if ((area < maxArea) && (area > nxtMaxArea) & (area > lastMaxArea)) { contourList.Remove(secondContour); nxtMaxArea = area; secondContour = contours; contourList.Add(secondContour); } if ((area < maxArea) && (area < nxtMaxArea) && (area > lastMaxArea)) { contourList.Remove(thirdContour); lastMaxArea = area; thirdContour = contours; contourList.Add(thirdContour); } } } return contourList; }
///<summary> ///Create an ellipse with specific parameters ///</summary> ///<param name="center"> The center of the ellipse</param> ///<param name="size"> The width and height of the ellipse</param> ///<param name="angle"> The rotation angle in radian for the ellipse</param> public Ellipse(PointF center, SizeF size, float angle) { _box2D = new MCvBox2D(center, size, angle); }
private void ExtractContourAndHull(Image<Gray, byte> skin) { List<Contour<Point>> contourList = new List<Contour<Point>>(); Contour<Point> contours = skin.FindContours(Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_LIST, contourStorage); Contour<Point> biggestContour = null; Double current = 0; Double largest = 0; while (contours != null) { current = contours.Area; if (current > largest) { largest = current; biggestContour = contours; } contours = contours.HNext; } if (biggestContour != null) { //currentFrame.Draw(biggestContour, new Bgr(Color.DarkViolet), 2); Contour<Point> currentContour = biggestContour.ApproxPoly(biggestContour.Perimeter * 0.0025, contourStorage); currentFrame.Draw(currentContour, new Bgr(System.Drawing.Color.LimeGreen), 2); biggestContour = currentContour; hull = biggestContour.GetConvexHull(Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE); box = biggestContour.GetMinAreaRect(); PointF[] points = box.GetVertices(); //handRect = box.MinAreaRect(); //currentFrame.Draw(handRect, new Bgr(200, 0, 0), 1); Point[] ps = new Point[points.Length]; for (int i = 0; i < points.Length; i++) ps[i] = new Point((int)points[i].X, (int)points[i].Y); currentFrame.DrawPolyline(hull.ToArray(), true, new Bgr(200, 125, 75), 2); currentFrame.Draw(new CircleF(new PointF(box.center.X, box.center.Y), 3), new Bgr(200, 125, 75), 2); //ellip.MCvBox2D= CvInvoke.cvFitEllipse2(biggestContour.Ptr); //currentFrame.Draw(new Ellipse(ellip.MCvBox2D), new Bgr(Color.LavenderBlush), 3); PointF center; float radius; //CvInvoke.cvMinEnclosingCircle(biggestContour.Ptr, out center, out radius); //currentFrame.Draw(new CircleF(center, radius), new Bgr(System.Drawing.Color.Gold), 2); //currentFrame.Draw(new CircleF(new PointF(ellip.MCvBox2D.center.X, ellip.MCvBox2D.center.Y), 3), new Bgr(100, 25, 55), 2); //currentFrame.Draw(ellip, new Bgr(Color.DeepPink), 2); //CvInvoke.cvEllipse(currentFrame, new Point((int)ellip.MCvBox2D.center.X, (int)ellip.MCvBox2D.center.Y), new System.Drawing.Size((int)ellip.MCvBox2D.size.Width, (int)ellip.MCvBox2D.size.Height), ellip.MCvBox2D.angle, 0, 360, new MCvScalar(120, 233, 88), 1, Emgu.CV.CvEnum.LINE_TYPE.EIGHT_CONNECTED, 0); //currentFrame.Draw(new Ellipse(new PointF(box.center.X, box.center.Y), new SizeF(box.size.Height, box.size.Width), box.angle), new Bgr(0, 0, 0), 2); filteredHull = new Seq<Point>(contourStorage); for (int i = 0; i < hull.Total; i++) { if (Math.Sqrt(Math.Pow(hull[i].X - hull[i + 1].X, 2) + Math.Pow(hull[i].Y - hull[i + 1].Y, 2)) > box.size.Width / 10) { filteredHull.Push(hull[i]); } } defects = biggestContour.GetConvexityDefacts(contourStorage, Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE); defectArray = defects.ToArray(); } }
private void SensorColorFrameReady(object sender, ColorImageFrameReadyEventArgs e) { using (ColorImageFrame colorFrame = e.OpenColorImageFrame()) { //System.Threading.Thread.Sleep(50); if (colorFrame != null) { Bitmap b = convertFromColorFrame(colorFrame); frameHeight = b.Height; frameWidth = b.Width; currentFrame = new Image<Bgr, Byte>(b); removeFace(b); if (currentFrame != null) { skinDetector = new YCrCbSkinDetector(); Image<Gray, Byte> skin = skinDetector.DetectSkin(currentFrame, YCrCb_min, YCrCb_max); Contour<Point> bContour = biggestContour(skin); if (bContour != null) { box = bContour.GetMinAreaRect(); currentFrame.Draw(new CircleF(new PointF(box.center.X, box.center.Y), 3), new Bgr(200, 125, 75), 2); currentFrame.Draw(bContour, new Bgr(System.Drawing.Color.LimeGreen), 2); extractContourInfo(bContour, 5, currentFrame); findFingerTips(bContour, 5); drawTips(tipPts, foldPts); } imageBoxSkin.Image = skin; imageBoxFrameGrabber.Image = currentFrame; } } } }
// Extrait la "coque" du contour et les verticles afin de pouvoir calculer plus tard le nombre de doigts détectés // Ce code vient en partie de ce projet : https://www.youtube.com/watch?v=Fjj9gqTCTfc public void ExtractHull() { try { // Récupère la "coque" du plus grand contour ainsi que le rectangle qui l'englobe hull = biggestContour.GetConvexHull(Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE); box = biggestContour.GetMinAreaRect(); // Récupère les vertexes de la box PointF[] points = box.GetVertices(); // On va créer un tableau de "Point" avec tous les points trouvés par "GetVerticles" Point[] ps = new Point[points.Length]; for (int i = 0; i < points.Length; i++) { ps[i] = new Point((int)points[i].X, (int)points[i].Y); } // Dessine la "coque" (qui entoure tous les verticles) en rouge sur l'image traitée imgProc.DrawPolyline(hull.ToArray(), true, new Bgr(Color.Red), 2); // Dessine un cercle bleu au centre de la box imgProc.Draw(new CircleF(new PointF(box.center.X, box.center.Y), 5), new Bgr(Color.Blue), 2); // Va filtrer les points de la "coque" afin de ne garder que ceux qui sont vraiment utiles filteredHull = new Seq<Point>(hullStorage); for (int i = 0; i < hull.Total; i++) { if (Math.Sqrt(Math.Pow(hull[i].X - hull[i + 1].X, 2) + Math.Pow(hull[i].Y - hull[i + 1].Y, 2)) > box.size.Width / 10) { filteredHull.Push(hull[i]); } } defects = biggestContour.GetConvexityDefacts(hullStorage, Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE); defectArray = defects.ToArray(); } catch(Exception ex) { return; } }
public static extern int cvCamShift( IntPtr probImage, Rectangle window, MCvTermCriteria criteria, out MCvConnectedComp comp, out MCvBox2D box);
//::::::::::::Method to calculate the convex hull::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: public List<object> HandConvexHull(Image<Gray, Byte> frame, Rectangle Roi) { List<object> ListReturn = new List<object>(); Image<Gray, Byte> BinaryImage; //PointF centerPalm; BinaryImage = frame.Copy(Roi); BinaryImage = openingOperation(BinaryImage); BinaryImage = closeOperation(BinaryImage); BinaryImage.Save(path1 + numFrames.ToString() + ".png"); BinaryImage = binaryNiBlack(BinaryImage); //naryImage = binaryThresholdNiBlack(BinaryImage); // using (MemStorage storage = new MemStorage()) { Double result1 = 0; Double result2 = 0; Contour<System.Drawing.Point> contours = BinaryImage.FindContours(Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_LIST, storage); Contour<System.Drawing.Point> biggestContour = null; while (contours != null) { result1 = contours.Area; if (result1 > result2) { result2 = result1; biggestContour = contours; } contours = contours.HNext; } if (biggestContour != null) { Contour<System.Drawing.Point> concurrentContour = biggestContour.ApproxPoly(biggestContour.Perimeter * 0.0025, storage); biggestContour = concurrentContour; Hull = biggestContour.GetConvexHull(Emgu.CV.CvEnum.ORIENTATION.CV_COUNTER_CLOCKWISE); defects = biggestContour.GetConvexityDefacts(storage, Emgu.CV.CvEnum.ORIENTATION.CV_COUNTER_CLOCKWISE); defectsArray = defects.ToArray(); box = biggestContour.GetMinAreaRect(); points = box.GetVertices(); contourArea = result2; contourPerimeter = biggestContour.Perimeter; convexHullArea = Hull.Area; convexHullPerimeter = Hull.Perimeter; BinaryImage.Draw(Hull, new Gray(155), 1); //ABinaryImage.Save(path1 + "ConvexHull_" + numFrames.ToString() + ".png"); ListReturn = GetFingersHand(BinaryImage); ListReturn.Add(contourPerimeter); ListReturn.Add(contourArea); ListReturn.Add(convexHullPerimeter); ListReturn.Add(convexHullArea); } } numFrames++; return ListReturn; }//end HandConvexHull
//::::::::::::Method to calculate the convex hull::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: public List<object> HandConvexHull(Image<Gray, Byte> frame, Rectangle Roi) { List<object> ListReturn = new List<object>(); Image<Gray, Byte> BinaryImage; Image<Gray,Byte> frameImagePtr; BinaryImage = frame.Copy(Roi); //BinaryImage.Save(path1 + numFrames.ToString() + ".png"); //Binarization using Otsu algortihm frameImagePtr= BinaryImage; IntPtr framePtr = frameImagePtr.Ptr; IntPtr binaryPrt = BinaryImage.Ptr; CvInvoke.cvThreshold(framePtr, binaryPrt, 0, 255, Emgu.CV.CvEnum.THRESH.CV_THRESH_OTSU); BinaryImage.Save(path1 + numFrames.ToString() + "B_Otsu.png"); //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: BinaryImage = openingOperation(BinaryImage); BinaryImage = closeOperation(BinaryImage); //BinaryImage.Save(path1 + numFrames.ToString() + "B_OC.png"); using (MemStorage storage = new MemStorage()) { Double result1 = 0; Double result2 = 0; Contour<System.Drawing.Point> contours = BinaryImage.FindContours(Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_LIST, storage); Contour<System.Drawing.Point> biggestContour = null; while (contours != null) { result1 = contours.Area; if (result1 > result2) { result2 = result1; biggestContour = contours; } contours = contours.HNext; } if (biggestContour != null) { Contour<System.Drawing.Point> concurrentContour = biggestContour.ApproxPoly(biggestContour.Perimeter * 0.0025, storage); biggestContour = concurrentContour; Hull = biggestContour.GetConvexHull(Emgu.CV.CvEnum.ORIENTATION.CV_COUNTER_CLOCKWISE); defects = biggestContour.GetConvexityDefacts(storage, Emgu.CV.CvEnum.ORIENTATION.CV_COUNTER_CLOCKWISE); defectsArray = defects.ToArray(); box = biggestContour.GetMinAreaRect(); points = box.GetVertices(); CircleF centerBoxDraw = new CircleF(box.center, 4f); contourArea = result2; contourPerimeter = biggestContour.Perimeter; convexHullArea = Hull.Area; convexHullPerimeter = Hull.Perimeter; BinaryImage.Draw(Hull, new Gray(155), 1); BinaryImage.Draw(box, new Gray(100), 1); BinaryImage.Draw(centerBoxDraw, new Gray(200), 1); BinaryImage.Save(path1 + "ConvexHull_" + numFrames.ToString() + ".png"); ListReturn = GetFingers(BinaryImage); //::::::Old features //ListReturn.Add(contourPerimeter); //ListReturn.Add(contourArea); //ListReturn.Add(convexHullPerimeter); //ListReturn.Add(convexHullArea); } } numFrames++; return ListReturn; }//end HandConvexHull
private bool detectAndDrawHand(Contour<Point> hand) { bool realHand = false; double first = 0; Contour<Point> currentContour = hand.ApproxPoly(hand.Perimeter * 0.0025, contourStorage); hull = currentContour.GetConvexHull(Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE); box = currentContour.GetMinAreaRect(); //Calculate the center of the hand PointF center = new PointF(box.center.X, box.center.Y); float centerX = box.center.X; float centerY = box.center.Y; //Find all defects in the contour defects = currentContour.GetConvexityDefacts(contourStorage, Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE); defectArray = defects.ToArray(); if (defects != null) { List<double> tipDistance = new List<double>(); for (int i = 0; i < defects.Total; i++) { float sX = defectArray[i].StartPoint.X; float sY = defectArray[i].StartPoint.Y; double distance = (Math.Pow(sX - centerX, 2) + Math.Pow(sY - centerY, 2)); tipDistance.Add(distance); } for (int i = 0; i < tipDistance.Count(); i++) { if (i == 0) { first = tipDistance.ElementAt(i); } else if (i > 0) { double difference = first - tipDistance.ElementAt(i); if ((difference < 10) && (tipDistance.ElementAt(i) > -10)) { realHand = true; } } } if (realHand == true) { //Draw hand drawHand(currentContour, center); //Analysis hand gesture string gesture = analysisHandGesture(center); if ((gesture.Equals("Left Palm")) || (gesture.Equals("Left Fist")) || (gesture.Equals("Right Palm")) || (gesture.Equals("Right Fist"))) { PointF newCenter = new PointF(centerX, centerY); handMotionList.Add(skin); motionPoints.Add(newCenter); gestures.Add(gesture); runTimes.Add(time / 1000); } } } return realHand; }
public Form1() { InitializeComponent(); faceHaar = new CascadeClassifier(@"..\..\haar\haarcascade_frontalface.xml"); hsv_min = new Hsv(0, 45, 0); hsv_max = new Hsv(20, 255, 255); //YCrCb_min = new Ycc(0, 131, 80); YCrCb_min = new Ycc(0, 140, 0); YCrCb_max = new Ycc(255, 185, 135); currentFrameList = new List<Image<Bgr, byte>>(); grayFrameList = new List<Image<Gray, byte>>(); handMotionList = new List<Image<Gray, byte>>(); contourStorage = new MemStorage(); box = new MCvBox2D(); fingers = new List<LineSegment2D>(); motionPoints = new List<PointF>(); gestures = new List<string>(); runTimes = new List<long>(); faceEmotions = new List<string>(); }
/// <summary> /// Create an ellipse from the specific MCvBox2D /// </summary> /// <param name="box2d">The MCvBox2D representation of this ellipse</param> public Ellipse(MCvBox2D box2d) { _box2D = box2d; }
private void TrackBlobs() { try { using (MemStorage stor = new MemStorage()) { //Find contours with no holes try CV_RETR_EXTERNAL to find holes Contour<System.Drawing.Point> contours = thresholdedImage.FindContours( Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_EXTERNAL, stor); int contourCounter = 0; for (int i = 0; contours != null; contours = contours.HNext) { i++; if ((contours.Area > Math.Pow(sliderMinSize.Value, 2)) && (contours.Area < Math.Pow(sliderMaxSize.Value, 2))) { box = contours.GetMinAreaRect(); openCVImg.Draw(box, new Bgr(System.Drawing.Color.Red), 2); thresholdedImage.Draw(box, new Gray(255), 2); blobCount++; if (reverseX.IsChecked == true) { reverseXMult = -1; } else { reverseXMult = 1; } if (reverseY.IsChecked == true) { reverseYMult = -1; } else { reverseYMult = 1; } var x = box.center.X/sensor.ColorStream.FrameWidth; var y = box.center.Y/sensor.ColorStream.FrameHeight; xPos = (reverseXMult * (x - (float)centerXOffset.Value) + (reverseXMult * (float)xOffset.Value * x)) * (float)xMultiplier.Value ; yPos = (reverseYMult * (y - (float)centerYOffset.Value) + (reverseYMult * (float)yOffset.Value * y)) * (float)yMultiplier.Value; /* calculating moving avarage */ var smoothFactor = (float)smoothingFactor.Value / 100; oldX = (1 - smoothFactor) * xPos + oldX * smoothFactor; oldY = (1 - smoothFactor) * yPos + oldY * smoothFactor; // send osc data try { SendOsc(oldX, oldY); } catch (Exception ex) { Console.WriteLine("Failed to send osc: "); Console.WriteLine(ex); } } } } } catch { Console.WriteLine("Failed to do tracking"); } }