public static Bitmap FindColorCorrectedForBlob(FoundColorSpaces foundColorSpaces, Blob blob) { Bitmap bmp = foundColorSpaces.OriginalColorSpace.Clone(blob.Rectangle, foundColorSpaces.OriginalColorSpace.PixelFormat); return FindColorCorrectedForBlob(bmp); }
//Filter out non-character blobs private static List<Blob> filterBlobs(Blob[] blobs) { uint[] widths = new uint[blobs.Length]; uint[] heights = new uint[blobs.Length]; for(int i = 0; i < blobs.Length; i++) { widths[i] = checked((uint)blobs[i].Rectangle.Width); //Throws OverflowException if val < 0 heights[i] = checked((uint)blobs[i].Rectangle.Height); } //Filter out blobs that are too big or too small //Only remove blobs that are too big or too small in both dimensions, to allow for thin chars like I's double meanWidth = Stats.Mean(widths); double minWidth = meanWidth * BLOB_FILTER_MEAN_MULTIPLIER_MINIMUM; double maxWidth = meanWidth * BLOB_FILTER_MEAN_MULTIPLIER_MAXIMUM; double meanHeight = Stats.Mean(heights); double minHeight = meanHeight * BLOB_FILTER_MEAN_MULTIPLIER_MINIMUM; double maxHeight = meanHeight * BLOB_FILTER_MEAN_MULTIPLIER_MAXIMUM; List<Blob> chars = new List<Blob>(); foreach(Blob b in blobs) { int width = b.Rectangle.Width; int height = b.Rectangle.Height; //Is this Blob allowable if((width <= maxWidth && width >= minWidth) || //Width check (height <= maxHeight && height >= minHeight)) //Height check { chars.Add(b); } } return chars; }
public SkyObject(CatalogEntry entry, Blob blob) { CatEntry = entry; ObjectBlob = blob; Name = CatEntry.Name; Position = CatEntry.Position; }
public SkyObject(Blob blob) { CatEntry = null; ObjectBlob = blob; Name = ""; Position = new SkyVector(new HourAngle(), new Angle()); }
public override void Execute(Bitmap Image) { BlobCounter blobCounter = new BlobCounter(); blobCounter.MinHeight = 75; blobCounter.MinWidth = 75; blobCounter.CoupledSizeFiltering = true; blobCounter.ProcessImage(Image); Blob[] blobs = blobCounter.GetObjects(Image); int maxSize = 0; Blob maxObject = new Blob(0, new Rectangle(0, 0, 0, 0)); // find biggest blob if (blobs != null) { foreach (Blob blob in blobs) { int blobSize = blob.Rectangle.Width * blob.Rectangle.Height; if (blobSize > maxSize) { maxSize = blobSize; maxObject = blob; } } if (maxSize > 100) { if (Validity == ValidLocation.TRUE) { if (System.Math.Sqrt((CurrY - maxObject.Rectangle.Top) * (CurrY - maxObject.Rectangle.Top) + (CurrX - (maxObject.Rectangle.Left + maxObject.Rectangle.Right) / 2) * (CurrX - (maxObject.Rectangle.Left + maxObject.Rectangle.Right) / 2)) > 20) { Validity = ValidLocation.FALSE; TargetFoundCycle = 0; return; } else { TargetFoundCycle++; } } CurrX = (maxObject.Rectangle.Left + maxObject.Rectangle.Right) / 2; CurrY = maxObject.Rectangle.Top; Validity = ValidLocation.TRUE; } else { Validity = ValidLocation.FALSE; TargetFoundCycle = 0; } } else { TargetFoundCycle = 0; Validity = ValidLocation.FALSE; return; } }
// Copy constructur internal Blob( Blob source ) { // copy everything except image id = source.id; rect = source.rect; cog = source.cog; area = source.area; fullness = source.fullness; colorMean = source.colorMean; colorStdDev = source.colorStdDev; }
void DetectRowBounds(PageLayout cbi, Blob[] blobs) { if (blobs.Length == 0) { return; } if (cbi.Bounds == Rectangle.Empty) { return; } List<LayoutElement> rows = new List<LayoutElement>(); LayoutElement currentRow = null; // Attempt drawing lines between the rows. for (int y = cbi.Bounds.Top; y < cbi.Bounds.Bottom; y++) { Rectangle rowRect = new Rectangle(cbi.Bounds.Left, y, cbi.Bounds.Width, 1); var blobsInRow = blobs.Where(b => b.Rectangle.IntersectsWith(rowRect)); if (blobsInRow.FirstOrDefault() == null) { // Empty row detected. Commit current row (if any) TryAddRow(rows, currentRow); currentRow = null; } else { // Start new row if needed if (currentRow == null) { currentRow = new LayoutElement(); currentRow.Type = LayoutElementType.Row; } currentRow.Children.AddRange(blobsInRow.Select(x => LayoutElement.NewWord(cbi.PageSize, x.Rectangle))); // Advance to test the next empty space // TODO: beware of off-by-1 //y = currentRow.Bounds.Bottom - 1; } } // Add row at the end TryAddRow(rows, currentRow); FindAndRemoveHeaderAndFooter(cbi, rows); cbi.Children = rows; cbi.SetBoundsFromNodes(true); }
// Blob was selected - display its information private void blobsBrowser_BlobSelected(object sender, Blob blob) { propertyGrid.SelectedObject = blob; propertyGrid.ExpandAllGridItems(); }
private int FindNearestBlob() { Blob[] blobs; int blobCount; blobCounter.ObjectsOrder = ObjectsOrder.None; // Find the blobs blobCounter.ProcessImage(this.image); blobs = blobCounter.GetObjectsInformation(); blobCount = blobs.Count(); TotalBlobCount = blobCount; if (blobCount > 0) { Blob nearestBlob = new Blob(blobs[0]); float leastDistance = nearestBlob.CenterOfGravity.DistanceTo(this.Position); float currentDistance; foreach (Blob blob in blobs) { currentDistance = blob.CenterOfGravity.DistanceTo(this.Position); if (currentDistance < 50) { this.TrackedBlobCount = 1; if (currentDistance < leastDistance) { nearestBlob = blob; leastDistance = currentDistance; } } else { this.TrackedBlobCount = 0; } } if (this.TrackedBlobCount > 0) { this.currentBlob = nearestBlob; } else { // Do not update the current blob } } else { this.TrackedBlobCount = 0; } return blobCount; }
public bool Check(Blob blob) { if (blob.Rectangle.Height < MinDimension || blob.Rectangle.Width < MinDimension) { return false; } float proportion = (float)blob.Rectangle.Width / blob.Rectangle.Height; if (proportion > 1) { proportion = 1 / proportion; } if (proportion < MinProportion) { return false; } return true; }
private bool isCircle(Blob b, List<IntPoint> edge) { //bool circle = false; double c = 40.0; float centerX = b.CenterOfGravity.X; float centerY = b.CenterOfGravity.Y; double testRadius = util.floatDist(centerX, centerY, (float) edge[0].X, (float) edge[0].Y); for (int i = 1; i < edge.Count; i++) { float edgeX = edge[i].X; float edgeY = edge[i].Y; double tempRadius = util.floatDist(centerX, centerY, (float)edge[i].X, (float)edge[i].Y); if (!(tempRadius < testRadius + c && tempRadius > testRadius - c)) { return false; } } return true; }
private int FindLargestBlob() { Blob[] blobs; int blobCount; blobCounter.ObjectsOrder = ObjectsOrder.Area; // Find the blobs blobCounter.ProcessImage(this.image); blobs = blobCounter.GetObjectsInformation(); blobCount = blobs.Count(); if (blobCount > 0) { currentBlob = blobs[0]; } return blobCount; }
/// <summary> /// Process new frame. /// </summary> /// /// <remarks>Process new frame of video source and try to recognize gesture.</remarks> /// public void ProcessFrame( ref Bitmap image ) { // check background frame if ( backgroundFrame == null ) { // save image dimension width = image.Width; height = image.Height; frameSize = width * height; // create initial backgroung image backgroundFrame = grayscaleFilter.Apply( image ); return; } // check image dimension if ( ( image.Width != width ) || ( image.Height != height ) ) return; // apply the grayscale filter Bitmap currentFrame = grayscaleFilter.Apply( image ); // set backgroud frame as an overlay for difference filter differenceFilter.OverlayImage = backgroundFrame; // apply difference filter Bitmap motionObjectsImage = differenceFilter.Apply( currentFrame ); // lock motion objects image for further faster processing BitmapData motionObjectsData = motionObjectsImage.LockBits( new Rectangle( 0, 0, width, height ), ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed ); // apply threshold filter thresholdFilter.ApplyInPlace( motionObjectsData ); // apply opening filter to remove noise openingFilter.ApplyInPlace( motionObjectsData ); // process blobs blobCounter.ProcessImage( motionObjectsData ); Blob[] blobs = blobCounter.GetObjectInformation( ); int maxSize = 0; Blob maxObject = new Blob( 0, new Rectangle( 0, 0, 0, 0 ) ); // find biggest blob if ( blobs != null ) { foreach ( Blob blob in blobs ) { int blobSize = blob.Rectangle.Width * blob.Rectangle.Height; if ( blobSize > maxSize ) { maxSize = blobSize; maxObject = blob; } } } // if we have only small objects then let's adopt to changes in the scene if ( ( maxObject.Rectangle.Width < 20 ) || ( maxObject.Rectangle.Height < 20 ) ) { // move background towards current frame moveTowardsFilter.OverlayImage = currentFrame; moveTowardsFilter.ApplyInPlace( backgroundFrame ); } if ( ( maxObject.Rectangle.Width >= minBodyWidth ) && ( maxObject.Rectangle.Height >= minBodyHeight ) && ( previousFrame != null ) ) { // check motion level between frames differenceFilter.OverlayImage = previousFrame; // apply difference filter Bitmap betweenFramesMotion = differenceFilter.Apply( currentFrame ); // lock image with between frames motion for faster further processing BitmapData betweenFramesMotionData = betweenFramesMotion.LockBits( new Rectangle( 0, 0, width, height ), ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed ); // apply threshold filter thresholdFilter.ApplyInPlace( betweenFramesMotionData ); // apply opening filter to remove noise openingFilter.ApplyInPlace( betweenFramesMotionData ); // calculate amount of changed pixels VerticalIntensityStatistics vis = new VerticalIntensityStatistics( betweenFramesMotionData ); int[] histogram = vis.Gray.Values; int changedPixels = 0; for ( int i = 0, n = histogram.Length; i < n; i++ ) { changedPixels += histogram[i] / 255; } // free temporary image betweenFramesMotion.UnlockBits( betweenFramesMotionData ); betweenFramesMotion.Dispose( ); // check motion level if ( (double) changedPixels / frameSize <= motionLimit ) { framesWithoutMotion++; } else { // reset counters framesWithoutMotion = 0; framesWithoutGestureChange = 0; notDetected = true; } // check if we don't have motion for a while if ( framesWithoutMotion >= minFramesWithoutMotion ) { if ( notDetected ) { // extract the biggest blob blobCounter.ExtractBlobsImage( motionObjectsData, maxObject ); // recognize gesture from the image Gesture gesture = gestureRecognizer.Recognize( maxObject.Image, true ); maxObject.Image.Dispose( ); // check if gestures has changed since the previous frame if ( ( gesture.LeftHand == previousGesture.LeftHand ) && ( gesture.RightHand == previousGesture.RightHand ) ) { framesWithoutGestureChange++; } else { framesWithoutGestureChange = 0; } // check if gesture was not changing for a while if ( framesWithoutGestureChange >= minFramesWithoutGestureChange ) { if ( GestureDetected != null ) { GestureDetected( this, gesture ); } notDetected = false; } previousGesture = gesture; } } } else { // reset counters framesWithoutMotion = 0; framesWithoutGestureChange = 0; notDetected = true; } // free motion objects' image motionObjectsImage.UnlockBits( motionObjectsData ); motionObjectsImage.Dispose( ); // dispose previous frame if ( previousFrame != null ) { previousFrame.Dispose( ); } // set current frame to previous previousFrame = currentFrame; }
public ProcessedBlob(Blob blob, List<IntPoint> edges, List<IntPoint> hull, Vector4 bounds, ApproximateLine[] lines, bool isQuad, List<IntPoint> quadPoints = null) { Blob = blob; Edges = edges; Hull = hull; Bounds = bounds; Lines = lines; IsQuad = isQuad; if (isQuad) { QuadPoints = quadPoints; } else { QuadPoints = new List<IntPoint>(); } }
public Marker(Blob blob) { _blob = blob; _distansefrommarkers = 0.0d; _distancefromcenter = 0.0d; }
/// <summary> /// The arrayListOfArrayLists of blobs is converted to a resultList. /// </summary> // BLOB COUNTER TO BLOB LIST private void BlobCounterToList(Blob[] blobs) { foreach (Blob b in blobs) { blobList.Add(b); } }
public List<IntPoint> GetEdgePoints(Blob blob) { BlobCounter blobCounter = new BlobCounter(); blobCounter.ProcessImage(ImageBitmap); return blobCounter.GetBlobsEdgePoints(blob); }
public static Bitmap Find(Blob blob, BlobCounter blobCounter, FoundColorSpaces colorSpaces) { List<IntPoint> blobPoints = new List<IntPoint>(); List<IntPoint> leftPoints, rightPoints; blobCounter.GetBlobsLeftAndRightEdges(blob, out leftPoints, out rightPoints); Bitmap bmp = new Bitmap(blob.Rectangle.Width, blob.Rectangle.Height, PixelFormat.Format24bppRgb); for (int c = 0; c < leftPoints.Count; c++) { IntPoint startLeft = leftPoints[c]; IntPoint endRight = rightPoints[c]; for (int x = startLeft.X; x <= endRight.X; x++) { blobPoints.Add(new IntPoint(x - blob.Rectangle.Left, startLeft.Y - blob.Rectangle.Top)); bmp.SetPixel(x - blob.Rectangle.Left, startLeft.Y - blob.Rectangle.Top, colorSpaces.OriginalColorSpace.GetPixel(x, startLeft.Y)); } } double[,] aData = new double[blobPoints.Count, 2]; double[,] eData = new double[blobPoints.Count, 2]; double[] bData = new double[blobPoints.Count]; double centroidX = 0; double centroidY = 0; double total = 0; for (int c = 0; c < blobPoints.Count; c++) { centroidX += blobPoints[c].X; centroidY += blobPoints[c].Y; total++; } centroidX /= total; centroidY /= total; for (int c = 0; c < blobPoints.Count; c++) { eData[c, 0] = blobPoints[c].X - centroidX; eData[c, 1] = blobPoints[c].Y - centroidY; aData[c, 0] = 1; aData[c, 1] = blobPoints[c].X; bData[c] = blobPoints[c].Y; } DenseMatrix E = DenseMatrix.OfArray(eData); DenseMatrix Eprime = (DenseMatrix)E.TransposeThisAndMultiply(E); DenseEvd eigen = new DenseEvd(Eprime); Vector<Complex> eigenValues = eigen.EigenValues(); int maxIndex = 0; double max = 0.0; for (int c = 0; c < eigenValues.Count; c++) { double eigenvalue = eigenValues[c].Real; if (eigenvalue > max) { max = eigenvalue; maxIndex = c; } } Matrix<double> eigenVectors = eigen.EigenVectors(); Vector<double> maxEigenVector = eigenVectors.Column(maxIndex); Matrix<double> xHat = DenseMatrix.OfColumns(2, 1, new List<Vector<double>>(new Vector<double>[] { maxEigenVector })); double radians = System.Math.Asin(xHat[0, 0]); double degrees = radians * (180 / System.Math.PI); // Why doesn't this work? //DenseMatrix A = DenseMatrix.OfArray(aData); //DenseVector b = new DenseVector(bData); //Matrix<double> xHat = (A.TransposeThisAndMultiply(A).Inverse() * A.Transpose() * b).ToColumnMatrix(); RotateBicubic rotate = new RotateBicubic(-degrees); bmp = rotate.Apply(bmp); return bmp; }
// Get array of objects images public static Blob[] GetObjects(Bitmap srcImg) { BlobCounter blobCounter = new BlobCounter(); // process the image blobCounter.ProcessImage(srcImg); int[] labels = blobCounter.ObjectLabels; int count = blobCounter.ObjectsCount; // image size int width = srcImg.Width; int height = srcImg.Height; int i = 0, label; // --- STEP 1 - find each objects coordinates // create object coordinates arrays int[] x1 = new int[count + 1]; int[] y1 = new int[count + 1]; int[] x2 = new int[count + 1]; int[] y2 = new int[count + 1]; for (int k = 1; k <= count; k++) { x1[k] = width; y1[k] = height; } // walk through labels array for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++, i++) { // get current label label = labels[i]; // skip unlabeled pixels if (label == 0) continue; // check and update all coordinates if (x < x1[label]) { x1[label] = x; } if (x > x2[label]) { x2[label] = x; } if (y < y1[label]) { y1[label] = y; } if (y > y2[label]) { y2[label] = y; } } } // --- STEP 2 - get each object Blob[] objects = new Blob[count]; // lock source bitmap data BitmapData srcData = srcImg.LockBits( new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed); int srcStride = srcData.Stride; // create each image for (int k = 1; k <= count; k++) { int xmin = x1[k]; int xmax = x2[k]; int ymin = y1[k]; int ymax = y2[k]; int objectWidth = xmax - xmin + 1; int objectHeight = ymax - ymin + 1; // create new image Bitmap dstImg = AForge.Imaging.Image.CreateGrayscaleImage(objectWidth, objectHeight); // lock destination bitmap data BitmapData dstData = dstImg.LockBits( new Rectangle(0, 0, objectWidth, objectHeight), ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed); // copy image unsafe { byte * src = (byte *) srcData.Scan0.ToPointer() + ymin * srcStride + xmin; byte * dst = (byte *) dstData.Scan0.ToPointer(); int p = ymin * width + xmin; int srcOffset = srcStride - objectWidth; int dstOffset = dstData.Stride - objectWidth; int labelsOffset = width - objectWidth; // for each line for (int y = ymin; y <= ymax; y++) { // copy each pixel for (int x = xmin; x <= xmax; x++, src++, dst++, p++) { if (labels[p] == k) *dst = *src; } src += srcOffset; dst += dstOffset; p += labelsOffset; } } // unlock destination image dstImg.UnlockBits(dstData); objects[k - 1] = new Blob(dstImg, new Point(xmin, ymin), srcImg); } // unlock source image srcImg.UnlockBits(srcData); return objects; }
public SkyObject(SkyVector position, Blob blob) { Position = position; ObjectBlob = blob; }
public SkyObject(string name, SkyVector position, Blob blob) { Name = name; Position = position; ObjectBlob = blob; }
public List<Rectangle> GetBlobRectangles(Blob blob) { BlobCounter blobCounter = new BlobCounter(); blobCounter.ProcessImage(ImageBitmap); return blobCounter.GetObjectsRectangles().ToList(); }
public override void Execute(Bitmap Image) { BlobCounter blobCounter = new BlobCounter(); blobCounter.MinHeight = 75; blobCounter.MinWidth = 75; blobCounter.CoupledSizeFiltering = true; blobCounter.ProcessImage(Image); Blob[] blobs = blobCounter.GetObjects(Image); int maxSize = 0; int TmpX = -100, TmpY = -100; Blob maxObject = new Blob(0, new Rectangle(0, 0, 0, 0)); // find biggest blob if (blobs != null) { foreach (Blob blob in blobs) { int blobSize = blob.Rectangle.Width * blob.Rectangle.Height; if (blobSize > maxSize) { maxSize = blobSize; maxObject = blob; } } if (maxSize > 70) { TmpX = (maxObject.Rectangle.Left + maxObject.Rectangle.Right) / 2; TmpY = maxObject.Rectangle.Top; } } AForge.Imaging.VerticalIntensityStatistics VIS = new VerticalIntensityStatistics(Image); int[] HistVer = VIS.Gray.Values; AForge.Imaging.HorizontalIntensityStatistics HIS = new HorizontalIntensityStatistics(Image); int[] HistHor = HIS.Gray.Values; bool Found = false; for (int i = System.Math.Max(CurrY - GateLengthY / 2, 0); i <= System.Math.Min(CurrY + GateLengthY / 2, HistVer.Length - 2); i++) { if (((double)HistVer[i]) / 255 > 0) { Found = true; CurrY = i; break; } } if (!Found) { Validity = ValidLocation.FALSE; return; } Found = false; for (int i = System.Math.Max(0, CurrX - GateLengthX / 2); i <= System.Math.Min(HistHor.Length - 1, CurrX + GateLengthX / 2); i++) { if (Image.GetPixel(i, CurrY).Name != "ff000000") { Found = true; CurrX = i; break; } } if (!Found) { Validity = ValidLocation.FALSE; return; } /*if (System.Math.Sqrt((CurrX - TmpX) * (CurrX - TmpX) + (CurrY - TmpY) * (CurrY - TmpY)) > 80) { Validity = ValidLocation.FALSE; return; } else Validity = ValidLocation.TRUE; CurrX = TmpX; CurrY = TmpY;*/ Validity = ValidLocation.TRUE; }
private void SelectBlob(Blob _blob) { BitmapData imageData = _recogimg.LockBits( new Rectangle(0, 0, _image.Width, _recogimg.Height), ImageLockMode.ReadWrite, _recogimg.PixelFormat); UnmanagedImage _image8 = new UnmanagedImage(imageData); for (int x = _blob.Rectangle.X; x <= _blob.Rectangle.Right; x++) { _image8.SetPixel(x, _blob.Rectangle.Y, 0); _image8.SetPixel(x, _blob.Rectangle.Bottom, 0); } for (int y = _blob.Rectangle.Y; y <= _blob.Rectangle.Bottom; y++) { _image8.SetPixel(_blob.Rectangle.X, y, 0); _image8.SetPixel(_blob.Rectangle.Right, y, 0); } _recogimg.UnlockBits(imageData); }
private bool CheckBlob(Blob blob) { // The running idea is that we want a specific size blob, about the length and width of a finger. However if our filtering and thresholds are off this fails. if (blob.Rectangle.Width < maxWidth) { if (blob.Rectangle.Height > minHeight) { return true; } } if (blob.Rectangle.Height < maxWidth) { if (blob.Rectangle.Width > minHeight) { return true; } } return false; }