public static bool IsTissue(Bitmap image)
        {
            const double GRENZ_ENTROPIE = 0.5;

            var bitmapProcessor = new BitmapProcessor(image);//liefert schnelleren Zugriff auf die Pixel-Werte, alternativ auch SharpAccessory.Imaging.Processors.GrayscaleProcessor

            int[] greyArray = new int[256];

            for (var y = 0; y < bitmapProcessor.Height; y++)
            {
                for (var x = 0; x < bitmapProcessor.Width; x++)
                {
                    var r = bitmapProcessor.GetRed(x, y);
                    var g = bitmapProcessor.GetGreen(x, y);
                    var b = bitmapProcessor.GetBlue(x, y);

                    var grauwert = (int)(r + g + b) / 3;
                    greyArray[grauwert]++;
                }
            }
            bitmapProcessor.Dispose();

            //Calculate Shannon Entropie
            return(calcEntropie(greyArray) > GRENZ_ENTROPIE);
        }
Example #2
0
    public override ProcessResult Execute(ProcessExecutionParams p)
    {
        GrayscaleProcessor gp = new GrayscaleProcessor(new Bitmap(p.Bitmap), RgbToGrayscaleConversion.None);

        BitmapProcessor bp = new BitmapProcessor(p.Bitmap.Clone() as Bitmap);

        for (int dy = 0; dy < gp.Height; dy++)
        {
            for (int dx = 0; dx < gp.Width; dx++)
            {
                int pixel = (int)bp.GetPixel(dx, dy);

                int r = (pixel & 0x00ff0000) >> 16;
                int g = (pixel & 0x0000ff00) >> 08;
                int b = (pixel & 0x000000ff) >> 00;

                int max = Math.Max(Math.Max(r, g), b);
                int min = Math.Min(Math.Min(r, g), b);

                int range = max - min;

                int level = (r + g + b) / 3;

                int val = level - range;

                if (val > 255)
                {
                    val = 255;
                }
                if (val < 0)
                {
                    val = 0;
                }

                gp.SetPixel(dx, dy, (UInt32)level);
            }
        }

        GrayscaleProcessor gpSobel = (GrayscaleProcessor)gp.Clone();

        new SobelEdgeDetector().Execute(gpSobel);

        ObjectLayer l1stLevel = Execute1stLevelSegmentation(gp, gpSobel);

        ObjectLayer l2ndLevel = Execute2ndLevelSegmentation(l1stLevel, gp);

        gpSobel.WriteBack = false;
        gp.WriteBack      = false;

        gpSobel.Dispose();
        gp.Dispose();
        bp.Dispose();

        gpSobel.Bitmap.Dispose();
        gp.Bitmap.Dispose();
        bp.Bitmap.Dispose();

        l1stLevel.Name = "1st Level";
        l2ndLevel.Name = "2nd Level";

        return(new ProcessResult(new ObjectLayer[] { l1stLevel, l2ndLevel }));
    }
Example #3
0
        private static void Main(string[] args)
        {
            const double GRENZ_ENTROPIE = 0.1;

            foreach (var slideName in Util.GetSlideFilenames(new string[] { args[0] }))
            {
                using (var slideCache = new SlideCache(slideName)){
                    // scale=1 -> baselayer , sollte so klein wie möglich sein um die Rechenzeit zu minimieren
                    // targetSize Größe der zu prozessierenden Bilder, hängt von der hardware ab und bestimmt die Auflösung der Heatmap, für niedrige scale-Werte sollte auch die Größe reduziert werden
                    // Auflösung: Breite=tissueSlidePartitioner.Columns Höhe=tissueSlidePartitioner.Rows
                    // var: implizit typisiert, tatsächlich stark typisiert da der Compiler den Typ kennt; RMT->Goto To Definition
                    // Empfehlung: http://shop.oreilly.com/product/0636920040323.do die 5.0 gibt es auch als pdf im Internet
                    var tissueSlidePartitioner = new SlidePartitioner <bool>(slideCache.Slide, 0.2f, new Size(500, 500)); //Nicht unbedingt auf dem Baselayerr arbeiten zB. 1f --> 0.1
                    using (var overViewImage = slideCache.Slide.GetImagePart(0, 0, slideCache.Slide.Size.Width, slideCache.Slide.Size.Height, tissueSlidePartitioner.Columns, tissueSlidePartitioner.Rows)){
                        //TODO falls die Gewebeerkennung auf dem Übersichtsbild stattfinden soll, dann hier
                        slideCache.SetImage("overview", overViewImage);                       //speichert unter C:\ProgramData\processingRepository\[slideCache.SlideName]\...
                    }

                    //Multithreading
                    Parallel.ForEach(tissueSlidePartitioner.Values, (tile) =>
                    {
                        using (var tileImage = slideCache.Slide.GetImagePart(tile))
                        {
                            var containsTissue = false;
                            double entropie    = 0.0;
                            #region hier sollte containsTissue richtig bestimmt werden
                            var bitmapProcessor = new BitmapProcessor(tileImage);//liefert schnelleren Zugriff auf die Pixel-Werte, alternativ auch SharpAccessory.Imaging.Processors.GrayscaleProcessor

                            int[] greyArray = new int[256];

                            for (var y = 0; y < bitmapProcessor.Height; y++)
                            {
                                for (var x = 0; x < bitmapProcessor.Width; x++)
                                {
                                    var r = bitmapProcessor.GetRed(x, y);
                                    var g = bitmapProcessor.GetGreen(x, y);
                                    var b = bitmapProcessor.GetBlue(x, y);

                                    var grauwert = (int)(r + g + b) / 3;
                                    greyArray[grauwert]++;
                                }
                            }
                            bitmapProcessor.Dispose();

                            //Calculate Shannon Entropie
                            entropie = calcEntropie(greyArray);

                            //Contains Tissue ermitteln
                            if (0 == tile.Index.Y)
                            {
                                containsTissue = false;//oberste Reihe sollte kein Gewebe enthalten
                            }
                            else
                            {
                                //if (slideCache.Slide.GetAnnotationsInArea(tile.SourceArea).Any()) containsTissue = true;//Kacheln mit Annotationen enthalten Gewebe
                                if (entropie > GRENZ_ENTROPIE)
                                {
                                    containsTissue = true;
                                }
                            }
                            #endregion

                            //Wert zur Kachel speichern
                            tile.Data = containsTissue;

                            //Only for Debug
                            var saveImage = false;
                            if (saveImage)
                            {
                                string path = args[1] + @"\" + slideCache.SlideName + @"\";
                                if (containsTissue)
                                {
                                    path += @"isTissue\";
                                }
                                else
                                {
                                    path += @"noTissue\";
                                }

                                if (!Directory.Exists(path))
                                {
                                    Directory.CreateDirectory(path);
                                }
                                tileImage.Save(path + tile.Index.X + "-" + tile.Index.Y + ".png");
                                //var tileCache = slideCache.GetTileCache(tile.Index);
                                //tileCache.SetImage("rgb",tileImage);//speichert unter C:\ProgramData\processingRepository\[slideCache.SlideName]\[Index]\... ansonsten tileImage.Save("[uri].png")
                            }
                            Console.WriteLine(slideCache.SlideName + "-" + tile.Index + " done - containsTissue: " + containsTissue.ToString() + " - entropie: " + entropie.ToString());
                        }
                    });
                    //true wird zu grün, false zu rot; syntax ist lambda (=>) mit einem conditional operator (?)
                    Func <bool, Color> f = b =>
                    {
                        if (b)
                        {
                            return(Color.Red);
                        }
                        else
                        {
                            return(Color.Green);
                        }
                    };
                    using (var heatMap = tissueSlidePartitioner.GenerateHeatMap(f))
                    {
                        slideCache.SetImage("tissueHeatMap", heatMap);
                    }
                }
            }
        }
        static void Main(string[] args)
        {
            #region init
              if (0 == args.Length)
              {
            Console.WriteLine("no slide name");
            return;
              }
              var slideName = args[0];
              var processinHelper = new Processing(slideName);
              var slide = processinHelper.Slide;
              #endregion init

              var part = new WsiPartitioner(new Rectangle(new Point(0, 0), slide.Size), new Size(1000, 1000), new Size(0, 0), 1.0);
              var tissueData = new TiledProcessInformation<bool>(part, slideName);

              #region global tissue detection
              int overviewImageWidth = slide.Size.Width / OverviewTileSize;
              int overviewImageHeight = slide.Size.Height / OverviewTileSize;

              Bitmap overviewImage = slide.GetImagePart(0, 0, slide.Size.Width, slide.Size.Height, overviewImageWidth, overviewImageHeight);

              var bitmapProcessor = new BitmapProcessor(overviewImage);

              ObjectLayer overviewLayer = new TissueDetector().Execute(bitmapProcessor, Radius, NoiseLevel);

              bitmapProcessor.Dispose();

              DrawObjectsToImage(overviewImage, overviewLayer, Color.Black);
              overviewImage.Save(processinHelper.DataPath + "tissueDetectionOverview.png");
              #endregion global tissue detection

              //part.Tiles[]
              foreach (var tile in part)
              {
            #region global tissue detection
            var rect = tile.SourceRect;
            int overviewX = rect.X / OverviewTileSize;
            int overviewY = rect.Y / OverviewTileSize;
            int windowSize = rect.Width / OverviewTileSize;

            bool tileInObject = true;
            int partsOutside = 0;

            for (int y = 0; y < windowSize; y++)
            {
              for (int x = 0; x < windowSize; x++)
              {
            int newX = overviewX + x;
            int newY = overviewY + y;

            if (newX < 0 || newX >= overviewLayer.Map.Width || newY < 0 || newY >= overviewLayer.Map.Height) { continue; }

            uint id = overviewLayer.Map[newX, newY];
            if (id != 0) continue;
            partsOutside++;
            if (!(partsOutside >= Math.Pow(windowSize + 1, 2) * 0.75)) continue;
            tileInObject = false;
            break;
              }
              if (!tileInObject) { break; }
            }
            tissueData.AddDataToCurrentTile(tileInObject);
            #endregion global tissue detection
            if (tileInObject) Console.WriteLine(tile.SourceRect + ":" + partsOutside);
              }
              tissueData.ToFile(processinHelper.DataPath + "tissueData.tpi");
              using (Bitmap b = tissueData.GenerateHeatMap(tissue => tissue ? Color.Green : Color.Red))
            b.Save(processinHelper.DataPath + "tissueData.png");

              Console.WriteLine("done");
              Console.ReadKey();
        }
        private static void processInput()
        {
            int Radius = 2;
              int NoiseLevel = 10;

              Console.WriteLine("Processing Input...");
              foreach (var import in importItems)
              {
            Console.WriteLine();
            Console.WriteLine(import.FileName);

            Console.WriteLine("Slide extrahieren...");
            var processingHelper = new Processing(import.FileName);
            var slide = processingHelper.Slide;

            Console.WriteLine("Ausschnitt aus Slide extrahieren mit originaler Auflösung...");
            int partImageWidth = import.LowerRight.X - import.UpperLeft.X;
            int partImageHeight = import.LowerRight.Y - import.UpperLeft.Y;
            Bitmap partImage = slide.GetImagePart(
              import.UpperLeft.X, import.UpperLeft.Y,
              partImageWidth, partImageHeight,
              partImageWidth, partImageHeight
            );

            #region global tissue detection
            Console.WriteLine("Gewebe suchen und in separatem Layer speichern...");
            var bitmapProcessor = new BitmapProcessor(partImage);
            ObjectLayer overviewLayer = new TissueDetector().Execute(bitmapProcessor, Radius, NoiseLevel);
            bitmapProcessor.Dispose();

            Console.WriteLine("Gewebe-Layer in Ausschnitt zeichnen + speichern...");
            DrawObjectsToImage(partImage, overviewLayer, Color.Black);
            partImage.Save(processingHelper.DataPath + "ImagePartTissue.png");
            #endregion global tissue detection

            #region Deconvolution
            Console.WriteLine("Execute deconvolution 3...");
            var gpX = new ColorDeconvolution().Get3rdStain(partImage, ColorDeconvolution.KnownStain.HaematoxylinEosin);
            gpX.Dispose();
            Bitmap gpX_bmp = gpX.Bitmap;
            gpX_bmp.Save(processingHelper.DataPath + "ImagePartColor3.png");

            Console.WriteLine("Execute deconvolution 2...");
            var gpE = new ColorDeconvolution().Get2ndStain(partImage, ColorDeconvolution.KnownStain.HaematoxylinEosin);
            gpE.Dispose();
            Bitmap gpE_bmp = gpE.Bitmap;
            gpE_bmp.Save(processingHelper.DataPath + "ImagePartColor2.png");

            Console.WriteLine("Execute deconvolution 1...");
            var gpH = new ColorDeconvolution().Get1stStain(partImage, ColorDeconvolution.KnownStain.HaematoxylinEosin);
            gpH.Dispose();
            Bitmap gpH_bmp = gpH.Bitmap;
            gpH_bmp.Save(processingHelper.DataPath + "ImagePartColor1.png");
            #endregion Deconvolution

            #region execute edge detection
            Console.WriteLine("Execute edge detection...");
            SobelResponse responseH = Filtering.ExecuteSobel(gpH_bmp);
            SobelResponse responseE = Filtering.ExecuteSobel(gpE_bmp);
            var substracted = new double[responseH.Size.Width, responseH.Size.Height];
            var substractedRange = new Range<double>();
            for (var x = 0; x < responseH.Size.Width; x++)
            {
              for (var y = 0; y < responseH.Size.Height; y++)
              {
            var value = Math.Max(0, responseE.Gradient[x, y] - responseH.Gradient[x, y]);
            substracted[x, y] = value;
            substractedRange.Add(value);
              }
            }
            double[,] nonMaximumSupression = Filtering.ExecuteNonMaximumSupression(substracted, responseE.Orientation);
            Bitmap edges = Visualization.Visualize(nonMaximumSupression, Visualization.CreateColorizing(substractedRange.Maximum));
            edges.Save(processingHelper.DataPath + "ImagePartEdges.png");
            #endregion execute edge detection

            exportItems.Add(
              new Ausgabe {
            Identify = import.Identify,
            Result = false,
            Message = "kein Fehler"
              }
            );
              }
        }