/// <summary> /// Collects the labeling objects. /// </summary> /// <param name="count">The objects count.</param> /// <param name="map">The objects labels map.</param> /// <returns>The list of objects segments.</returns> private SegmentInfo[] CollectObjects(int count, byte[] map) { int label = 0; int position = 0; int[] x1 = new int[count + 1]; int[] y1 = new int[count + 1]; int[] x2 = new int[count + 1]; int[] y2 = new int[count + 1]; long[] cx = new long[count + 1]; long[] cy = new long[count + 1]; long[] area = new long[count + 1]; for (int j = 1; j <= count; ++j) { x1[j] = this.width; y1[j] = this.height; } for (int y = 0; y < this.height; ++y) { for (int x = 0; x < this.width; ++x, ++position) { label = map[position]; if (label == 0) { continue; } x1[label] = x < x1[label] ? x : x1[label]; x2[label] = x > x2[label] ? x : x2[label]; y1[label] = y < y1[label] ? y : y1[label]; y2[label] = y > y2[label] ? y : y2[label]; cx[label] += x; cy[label] += y; area[label]++; } } double absoluteAreaThrehold = 0; double absoluteWidthThrehold = 0; double absoluteHeightThrehold = 0; for (int i = 1; i <= count; ++i) { absoluteAreaThrehold = Math.Max(absoluteAreaThrehold, area[i]); absoluteWidthThrehold = Math.Max(absoluteWidthThrehold, x2[i] - x1[i]); absoluteHeightThrehold = Math.Max(absoluteHeightThrehold, y2[i] - y1[i]); cx[i] /= area[i]; cy[i] /= area[i]; } absoluteAreaThrehold = this.areaThreshold * absoluteAreaThrehold; absoluteWidthThrehold = this.sizeThreshold * absoluteWidthThrehold; absoluteHeightThrehold = this.sizeThreshold * absoluteHeightThrehold; List <SegmentInfo> result = new List <SegmentInfo>(); for (int j = 1; j <= count; ++j) { if (area[j] < absoluteAreaThrehold || (x2[j] - x1[j]) < (absoluteWidthThrehold) || (y2[j] - y1[j]) < absoluteHeightThrehold) { continue; } SegmentInfo info = ComputeSegmentInfo(j, map, x1[j], x2[j], y1[j], y2[j], (int)cx[j], (int)cy[j]); if (info != null) { result.Add(info); } } return(result.ToArray()); }
/// <summary> /// Extracts the objects from the specified image. /// </summary> /// <param name="image">The image.</param> /// <param name="segments">The fingerprint segments.</param> /// <param name="fingerImages">The cropped and rotated segments images.</param> /// <returns><c>true</c> if extractions completes successfully; otherwise, <c>false</c>.</returns> public bool Extract(Bitmap image, out SegmentInfo[] segments, out Image[] fingerImages) { if (!Extract(image, out segments)) { fingerImages = new Image[segments.Length]; return(false); } fingerImages = new Image[segments.Length]; PointF[] vertices = new PointF[4]; Matrix transformation = new Matrix(); int[] limits = new int[4]; for (int i = 0; i < segments.Length; ++i) { SegmentInfo info = segments[i]; int halfWidth = info.Size.Width / 2; int halfHeight = info.Size.Height / 2; transformation.Reset(); transformation.Translate(info.Centroid.X, info.Centroid.Y); transformation.Rotate(-info.Rotation); vertices[0] = new PointF(-halfWidth, -halfHeight); vertices[1] = new PointF(halfWidth, -halfHeight); vertices[2] = new PointF(-halfWidth, halfHeight); vertices[3] = new PointF(halfWidth, halfHeight); limits[0] = int.MaxValue; limits[1] = 0; limits[2] = int.MaxValue; limits[3] = 0; transformation.TransformPoints(vertices); for (int j = 0; j < 4; ++j) { limits[0] = (int)Math.Min(limits[0], vertices[j].X); limits[1] = (int)Math.Max(limits[1], vertices[j].X); limits[2] = (int)Math.Min(limits[2], vertices[j].Y); limits[3] = (int)Math.Max(limits[3], vertices[j].Y); } int cropWidth = limits[1] - limits[0]; int cropHeight = limits[3] - limits[2]; Bitmap segmentImage = new Bitmap(info.Size.Width, info.Size.Height); transformation.Reset(); transformation.Translate(-cropWidth / 2, -cropHeight / 2); transformation.Rotate(info.Rotation, MatrixOrder.Append); transformation.Translate(halfWidth, halfHeight, MatrixOrder.Append); using (Graphics gfx = Graphics.FromImage(segmentImage)) { gfx.Transform = transformation; gfx.InterpolationMode = InterpolationMode.HighQualityBicubic; gfx.SmoothingMode = SmoothingMode.HighQuality; gfx.DrawImage(image, 0.0f, 0.0f, new Rectangle(limits[0], limits[2], cropWidth, cropHeight), GraphicsUnit.Pixel); } fingerImages[i] = segmentImage; } return(true); }