This commit is contained in:
Andre Meyering 2018-11-15 14:47:47 +01:00
parent 2f0ef234e7
commit ef9e000c65
48 changed files with 2414 additions and 25 deletions

BIN
Bilder/Dynamik.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 617 KiB

BIN
Bilder/Gamma.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

BIN
Bilder/Histogramm-RGB.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 724 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

BIN
Bilder/Kontrast.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 770 KiB

View file

@ -35,8 +35,7 @@
\input{Kapitel/01_Einstieg.tex}
\input{Kapitel/02_Einleitung.tex}
\input{Kapitel/03_Bilderfassung.tex}
\input{Kapitel/04_Farbsysteme.tex}
\input{Kapitel/05_Codierung.tex}
\input{Kapitel/04_Vorverarbeitung.tex}
%------- Sonstiges ---------------------------------------------------
@ -46,7 +45,10 @@
\acro{CCD}{Charge Coupled Device}
\acro{DCT}{Diskrete Kosinustransformation}
\acro{JPEG}{Joint Photographic Experts Group}
\acro{LSI}{Linear Shifting Invariant}
\acro{LZW}{Lempel-Ziv-Welch}
\acro{LUT}{Look-Up-Table}
\acro{PO}{Punktoperation}
\end{acronym}
\newpage

View file

@ -0,0 +1,38 @@
import ij.*;
import ij.process.*;
import ij.gui.*;
import java.awt.*;
import ij.plugin.filter.*;
public class Kantenschaerfung_2018_11_07 implements PlugInFilter {
ImagePlus imp;
public int setup(String arg, ImagePlus imp) {
this.imp = imp;
return DOES_ALL;
}
public void run(ImageProcessor ip) {
int width = ip.getWidth();
int height = ip.getHeight();
ImageProcessor copy = ip.duplicate();
int[][] L ={{1,1,1},{1,-8,1},{1,1,1}};
for(int m = 1; m < width - 1; m++) {
for(int n = 1; n < height - 1; n++) {
int p = 0;
for(int i = -1; i <= 1; i++) {
for(int j = -1; j <= 1; j++) {
int I = copy.getPixel(m-i,n-j);
p += I * L[i+1][j+1];
}
}
p = copy.getPixel(m,n) - (int) (p * 0.5);
ip.putPixel(m,n,p);
}
}
}
}

View file

@ -0,0 +1,38 @@
import ij.*;
import ij.process.*;
import ij.gui.*;
import java.awt.*;
import ij.plugin.filter.*;
public class Laplace_2018_11_07 implements PlugInFilter {
ImagePlus imp;
public int setup(String arg, ImagePlus imp) {
this.imp = imp;
return DOES_ALL;
}
public void run(ImageProcessor ip) {
int width = ip.getWidth();
int height = ip.getHeight();
ImageProcessor copy = ip.duplicate();
int[][] L ={{1,1,1},{1,-8,1},{1,1,1}};
for(int m = 1; m < width - 1; m++) {
for(int n = 1; n < height - 1; n++) {
int p = 0;
for(int i = -1; i <= 1; i++) {
for(int j = -1; j <= 1; j++) {
int I = copy.getPixel(m-i,n-j);
p += I * L[i+1][j+1];
}
}
p = p*10 + 128; // Irgendein Faktor
ip.putPixel(m,n,p);
}
}
}
}

View file

@ -0,0 +1,35 @@
import ij.*;
import ij.process.*;
import ij.gui.*;
import java.awt.*;
import ij.plugin.filter.*;
public class Sobel_2018_10_31 implements PlugInFilter {
ImagePlus imp;
public int setup(String arg, ImagePlus imp) {
this.imp = imp;
return DOES_ALL;
}
public void run(ImageProcessor ip) {
int width = ip.getWidth();
int height = ip.getHeight();
ImageProcessor copy = ip.duplicate();
int[][] H ={{1,0,-1},{2,0,-2},{1,0,-1}};
for(int v = 1; v <= height-2; v++) {
for(int u = 1; u <= width-2; u++) {
int k = 0;
for(int j =-1; j <= 1; j++) {
for(int i =-1; j <= 1; j++) {
int I = copy.getPixel(u-i,v-j);
k = k + I * H[i+1][j+1];
}
}
ip.putPixel(u,v,k);
}
}
}
}

View file

@ -1 +0,0 @@
User plugins go here.

View file

@ -0,0 +1,72 @@
<pre><div class="text_to_html">import ij.*;
import ij.process.*;
import ij.gui.*;
import java.awt.*;
import ij.plugin.filter.*;
import ij.IJ;
import ij.ImagePlus;
import ij.gui.GenericDialog;
import ij.plugin.filter.PlugInFilter;
import ij.process.ImageProcessor;
public class Filter_Laplace implements PlugInFilter {
ImagePlus imp;
public int setup(String arg, ImagePlus imp) {
this.imp = imp;
return DOES_ALL;
}
public void run(ImageProcessor orig) {
int w = orig.getWidth();
int h = orig.getHeight();
double [] [] filter1 = {
{ 0 , 1 , 0 },
{ 1, -4 , 1},
{ 0 , 1, 0 }
};
double [] [] filter2 = {
{ 1 , 2 , 1 },
{ 0 , 0 , 0 },
{ -1 , -2, -1 }
};
ImageProcessor copy = orig.duplicate();
for (int v = 1; v <= h-2; v++) {
for (int u = 1; u <= w-2; u++){
double sum1 = 0;
// double sum2 = 0;
for (int j = -1; j <= 1; j++) {
for (int i = -1; i <= 1; i++){
int p = copy.getPixel(u-i,v-j);
double c1 = filter1[j+1][i+1];
// double c2 = filter2[j+1][i+1];
sum1 = sum1 + p*c1 ;
// sum2 = sum2 + p*c2;
}
}
int q = (int) Math.round(sum1);
// int q = (int) Math.round(Math.sqrt(sum1*sum1+sum2*sum2));
orig.putPixel(u,v,q);
}
}
}
}
</div></pre>

View file

@ -0,0 +1,44 @@
<pre><div class="text_to_html">import ij.*;
import ij.process.*;
import ij.gui.*;
import java.awt.*;
import ij.plugin.filter.PlugInFilter;
import java.util.Arrays;
public class Filter_Median5 implements PlugInFilter {
public int setup(String arg, ImagePlus imp) {
return DOES_ALL;
}
public void run(ImageProcessor orig) {
int w = orig.getWidth();
int h = orig.getHeight();
ImageProcessor copy = orig.duplicate();
int[] P = new int[9]; //Vector to hold Pixel from 3x3 matrix
for (int v = 1; v <= h-2 ; v++) {
for (int u = 1; u <= w-2; u++) {
int k = 0;
for (int j=-1; j<=1; j++){
for (int i=-1; i<=1; i++){
P[k] = copy.getPixel(u+i,v+j);
k++;
}
}
Arrays.sort(P);
orig.putPixel(u,v, P[4]);
}
}
}
}
</div></pre>

View file

@ -0,0 +1,72 @@
<pre><div class="text_to_html">import ij.*;
import ij.process.*;
import ij.gui.*;
import java.awt.*;
import ij.plugin.filter.*;
import ij.IJ;
import ij.ImagePlus;
import ij.gui.GenericDialog;
import ij.plugin.filter.PlugInFilter;
import ij.process.ImageProcessor;
public class Filter_operator implements PlugInFilter {
ImagePlus imp;
public int setup(String arg, ImagePlus imp) {
this.imp = imp;
return DOES_ALL;
}
public void run(ImageProcessor orig) {
int w = orig.getWidth();
int h = orig.getHeight();
double [] [] filter1 = {
{ 1 , 0 , -1 },
{ 2 , 0 , -2},
{ 1 , 0, -1 }
};
double [] [] filter2 = {
{ 1 , 2 , 1 },
{ 0 , 0 , 0 },
{ -1 , -2, -1 }
};
ImageProcessor copy = orig.duplicate();
for (int v = 1; v <= h-2; v++) {
for (int u = 1; u <= w-2; u++){
double sum1 = 0;
double sum2 = 0;
for (int j = -1; j <= 1; j++) {
for (int i = -1; i <= 1; i++){
int p = copy.getPixel(u-i,v-j);
double c1 = filter1[j+1][i+1];
double c2 = filter2[j+1][i+1];
sum1 = sum1 + p*c1 ;
sum2 = sum2 + p*c2;
}
}
// int q = (int) Math.round(sum1);
int q = (int) Math.round(Math.sqrt(sum1*sum1+sum2*sum2));
orig.putPixel(u,v,q);
}
}
}
}
</div></pre>

Binary file not shown.

BIN
Folien_Lausen/CCD-PIXEL.pdf Normal file

Binary file not shown.

BIN
Folien_Lausen/CIE.pdf Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Folien_Lausen/Jpeg.pdf Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Folien_Lausen/Moire.pdf Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load diff

View file

@ -101,3 +101,12 @@ Was sollten wir Lernen?
TODO
CCD Sensor, PhotoEffekt, Photonenrauschen (Poisson Statistik),, Phononen/CCD Rauschen, Verstärker/Quantisierungsrauschen, Bayer Maske,
\section{Farbsysteme}\label{sec:Farbsysteme}
Farben
TODO: Andre Grafik 5
rgba <--> cmyk

View file

@ -1,8 +0,0 @@
\chapter{Farbsysteme}\label{sec:Farbsysteme}
Farben
TODO: Andre Grafik 5
rgba <--> cmyk

View file

@ -1,6 +1,6 @@
\chapter{Bildvorverarbeitung}
\section{Codierung und Kompression}
\subsection{title}{LZW / LZ78}\index{LZW}\index{LZ78}
\subsection{LZW / LZ78}\index{LZW}\index{LZ78}
Der \ac{LZW}-Algorithmus ist die bekannteste Form der LZ78-Kompression.
\autoref{code:lzw} zeigt die Funktionsweise dieses Algorithmus.
@ -79,7 +79,8 @@ Bei üblichen Bildern werden pro Pixel drei Farben (rot, grün, blau) gespeicher
\begin{wrapfigure}{r}{5cm}
\centering
\includegraphics[width=5cm]{./Bilder/JPEG_YCbCr.png}
\caption{RGB Alternative -- YCbCr}
\caption[RGB Alternative -- YCbCr]{\unskip}
RGB Alternative -- YCbCr
\label{fig:jpeg_YCbCr}
\end{wrapfigure}
Anstatt pro Pixel 24~Bit zu speichern, kann der RGB Farbraum auch nach YCbCr umgewandelt werden. Nehmen wir $4\times 4$ Pixel:
@ -110,17 +111,18 @@ Y ist dabei wieder die Luminanz und U und V bilden den eigentlichen Farbwert. \a
.....\todo{Berechnung Farbwerte}
\subsubsection{Diskrete Kosinustransformation}\index{DCT}
\subsection{Diskrete Kosinustransformation}\index{DCT}
\begin{wrapfigure}[6]{r}{5cm}
\centering
\includegraphics[width=5cm]{./Bilder/DCT.png}
\caption{\acf{DCT}}
\caption[\acl{DCT}]{\unskip}
\acf{DCT}
\label{fig:dct}
\end{wrapfigure}
\ac{JPEG} unterteilt das Bild in $8\times 8$ Pixel große Subbilder. \ac{DCT}\todo{DCT, Formeln...}
\subsubsection{Quantisierung}
\subsection{Quantisierung}
% Von https://www.tu-chemnitz.de/informatik/ThIS/downloads/courses/ws02/datkom/JPEG_Kompression.pdf
\begin{align*}
\hat{G}^q_{uv} = INT[\frac{G_{uv}}{q_{uv}}] \\
@ -153,32 +155,140 @@ Ist $q_{uv}$ überall 1, dann hat das Bild die beste Qualität, da die Amplitude
q_{uv} &= 8 \\
INT[\frac{G_{uv}}{q_{uv}}] &= 3 \rightarrow Dekodierung: 3\times 8 = 24=G_{uv}
\end{align*}
\todo{MÜsste das Abrunden sein?}
\todo{Müsste das Abrunden sein?}
\subsubsection{Serialisierung der Matrix}
\subsection{Serialisierung der Matrix}
\begin{wrapfigure}{r}{5cm}
\centering
\includegraphics[width=5cm]{./Bilder/Jpeg_Serialisierung.png}
\caption{Serialisierung der Matrix in der Zig-Zag-Ordnung}
\caption[Serialisierung der Matrix in der Zig-Zag-Ordnung]{\unskip}
Serialisierung der Matrix in der Zig-Zag-Ordnung
\label{fig:jpeg_serialisierung}
\end{wrapfigure}
% Stammt aus: https://www.tu-chemnitz.de/informatik/ThIS/downloads/courses/ws02/datkom/JPEG_Kompression.pdf
Die DC-Koeffizienten (Matrixinhalt an Position $1,1$) benachbarter Blöcke unterscheiden sich nur wenig und werden daher als Differenz zum Vorgängerblock übertragen.
Die Koeffizienten werden im Zick-Zack angeordnet, was gleichzeitig einer Anordnung nach Ihrer Wichtigkeit entsprechend der visuellen Wahrnehmung entspricht. \autoref{fig:jpeg_serialisierung} stellt dies dar.
\subsubsection{RLC (Lauflängenkodierung)}
\subsection{RLC (Lauflängenkodierung)}
Anschließend folgt eine Lauflängenkodierung der serialisierten Matrix. Das funktioniert aufgrund der langen Nullketten sehr gut. Siehe \autoref{sec:rlc} und die vorhergehende Matrix.
\subsubsection{Huffman-Kodierung}
\subsection{Huffman-Kodierung}
Es ergibt sich, dass die Huffman-Tabelle sehr klein ist.
Natürliche Bilder haben in jedem $8\times 8$ Block Helligkeit. Schmeißen wir dies raus, dann funktioniert RCL und Huffman gut \todo{Wie meinte er das?}
\subsubsection{Kantenerkennung bei JPEG}
\subsection{Kantenerkennung bei JPEG}
\todo{Grafik Diagram}
\section{JPEG 2000}
\subsection{JPEG 2000}\index{JPEG 2000}
JPEG 2000 ist eine erweiterte Version von JPEG. Sie verspricht eine bessere Qualität bei geringen Bitraten.
Anstatt der \ac{DCT} werden Wavelets verwendet und anstatt der Huffman Kodierung wird eine arithmetische verwendet.
Es gibt keine fest Blockgröße für die Wavelet-Transformation.
Trotz dieser Unterschiede ist die Bildqualität nicht zwingend besser als bei JPEG. Sie macht sich nur bei starker Kompression bemerkbar.
\section{Moire Effekt bei JPEG}
Wenn ein Bild mehrere Male als JPEG mit unterschiedlichen Quantisierungsmatrizen gespeichert wird, so ergeben sich Artefakte, die dem Moire Effekt ähnlich sind.
\subsection{Moire Effekt bei JPEG}\index{Moire}
Wenn ein Bild mehrere Male als JPEG mit unterschiedlichen Quantisierungsmatrizen gespeichert wird, so ergeben sich Artefakte, die dem Moirè Effekt ähnlich sind.
\section{Analogien eines Bildes}
\subsection{Histogramm}\index{Histogramm}
Man kann in einem Histogramm den Mittelwert der Grauwerte, die Anzahl der Einträge, die Streuung, die Anzahl der vorkommenden Helligkeitsklassen und die Spannweite ablesen.
\medskip
\begin{Hinweis}
Zu sagen, ein \enquote{Histogramm zeige die Häufigkeiten von Grauwerten} ist falsch!
Dies wurde von Herrn Lausen \textit{mehrmals} in aller Deutlichkeit erwähnt. Korrekt ist:
\enquote{Ein Histogramm ist die Darstellung der Besetzungshäufigkeit von Helligkeitsklassen in einem Bild.}
\end{Hinweis}
\subsubsection{Histogramm bei RGB}
Die einzelnen Farbkanäle können auch dazu verwendet werden, Objekte aufgrund ihrer Farbe zu identifizieren.
Somit ergibt sich für jede der drei Farben ein Histogramm, wie in \autoref{fig:histogramm_rgb} zu sehen ist.
\begin{figure}[h!]
\centering
\includegraphics[width=\textwidth]{./Bilder/Histogramm-RGB.png}
\caption{Histogramm RGB}
\label{fig:histogramm_rgb}
\end{figure}
\subsection{Gammakorrektur}\index{Gamma}
\begin{wrapfigure}[10]{l}{8cm}
\centering
\vspace{-11mm}
\includegraphics[width=8cm]{./Bilder/Gamma.png}
\caption{Gammakorrektur}
\label{fig:gamma}
\end{wrapfigure}
Das menschliche Auge sieht logarithmisch.
Dies bedeutet, dass eine Verdopplung der Helligkeit nicht gleich einer Verdopplung der wahrgenommenen Helligkeit entspricht.
Die Gamma-Korrektur spreizt die Grauwerte in dem oberen oder unteren Wertebereich und staucht sie dafür in dem jeweils anderen.
In \autoref{fig:gamma} ist eine solche Korrektur abgebildet.
Die x-Achse repräsentiert das Originalbild $I$ und die y-Achse das veränderte $I' = I^\gamma$. Bei $\gamma < 1$ wird das Bild heller, bei $\gamma > 1$ wird es dunkler. Diese Umrechnung funktioniert nur, wenn die Werte im Bereich $[0, 1]$ liegen. Somit besteht die vollständige Umrechnung aus:
\vspace{-9mm}
\begin{align*}
I_{\gamma}' = INT[(\frac{I}{I_{max}})^\gamma\cdot I_{max}]
\end{align*}
\vspace{-10mm}
\subsection{Kontrast}\index{Kontrast}
\begin{wrapfigure}[9]{r}{8cm}
\centering
\vspace{-6mm}
\includegraphics[width=8cm]{./Bilder/Kontrast.png}
\caption{Kontrastspreizung}
\label{fig:kontrast}
\end{wrapfigure}
Als Kontrast wird die Spannweite zwischen maximalem und minimalem Helligkeitswert bezeichnet.
Kontrast kann man \enquote{spreizen}, \dash die Minimal- und Maximalwerte heraufsetzen.
\autoref{fig:kontrast} zeigt ein Bild mit unterschiedlichen Kontrasten (vor und nach Spreizung).
Sei $[a_{min}, a_{max}]$ der zu spreizende Bereich, so lässt sich das neue Bild berechnen mit:
\qquad $I'=f(I)=INT[\frac{I-a_{min}}{a_{max}-a_{min}}\cdot I_{max}]$
Diese Operation ist eine homogene \acf{PO} und kann effizient mit einer \acf{LUT} berechnet werden.
\subsection{Dynamik}\index{Dynamik}
\begin{wrapfigure}[9]{r}{8cm}
\centering
\vspace{-6mm}
\includegraphics[width=8cm]{./Bilder/Dynamik.png}
\caption{Dynamik eines Bildes}
\label{fig:dynamik}
\end{wrapfigure}
Die Dynamik eines Bildes gibt an, wie viele Grauwertklassen besetzt sind.
Obwohl der Kontrast groß ist ($I_{max} - I_{min}$) kann die Dynamik variieren.
In \autoref{fig:dynamik} sind im rechten Bild nur wenige Grauwerte besetzt. Man sagt, das Bild hat wenig Dynamik.
Natürliche Bilder haben meist eine hohe Dynamik und keine \enquote{Lücken}. An diesen kann man \ua bearbeitete
Bilder erkennen.
\subsection{Einfluss JPEG-Konvertierung}
\begin{wrapfigure}[6]{r}{8cm}
\centering
\vspace{-3cm}
\includegraphics[width=8cm]{./Bilder/Kompressionseinfluss.png}
\caption{Kompressionseinfluss}
\label{fig:Kompressionseinfluss}
\end{wrapfigure}
Eine Kompression kann auf das Histogramm Einfluss haben. Ein Bild mit nur einem Grauwert hat nach der Dekompression plötzlich deutlich mehr Grauwerte im Histogramm. Dies liegt an der Funktionsweise von JPEG mit \ac{DCT}.
\section{LSI-Filter}\index{LSI-Filter}
In der Bildverarbeitung werden häufig \ac{LSI}-Filter verwendet (z)u deutsch \enquote{lineare Verschiebungsinvarianz}).
\begin{Tipp}[frametitle={Faltung}]
\vspace{-5mm}
\begin{align*}
Kommutativität&& \mathcal{H}_1\mathcal{H}_2&=\mathcal{H}_2\mathcal{H}_1 \\
Assoziativität&& (\mathcal{H}_1\mathcal{H}_2)\mathcal{H}_3 &= \mathcal{H}_1(\mathcal{H}_2\mathcal{H}_3) \\
Distributivität &&(\mathcal{H}_1+\mathcal{H}_2)\cdot\mathcal{H}_3&=\mathcal{H}_1\mathcal{H}_3+\mathcal{H}_2\mathcal{H}*3
\end{align*}
\end{Tipp}
\begin{align*}
\mathcal{H}^{mn}\mathcal{S} &= {}^{mn}\mathcal{S}\mathcal{H}
\end{align*}
\includepdf[pages=-]{2018-10-31.pdf}

Binary file not shown.

BIN
Tafel_2018-10-17.pdf Normal file

Binary file not shown.