// Process image searching for glyphs and highlighting them public List <ExtractedGlyphData> ProcessImage(Bitmap bitmap) { List <ExtractedGlyphData> glyphs = new List <ExtractedGlyphData>( ); lock ( sync ) { glyphTracker.ImageSize = bitmap.Size; // get list of recognized glyphs glyphs.AddRange(recognizer.FindGlyphs(bitmap)); List <int> glyphIDs = glyphTracker.TrackGlyphs(glyphs); if (glyphs.Count > 0) { if ((visualizationType == VisualizationType.BorderOnly) || (visualizationType == VisualizationType.Name)) { Graphics g = Graphics.FromImage(bitmap); int i = 0; // highlight each found glyph foreach (ExtractedGlyphData glyphData in glyphs) { List <IntPoint> glyphPoints = (glyphData.RecognizedGlyph == null) ? glyphData.Quadrilateral : glyphData.RecognizedQuadrilateral; Pen pen = new Pen(((glyphData.RecognizedGlyph == null) || (glyphData.RecognizedGlyph.UserData == null)) ? Color.Red : ((GlyphVisualizationData)glyphData.RecognizedGlyph.UserData).Color, 3); // highlight border g.DrawPolygon(pen, ToPointsArray(glyphPoints)); string glyphTitle = null; // prepare glyph's title if ((visualizationType == VisualizationType.Name) && (glyphData.RecognizedGlyph != null)) { glyphTitle = string.Format("{0}: {1}", glyphIDs[i], glyphData.RecognizedGlyph.Name); } else { glyphTitle = string.Format("Tracking ID: {0}", glyphIDs[i]); } // show glyph's title if (!string.IsNullOrEmpty(glyphTitle)) { // get glyph's center point IntPoint minXY, maxXY; PointsCloud.GetBoundingRectangle(glyphPoints, out minXY, out maxXY); IntPoint center = (minXY + maxXY) / 2; // glyph's name size SizeF nameSize = g.MeasureString(glyphTitle, defaultFont); // paint the name Brush brush = new SolidBrush(pen.Color); g.DrawString(glyphTitle, defaultFont, brush, new System.Drawing.Point(center.X - (int)nameSize.Width / 2, center.Y - (int)nameSize.Height / 2)); brush.Dispose( ); } i++; pen.Dispose( ); } } else if (visualizationType == VisualizationType.Image) { // lock image for further processing BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat); UnmanagedImage unmanagedImage = new UnmanagedImage(bitmapData); // highlight each found glyph foreach (ExtractedGlyphData glyphData in glyphs) { if ((glyphData.RecognizedGlyph != null) && (glyphData.RecognizedGlyph.UserData != null)) { GlyphVisualizationData visualization = (GlyphVisualizationData)glyphData.RecognizedGlyph.UserData; if (visualization.ImageName != null) { // get image associated with the glyph Bitmap glyphImage = EmbeddedImageCollection.Instance.GetImage(visualization.ImageName); if (glyphImage != null) { // put glyph's image onto the glyph using quadrilateral transformation quadrilateralTransformation.SourceImage = glyphImage; quadrilateralTransformation.DestinationQuadrilateral = glyphData.RecognizedQuadrilateral; quadrilateralTransformation.ApplyInPlace(unmanagedImage); } } } } bitmap.UnlockBits(bitmapData); } } } return(glyphs); }
private void ProcessImage(Bitmap bitmap) { // lock image BitmapData bitmapData = bitmap.LockBits( new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat); // step 1 - turn background to black ColorFiltering colorFilter = new ColorFiltering(); colorFilter.Red = new IntRange(Properties.Settings.Default.camFilterRed1, Properties.Settings.Default.camFilterRed2); colorFilter.Green = new IntRange(Properties.Settings.Default.camFilterGreen1, Properties.Settings.Default.camFilterGreen2); colorFilter.Blue = new IntRange(Properties.Settings.Default.camFilterBlue1, Properties.Settings.Default.camFilterBlue2); colorFilter.FillOutsideRange = Properties.Settings.Default.camFilterOutside; colorFilter.ApplyInPlace(bitmapData); // step 2 - locating objects BlobCounter blobCounter = new BlobCounter(); blobCounter.FilterBlobs = true; blobCounter.MinHeight = (int)Properties.Settings.Default.camShapeSizeMin * (int)cameraZoom; blobCounter.MinWidth = (int)Properties.Settings.Default.camShapeSizeMin * (int)cameraZoom; blobCounter.MaxHeight = (int)Properties.Settings.Default.camShapeSizeMax * (int)cameraZoom; blobCounter.MaxWidth = (int)Properties.Settings.Default.camShapeSizeMax * (int)cameraZoom; blobCounter.ProcessImage(bitmapData); Blob[] blobs = blobCounter.GetObjectsInformation(); bitmap.UnlockBits(bitmapData); // step 3 - check objects' type and highlight SimpleShapeChecker shapeChecker = new SimpleShapeChecker(); shapeChecker.MinAcceptableDistortion = (float)Properties.Settings.Default.camShapeDist; shapeChecker.RelativeDistortionLimit = (float)Properties.Settings.Default.camShapeDistMax; Graphics g = Graphics.FromImage(bitmap); Pen yellowPen = new Pen(Color.Yellow, 5); // circles Pen redPen = new Pen(Color.Red, 10); // circles Pen greenPen = new Pen(Color.Green, 5); // known triangle double lowestDistance = xmid; double distance; shapeFound = false; DoublePoint center; double shapeRadius = 1; for (int i = 0, n = blobs.Length; i < n; i++) { List <IntPoint> edgePoints = blobCounter.GetBlobsEdgePoints(blobs[i]); double radius; // is circle ? // g.DrawPolygon(greenPen, ToPointsArray(edgePoints)); if (Properties.Settings.Default.camShapeCircle && shapeChecker.IsCircle(edgePoints, out center, out radius)) { shapeFound = true; distance = center.DistanceTo(picCenter); g.DrawEllipse(yellowPen, (float)(shapeCenter.X - shapeRadius), (float)(shapeCenter.Y - shapeRadius), (float)(shapeRadius * 2), (float)(shapeRadius * 2)); if (lowestDistance > Math.Abs(distance)) { lowestDistance = Math.Abs(distance); shapeCenter = center; shapeRadius = radius; } } List <IntPoint> corners; if (Properties.Settings.Default.camShapeRect && shapeChecker.IsQuadrilateral(edgePoints, out corners)) //.IsConvexPolygon { IntPoint minxy, maxxy, centxy; shapeFound = true; PolygonSubType subType = shapeChecker.CheckPolygonSubType(corners); g.DrawPolygon(yellowPen, ToPointsArray(corners)); PointsCloud.GetBoundingRectangle(corners, out minxy, out maxxy); centxy = (minxy + maxxy) / 2; distance = picCenter.DistanceTo(centxy);// PointsCloud.GetCenterOfGravity(corners)); if (lowestDistance > Math.Abs(distance)) { lowestDistance = Math.Abs(distance); shapeCenter = centxy; // PointsCloud.GetCenterOfGravity(corners); shapeRadius = maxxy.DistanceTo(minxy) / 2; // 50; } } } if (shapeFound) { g.DrawEllipse(redPen, (float)(shapeCenter.X - shapeRadius * 1.2), (float)(shapeCenter.Y - shapeRadius * 1.2), (float)(shapeRadius * 2.4), (float)(shapeRadius * 2.4)); } yellowPen.Dispose(); redPen.Dispose(); greenPen.Dispose(); g.Dispose(); // put new image to clipboard // Clipboard.SetDataObject(bitmap); // and to picture box pictureBoxVideo.BackgroundImage = bitmap; //UpdatePictureBoxPosition(); }
/// <summary> /// Find corners of quadrilateral/triangular area in the specified image. /// </summary> /// /// <param name="image">Source image to search quadrilateral for.</param> /// /// <returns>Returns a list of points, which are corners of the quadrilateral/triangular area found /// in the specified image. The first point in the list is the point with lowest /// X coordinate (and with lowest Y if there are several points with the same X value). /// Points are in clockwise order (screen coordinates system).</returns> /// /// <exception cref="UnsupportedImageFormatException">Unsupported pixel format of the source image.</exception> /// public List <IntPoint> ProcessImage(UnmanagedImage image) { CheckPixelFormat(image.PixelFormat); // get source image size int width = image.Width; int height = image.Height; // collection of points List <IntPoint> points = new List <IntPoint>( ); // collect edge points unsafe { byte *src = (byte *)image.ImageData.ToPointer( ); int stride = image.Stride; bool lineIsEmpty; if (image.PixelFormat == PixelFormat.Format8bppIndexed) { // for each row for (int y = 0; y < height; y++) { lineIsEmpty = true; // scan from left to right for (int x = 0; x < width; x++) { if (src[x] != 0) { points.Add(new IntPoint(x, y)); lineIsEmpty = false; break; } } if (!lineIsEmpty) { // scan from right to left for (int x = width - 1; x >= 0; x--) { if (src[x] != 0) { points.Add(new IntPoint(x, y)); break; } } } src += stride; } } else { // 24 or 32 bpp color image int pixelSize = System.Drawing.Image.GetPixelFormatSize(image.PixelFormat) / 8; byte *ptr = null; // for each row for (int y = 0; y < height; y++) { lineIsEmpty = true; // scan from left to right ptr = src; for (int x = 0; x < width; x++, ptr += pixelSize) { if ((ptr[RGB.R] != 0) || (ptr[RGB.G] != 0) || (ptr[RGB.B] != 0)) { points.Add(new IntPoint(x, y)); lineIsEmpty = false; break; } } if (!lineIsEmpty) { // scan from right to left ptr = src + width * pixelSize - pixelSize; for (int x = width - 1; x >= 0; x--, ptr -= pixelSize) { if ((ptr[RGB.R] != 0) || (ptr[RGB.G] != 0) || (ptr[RGB.B] != 0)) { points.Add(new IntPoint(x, y)); break; } } } src += stride; } } } return(PointsCloud.FindQuadrilateralCorners(points)); }
// Process both images transforming source image into quadrilateral in destination image private unsafe void ProcessFilter(UnmanagedImage dstImage, UnmanagedImage srcImage) { // get source and destination images size int srcWidth = srcImage.Width; int srcHeight = srcImage.Height; int dstWidth = dstImage.Width; int dstHeight = dstImage.Height; int pixelSize = Image.GetPixelFormatSize(srcImage.PixelFormat) / 8; int srcStride = srcImage.Stride; int dstStride = dstImage.Stride; // get bounding rectangle of the quadrilateral IntPoint minXY, maxXY; PointsCloud.GetBoundingRectangle(destinationQuadrilateral, out minXY, out maxXY); // make sure the rectangle is inside of destination image if ((maxXY.X < 0) || (maxXY.Y < 0) || (minXY.X >= dstWidth) || (minXY.Y >= dstHeight)) { return; // nothing to do, since quadrilateral is completely outside } // correct rectangle if required if (minXY.X < 0) { minXY.X = 0; } if (minXY.Y < 0) { minXY.Y = 0; } if (maxXY.X >= dstWidth) { maxXY.X = dstWidth - 1; } if (maxXY.Y >= dstHeight) { maxXY.Y = dstHeight - 1; } int startX = minXY.X; int startY = minXY.Y; int stopX = maxXY.X + 1; int stopY = maxXY.Y + 1; int offset = dstStride - (stopX - startX) * pixelSize; // calculate tranformation matrix List <IntPoint> srcRect = new List <IntPoint>( ); srcRect.Add(new IntPoint(0, 0)); srcRect.Add(new IntPoint(srcWidth - 1, 0)); srcRect.Add(new IntPoint(srcWidth - 1, srcHeight - 1)); srcRect.Add(new IntPoint(0, srcHeight - 1)); double[,] matrix = QuadTransformationCalcs.MapQuadToQuad(destinationQuadrilateral, srcRect); // do the job byte *ptr = (byte *)dstImage.ImageData.ToPointer( ); byte *baseSrc = (byte *)srcImage.ImageData.ToPointer( ); // allign pointer to the first pixel to process ptr += (startY * dstStride + startX * pixelSize); if (!useInterpolation) { byte *p; // for each row for (int y = startY; y < stopY; y++) { // for each pixel for (int x = startX; x < stopX; x++) { double factor = matrix[2, 0] * x + matrix[2, 1] * y + matrix[2, 2]; double srcX = (matrix[0, 0] * x + matrix[0, 1] * y + matrix[0, 2]) / factor; double srcY = (matrix[1, 0] * x + matrix[1, 1] * y + matrix[1, 2]) / factor; if ((srcX >= 0) && (srcY >= 0) && (srcX < srcWidth) && (srcY < srcHeight)) { // get pointer to the pixel in the source image p = baseSrc + (int)srcY * srcStride + (int)srcX * pixelSize; // copy pixel's values for (int i = 0; i < pixelSize; i++, ptr++, p++) { *ptr = *p; } } else { // skip the pixel ptr += pixelSize; } } ptr += offset; } } else { int srcWidthM1 = srcWidth - 1; int srcHeightM1 = srcHeight - 1; // coordinates of source points double dx1, dy1, dx2, dy2; int sx1, sy1, sx2, sy2; // temporary pointers byte *p1, p2, p3, p4; // for each row for (int y = startY; y < stopY; y++) { // for each pixel for (int x = startX; x < stopX; x++) { double factor = matrix[2, 0] * x + matrix[2, 1] * y + matrix[2, 2]; double srcX = (matrix[0, 0] * x + matrix[0, 1] * y + matrix[0, 2]) / factor; double srcY = (matrix[1, 0] * x + matrix[1, 1] * y + matrix[1, 2]) / factor; if ((srcX >= 0) && (srcY >= 0) && (srcX < srcWidth) && (srcY < srcHeight)) { sx1 = (int)srcX; sx2 = (sx1 == srcWidthM1) ? sx1 : sx1 + 1; dx1 = srcX - sx1; dx2 = 1.0 - dx1; sy1 = (int)srcY; sy2 = (sy1 == srcHeightM1) ? sy1 : sy1 + 1; dy1 = srcY - sy1; dy2 = 1.0 - dy1; // get four points p1 = p2 = baseSrc + sy1 * srcStride; p1 += sx1 * pixelSize; p2 += sx2 * pixelSize; p3 = p4 = baseSrc + sy2 * srcStride; p3 += sx1 * pixelSize; p4 += sx2 * pixelSize; // interpolate using 4 points for (int i = 0; i < pixelSize; i++, ptr++, p1++, p2++, p3++, p4++) { *ptr = (byte)( dy2 * (dx2 * (*p1) + dx1 * (*p2)) + dy1 * (dx2 * (*p3) + dx1 * (*p4))); } } else { // skip the pixel ptr += pixelSize; } } ptr += offset; } } }
public unsafe List <IntPoint> ProcessImage(UnmanagedImage image) { CheckPixelFormat(image.PixelFormat); int width = image.Width; int height = image.Height; List <IntPoint> list = new List <IntPoint>(); byte * ptr = (byte *)image.ImageData.ToPointer(); int stride = image.Stride; if (image.PixelFormat == PixelFormat.Format8bppIndexed) { for (int i = 0; i < height; i++) { bool flag = true; for (int j = 0; j < width; j++) { if (ptr[j] != 0) { list.Add(new IntPoint(j, i)); flag = false; break; } } if (!flag) { for (int num = width - 1; num >= 0; num--) { if (ptr[num] != 0) { list.Add(new IntPoint(num, i)); break; } } } ptr += stride; } } else { int num2 = System.Drawing.Image.GetPixelFormatSize(image.PixelFormat) / 8; byte *ptr2 = null; for (int k = 0; k < height; k++) { bool flag = true; ptr2 = ptr; int num3 = 0; while (num3 < width) { if (ptr2[2] != 0 || ptr2[1] != 0 || *ptr2 != 0) { list.Add(new IntPoint(num3, k)); flag = false; break; } num3++; ptr2 += num2; } if (!flag) { ptr2 = ptr + (long)width * (long)num2 - num2; int num4 = width - 1; while (num4 >= 0) { if (ptr2[2] != 0 || ptr2[1] != 0 || *ptr2 != 0) { list.Add(new IntPoint(num4, k)); break; } num4--; ptr2 -= num2; } } ptr += stride; } } return(PointsCloud.FindQuadrilateralCorners(list)); }
public unsafe List <IntPoint> ProcessImage(UnmanagedImage image) { bool flag; this.CheckPixelFormat(image.PixelFormat); int width = image.Width; int height = image.Height; List <IntPoint> list = new List <IntPoint>(); byte * numPtr = (byte *)image.ImageData.ToPointer(); int stride = image.Stride; if (image.PixelFormat == PixelFormat.Format8bppIndexed) { for (int i = 0; i < height; i++) { flag = true; for (int j = 0; j < width; j++) { if (numPtr[j] != 0) { list.Add(new IntPoint(j, i)); flag = false; break; } } if (!flag) { for (int k = width - 1; k >= 0; k--) { if (numPtr[k] != 0) { list.Add(new IntPoint(k, i)); break; } } } numPtr += stride; } } else { int num7 = Image.GetPixelFormatSize(image.PixelFormat) / 8; byte *numPtr2 = null; for (int m = 0; m < height; m++) { flag = true; numPtr2 = numPtr; int x = 0; while (x < width) { if (((numPtr2[2] != 0) || (numPtr2[1] != 0)) || (numPtr2[0] != 0)) { list.Add(new IntPoint(x, m)); flag = false; break; } x++; numPtr2 += num7; } if (!flag) { numPtr2 = (numPtr + (width * num7)) - num7; int num10 = width - 1; while (num10 >= 0) { if (((numPtr2[2] != 0) || (numPtr2[1] != 0)) || (numPtr2[0] != 0)) { list.Add(new IntPoint(num10, m)); break; } num10--; numPtr2 -= num7; } } numPtr += stride; } } return(PointsCloud.FindQuadrilateralCorners(list)); }
private async Task CalibThread(FrameReadyEventArgs e) { Debug.WriteLine("Calibrating " + _calibrationStep + " "); e.Frame.Bitmap.Save(@"C:\temp\daforge\src\img" + (_calibrationStep < 10?"0":"") + _calibrationStep + "-" + _errors + ".jpg", ImageFormat.Jpeg); if (_errors > 100) { //calibration not possible return; } if (_calibrationStep > CalibrationFrames) { // A concurrency problem, do nothing } if (_calibrationStep == CalibrationFrames) { _cc.FrameReady -= BaseCalibration; _calibrationStep++; //Grid.Calculate(); _vs.Close(); CalibrationCompleted(this, new EventArgs()); } else { if (_calibrationStep > 2) { // analyse diffimage _vs.Clear(); var img = diffFilter.Apply(e.Frame.Bitmap); var mf = new GaussianBlur(0.6, 5); var gf = Grayscale.CommonAlgorithms.BT709; #if DEBUG actImg = (Bitmap)img.Clone(); #endif img = gf.Apply(img); var stats = new ImageStatistics(img); mf.ApplyInPlace(img); mf = new GaussianBlur(0.7, 7); mf.ApplyInPlace(img); var tf = new Threshold((int)(stats.GrayWithoutBlack.Mean + stats.GrayWithoutBlack.StdDev * 2.0)); tf.ApplyInPlace(img); img.Save(@"C:\temp\daforge\diff\img" + _calibrationStep + "-" + _errors + ".jpg", ImageFormat.MemoryBmp); var blobCounter = new BlobCounter { ObjectsOrder = ObjectsOrder.YX, MaxHeight = 30, MinHeight = 10, MaxWidth = 30, MinWidth = 10, FilterBlobs = true, CoupledSizeFiltering = false }; blobCounter.ProcessImage(img); if (ProcessBlobs(blobCounter)) { _calibrationStep++; } else { _errors++; } #if DEBUG actImg.Save(@"C:\temp\daforge\squares\img" + _calibrationStep + ".jpg", ImageFormat.Jpeg); #endif DrawMarkers(); } else { switch (_calibrationStep) { case 2: var bm = UnmanagedImage.FromManagedImage(e.Frame.Bitmap); //diffFilter.OverlayImage.Save(@"C:\temp\daforge\diff\src" + _errors + ".jpg", ImageFormat.Jpeg); bm = diffFilter.Apply(bm); var gf = new GaussianBlur(0.8, 5); gf.ApplyInPlace(bm); var cf = new ColorFiltering(new IntRange(10, 255), new IntRange(20, 255), new IntRange(20, 255)); cf.ApplyInPlace(bm); var blobCounter = new BlobCounter { ObjectsOrder = ObjectsOrder.Size, MinHeight = 200, MinWidth = 300, //BackgroundThreshold = Color.FromArgb(255, 20, 20, 50), //CoupledSizeFiltering = false, FilterBlobs = true }; blobCounter.ProcessImage(bm); bm.ToManagedImage() .Save(@"C:\temp\daforge\diff\img" + _calibrationStep + "-" + _errors + ".jpg", ImageFormat.Jpeg); var blobs = blobCounter.GetObjectsInformation(); if (blobs.Any()) { int i = 0; List <IntPoint> corners; do { corners = PointsCloud.FindQuadrilateralCorners(blobCounter.GetBlobsEdgePoints(blobs[i++])); } while (corners.Count != 4); RecursiveAForgeCalibrator.GridBlobs.InPlaceSort(corners); Grid.TopLeft = new Point(corners[0].X, corners[0].Y); Grid.TopRight = new Point(corners[1].X, corners[1].Y); Grid.BottomLeft = new Point(corners[2].X, corners[2].Y); Grid.BottomRight = new Point(corners[3].X, corners[3].Y); if (Grid.TopLeft.X > 10 && Grid.TopRight.X < _vs.Width - 5 && Grid.BottomLeft.X > 5 && Grid.BottomRight.X < _vs.Width - 5 && Grid.TopLeft.Y > 10 && Grid.TopRight.Y > 5 && Grid.BottomLeft.Y < _vs.Height - 5 && Grid.BottomRight.Y < _vs.Height - 5 && Grid.TopLeft.X < Grid.BottomRight.X && Grid.BottomLeft.X < Grid.TopRight.X && Grid.BottomLeft.X < Grid.BottomRight.X && Grid.TopLeft.Y < Grid.BottomLeft.Y && Grid.TopLeft.Y < Grid.BottomRight.Y && Grid.TopRight.Y < Grid.BottomLeft.Y && Grid.TopRight.Y < Grid.BottomRight.Y) { _calibrationStep++; _vs.Clear(); Grid.AddPoint(new Point(), new Point(corners[0].X, corners[0].Y)); Grid.AddPoint(new Point(0, _vs.Height), new Point(corners[1].X, corners[1].Y)); Grid.AddPoint(new Point(_vs.Width, 0), new Point(corners[2].X, corners[2].Y)); Grid.AddPoint(new Point(_vs.Width, _vs.Height), new Point(corners[3].X, corners[3].Y)); DrawMarkers(); } else { _calibrationStep = 0; _errors++; } } else { _calibrationStep = 0; _errors++; } break; case 1: diffFilter.OverlayImage = e.Frame.Bitmap; //diffFilter.OverlayImage.Save(@"C:\temp\daforge\diff\srcf" + _errors + ".jpg", ImageFormat.Jpeg); //_vs.AddRect(0, 0, (int) _vs.Width, (int) _vs.Height, Color.FromArgb(255, 255, 255, 255)); _vs.Clear(); DrawInverted(0, 0, _vs.Width, _vs.Height); _vs.Draw(); _calibrationStep++; break; case 0: Grid = new Grid(e.Frame.Bitmap.Width, e.Frame.Bitmap.Height); Grid.ScreenSize = new Rectangle(0, 0, _vs.Width, _vs.Height); var thread = new Thread(() => { _vs.Show(); }); thread.SetApartmentState(ApartmentState.STA); thread.Start(); thread.Join(); DrawBackground(); _vs.Draw(); _calibrationStep++; break; } } } Debug.WriteLine("Releasing"); await Task.Delay(500); _sem.Release(); }
// Set image to display by the control public int SetImage(Bitmap image) { leftEdges.Clear(); rightEdges.Clear(); topEdges.Clear(); bottomEdges.Clear(); hulls.Clear(); quadrilaterals.Clear(); this.image = global::AForge.Imaging.Image.Clone(image, PixelFormat.Format24bppRgb); imageWidth = this.image.PixelWidth; imageHeight = this.image.PixelHeight; #if !SILVERLIGHT && !UNITY_WEBPLAYER selectedBlobID = 0; blobCounter.ProcessImage(this.image); blobs = blobCounter.GetObjectsInformation(); GrahamConvexHull grahamScan = new GrahamConvexHull(); foreach (Blob blob in blobs) { List <IntPoint> leftEdge = new List <IntPoint>(); List <IntPoint> rightEdge = new List <IntPoint>(); List <IntPoint> topEdge = new List <IntPoint>(); List <IntPoint> bottomEdge = new List <IntPoint>(); // collect edge points blobCounter.GetBlobsLeftAndRightEdges(blob, out leftEdge, out rightEdge); blobCounter.GetBlobsTopAndBottomEdges(blob, out topEdge, out bottomEdge); leftEdges.Add(blob.ID, leftEdge); rightEdges.Add(blob.ID, rightEdge); topEdges.Add(blob.ID, topEdge); bottomEdges.Add(blob.ID, bottomEdge); // find convex hull List <IntPoint> edgePoints = new List <IntPoint>(); edgePoints.AddRange(leftEdge); edgePoints.AddRange(rightEdge); List <IntPoint> hull = grahamScan.FindHull(edgePoints); hulls.Add(blob.ID, hull); List <IntPoint> quadrilateral = null; // find quadrilateral if (hull.Count < 4) { quadrilateral = new List <IntPoint>(hull); } else { quadrilateral = PointsCloud.FindQuadrilateralCorners(hull); } quadrilaterals.Add(blob.ID, quadrilateral); // shift all points for vizualization IntPoint shift = new IntPoint(1, 1); PointsCloud.Shift(leftEdge, shift); PointsCloud.Shift(rightEdge, shift); PointsCloud.Shift(topEdge, shift); PointsCloud.Shift(bottomEdge, shift); PointsCloud.Shift(hull, shift); PointsCloud.Shift(quadrilateral, shift); } #endif UpdateDrawOffset(); Refresh();// Invalidate(); return (#if SILVERLIGHT || UNITY_WEBPLAYER 0); #else blobs.Length; #endif }
/// <summary> /// Given the Window UI Screenshot, tries to detect all the buttons in it and returns all of them. /// </summary> /// <param name="res">Where to put candidate controls</param> /// <param name="bitmap">Bitmap containing the pixels of the UI to analyze</param> /// <param name="shouldInvert">If true, the bitmap will be inverted before analysis</param> /// <param name="minWidth">Minimum width of patterns to recognize</param> /// <param name="minHeight">Minimum height of patterns to recognize</param> /// <returns>void</returns> private void ScanWithVisualRecognition(ref CandidateSet res, Bitmap original, bool shouldInvert, int minWidth, int minHeight, Window w, IRankingPolicy policy) { // Setup the Blob counter BlobCounter blobCounter = new BlobCounter(); blobCounter.BackgroundThreshold = Color.FromArgb(10, 10, 10); blobCounter.FilterBlobs = true; blobCounter.CoupledSizeFiltering = false; blobCounter.MinHeight = minHeight; blobCounter.MinWidth = minWidth; List <Blob> blobs = new List <Blob>(); // Button scanning // Apply the grayscale. This is needed for AForge's filters using (Bitmap grey_scaled = Grayscale.CommonAlgorithms.BT709.Apply(original)) { // Invert the image if requested if (shouldInvert) { Invert invert = new Invert(); invert.ApplyInPlace(grey_scaled); } //grey_scaled.Save("C:\\users\\alberto geniola\\desktop\\dbg\\gray_scaled_" + toinvert + ".bmp"); using (Bitmap t1 = new Threshold(64).Apply(grey_scaled)) { using (var tmp = new Bitmap(t1.Width, t1.Height)) { using (Graphics g = Graphics.FromImage(tmp)) { g.DrawImage(t1, 0, 0); } // The blob counter will analyze the bitmap looking for shapes blobCounter.ProcessImage(tmp); var tmparr = blobCounter.GetObjectsInformation(); blobs.AddRange(tmparr); } } using (Bitmap t2 = new SISThreshold().Apply(grey_scaled)) { using (var tmp = new Bitmap(t2.Width, t2.Height)) { using (Graphics g = Graphics.FromImage(tmp)) { g.DrawImage(t2, 0, 0); } //tmp.Save("C:\\users\\alberto geniola\\desktop\\dbg\\t2_" + toinvert + ".bmp"); // The blob counter will analyze the bitmap looking for shapes blobCounter.ProcessImage(tmp); var tmparr = blobCounter.GetObjectsInformation(); blobs.AddRange(tmparr); } } } // Let's analyze every single shape for (int i = 0, n = blobs.Count; i < n; i++) { List <IntPoint> edgePoints = blobCounter.GetBlobsEdgePoints(blobs[i]); if (edgePoints.Count > 1) { IntPoint p0, p1; PointsCloud.GetBoundingRectangle(edgePoints, out p0, out p1); var r = new Rectangle(p0.X, p0.Y, p1.X - p0.X, p1.Y - p0.Y); // Skip any shape representing the border of the whole window ( +10px padding) if (r.Width >= (original.Width - 10)) { continue; } // This is most-likely a button! // Crop the image and pass it to the OCR engine for text recognition using (Bitmap button = new Bitmap(r.Width, r.Height)) { // Scan the original shape String txt = null; using (var g1 = Graphics.FromImage(button)) { g1.DrawImage(original, 0, 0, r, GraphicsUnit.Pixel); } // Process OCR on that image txt = scanButton(button); if (String.IsNullOrEmpty(txt)) { using (Bitmap tmp = Grayscale.CommonAlgorithms.BT709.Apply(button)) { if (shouldInvert) { new Invert().ApplyInPlace(tmp); } new SISThreshold().ApplyInPlace(tmp); txt = scanButton(tmp); } } // If still nothing is found, repeat the analysis with the second version of the filter if (String.IsNullOrEmpty(txt)) { using (Bitmap tmp = Grayscale.CommonAlgorithms.BT709.Apply(button)) { if (shouldInvert) { new Invert().ApplyInPlace(tmp); } new Threshold(64).ApplyInPlace(tmp); txt = scanButton(tmp); } } // At this point we should have a result. Add it to list if it does not overlap any UIAutomated element UIControlCandidate t = new UIControlCandidate(); t.PositionWindowRelative = r; var winLoc = w.WindowLocation; t.PositionScreenRelative = new Rectangle(r.X + winLoc.X, r.Y + winLoc.Y, r.Width, r.Height); t.Text = txt; t.Score = policy.RankElement(t); // If the item falls into the same area of a UI element, ignore it. bool overlaps = false; foreach (var el in res) { if (el.AutoElementRef != null && el.PositionScreenRelative.IntersectsWith(t.PositionScreenRelative)) { overlaps = true; break; } } if (!overlaps) { res.Add(t); } } } } }
public void GetBlobs(string input, string output) { // process binary image Bitmap image = new Bitmap(input); // lock image BitmapData bitmapData = image.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadWrite, image.PixelFormat); // step 1 - turn background to black ColorFiltering colorFilter = new ColorFiltering(); colorFilter.Red = new IntRange(0, 64); colorFilter.Green = new IntRange(0, 64); colorFilter.Blue = new IntRange(0, 64); colorFilter.FillOutsideRange = false; colorFilter.ApplyInPlace(bitmapData); // step 2 - locating objects BlobCounter blobCounter = new BlobCounter(); blobCounter.FilterBlobs = true; blobCounter.MinHeight = 5; blobCounter.MinWidth = 5; blobCounter.ProcessImage(bitmapData); Blob[] blobs = blobCounter.GetObjectsInformation(); image.UnlockBits(bitmapData); // step 3 - check objects' type and highlight SimpleShapeChecker shapeChecker = new SimpleShapeChecker(); Graphics g = Graphics.FromImage(image); Pen redPen = new Pen(Color.Red, 2); Pen yellowPen = new Pen(Color.Yellow, 2); Pen greenPen = new Pen(Color.Green, 2); Pen bluePen = new Pen(Color.Blue, 2); for (int i = 0, n = blobs.Length; i < n; i++) { List <IntPoint> edgePoints = blobCounter.GetBlobsEdgePoints(blobs[i]); Accord.Point center; float radius; if (shapeChecker.IsCircle(edgePoints, out center, out radius)) { g.DrawEllipse(yellowPen, (float)(center.X - radius), (float)(center.Y - radius), (float)(radius * 2), (float)(radius * 2)); } else { List <IntPoint> corners; if (shapeChecker.IsQuadrilateral(edgePoints, out corners)) { if (shapeChecker.CheckPolygonSubType(corners) == PolygonSubType.Rectangle) { g.DrawPolygon(greenPen, ToPointsArray(corners)); } else { g.DrawPolygon(bluePen, ToPointsArray(corners)); } } else { corners = PointsCloud.FindQuadrilateralCorners(edgePoints); g.DrawPolygon(redPen, ToPointsArray(corners)); } } } redPen.Dispose(); greenPen.Dispose(); bluePen.Dispose(); yellowPen.Dispose(); g.Dispose(); // step 4 - save the image image.Save(output); }
/// <summary> /// Detects and recognizes cards from source image /// </summary> /// <param name="source">Source image to be scanned</param> /// <returns>Recognized Cards</returns> public CardCollection Recognize(Bitmap source) { var height = ((double)source.Height / (double)source.Width * 640d); ResizeBilinear ImageResizer = new ResizeBilinear(640, (int)height); source = ImageResizer.Apply(source); CardCollection collection = new CardCollection(); //Collection that will hold cards Bitmap temp = source.Clone() as Bitmap; //Clone image to keep original image FiltersSequence seq = new FiltersSequence(); seq.Add(Grayscale.CommonAlgorithms.BT709); //First add grayScaling filter seq.Add(new OtsuThreshold()); //Then add binarization(thresholding) filter temp = seq.Apply(source); // Apply filters on source image //Extract blobs from image whose size width and height larger than 150 BlobCounter extractor = new BlobCounter(); extractor.FilterBlobs = true; extractor.MinWidth = extractor.MinHeight = 150; extractor.MaxWidth = extractor.MaxHeight = 350; extractor.ProcessImage(temp); //Will be used transform(extract) cards on source image QuadrilateralTransformation quadTransformer = new QuadrilateralTransformation(); //Will be used resize(scaling) cards ResizeBilinear resizer = new ResizeBilinear(CardWidth, CardHeight); var Blobs = extractor.GetObjectsInformation(); foreach (Blob blob in Blobs) { //Get Edge points of card List <IntPoint> edgePoints = extractor.GetBlobsEdgePoints(blob); //Calculate/Find corners of card on source image from edge points List <IntPoint> corners = PointsCloud.FindQuadrilateralCorners(edgePoints); quadTransformer.SourceQuadrilateral = corners; //Set corners for transforming card quadTransformer.AutomaticSizeCalculaton = true; Bitmap cardImg = quadTransformer.Apply(source); //Extract(transform) card image if (cardImg.Width > cardImg.Height) //If card is positioned horizontally { cardImg.RotateFlip(RotateFlipType.Rotate90FlipNone); //Rotate } cardImg = resizer.Apply(cardImg); //Normalize card size Card card = new Card(cardImg, corners.ToArray()); //Create Card Object char color; try { color = ScanColor(card.GetTopLeftPart()); //Scan color } catch (Exception ex) { continue; } bool faceCard = IsFaceCard(cardImg); //Determine type of card(face or not) if (!faceCard) { card.Suit = ScanSuit(cardImg, color); //Scan Suit of non-face card card.Rank = ScanRank(cardImg); //Scan Rank of non-face card } else { Bitmap topLeft = card.GetTopLeftPart(); seq.Clear(); seq.Add(Grayscale.CommonAlgorithms.BT709); seq.Add(new BradleyLocalThresholding()); topLeft = seq.Apply(topLeft); BlobsFiltering bFilter = new BlobsFiltering(5, 5, 150, 150); bFilter.ApplyInPlace(topLeft); //Filter blobs that can not be a suit // topLeft.Save("topleft.bmp", ImageFormat.Bmp); card.Suit = ScanFaceSuit(topLeft, color); //Scan suit of face card card.Rank = ScanFaceRank(topLeft); //Scan rank of face card } collection.Add(card); //Add card to collection } return(collection); }
/// <summary> /// Scans dominant color on image and returns it. /// Crops rank part on image and analyzes suit part on image /// </summary> /// <param name="bmp">Bitmap to be scanned</param> /// <returns>Returns 'B' for black , 'R' for red</returns> private char ScanColor(Bitmap bmp) { System.Diagnostics.Debug.Flush(); System.Diagnostics.Debug.Print("I'm here"); char color = 'B'; //Crop rank part Crop crop = new Crop(new Rectangle(0, bmp.Height / 2, bmp.Width, bmp.Height / 2)); bmp = crop.Apply(bmp); Bitmap temp = commonSeq.Apply(bmp); //Apply filters //Find suit blob on image BlobCounter counter = new BlobCounter(); counter.ProcessImage(temp); Blob[] blobs = counter.GetObjectsInformation(); if (blobs.Length > 0) //If blobs found { Blob max = blobs[0]; //Find blob whose size is biggest foreach (Blob blob in blobs) { if (blob.Rectangle.Height > max.Rectangle.Height) { max = blob; } else if (blob.Rectangle.Height == max.Rectangle.Height) { max = blob.Rectangle.Width > max.Rectangle.Width ? blob : max; } } QuadrilateralTransformation trans = new QuadrilateralTransformation(); trans.SourceQuadrilateral = PointsCloud.FindQuadrilateralCorners(counter.GetBlobsEdgePoints(max)); bmp = trans.Apply(bmp); //Extract suit } //Lock Bits for processing BitmapData imageData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, bmp.PixelFormat); int totalRed = 0; int totalBlack = 0; unsafe { //Count red and black pixels try { UnmanagedImage img = new UnmanagedImage(imageData); int height = img.Height; int width = img.Width; int pixelSize = (img.PixelFormat == PixelFormat.Format24bppRgb) ? 3 : 4; byte *p = (byte *)img.ImageData.ToPointer(); // for each line for (int y = 0; y < height; y++) { // for each pixel for (int x = 0; x < width; x++, p += pixelSize) { int r = (int)p[RGB.R]; //Red pixel value int g = (int)p[RGB.G]; //Green pixel value int b = (int)p[RGB.B]; //Blue pixel value if (r > g + b) //If red component is bigger then total of green and blue component { totalRed++; //then its red } else if (r <= g + b && (r < 50 && g < 50)) //If all components less 70 { totalBlack++; //then its black } } } } finally { bmp.UnlockBits(imageData); //Unlock } } if (totalRed > totalBlack) //If red is dominant { color = 'R'; //Set color as Red } return(color); }
private void button2_Click(object sender, EventArgs e) { Bitmap bmp = new Bitmap(pictureBox1.Image); Bitmap bmpsobe; Bitmap bmpmedian; Bitmap otsu; if (pictureBox1.Image == null) { MessageBox.Show("Lütfen önce bir resim Seçin"); } else { progressBar1.Visible = true; int i, j; Color ort;//Color sınıfından bir renk nesne tanımlıyoruz. //int r,g,b; progressBar1.Maximum = bmp.Width * bmp.Height; //İşlem çubuğunun maksimim olduğu yer for döngüsünün sonundaki piksel değerine erişmemiz durumundadır. for (i = 0; i <= bmp.Width - 1; i++) //dikey olarak görüntümüzü tarıyoruz. { for (j = 0; j <= bmp.Height - 1; j++) //yatay olarak görüntümüzü tarıyoruz. { ort = bmp.GetPixel(i, j); ort = Color.FromArgb((byte)((ort.R + ort.G + ort.B) / 3), (byte)((ort.R + ort.G + ort.B) / 3), (byte)((ort.R + ort.G + ort.B) / 3)); bmp.SetPixel(i, j, ort); if ((i % 10) == 0)//her on satırda bir göstergeyi güncelle { progressBar1.Value = i * bmp.Height + j; Application.DoEvents(); } } } } //////////////////////// Median ////////////// bmpmedian = ExtBitmap.MedianFilter(bmp, 3); /////////////////////// SOBEL /////////////// bmpsobe = ExtBitmap.Sobel3x3Filter(bmpmedian, true); Bitmap bmpsobe1 = (Bitmap)bmpsobe.Clone(); /////////// otsu int x, y; int genislik = bmpsobe1.Width; int yukseklik = bmpsobe1.Height; byte[] pixeller = new byte[(int)genislik * yukseklik]; Bitmap resim = (Bitmap)bmpsobe1.Clone(); for (y = 0; y < yukseklik; y++) { for (x = 0; x < genislik; x++) { // Pixelleri kütüphanenin işleyebileceği tek boyutlu bir diziye atıyoruz. // Gri seviyede tüm ana renkler eşit olduğu için sadece kırmızıyı okumak gri seviye için yeterli. pixeller[y * genislik + x] = resim.GetPixel(x, y).R; } } byte esikDeger = 0; OtsuEsikleme(ref pixeller[0], ref esikDeger, genislik, yukseklik); int renkk; for (y = 0; y < yukseklik; y++) { for (x = 0; x < genislik; x++) { renkk = pixeller[y * genislik + x]; // gri resim.SetPixel(x, y, Color.FromArgb(renkk, renkk, renkk)); // Gri seviyeyi argb moduna dönüştürüp resme aktarıyoruz. } } otsu = (Bitmap)resim.Clone(); Bitmap bmperosion; Bitmap bmpdilation; Bitmap bmpclosing; bmperosion = ExtBitmap.DilateAndErodeFilter(otsu, 3, akıllıgecissistemleri.ExtBitmap.MorphologyType.Erosion, true, true, true); Bitmap bmperosionn = (Bitmap)bmperosion.Clone(); bmpdilation = ExtBitmap.DilateAndErodeFilter(bmperosionn, 7, akıllıgecissistemleri.ExtBitmap.MorphologyType.Dilation, true, true, true); Bitmap bmpdilationn = (Bitmap)bmpdilation.Clone(); Bitmap one = (Bitmap)bmpdilationn.Clone(); BlobsFiltering filter0 = new BlobsFiltering(); // filtre ayarlaması filter0.CoupledSizeFiltering = true; filter0.MinWidth = 70; filter0.MinHeight = 40; // filtre uygula filter0.ApplyInPlace(one); Bitmap one2 = (Bitmap)one.Clone(); bmpclosing = ExtBitmap.CloseMorphologyFilter(one2, 15, true, true, true); Bitmap bmperosio = (Bitmap)bmpclosing.Clone(); Bitmap bmperosionson = ExtBitmap.DilateAndErodeFilter(bmperosio, 9, akıllıgecissistemleri.ExtBitmap.MorphologyType.Erosion, true, true, true); Bitmap blobson = (Bitmap)bmperosionson.Clone(); BlobsFiltering filterson = new BlobsFiltering(); // filtre ayarla filterson.CoupledSizeFiltering = true; filterson.MinWidth = 50; filterson.MinHeight = 200; // filtre uygula filterson.ApplyInPlace(blobson); Bitmap rect = (Bitmap)blobson.Clone(); Bitmap one1 = (Bitmap)rect.Clone(); ConnectedComponentsLabeling filter = new ConnectedComponentsLabeling(); // filtre uygula Bitmap newImage = filter.Apply(one1); Bitmap newImage1 = (Bitmap)newImage.Clone(); // obje sayısını kontrol et int objectCount = filter.ObjectCount; BlobCounter blobCounter = new BlobCounter(); blobCounter.ProcessImage(rect); Blob[] blobs = blobCounter.GetObjectsInformation(); // Görüntüye çizmek için Graphic nesnesi ve bir kalem oluştur Graphics g = Graphics.FromImage(rect); Pen bluePen = new Pen(Color.Blue, 2); // her nesne kpntrol edilir ve etrafında daire çizilir. for (int i = 0, n = blobs.Length; i < n; i++) { /* * x1=0 * x2=1 * y1=2 * y2=3 */ List <IntPoint> edgePoints = blobCounter.GetBlobsEdgePoints(blobs[i]); List <IntPoint> corners = PointsCloud.FindQuadrilateralCorners(edgePoints); int[] sinirlar = sinir(corners); sinirlar[0] = sinirlar[0] - 2; sinirlar[1] = sinirlar[1] + 2; sinirlar[2] = sinirlar[2] - 2; sinirlar[3] = sinirlar[3] + 2; int en = sinirlar[1] - sinirlar[0]; int boy = sinirlar[3] - sinirlar[2]; float ort = (float)en / (float)boy; List <IntPoint> ucnoktalar = new List <IntPoint>(); ucnoktalar.Add(new IntPoint(sinirlar[0], sinirlar[2])); ucnoktalar.Add(new IntPoint(sinirlar[1], sinirlar[2])); ucnoktalar.Add(new IntPoint(sinirlar[1], sinirlar[3])); ucnoktalar.Add(new IntPoint(sinirlar[0], sinirlar[3])); g.DrawPolygon(bluePen, ToPointsArray(ucnoktalar)); g.DrawString("Plaka kordinatlari : (x,y): (" + sinirlar[0].ToString() + "," + sinirlar[2].ToString() + ")\n en, boy,ort: " + (sinirlar[1] - sinirlar[0]).ToString() + ", " + (sinirlar[3] - sinirlar[2]).ToString() + "," + ort.ToString() + " blob sayisi:" + blobs.Length.ToString(), new Font("Arial", 8), Brushes.White, new System.Drawing.Point(sinirlar[0], sinirlar[3] + 4)); } bluePen.Dispose(); g.Dispose(); Bitmap rect1 = (Bitmap)pictureBox1.Image.Clone(); Graphics g1 = Graphics.FromImage(rect1); Pen bluePen2 = new Pen(Color.Red, 2); // her nesne kpntrol edilir ve etrafında daire çizilir. List <Blob> bloplar = new List <Blob>(); for (int i = 0, n = blobs.Length; i < n; i++) { /* x1,y1--------x2,y1 * x1=0 | | * x2=1 | | * y1=2 x1,y2--------x2,y2 * y2=3 */ List <IntPoint> edgePoints = blobCounter.GetBlobsEdgePoints(blobs[i]); List <IntPoint> corners = PointsCloud.FindQuadrilateralCorners(edgePoints); int[] sinirlar = sinir(corners); sinirlar[0] = sinirlar[0] - 5; sinirlar[1] = sinirlar[1]; sinirlar[2] = sinirlar[2] - 5; sinirlar[3] = sinirlar[3] + 5; int en = sinirlar[1] - sinirlar[0]; int boy = sinirlar[3] - sinirlar[2]; float ort = (float)en / (float)boy; if (ort >= 3 && ort <= 5.7) { g1.DrawLines(bluePen2, new System.Drawing.Point[] { new System.Drawing.Point(sinirlar[0], sinirlar[2]), new System.Drawing.Point(sinirlar[1], sinirlar[2]), new System.Drawing.Point(sinirlar[1], sinirlar[3]), new System.Drawing.Point(sinirlar[0], sinirlar[3]), new System.Drawing.Point(sinirlar[0], sinirlar[2]) }); g1.DrawString("Plaka kordinatlari : (x,y): (" + sinirlar[0].ToString() + "," + sinirlar[2].ToString() + ")\n en, boy,ort: " + (sinirlar[1] - sinirlar[0]).ToString() + ", " + (sinirlar[3] - sinirlar[2]).ToString() + "," + ort.ToString() + " blob sayisi:" + blobs.Length.ToString(), new Font("Arial", 8), Brushes.White, new System.Drawing.Point(sinirlar[0], sinirlar[3] + 4)); } } bluePen2.Dispose(); g1.Dispose(); Bitmap bn = null; Bitmap kes1 = (Bitmap)rect1.Clone(); Graphics g2 = Graphics.FromImage(kes1); Pen bluePen3 = new Pen(Color.Red, 2); // her nesne kpntrol edilir ve etrafında daire çizilir. for (int i = 0, n = blobs.Length; i < n; i++) { /* x1,y1--------x2,y1 * x1=0 | | * x2=1 | | * y1=2 x1,y2--------x2,y2 * y2=3 */ List <IntPoint> edgePoints = blobCounter.GetBlobsEdgePoints(blobs[i]); List <IntPoint> corners = PointsCloud.FindQuadrilateralCorners(edgePoints); int[] sinirlar = sinir(corners); sinirlar[0] = sinirlar[0] - 5; sinirlar[1] = sinirlar[1]; sinirlar[2] = sinirlar[2] - 5; sinirlar[3] = sinirlar[3] + 5; int en = sinirlar[1] - sinirlar[0]; int boy = sinirlar[3] - sinirlar[2]; float ort = en / boy; if (ort >= 3 && ort <= 5.7) { g2.DrawLines(bluePen3, new System.Drawing.Point[] { new System.Drawing.Point(sinirlar[0], sinirlar[2]), new System.Drawing.Point(sinirlar[1], sinirlar[2]), new System.Drawing.Point(sinirlar[1], sinirlar[3]), new System.Drawing.Point(sinirlar[0], sinirlar[3]), new System.Drawing.Point(sinirlar[0], sinirlar[2]) }); for (int ii = 0; ii < kes1.Width; ii++) { for (int ji = 0; ji < kes1.Height; ji++) { if ((ii >= sinirlar[0] && ii <= sinirlar[1]) && (ji >= sinirlar[2]) && ji <= sinirlar[3]) { continue; } else { kes1.SetPixel(ii, ji, Color.Black); } } } bn = new Bitmap(en, boy); Graphics g3 = Graphics.FromImage(bn); g3.DrawImage(kes1, -sinirlar[0], -sinirlar[2]); pictureBox2.Image = bn; } } bluePen3.Dispose(); g2.Dispose(); //form(bmp, "Grayscala"); //form(bmpmedian, "Median"); //form(bmpsobe, "sobel"); //form(otsu, "otsu"); //form(bmperosion, "erosion"); //form(bmpdilationn, "dilation"); //form(one, "one"); //form(bmpclosing, "closing"); //form(bmperosionson, "son"); //form(blobson, "blobson"); //form(newImage, "one1"); //form(rect, "rect"); //form(rect1, "rect1"); //form(kes1, "kes1"); //form(bn, "bn"); }
private ImageSource ProcessImageSourceForBitmap(Bitmap bmp) { BitmapData bitmapData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, bmp.PixelFormat); EuclideanColorFiltering filter = new EuclideanColorFiltering(); filter.CenterColor = new RGB(byte.Parse(redTextBox.Text), byte.Parse(greenTextBox.Text), byte.Parse(blueTextBox.Text)); filter.Radius = short.Parse(radiusTextBox.Text); filter.ApplyInPlace(bitmapData); BlobCounter blobCounter = new BlobCounter(); blobCounter.FilterBlobs = true; blobCounter.MinHeight = 15; blobCounter.MinWidth = 15; blobCounter.MaxHeight = bitmapData.Width - 1; blobCounter.MaxWidth = bitmapData.Width - 1; blobCounter.ProcessImage(bitmapData); Blob[] blobs = blobCounter.GetObjectsInformation(); bmp.UnlockBits(bitmapData); SimpleShapeChecker shapeChecker = new SimpleShapeChecker(); Graphics g = Graphics.FromImage(bmp); System.Drawing.Pen redPen = new System.Drawing.Pen(System.Drawing.Color.Red, 5); System.Drawing.Pen yellowPen = new System.Drawing.Pen(System.Drawing.Color.Yellow, 5); System.Drawing.Pen greenPen = new System.Drawing.Pen(System.Drawing.Color.Green, 5); System.Drawing.Pen bluePen = new System.Drawing.Pen(System.Drawing.Color.Blue, 5); for (int i = 0, n = blobs.Length; i < n; i++) { List <IntPoint> edgePoints = blobCounter.GetBlobsEdgePoints(blobs[i]); AForge.Point center; float radius; if (shapeChecker.IsCircle(edgePoints, out center, out radius)) { g.DrawEllipse(yellowPen, (float)(center.X - radius), (float)(center.Y - radius), (float)(radius * 2), (float)(radius * 2)); } else { List <IntPoint> corners; if (shapeChecker.IsQuadrilateral(edgePoints, out corners)) { if (shapeChecker.CheckPolygonSubType(corners) == PolygonSubType.Rectangle) { g.DrawPolygon(greenPen, ToPointsArray(corners)); } else { g.DrawPolygon(bluePen, ToPointsArray(corners)); } } else { corners = PointsCloud.FindQuadrilateralCorners(edgePoints); g.DrawPolygon(redPen, ToPointsArray(corners)); } } } redPen.Dispose(); greenPen.Dispose(); bluePen.Dispose(); yellowPen.Dispose(); g.Dispose(); var handle = bmp.GetHbitmap(); try { return(Imaging.CreateBitmapSourceFromHBitmap(handle, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions())); } finally { DeleteObject(handle); } }
/* Odświezanie okna z obrazem */ void RefreshWindow(object sender, EventArgs arg) { //Pobieranie ramki image = capture.QueryFrame(); image = image.Flip(FLIP.HORIZONTAL); imageBox1.Image = image; //YCbCr or Bgr(RGB) //Warto zwrócić uwagę na to że Ycc to Y,Cr,Cb a nie Y,Cb,Cr, oraz Bgr to Blue,Green,Red if (radioButton1.Checked) { imageGray = image.Resize((double)nupScale.Value, INTER.CV_INTER_CUBIC).Convert <Ycc, Byte>(). InRange(new Ycc((double)nudW1.Value, (double)nudW3.Value, (double)nudW2.Value), new Ycc((double)nudW4.Value, (double)nudW6.Value, (double)nudW5.Value)); } else { imageGray = image.InRange(new Bgr((double)nudW3.Value, (double)nudW2.Value, (double)nudW1.Value), new Bgr((double)nudW6.Value, (double)nudW5.Value, (double)nudW4.Value)); } if (medianCB.Checked) { imageGray = imageGray.SmoothMedian((int)nudMedian.Value); } //Image<Gray, Byte> sgm = new Image<Gray, Byte>(imageGray.Size); Bitmap bmp = imageGray.ToBitmap(); bc.ProcessImage(bmp); Blob[] blob = bc.GetObjectsInformation(); //one hand version //int iters = bc.ObjectsCount > 1 ? 1 : bc.ObjectsCount; int iters = bc.ObjectsCount > 2 ? 2 : bc.ObjectsCount; if (iters > 1) { //both hands version //lewa reka to ta z prawej strony obrazu (zwierciadlo), nie zakladamy ze user gestykuluje na krzyz, keep it simple blob = blob.Take(2).OrderByDescending(a => a.CenterOfGravity.X).ToArray <Blob>(); } int centerOfGravityLHandX = 0, centerOfGravityLHandY = 0, centerOfGravityRHandX = 0, centerOfGravityRHandY = 0; string[] gestureLabel = new string[2]; int i = 0; for (; i < iters; ++i) { IntPoint minXY, maxXY; PointsCloud.GetBoundingRectangle(bc.GetBlobsEdgePoints(blob[i]), out minXY, out maxXY); Bitmap clonimage = (Bitmap)bmp.Clone(); BitmapData data = bmp.LockBits(new Rectangle(0, 0, imageGray.Width, imageGray.Height), ImageLockMode.ReadWrite, bmp.PixelFormat); Drawing.Rectangle(data, blob[i].Rectangle, Color.White); bmp.UnlockBits(data); int X = maxXY.X, Y = maxXY.Y; int x = minXY.X, y = minXY.Y; observed[0, i] = blob[i].Fullness; /* malinowska kryjaka liczy obwod ze wzoru na prostokąt, nasza liczy piksele krawedziowe */ //Malinowska(i) = (2*bb(3)+2*bb(4))/(2*sqrt(pi*S)) - 1; observed[2, i] = (double)(bc.GetBlobsEdgePoints(blob[i]).Count) / 2 / Math.Sqrt(Math.PI * blob[i].Area) - 1; //MalinowskaZ(i) = 2*sqrt(pi*S)/(2*bb(3)+2*bb(4)); observed[3, i] = 2 * Math.Sqrt(Math.PI * blob[i].Area) / (double)(bc.GetBlobsEdgePoints(blob[i]).Count); int gx = (int)blob[i].CenterOfGravity.X, gy = (int)blob[i].CenterOfGravity.Y; //Sprawdzenie która ręka prawa, a która lewa if (gx > centerOfGravityRHandX) { centerOfGravityLHandX = centerOfGravityRHandX; centerOfGravityLHandY = centerOfGravityRHandY; centerOfGravityRHandX = gx; centerOfGravityRHandY = gy; } else { centerOfGravityLHandX = gx; centerOfGravityLHandY = gy; } double blairsum = 0; int ftx = 0, ftxMax = 0; byte[, ,] dd = imageGray.Data; for (int j = y; j < Y; ++j) { if (ftx > ftxMax) { ftxMax = ftx; } ftx = 0;//bo moze sie zdazyc ze zliczy wiecej linii naraz, patrz: idealny prostokat for (int k = x; k < X; ++k) { if (dd[j, k, 0] != 0) { ++ftx; blairsum += (k - gx) * (k - gx) + (j - gy) * (j - gy);//distance squared } else { if (ftx > ftxMax) { ftxMax = ftx; } ftx = 0; } dd[j, k, 0] = 255; } } /* aby policzyc ftyMax trzeba puscic jeszcze jedna petle tak aby wewnetrzna szla po y-kach * ale mozna tez aproksymowac ftYmax przez boundingbox.Y, wtedy * przewidywalem najwieksze rozbieznosci przy skosnych lub dziurawych obiektach; * ale blad byl ponizej procenta, wiec szkoda tracic czas na kolejne O(n*n) * * int fty = 0, ftyMax = 0; * for (int j = x; j < X; ++j) { * if (fty > ftyMax) ftyMax = fty; * fty = 0; * for (int i = y; i < Y; ++i) * if (dd[i, j, 0] != 0) ++fty; * else { * if (fty > ftyMax) ftyMax = fty; * fty = 0; * } * } * feret = (double)ftxMax / ftyMax; */ observed[4, i] = (double)ftxMax / (Y - y); //feret observed[1, i] = (double)(blob[i].Area) / Math.Sqrt(2 * Math.PI * blairsum); //blair gestChance[GEST.SLAYER] = dist(slayer, i); gestChance[GEST.THUMBLEFT] = dist(thumbleft, i); gestChance[GEST.THUMBUP] = dist(thumbup, i); gestChance[GEST.SHAKA] = dist(shaka, i); gestChance[GEST.FIST] = dist(fist, i); gestChance[GEST.VICTORY] = dist(victory, i); gestChance[GEST.VOPEN] = dist(vopen, i); gestChance[GEST.HOPEN] = dist(hopen, i); gestChance[GEST.FINGERS] = dist(fingers, i); gestChance[GEST.SCISSORS] = dist(scissors, i); //list fold - get key of minimal value KeyValuePair <GEST, double> elem = gestChance.Aggregate((l, r) => l.Value < r.Value ? l : r); found[i] = (elem.Value < TOLERANCE) ? elem.Key : GEST.BLANK; if (elem.Key == GEST.FIST && (double)(X - x) / (Y - y) < .6) { found[i] = GEST.VOPEN; } gestureLabel[i] = labels[(int)found[i]]; } g1value.Text = gestureLabel[1]; g2value.Text = gestureLabel[0]; compactnessLbl.Text = observed[0, 1].ToString(format); blairLbl.Text = observed[1, 1].ToString(format); malinowskaLbl.Text = observed[2, 1].ToString(format); malzmodLbl.Text = observed[3, 1].ToString(format); feretLbl.Text = observed[4, 1].ToString(format); comp2.Text = observed[0, 0].ToString(format); blair2.Text = observed[1, 0].ToString(format); mal2.Text = observed[2, 0].ToString(format); malz2.Text = observed[3, 0].ToString(format); feret2.Text = observed[4, 0].ToString(format); /* for blobs not detected */ for (; i < 2; ++i) { observed[0, i] = observed[1, i] = observed[2, i] = observed[3, i] = observed[4, i] = NOT_FOUND; } imageGray = new Image <Gray, Byte>(bmp); imageGray = imageGray.Erode((int)nudErode.Value); imageGray = imageGray.Dilate((int)nudDilate.Value); imageBox2.Image = imageGray; //Zmiana pozycji myszki od środka ciężkości lewej ręki if (centerOfGravityLHandX * centerOfGravityLHandY != 0 && !blockMouseControl) { double smoothness = (double)nudSmoothness.Value; double sensitivity = (double)nudSensitivity.Value; int newPositionX = screenWidth - (int)(centerOfGravityLHandX / (imageGray.Width * .2) * sensitivity * screenWidth); //- imageGray.Width*1/5 int newPositionY = (int)((centerOfGravityLHandY - imageGray.Height * .5) / (imageGray.Height * .25) * sensitivity * screenHeight); int diffX = Cursor.Position.X + newPositionX; int diffY = Cursor.Position.Y - newPositionY; newPositionX = Cursor.Position.X - (int)(diffX / smoothness); newPositionY = Cursor.Position.Y - (int)(diffY / smoothness); MouseSimulating.SetMousePosition(newPositionX, newPositionY); //Wyliczanie akcji do podjęcia if (found[1] == GEST.BLANK || prevGestureLeft != found[1]) { frameCounterLeft = 0; prevGestureLeft = found[1]; } if (found[0] == GEST.BLANK || prevGestureRight != found[0]) { frameCounterRight = 0; prevGestureRight = found[0]; } if (frameCounterLeft == 30) //ile klatek musi - 30 kl/s { if (prevGestureLeft == GEST.FIST) { MouseSimulating.PressLPM(); } else if (prevGestureLeft == GEST.VOPEN) { MouseSimulating.ReleaseLPM(); } frameCounterLeft = 0; } else { frameCounterLeft++; } if (frameCounterRight == 30) { if (prevGestureRight == GEST.FIST) { MouseSimulating.ClickLPM(); } else if (prevGestureRight == GEST.SLAYER) { MouseSimulating.ScrollUP(200); } else if (prevGestureRight == GEST.VICTORY) { MouseSimulating.ScrollDOWN(200); } else if (prevGestureRight == GEST.FINGERS) { MouseSimulating.ClickPPM(); } else if (prevGestureRight == GEST.THUMBUP) { KeyboardSimulating.SendCtrlC(); } else if (prevGestureRight == GEST.THUMBLEFT) { KeyboardSimulating.SendCtrlV(); } else if (prevGestureRight == GEST.SCISSORS) { KeyboardSimulating.SendCtrlX(); } else if (prevGestureRight == GEST.HOPEN) { MouseSimulating.ClickLPM(); MouseSimulating.ClickLPM(); } else if (prevGestureRight == GEST.SHAKA) { MouseSimulating.ClickMouseButton4(); } frameCounterRight = 0; } else { frameCounterRight++; } } }