Beispiel #1
0
        public void ToByteArray_test8pp(PixelFormat pixelFormat, int w, int h, int expected)
        {
            int[,] values = Vector.Range(0, 255).Get(0, h * w).Reshape(h, w);
            UnmanagedImage image = values.ToBitmap().ToUnmanagedImage();

            int formatBytes = pixelFormat.GetPixelFormatSizeInBytes();

            byte[] b = image.ToByteArray();

            Assert.AreEqual(w * h * formatBytes, b.Length);
            Assert.AreEqual(expected, b.Length);

            // Reconstruct the original matrix
            UnmanagedImage r = UnmanagedImage.FromByteArray(b, w, h, pixelFormat);

            byte[,] actual = r.ToManagedImage().ToMatrix(0, 0, 255);

            Assert.AreEqual(values, actual);
        }
        public void ToByteArray_test_general(PixelFormat pixelFormat, int w, int h, int expected)
        {
            int c = pixelFormat.GetNumberOfChannels();

            byte[,,] values = (byte[, , ])Vector.Range((byte)0, (byte)255).Get(0, h * w).Reshape(new[] { h, w, c });
            UnmanagedImage image = values.ToBitmap().ToUnmanagedImage();

            int formatBytes = pixelFormat.GetPixelFormatSizeInBytes();

            byte[] b = image.ToByteArray();

            Assert.AreEqual(w * h * formatBytes, b.Length);
            Assert.AreEqual(expected, b.Length);

            // Reconstruct the original matrix
            UnmanagedImage r = UnmanagedImage.FromByteArray(b, w, h, pixelFormat);

            byte[,,] actual = r.ToManagedImage().ToMatrix((byte)0, (byte)255);

            Assert.AreEqual(values, actual);
        }
Beispiel #3
0
        public void ToByteArray_test_general(PixelFormat pixelFormat, int w, int h, int expected)
        {
            int c = pixelFormat.GetNumberOfChannels();

            byte[,,] values = (byte[, , ])Vector.Range((byte)0, (byte)255).Get(0, c * h * w).Reshape(new[] { h, w, c });
            UnmanagedImage image = values.ToBitmap().ToUnmanagedImage();

            int formatBytes = pixelFormat.GetPixelFormatSizeInBytes();

            byte[] b = image.ToByteArray();

            Assert.AreEqual(w * h * formatBytes, b.Length, "{0} * {1} * {2}, {3}", w, h, formatBytes, b.Length);
            Assert.AreEqual(expected, b.Length, "{0}, {1}", expected, b.Length);

            // Reconstruct the original matrix
            UnmanagedImage r = UnmanagedImage.FromByteArray(b, w, h, pixelFormat);

            byte[,,] actual = r.ToManagedImage().ToMatrix((byte)0, (byte)255);
            string a = String.Join(" ", (string[])Accord.Math.Matrix.ToString(actual).DeepFlatten());
            string e = String.Join(" ", (string[])Accord.Math.Matrix.ToString(values).DeepFlatten());

            Assert.AreEqual(e, a, "{0} == {1}", e, a);
        }
Beispiel #4
0
        static void Main(string[] args)
        {
            var metapath = ".\\..\\..\\..\\demo\\4.input.jpg.meta.json";

            var meta = Newtonsoft.Json.JsonConvert.DeserializeObject <OCR.Shared.ImageInfo>(File.ReadAllText(metapath));

            while (true)
            {
                var pos  = Console.ReadLine().Split(' ').Select(p => int.Parse(p)).ToArray();
                var rect = new OCR.Shared.Rect {
                    X = pos[0], Y = pos[1], W = pos[2], H = pos[3]
                };

                var filtered = meta.Words.Where(
                    p =>
                    p.GravityCenter.X >= rect.X && p.GravityCenter.X <= rect.X + rect.W && p.GravityCenter.Y >= rect.Y && p.GravityCenter.Y <= rect.Y + rect.H ||
                    p.GeometryCenter.X >= rect.X && p.GeometryCenter.X <= rect.X + rect.W && p.GeometryCenter.Y >= rect.Y && p.GeometryCenter.Y <= rect.Y + rect.H).ToArray();

                var newrect = new OCR.Shared.Rect {
                    X = filtered.Min(p => p.Position.X), Y = filtered.Min(p => p.Position.Y), W = 0, H = 0
                };

                foreach (var word in filtered)
                {
                    var width  = word.Position.X - newrect.X + word.Position.W;
                    var height = word.Position.Y - newrect.Y + word.Position.H;
                    if (newrect.W < width)
                    {
                        newrect.W = width;
                    }
                    if (newrect.H < height)
                    {
                        newrect.H = height;
                    }
                }

                var bytes = new byte[newrect.W * newrect.H];
                for (var i = 0; i < newrect.W * newrect.H; i++)
                {
                    bytes[i] = 0xFF;
                }

                foreach (var word in filtered)
                {
                    var offsetx = word.Position.X - newrect.X;
                    var offsety = word.Position.Y - newrect.Y;

                    for (var j = 0; j < word.Position.H; j++)
                    {
                        for (var i = 0; i < word.Position.W; i++)
                        {
                            var d = word.Data[j * word.Position.W + i];
                            if (d == 0xFF)
                            {
                                continue;
                            }

                            bytes[(offsety + j) * newrect.W + offsetx + i] = d;
                        }
                    }
                }

                var umbmp = UnmanagedImage.FromByteArray(bytes, newrect.W, newrect.H, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
                umbmp.ToManagedImage().Save(meta.FileName + "." + newrect.X + "." + newrect.Y + "." + newrect.W + "." + newrect.H + ".crop.jpg", System.Drawing.Imaging.ImageFormat.Png);
            }
        }
Beispiel #5
0
        static void Process2(string fileName)
        {
            Console.WriteLine(fileName);

            var meta = new OCR.Shared.ImageInfo
            {
                FileName     = fileName,
                MaskName     = fileName + ".mask.png",
                FilteredName = fileName + ".filtered.png",
                Words        = new List <OCR.Shared.Blob>(),
                Areas        = new List <OCR.Shared.Rect>()
            };

            using (var img = System.Drawing.Image.FromFile(fileName))
                using (var bmp = new Bitmap(img))
                {
                    var gray = new FiltersSequence(Grayscale.CommonAlgorithms.BT709, new GaussianSharpen(), new ContrastCorrection(20))
                               .Apply(UnmanagedImage.FromManagedImage(bmp));
                    gray.ToManagedImage().Save(fileName + ".gray.png", System.Drawing.Imaging.ImageFormat.Png);

                    var bw = new FiltersSequence(new BradleyLocalThresholding {
                        PixelBrightnessDifferenceLimit = 0.20f
                    }, new Invert())
                             .Apply(gray);
                    bw.ToManagedImage().Save(fileName + ".bw.png", System.Drawing.Imaging.ImageFormat.Png);

                    var mask = new FiltersSequence(new Dilation(), new BlobsFiltering(5, 5, gray.Width / 2, gray.Height / 2, false))
                               .Apply(bw);
                    mask.ToManagedImage().Save(meta.MaskName, System.Drawing.Imaging.ImageFormat.Png);

                    {
                        var ccs     = new BlobCounter(mask).GetObjectsRectangles();
                        var sortedw = ccs.Select(p => p.Width).OrderBy(p => p).ToArray();
                        var sortedh = ccs.Select(p => p.Height).OrderBy(p => p).ToArray();

                        meta.MedianWordSize = new OCR.Shared.Point {
                            X = sortedw[sortedw.Length / 2], Y = sortedh[sortedh.Length / 2]
                        };

                        Console.WriteLine($"Median: {meta.MedianWordSize.X}, {meta.MedianWordSize.Y}");
                    }

                    var filtered = new FiltersSequence(new Invert(), new Intersect(mask), new Invert())
                                   .Apply(gray);

                    var filteredBmp = filtered.ToManagedImage();
                    filteredBmp.Save(meta.FilteredName, System.Drawing.Imaging.ImageFormat.Png);

                    var rgb = new GrayscaleToRGB().Apply(filtered);

                    mask = new FiltersSequence(new HorizontalRunLengthSmoothing(meta.MedianWordSize.X * 2), new VerticalRunLengthSmoothing(meta.MedianWordSize.Y * 2))
                           .Apply(mask);
                    mask.ToManagedImage().Save(fileName + ".area.png", System.Drawing.Imaging.ImageFormat.Png);

                    foreach (Rectangle rect in new BlobCounter(mask).GetObjectsRectangles())
                    {
                        Drawing.FillRectangle(mask, rect, Color.White);
                    }
                    mask.ToManagedImage().Save(fileName + ".rect.png", System.Drawing.Imaging.ImageFormat.Png);

                    foreach (Rectangle rect in new BlobCounter(mask).GetObjectsRectangles())
                    {
                        meta.Areas.Add(new OCR.Shared.Rect {
                            X = rect.X, Y = rect.Y, W = rect.Width, H = rect.Height
                        });
                        Drawing.Rectangle(rgb, rect, Color.Red);
                    }

                    new Intersect(mask).ApplyInPlace(bw);

                    foreach (var blob in new BlobCounter(bw).GetObjects(bw, false))
                    {
                        var outRect = new OCR.Shared.Rect {
                            X = blob.Rectangle.X - 1, Y = blob.Rectangle.Y - 1, W = blob.Rectangle.Width + 2, H = blob.Rectangle.Height + 2
                        };
                        if (outRect.X < 0)
                        {
                            outRect.X = 0; outRect.W--;
                        }
                        if (outRect.Y < 0)
                        {
                            outRect.Y = 0; outRect.H--;
                        }
                        if (outRect.X + outRect.W > bw.Width)
                        {
                            outRect.W = bw.Width - outRect.X;
                        }
                        if (outRect.Y + outRect.H > bw.Height)
                        {
                            outRect.H = bw.Height - outRect.Y;
                        }

                        var gravityCenter = new OCR.Shared.Point {
                            X = (int)blob.CenterOfGravity.X, Y = (int)blob.CenterOfGravity.Y
                        };
                        var geometryCenter = new OCR.Shared.Point {
                            X = blob.Rectangle.X + blob.Rectangle.Width / 2, Y = blob.Rectangle.Y + blob.Rectangle.Height / 2
                        };

                        var bytedata    = blob.Image.ToByteArray();
                        var newbytedata = new byte[outRect.W * outRect.H];
                        for (var j = 0; j < outRect.H - 2; j++)
                        {
                            for (var i = 0; i < outRect.W - 2; i++)
                            {
                                newbytedata[j * outRect.W + i + 1] = bytedata[j * (outRect.W - 2) + i];
                            }
                        }
                        var blobImg = new FiltersSequence(new Dilation()).Apply(UnmanagedImage.FromByteArray(newbytedata, outRect.W, outRect.H, System.Drawing.Imaging.PixelFormat.Format8bppIndexed));

                        var area = new Rectangle(outRect.X, outRect.Y, outRect.W, outRect.H);
                        Drawing.Rectangle(rgb, area, Color.Blue);

                        Drawing.FillRectangle(rgb, new Rectangle(geometryCenter.X - 2, geometryCenter.Y - 2, 5, 5), Color.Magenta);
                        Drawing.FillRectangle(rgb, new Rectangle(gravityCenter.X - 2, gravityCenter.Y - 2, 5, 5), Color.Cyan);

                        var bits = filteredBmp.LockBits(area, System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);

                        meta.Words.Add(
                            new OCR.Shared.Blob
                        {
                            Id             = blob.ID,
                            Data           = new FiltersSequence(new Invert(), new Intersect(blobImg), new Invert()).Apply(new UnmanagedImage(bits)).ToByteArray(),
                            Position       = outRect,
                            GravityCenter  = gravityCenter,
                            GeometryCenter = geometryCenter
                        });

                        filteredBmp.UnlockBits(bits);
                    }



                    rgb.ToManagedImage().Save(fileName + ".marked.png", System.Drawing.Imaging.ImageFormat.Png);

                    File.WriteAllText(fileName + ".meta.json", Newtonsoft.Json.JsonConvert.SerializeObject(meta, Newtonsoft.Json.Formatting.Indented));
                }
        }
Beispiel #6
0
        private UnmanagedImage CreateImage(int frame, TifFileInfo fi, int threshold)
        {
            byte[] image    = new byte[fi.sizeX * fi.sizeY];
            int    position = 0;

            byte zeroInd = 0;

            if (fi.fillHoles)
            {
                zeroInd = 1;
            }

            if (fi.bitsPerPixel == 8)
            {
                byte[][] oldImage = fi.image8bitFilter[frame];
                for (int y = 0; y < fi.sizeY; y++)
                {
                    image[position] = zeroInd;
                    position++;

                    for (int x = 1; x < fi.sizeX - 1; x++, position++)
                    {
                        if (oldImage[y][x] < threshold)
                        {
                            image[position] = 0;
                        }
                        else
                        {
                            image[position] = 255;
                        }
                    }

                    image[position] = zeroInd;
                    position++;
                }
            }
            else if (fi.bitsPerPixel == 16)
            {
                ushort[][] oldImage = fi.image16bitFilter[frame];
                for (int y = 0; y < fi.sizeY; y++)
                {
                    image[position] = zeroInd;
                    position++;

                    for (int x = 1; x < fi.sizeX - 1; x++, position++)
                    {
                        if (oldImage[y][x] < threshold)
                        {
                            image[position] = 0;
                        }
                        else
                        {
                            image[position] = 255;
                        }
                    }

                    image[position] = zeroInd;
                    position++;
                }
            }
            //start fill holes
            if (zeroInd == 1)
            {
                FillHoles(image, fi.sizeX);
            }
            //return image
            return(UnmanagedImage.FromByteArray(image, fi.sizeX, fi.sizeY, System.Drawing.Imaging.PixelFormat.Format8bppIndexed));
        }
Beispiel #7
0
        private bool watershedSegment(byte[] pixels, int width, int height)
        {
            // Create an array with the coordinates of all points between value 1 and 254
            // This method, suggested by Stein Roervik (stein_at_kjemi-dot-unit-dot-no),
            // greatly speeds up the watershed segmentation routine.

            ImageStatistics @is = new ImageStatistics(UnmanagedImage.FromByteArray(pixels, width, height, PixelFormat.Format8bppIndexed));

            int[] histogram = @is.Gray.Values;

            int arraySize = width * height - histogram[0] - histogram[255];

            int[] coordinates  = new int[arraySize];   //from pixel coordinates, low bits x, high bits y
            int   highestValue = 0;
            int   maxBinSize   = 0;
            int   offset       = 0;

            int[] levelStart = new int[256];

            for (int v = 1; v < 255; v++)
            {
                levelStart[v] = offset;
                offset       += histogram[v];
                if (histogram[v] > 0)
                {
                    highestValue = v;
                }
                if (histogram[v] > maxBinSize)
                {
                    maxBinSize = histogram[v];
                }
            }

            int[] levelOffset = new int[highestValue + 1];

            for (int y = 0, i = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++, i++)
                {
                    int v = pixels[i] & 255;

                    if (v > 0 && v < 255)
                    {
                        offset = levelStart[v] + levelOffset[v];
                        coordinates[offset] = x | y << intEncodeShift;
                        levelOffset[v]++;
                    }
                } // for x
            }     // for y

            // Create an array of the points (pixel offsets) that we set to 255 in one pass.
            // If we remember this list we need not create a snapshot of the ImageProcessor.
            int[] setPointList = new int[Math.Min(maxBinSize, (width * height + 2) / 3)];

            // now do the segmentation, starting at the highest level and working down.
            // At each level, dilate the particle (set pixels to 255), constrained to pixels
            // whose values are at that level and also constrained (by the fateTable)
            // to prevent features from merging.
            int[] table = makeFateTable();

            int[] directionSequence = new int[] { 7, 3, 1, 5, 0, 4, 2, 6 }; // diagonal directions first

            for (int level = highestValue; level >= 1; level--)
            {
                int remaining = histogram[level];  //number of points in the level that have not been processed
                int idle      = 0;

                while (remaining > 0 && idle < 8)
                {
                    int dIndex = 0;
                    do
                    {
                        // expand each level in 8 directions
                        int n = processLevel(directionSequence[dIndex % 8], pixels, table,
                                             levelStart[level], remaining, coordinates, setPointList, width, height);

                        //IJ.log("level="+level+" direction="+directionSequence[dIndex%8]+" remain="+remaining+"-"+n);

                        remaining -= n;  // number of points processed

                        if (n > 0)
                        {
                            idle = 0;    // nothing processed in this direction?
                        }
                        dIndex++;
                    } while (remaining > 0 && idle++ < 8);
                }

                // any pixels that we have not reached?
                if (remaining > 0 && level > 1)
                {
                    int nextLevel = level; // find the next level to process
                    do
                    {
                        nextLevel--;
                    }while (nextLevel > 1 && histogram[nextLevel] == 0);

                    // in principle we should add all unprocessed pixels of this level to the
                    // tasklist of the next level. This would make it very slow for some images,
                    // however. Thus we only add the pixels if they are at the border (of the
                    // image or a thresholded area) and correct unprocessed pixels at the very
                    // end by CleanupExtraLines

                    if (nextLevel > 0)
                    {
                        int newNextLevelEnd = levelStart[nextLevel] + histogram[nextLevel];

                        for (int i = 0, p = levelStart[level]; i < remaining; i++, p++)
                        {
                            int  xy        = coordinates[p];
                            int  x         = xy & intEncodeXMask;
                            int  y         = (xy & intEncodeYMask) >> intEncodeShift;
                            int  pOffset   = x + y * width;
                            bool addToNext = false;

                            if (x == 0 || y == 0 || x == width - 1 || y == height - 1)
                            {
                                addToNext = true; // image border
                            }
                            else
                            {
                                for (int d = 0; d < 8; d++)
                                {
                                    if (isWithin(x, y, d, width, height) && pixels[pOffset + dirOffset[d]] == 0)
                                    {
                                        addToNext = true; // border of area below threshold
                                        break;
                                    }
                                }
                            }

                            if (addToNext)
                            {
                                coordinates[newNextLevelEnd++] = xy;
                            }
                        }
                        // tasklist for the next level to process becomes longer by this:
                        histogram[nextLevel] = newNextLevelEnd - levelStart[nextLevel];
                    }
                }
            }
            return(true);
        }