2x1=10

because numbers are people, too
Persönliches
Fotografie
Programmierung
    • Fliptri/Flipquad Image Filtering

      Neugierig und etwas gelang­weilt kam ich heute auf die Idee, auszupro­bieren, was wohl passieren würde, wenn man die bei­den Super­sam­pling-Ver­fahren Flip­tri und Flipquad als Fil­ter eines beste­hen­den Bildes inter­pretiert. Resul­tat des Abends: Wir reden nicht darüber.

      Grundlage

      Bei­den Ver­fahren liegt zugrunde, dass zur Erzeu­gung eines Pix­els mehrere umgebende (Sub-)Pixel aus­gew­ertet wer­den, wobei das Muster der Auswer­tung für anliegende Bild­punk­te hor­i­zon­tal und/oder ver­tikal gespiegelt — geflippt — wird. Die bei­den Ver­fahren unter­schei­den sich dabei lediglich hin­sichtlich der Anzahl der Sam­pling­punk­te.

      Anschaulich­er in der Grafik: Jew­eils drei Sam­pling­punk­te (rot) ergeben einen Bild­punkt (blau) bei Flip­tri; Bei Flipquad sind es vier Sam­pling­punk­te pro Bild­punkt.

      Visualisierung von Fliptri und Flipquad

      Der resul­tierende Bild­punkt B ist dabei schlichtweg die gewichtete Summe aller Sam­pling­punk­te S:


      \begin{align}
      B = \frac{1}{N} \sum \limits_{i=1}^N S_i
      \end{align}

      Implementierung in Matlab

      Fliptri

      Zu jedem Punkt müssen drei umgebende Pix­el aufgenom­men wer­den. Im unge­spiegel­ten Fall liegen diese an den Koor­di­nat­en (x-1, y-1), (x, y+1) und (x+1, y). Wie aus der Abbil­dung zu erken­nen ist, müssen die X- und Y-Koor­di­nat­en (genauer: Deren Off­sets -1, 0 und +1) für jede ger­ade Zeile gespiegelt wer­den, was man durch fol­gen­den Kun­st­griff erre­icht:

      x_sample = x_offset*(-1)^x + x;
      y_sample = y_offset*(-1)^y + y;
      

      Der Rest ist schnell erledigt:

      function pixel = fliptri(x, y, rgb)
      
          %   1   2   3
          % +---+---+---+
          % | X |   |   |
          % +---+---+---+
          % |   |   | X |
          % +---+---+---+
          % |   | X |   |
          % +---+---+---+
          coords = [ -1  0 +1;  % X
                     -1 +1  0]; % Y
      
          N = length(coords);
      
          % Flip 
          sgn_x = (-1)^x;
          sgn_y = (-1)^y;
      
          % Sample
          for s=1:N
              sample(s, 1:3) = rgb( ...
                       x+coords(1,s)*sgn_x, ...
                       y+coords(2,s)*sgn_y, ...
                       1:3);
          end
      
          % Combine
          pixel = sum(sample) / N;
      end
      

      Zulet­zt muss das Bild noch geladen und gefiltert wer­den. (Da die Größe des gedacht­en Fil­terk­er­nels der Größe drei entspricht, müssen die Start- und Endin­dizes jew­eils um den Wert 1 reduziert wer­den.)

      % Load the image
      rgb = imread('aliased.png');
      
      % Sample the image
      imagesize   = size(rgb);
      width       = imagesize(1);
      height      = imagesize(2);
      rgb_sampled = uint8(zeros(imagesize));
      for y=2:height-1
          for x=2:width-1
              rgb_sampled(x, y, 1:3) = fliptri(x, y, rgb);
          end
      end
      

      Flipquad

      Ana­log zum Flip­tri funk­tion­iert der Flipquad-Algo­rith­mus, allerd­ings ist die Off­setko­r­rek­tur hier vom Wert zwei, und es wer­den vier, statt drei Werten ver­ar­beit­et:

      function pixel = flipquad(x, y, rgb)
      
          %   1   2   3   4   5
          % +---+---+---+---+---+
          % |   | X |   |   |   |
          % +---+---+---+---+---+
          % |   |   |   |   | X |
          % +---+---+---+---+---+
          % |   |   |   |   |   |
          % +---+---+---+---+---+
          % | X |   |   |   |   |
          % +---+---+---+---+---+
          % |   |   |   | X |   |
          % +---+---+---+---+---+
      
          coords = [ -2 -1 +1 +2;  % X
                     -1 +2 -2 +1]; % Y  
      
          N = length(coords);
      
          % Flip 
          sgn_x = (-1)^x;
          sgn_y = (-1)^y;
      
          % Sample
          sample = zeros(3,3);
          for s=1:N
              sample(s, 1:3) = rgb( x+coords(1,s)*sgn_x, ...
                                    y+coords(2,s)*sgn_y, ...
                                    1:3);
          end
      
          % Combine
          pixel = sum(sample) / N;
      end
      

      Der Rest funk­tion­iert wie gehabt.

      Das Ergebnis

      Ernüchternd scheiße.

      Originalbild

      Fliptri-gefiltertes Bild

      Fliptri-gefilterte Version des Rerferenzbildes

      Flipquad-gefiltertes Bild

      Fliptri-gefilterte Version des Rerferenzbildes

      Und das war das.

      Wie ich ein­gangs bere­its erwäh­nte: … — aber wenig­stens war man dabei. Prost.

      November 4th, 2011 GMT +1 von
      Markus
      2011-11-4T03:58:08+01:00 2018-03-4T14:44:01+01:00 · 0 Kommentare
      Matlab
      MATLAB Image Processing
      • Android: Bitmap von SurfaceView erzeugen

        Um einen Screen­shot ein­er View zu erzeu­gen, wird gemein­hin emp­fohlen, den Draw­ing Cache der View zu miss­brauchen, indem man ihn gegebe­nen­falls erzwingt und dann kopiert:

        public class LameFooView extends SurfaceView {
        
        	@NotNull
        	public final Bitmap getScreenCopy() {
        		boolean cacheEnabled = isDrawingCacheEnabled();
        		if (!cacheEnabled) buildDrawingCache();
        
        		Bitmap cache = getDrawingCache(); // <-- there be dragons
        		Bitmap screenshot = new Bitmap(cache); 
        
        		// destroy the cache if it wasn't enabled, then return
        		if(!cacheEnabled) destroyDrawingCache();
        		return screenshot;
        	}
        
        }
        

        Aus Grün­den pur­er Gehäs­sigkeit lieferte der Aufruf von getDrawingCache() in mein­er vererbten SurvaceView allerd­ings immer null, wom­it die ganze Aktion gestor­ben war.

        Faszinieren­der­weise funk­tion­ierte stattdessen der Ansatz, die View erneut auf eine eigene Bitmap zu ren­dern, indem man der eige­nen draw()-Meth­ode ein raubkopiertes Canvas übergibt:

        public class AwesomeFooView extends SurfaceView {
        
        	@NotNull
        	public final Bitmap getScreenCopy() {
        		Bitmap bitmap = Bitmap.createBitmap(
        			getWidth(), 
        			getHeight(), 
        			Bitmap.Config.ARGB_8888
        			);
        
        		Canvas temporaryCanvas = new Canvas(bitmap);
        		draw(temporaryCanvas); // Voodoo.
        	
        		return bitmap;
        	}
        
        }
        

        Wer also vor einem ähn­lichen Prob­lem ste­ht — so geht es auch.

        Pro-Tipp

        Wie der Doku­men­ta­tion von View.draw() zu ent­nehmen ist, muss die View zum Zeit­punkt des Abpausens bere­its den Lay­out-Durch­gang durch­laufen haben. Dies lässt sich mit einem gewis­senhaften Aufruf von View.layout() erzwin­gen:

        measure(getWidth(), getHeight());
        layout(0, 0, getWidth(), getHeight());
        

        Prob­lem gelöst.

        November 2nd, 2011 GMT +1 von
        Markus
        2011-11-2T02:57:17+01:00 2011-11-2T05:44:19+01:00 · 3 Kommentare
        Bitmap Canvas
        Android
        • Android: Anzahl der verfügbaren Activities für Intent ermitteln

          Die Auf­gabe war ein­fach: Per Open Intents-Action org.openintents.action.PICK_COLOR (und startActivityForResult()) einen Farb­wäh­ler zu starten, die Farbe auszuw­erten, ???, Prof­it.
          Lei­der steck­te der Teufel im Detail, ich hat­te keinen Farb­wäh­ler instal­liert und wie zu erwarten, schoss sich die Activ­i­ty mit ein­er ActivityNotFoundException ins Nir­vana. Ste­ht ja auch in der Doku. Wusste ich dann auch.

          Ein Lösungsansatz ist nun, die Excep­tion zu fan­gen und glück­lich zu sein. Gibt aber keine Bonus­punk­te. Daher löst das Prob­lem mit­tels Pack­age­M­an­agers und query­In­ten­tAc­tiv­i­ties() wie fol­gt:

          List<ResolveInfo> list = getPackageManager().queryIntentActivities(
          	theIntentToStart, 
          	PackageManager.MATCH_DEFAULT_ONLY
          	);
          
          if (list.size() == 0) { // Voodoo.
          	return;
          }
          
          startActivity(theIntentToStart);
          

          Ich habe die neuge­wonnene Infor­ma­tion dann dafür genutzt, den aus­lösenden Menüpunkt gar nicht erst anzuzeigen. (Den OI-Farb­wäh­ler habe ich später trotz­dem nicht überzeu­gen kön­nen, mir Ergeb­nisse zu liefern.)

          November 2nd, 2011 GMT +1 von
          Markus
          2011-11-2T02:36:37+01:00 2011-11-2T02:37:58+01:00 · 0 Kommentare
          Intent Open Intents
          Android
          • SVN merge: “Querying mergeinfo requires version 3 of the FSFS filesystem schema

            Eben mal wieder einen merge gewagt und schwup­ps, klopfte das Prob­lem­män­nchen an die Tür. Begrüßt mit ein­er hüb­schen Fehler­mel­dung ging die Sucherei los.

            SVN reintegrate branch problem, mergeinfo requires FSFS version 3

            Error: Querying mergeinfo requires version 3 of the FSFS filesystem schema; 
                   filesystem '<pfad>/db' uses only version 1
            

            Und dann stehste da. Thanks to Google fand sich auf server­fault, dem Admin­is­tra­tions-Ableger des glo­r­re­ichen Stack­Over­flow, eine Lösung des Prob­lems. Weit­er­lesen »

            April 21st, 2011 GMT +1 von
            Markus
            2011-04-21T17:54:58+01:00 2011-04-21T17:56:01+01:00 · 2 Kommentare
            svn
            Version Control
            • Gitosis vs. UTF-8 BOM: “File contains no section headers.”

              Ich hat­te kür­zlich das Prob­lem, meine aus­gecheck­te gitosis.conf in einem Edi­tor zu bear­beit­en, der sie als UTF-8 mit Byte Order Mark abspe­icherte. Im Grunde ist dage­gen nichts einzuwen­den, da Pro­gramme den Mark­er automa­tisch erken­nen und die Datei als UTF-8 erken­nen soll­ten — Git/Gitosis zählt in dieser Hin­sicht lei­der noch nicht zu den schlaueren.
              Das Resul­tat ist nach einem git push — kurz gesagt — die Mel­dung ConfigParser.MissingSectionHeaderError: File contains no section headers. Und das fol­gende Pracht­stück an Aus­gabe: Weit­er­lesen »

              April 5th, 2011 GMT +1 von
              Markus
              2011-04-5T17:11:13+01:00 2011-04-5T22:03:31+01:00 · 0 Kommentare
              git
              Version Control
    1. « newer
    2. 1
    3. 2
    4. 3
    5. 4
    6. 5
    7. 6
    8. 7
    9. 8
    10. 9
    11. older »
    • Kategorien

      • .NET
        • ASP.NET
        • Core
        • DNX
      • Allgemein
      • Android
      • Data Science
      • Embedded
      • FPGA
      • Humor
      • Image Processing
      • Kalman Filter
      • Machine Learning
        • Caffe
        • Hidden Markov Models
        • ML Summarized
        • Neural Networks
        • TensorFlow
      • Mapping
      • MATLAB
      • Robotik
      • Rust
      • Signal Processing
      • Tutorial
      • Version Control
    • Neueste Beiträge

      • Summarized: The E-Dimension — Why Machine Learning Doesn’t Work Well for Some Problems?
      • Use your conda environment in Jupyter Notebooks
      • Building OpenCV for Anaconda Python 3
      • Using TensorFlow’s Supervisor with TensorBoard summary groups
      • Getting an image into and out of TensorFlow
    • Kategorien

      .NET Allgemein Android ASP.NET Caffe Core Data Science DNX Embedded FPGA Hidden Markov Models Humor Image Processing Kalman Filter Machine Learning Mapping MATLAB ML Summarized Neural Networks Robotik Rust Signal Processing TensorFlow Tutorial Version Control
    • Tags

      .NET Accelerometer Anaconda Bitmap Bug Canvas CLR docker FPGA FRDM-KL25Z FRDM-KL26Z Freescale git Gyroscope Integration Drift Intent J-Link Linear Programming Linux Magnetometer Matlab Mono Naismith OpenCV Open Intents OpenSDA Optimization Pipistrello Player/Stage PWM Python Sensor Fusion Simulink Spartan 6 svn tensorflow Tilt Compensation TRIAD ubuntu Windows Xilinx Xilinx SDK ZedBoard ZYBO Zynq
    • Letzte Kommetare

      • Lecke Mio bei Frequency-variable PWM generator in Simulink
      • Vaibhav bei Use your conda environment in Jupyter Notebooks
      • newbee bei Frequency-variable PWM generator in Simulink
      • Markus bei Using TensorFlow’s Supervisor with TensorBoard summary groups
      • Toke bei Using TensorFlow’s Supervisor with TensorBoard summary groups
    • Blog durchsuchen

    • Januar 2021
      M D M D F S S
      « Mrz    
       123
      45678910
      11121314151617
      18192021222324
      25262728293031
    • Self

      • Find me on GitHub
      • Google+
      • Me on Stack­Ex­change
      • Ye olde blog
    • Meta

      • Anmelden
      • Beitrags-Feed (RSS)
      • Kommentare als RSS
      • WordPress.org
    (Generiert in 0,339 Sekunden)

    Zurück nach oben.