Bradley Local Thresholding plugin imagej

Hey Leute, ich möchte oben genanntes Verfahren auf folgendes Bild anwenden:
yrPdf.png

Ziel ist es, den Hintergrund auf schwarz, die Zellen auf weiß zu setzten.
Mit dem im folgenden implementierten Codeausschnitt bekomme ich für width=75 und tt=5 das folgende Ergebnis:
CqPr7.png

Mit anderen Werten wird es nicht wirklich besser, d.h. das Hintergrundrauschen bleibt. Kann mir da jemand weiterhelfen?

Java:
for (int x = 0; x < ip.getWidth(); x++) {
            for (int y = 0; y < ip.getHeight(); y++) {
                int x1 = x - width/2;               
                int x2 = x + width/2;               
                int y1 = y - width/2;
                int y2 = y + width/2;
               
                if (x1 <= 0) {
                    x1 = 1;
                }
                if (x2 > ip.getWidth()) {
                    x2 = ip.getWidth();
                }
                if (y1 <= 0) {
                    y1 = 1;
                }
                if (y2 > ip.getHeight()) {
                    y2 = ip.getHeight();
                }
               
                float sum = 0;
                float count = 0;
                count = (x2-x1) * (y2-y1);
                sum = integral[x2][y2] - integral[x2][y1-1] - integral[x1-1][y2] + integral[x1-1][y1-1];
                if (image[x][y] * count <= (sum * (100-tt)/100)) {
                    ergebnis[x][y] = 0;
                } else {
                    ergebnis[x][y] = 1;
                }
            }
        }
 

JCODA

Top Contributor
Mhh, interessant.
Du hättest noch deine Quelle für den Algorithmus nennen können. Außerdem ist dein Code ein bisschen aus dem Zusammenhang gerissen.
Nach https://github.com/rmtheis/bradley-adaptive-thresholding/blob/master/main.cpp interpretiere ich mal, dass integral eine Art SummedAreaTable (https://en.wikipedia.org/wiki/Summed_area_table) ist ... oh tatsächlich heißt das deutsche Wort Integralbild (https://de.wikipedia.org/wiki/Integralbild) dafür ...
Jedenfalls wäre der Rest des Programmes für mich noch interessant, am besten in einer sofort kompilierbaren Form, dann könnte ich selbst ein bisschen an den Werten schrauben.
Hast du bereits mal t = 15 (ähnlich dem Code von der obigen Quelle) probiert?
Ansonsten sehe ich momentan keine Unterschiede zu obigen Code.
 
Also das ist die Methode, mit der ich mein Integralbild erstelle. Das sieht soweit ganz gut aus meiner Meinung nach.
Java:
private FloatProcessor getIntegralImage(FloatProcessor ip) {
        float[][] image = ip.getFloatArray();
        FloatProcessor integral = new FloatProcessor(ip.getWidth() + 1, ip.getHeight() + 1);
        float[][] ergebnis = integral.getFloatArray();
        for (int x = 1; x <= ip.getWidth(); x++) {
            for (int y = 1; y <= ip.getHeight(); y++) {
                ergebnis[x][y] = image[x - 1][y - 1] + ergebnis[x][y - 1] + ergebnis[x - 1][y] - ergebnis[x - 1][y - 1];
            }
        }
       
        integral.setFloatArray(ergebnis);
        // new ImagePlus("Integral", integral).show();
        return integral;
    }

Hier folgt dann die Methode, mit der ich mein Endresultat erzeugen will.
Java:
private FloatProcessor bradleySegmentation(FloatProcessor ip, int width, float tt) {
        float[][] image = ip.getFloatArray();
        FloatProcessor result = new FloatProcessor(ip.getWidth(), ip.getHeight());
        float[][] ergebnis = result.getFloatArray();
        FloatProcessor ii = getIntegralImage(ip);
        float[][] integral = ii.getFloatArray();
       
        for (int x = 0; x < ip.getWidth(); x++) {
            for (int y = 0; y < ip.getHeight(); y++) {
                int x1 = x - width/2;               
                int x2 = x + width/2;               
                int y1 = y - width/2;
                int y2 = y + width/2;
               
                if (x1 <= 0) {
                    x1 = 1;
                }
                if (x2 > ip.getWidth()) {
                    x2 = ip.getWidth();
                }
                if (y1 <= 0) {
                    y1 = 1;
                }
                if (y2 > ip.getHeight()) {
                    y2 = ip.getHeight();
                }
               
                float sum = 0;
                float count = 0;
                count = (x2-x1) * (y2-y1);
                sum = integral[x2][y2] - integral[x2][y1-1] - integral[x1-1][y2] + integral[x1-1][y1-1];
                if (image[x][y] * count <= (sum * (100-tt)/100)) {
                    ergebnis[x][y] = 0;
                } else {
                    ergebnis[x][y] = 1;
                }
            }
        }
                   
        result.setFloatArray(ergebnis);
        return result;
    }

und schliesslich lass ich es mir in der run-Methode anzeigen.

Java:
FloatProcessor braro = bradleySegmentation(ip.convertToFloatProcessor(), 75, 5);
            ImagePlus bar = new ImagePlus("Bradley and Roth", braro);
            bar.show();

tt= 15 hab ich probiert, das sieht noch "schlechter" aus. Glaub mir, ich habe schon einige Werte eingesetzt, es will nicht so recht.^^
 
Alternativ das Ganze gleich kompakt in der run-Methode:
Java:
import ij.ImagePlus;
import ij.plugin.filter.PlugInFilter;
import ij.process.FloatProcessor;
import ij.process.ImageProcessor;


public class Rotate_Filter implements PlugInFilter {

    @Override
    public void run(ImageProcessor ip) {
        float[][] image = ip.getFloatArray();
        FloatProcessor integral = new FloatProcessor(ip.getWidth() + 1, ip.getHeight() + 1);
        float[][] ergebnis = integral.getFloatArray();
        for (int x = 1; x <= ip.getWidth(); x++) {
            for (int y = 1; y <= ip.getHeight(); y++) {
                ergebnis[x][y] = image[x - 1][y - 1] + ergebnis[x][y - 1] + ergebnis[x - 1][y] - ergebnis[x - 1][y - 1];
            }
        }
       
        integral.setFloatArray(ergebnis);
        // new ImagePlus("Integral", integral).show();
       
        FloatProcessor result = new FloatProcessor(ip.getWidth(), ip.getHeight());
        float[][] ergebnis1 = result.getFloatArray();
       
       
        for (int x = 0; x < ip.getWidth(); x++) {
            for (int y = 0; y < ip.getHeight(); y++) {
                int x1 = x - 75/2;               
                int x2 = x + 75/2;               
                int y1 = y - 75/2;
                int y2 = y + 75/2;
               
                if (x1 <= 0) {
                    x1 = 1;
                }
                if (x2 > ip.getWidth()) {
                    x2 = ip.getWidth();
                }
                if (y1 <= 0) {
                    y1 = 1;
                }
                if (y2 > ip.getHeight()) {
                    y2 = ip.getHeight();
                }
               
                float sum = 0;
                float count = 0;
                count = (x2-x1) * (y2-y1);
                sum = ergebnis[x2][y2] - ergebnis[x2][y1-1] - ergebnis[x1-1][y2] + ergebnis[x1-1][y1-1];
                if (image[x][y] * count <= (sum * (100-5)/100)) {
                    ergebnis1[x][y] = 0;
                } else {
                    ergebnis1[x][y] = 1;
                }
            }
        }
                   
        result.setFloatArray(ergebnis1);
        new ImagePlus("Bradley", result).show();
       
    }
   

    @Override
    public int setup(String arg0, ImagePlus arg1) {
        // TODO Auto-generated method stub
        return DOES_8G;
    }

}
 
Das ist auf jeden Fall besser, leider immer noch nicht mein gewünschtes Ergebnis. Ich bleib dran und poste die Lösung hier (falls ich sie jemals herausfinde^^)
 
Aktualisierter Code:
Java:
private FloatProcessor bradleySegmentation(FloatProcessor ip, int width, float tt) {
        float[][] image = ip.getFloatArray();
        FloatProcessor result = new FloatProcessor(ip.getWidth(), ip.getHeight());
        float[][] ergebnis = result.getFloatArray();
        FloatProcessor ii = getIntegralImage(ip);
        float[][] integral = ii.getFloatArray();
        float[][] sum = new float[ip.getWidth()][ip.getHeight()];
       
        for (int x = 0; x < ip.getWidth() - width; x++) {
            for (int y = 0; y < ip.getHeight() - width; y++) {
                float summe = 0;
                summe = integral[x + width][y + width] - integral[x][y + width] - integral[x + width][y] + integral[x][y];
                sum[x + (width - 1) / 2][y + (width - 1) / 2] = summe;
            }
        }       
               
        // FloatProcessor s = new FloatProcessor(sum);
        // new ImagePlus ("sum", s).show();
       
        for (int x = 0; x < ip.getWidth(); x++) {
            for (int y = 0; y < ip.getHeight(); y++) {               
                float count = width * width;
                if (image[x][y] * count <= (sum[x][y] * (100-tt)/100)) {
                    ergebnis[x][y] = 0;
                } else {
                    ergebnis[x][y] = 1;
                }
            }   
        }
                   
        result.setFloatArray(ergebnis);
        return result;
    }
Vorher Ausgangsbild invertieren und mit width = 150/149 und tt=5.1 folgendes Ergebnis:
6cskE.png
 

Ähnliche Java Themen

Neue Themen


Oben