logischer Fehler im Code


  • Mod

    Hi!

    Ich habe mein Spielzeug kaputt gemacht! 😞

    Genauer gesagt handelt es sich um eine Klasse, die einen Bildpunkt bi-kubisch interpolieren soll. Also wenn man einen Punkt als Paar von floats gegeben hat, dann soll ein Objekt meiner Klasse ein bi-kubisches Polygon über die 4*4 umgebenden gegebenen Bildpunkte legen und damit bestimmen, welchen genauen Wert wohl der gesuchte Bildpunkt hat. Das ganze hat schonmal funktioniert, dann habe ich aber eine kleine Veränderung gemacht und jetzt funktioniert es nicht mehr. Ich muss für die Berechnung ein lineares Gleichungssystem lösen. Das mache ich jetzt auf eine andere Art und Weise. Allerdings werden die Gleichungssysteme wohl korrekt gelöst. Ich habe die Funktionsweise meiner Matrix-Klasse, die ich dazu verwende, mehrmals geprüft.

    Fehlerbeschreibung:

    Ich nutze das zum Vergrößern von Bildern. Jetzt treten aber im Vergrößerten Bild dunkle, horizontale Streifen auf (so ähnlich, wie bei diesen alten Videos, wo jede 2. Zeile schwarz war). Zudem scheint es vertikal Übergänge von hell nach dunkel zu geben. Ansonsten sieht es so aus, als ob das tatsächliche Bild dahinter liegt.

    Code:

    [java]
    package image.pixelInterpolator;

    import image.PixelInterpolator;
    import myMath.MyMath;
    import myMath.matrix.Matrix;

    /**
    *
    * @author Otaku 2
    */
    public final strictfp class BiCubicInterpolator extends PixelInterpolator
    {
    private static float [][] inverseMatrix;

    /** Creates a new instance of BiCubicInterpolator /
    public BiCubicInterpolator ()
    {
    if (inverseMatrix == null)
    {
    int x,y;
    float [][] equationSystem = new float [16][];
    for (x = 0 ; x < 4 ; ++x)
    {
    for (y = 0 ; y < 4 ; ++y)
    {
    equationSystem [4
    x+y] = createBiCubicPolygonValues ((float)x - 1.5f,
    (float)y - 1.5f);
    }
    }
    inverseMatrix = Matrix.invert(equationSystem);
    }
    }

    public final int interpolate (final int[] values, final int width,
    final int height, final float x,
    final float y)
    {
    int xOffset = MyMath.floor (x) - 1;
    int yOffset = MyMath.floor 👍 - 1;
    int i,j;
    int currentX, currentY;
    final float [] tempArray = new float [16];
    for (j = 0 ; j < 4 ; ++j)
    {
    currentY = yOffset+j;
    if ((currentY < 0) || (currentY >= height)) continue;
    for (i = 0 ; i < 4 ; ++i)
    {
    currentX = xOffset+i;
    if ((currentX < 0) || (currentX >= width)) continue;
    tempArray [4*i+j] = (float)values [currentY*width+currentX];
    }
    }
    final float [] coefficients = Matrix.multiply(inverseMatrix,tempArray);
    final float result = getBiCubicPolygonResult (x - (float)xOffset - 1.5f,
    y - (float)yOffset - 1.5f,
    coefficients);
    if (result > 255.0f) return 255;
    if (result < 0.0f) return 0;
    return MyMath.round (result);
    }

    private static float [] createBiCubicPolygonValues (final float x,
    final float y)
    {
    int i,j;
    float [] xPowers = {1.0f,x,x*x,x*xx};
    float [] yPowers = {1.0f,y,y*y,y*y
    y};
    float [] polygonValues = new float [16];
    for (i = 0 ; i < 4 ; ++i)
    {
    for (j = 0 ; j < 4 ; ++j)
    {
    polygonValues [4*i+j] = xPowers [i] * yPowers [j];
    }
    }
    return polygonValues;
    }

    private static float getBiCubicPolygonResult (final float x,
    final float y,
    final float [] coefficients)
    {
    int i,j;
    float [] xPowers = {1.0f,x,x*x,x*xx};
    float [] yPowers = {1.0f,y,y*y,y*y
    y};
    float result = 0.0f;
    for (i = 0 ; i < 4 ; ++i)
    {
    for (j = 0 ; j < 4 ; ++j)
    {
    result += coefficients[i*4+j] * xPowers [i] * yPowers [j];
    }
    }
    return result;
    }
    }[/code]

    Ich habe wirklich keine Ahnung, wo hier der Fehler liegt. Sieht einer von euch den Fehler?



  • Sach ma, wie dat ganze eigentlich funktioniert, aufgebaut ist, etc...


  • Mod

    In dem Programm funktioniert das folgendermaßen:

    1. Ich erzeuge mir ein vergrößertes Bild, welches erstmal noch vollkommen leer ist.

    2. Ich mache für jeden Bildpunkt des neuen Bildes folgendes:

    • Ich erzeuge mir den Ursprungspunkt auf dem Ausgangsbild als float-Paar. Wenn das Ausgangsbild die Maße 100*100 hat und ich auf einem Zielbild der Größe 200*200 den Punkt (1/1) zurückrechne, dann komme ich also auf den Punkt (0.5/0.5).
    • Ich interpoliere Rot-, Grün- und Blauwert des zurückgerechneten Pixels. Das kann zum Beispiel mit dem Bi-kubischen Interpolator von da oben geschehen.
    • Ich setze den Pixel des Zielbildes auf die Werte, die ich bei der Interpolation rausgekriegt habe.

    Jetzt zur bi-kubischen Interpolation:

    Wenn man n Punkte gegeben hat, dann kann man da ein eindeutiges Polynom vom Grad n-1 durchlegen. Dafür muss man ein lineares Gleichungssystem lösen. Beispiel:

    Ich habe die Punkte x1=0, y1=1 und x2=1, y2=3 und x3=2, y3=2. Daraus ergeben sich folgende Gleichungen für ein Polygon 2. Grades:

    1. a2*(02)+a1*(01)+a0*(0^0)=1
    2. a2*(12)+a1*(11)+a0*(1^0)=3
    3. a2*(22)+a1*(21)+a0*(2^0)=2

    Mit diesen Gleichungen bestimme ich a0, a1 und a2 des Polygons a2*(x2)+a1*(x1)+a0*(x^0), welches dann durch alle Punkte geht.

    In meinem Programm läuft das genauso ab, allerdings habe ich da kein eindimensionales Polygon vom Grad 2, sondern ein bi-kubisches, also ein 2-dimensionales Polygon, das bis x^3 und y^3 geht.

    Wie mache ich das genau?

    Ein lineares Gleichungssystem kann man als folgendermaßen schreiben:
    (M = Matrix, a,b = Spaltenvektor)

    M*a=b

    Dabei stehen in a die gesuchten Variablen und in b steht das, was in dem oberen Gleichungssystem hinter dem Gleichheitszeichen steht. In M steht der Rest.

    Wenn ich hier M invertiere und beide Seiten mit der invertierten Matrix multipliziere, dann ergibt sich folgendes:

    a=(M^-1)*b

    Bei dem Interpolator brauche ich die Matrix nur einmal invertieren, weil sie immer gleich ist. Das mache ich im Konstruktor. M^-1 ist also die "inverseMatrix". Warum ist die Matrix immer gleich? Ich verschiebe einfach den Punkt, den ich interpolieren will so, dass der Punkt zwischen -0.5 und 0.5 liegt. Natürlich nehme ich aber die richtigen umliegenden Punkte zur Interpolation. Das geschieht jeweils in der interpolate-Methode. Die Werte der umliegenden Punkte werden hier immer in das tempArray gesteckt (das ist b in dem oberen Beispiel). Dann multipliziere ich M^-1 mit b, um a herauszukriegen. a ist in meinem Programm das Array coefficients. Mit a und dem gegebenen Punkt kann ich mir dann den interpolierten Wert ausrechnen. Das geschieht in getBiCubicPolygonResult.

    ...und das war es eigentlich.



  • ... logisch oder? 🙂

    (Anm. d. Mod.: ***Ich liebe Imaging... ;)***)


  • Mod

    Original erstellt von CengizS:
    **... logisch oder? 🙂

    (Anm. d. Mod.: ***Ich liebe Imaging... ;)*)

    Erklärung bitte! 🙂

    IMHO ist beim Programmieren alles logisch! ...bei der Bildverarbeitung braucht man leider ne ganze Menge Mathe, aber die ist ja sowieso logisch! 🙂 🙄


Anmelden zum Antworten