Image downsampling Problem



  • Hey, ich befasse mich momentan mit der digitalen Bildverarbeitung und bin leider auf ein Problem gestoßen für dass ich nun eine Lösung suche.

    Es geht um das downsampling/Shrinking von Bildern.
    Wenn ich ein Bild vorliegen habe dass die Abmessungen von 200x200 aufweist und dieses nun auf 100x100 reduzieren möchte gibt es ja verschiedenste Methoden dies zu bewerkstelligen. Zum Beispiel durch Interpolationsverfahren oder durch einfaches weg lassen jeden zweiten Wertes.
    Allerdings versuche ich seit tagen hoffnungslos herauszufinden wie man eine Bildgröße von 200x200 auf 101x125 reduzieren kann.

    Kann mir das vielleicht jemand von euch erklären?

    Gruß
    Robin



  • Hast du schon den Wiki-Artikel Skalierung (Computergrafik) dazu durchgelesen? Dort sind die verschiedenen mathematischen Operationen (Filter) erklärt.



  • In welcher Programmiersprache soll das denn passieren? Da gibt´s mit Sicherheit fertige Bibliotheken, die man benutzen kann.



  • Ja den Beitrag kenne ich.
    Habe ihn gerade auch sicherheitshalber nochmal gelesen.
    In den Beitrag geht es ja aber auch hauptsächlich um das vergrößern von Bildern und nicht um das verkleinern.
    Das verfahren mittels radial symmetrischem Rekonstruktionsfilter ist ganz interessant aber lässt sich glaube ich sehr schwierig auf die Verkleinerung eines Bildes anwenden.

    Meine Idee war eigentlich die Differenz zwischen den Abmessungen zu bilden.
    Also:
    200x200 -> 101x125
    ergibt dann
    d99xd75

    nun schaut man wie oft die Differenz in die ursprüngliche Größe passt was dann die Schrittweite einer schleife die über das Bild läuft darstellen würde welche die jeweiligen Pixel rauschmeißt/löscht.
    Also wäre das dann:

    1. 200/99 = 2,02020202
    2. 200/75 = 2,666666667

    in x Richtung wäre dann ein Rest von 0,02020202 also 2 Pixeln vorhanden und in y Richtung
    ein Rest von 50 Pixeln.

    Nur wie löse ich jetzt das Problem mit den übrigen Pixeln?
    hoffe ihr könnten den Gedankengang nachvollziehen.

    Das ganze soll in c++ bzw managed c++ geschrieben werden und auf Bilder und Punktwolken angewendet werden.



  • @101182021
    Du darfst halt nicht davon ausgehen, dass jeder Ausgabebildpunkt sich aus der gleichen Anzahl der Eingabebildpunkte zusammensetzt. Ich würde erst garnicht versuchen, das selbst zu machen.
    Vllt ist die CIMG library brauchbar:



  • Danke dir.
    habe das Problem jetzt gelöst indem ich so zu sagen die neue Matrix(kleinere) über die alte(große) gelegt habe, dann die Schrittweite der neuen auf die Abmessungen der alten angepasst habe und anschließend lokal eine bilineare Interpolation angewendet habe.



  • @101182021
    Klingt gut. Nur ein kleiner Hinweis: Bilineare Interpolation funktioniert nur brauchbar so lange die Grösse des neuen Bildes min. 50% (pro Achse) ist. Wenn du um mehr als das verkleinern willst, und "schöne" Ergebnisse bekommen willst, brauchst du was anderes.



  • @101182021 Um ein Bitmap mit beliebiger Auflösung auf 320x200 zu skalieren, ging das so:

    unsigned char disp[(x_max*y_max)];
     bmp.seekg(bmp.tellg()+1);
     bmp.read(disp,sizeof(unsigned char)*x_max*y_max );
     signed int x,y;
     double ipv_x=(double)x_max/320.0;
     double ipv_y=(double)y_max/200.0;
     x=0;
     y=0;
    
     while(y<199)
     {
      x=0;
      while(x<320)
      {
       GrPlotNC(x,199-y,disp[((unsigned int)(y*ipv_y)*x_max+(unsigned int)(x*ipv_x))]);
       x++;
      }
      y++;
     }
     bmp.close();
    
    

    Für ein besseres Resultat bei der Interpolation beim Verkleinern müßte man einfach nur ein paarmal vorher über das Quellbild mit irgendeinem Weichzeichner drüber. Stellt sich halt die Frage, wie man das am Besten macht. Problem ist wohl auch, daß der Weichzeichner das Bild in eine bestimmte Richtung verschliert, wenn man ihn nicht gleichmäßig ausbreitet oder man das mit einer leichten Verschiebung nachkorrigiert.



  • @Klagenderlamer sagte in Image downsampling Problem:

    Für ein besseres Resultat bei der Interpolation beim Verkleinern müßte man einfach nur ein paarmal vorher über das Quellbild mit irgendeinem Weichzeichner drüber.

    Normalerweise macht man das alles in einem Schritt. Verkleinern und Weichzeichnen sind sehr ähnliche Vorgänge. Bei beiden kommen Tiefpassfilter zum Einsatz. Der Unterschied beim Verkleinern ist dass man weniger Samples berechnet und dass die Koordinaten der Samples keine Integerwerte sind.

    Erst weichzeichnen und dann mit bilinearem Filter verkleinern kann man zwar machen, ist aber unnötig langsam. Und es wird deutlich schlechtere Ergebnisse liefern als wenn man z.B. direkt mit einem Lanczos Kernel resampled.

    Das ist aber alles etwas was ich eher nicht selbst implementieren würde. Da gibt's genügend gute, fertige Teile. OpenCV sollte z.B. alles mitbringen was man braucht. Selbst implementieren macht da mMn. nur Sinn als Übung.

    Problem ist wohl auch, daß der Weichzeichner das Bild in eine bestimmte Richtung verschliert, wenn man ihn nicht gleichmäßig ausbreitet oder man das mit einer leichten Verschiebung nachkorrigiert.

    Wenn man beim Weichzeichnen das Bild verschiebt, dann macht man was falsch. Sogar wenn man kausale IIR Filter zum Weichzeichnen verwendet ist es relativ einfach ein nicht verschobenes Ergebnis zu bekommen. Und zwar indem man 1x vorwärts und 1x rückwärts filtert.


Log in to reply