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
        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);
                    }
                }
            }
        }