- PNG-Dateien in C++
- Gaußscher Glättungs Kernel
- WebCam mit OpenCV
In der Bildverarbeitung werden oft Kernels (1) eingesetzt um ein Bild zu transformieren. Zum Beispiel wird ein Bild insgesamt weicher, wenn ein Gaußscher Glättungs-Filter angewendet wird. Bei dem Filter handelt es sich um einen Kernel, d.h. um eine nach einem bestimmten Schema aufgebaute N x N – Matrix.
(1) nicht zu verwechseln mit den Kernels in Support Vektor Maschinen.
Anwendung findet diese Technik bei der Unterdrückung des vom Aufnahmegerät erzeugten zufälligen Rauschen sowohl in Fotos aber auch in jedem einzelnen Frame eines Videos.
Der gaußsche Glättungs-Kernel wird mit folgender Formel hergestellt.
g(x, y, s)=\frac{1}{2\pi\sigma^2}e^{-\frac{x^2+y^2}{2\sigma^2}}Folgendes Code-Schnipsel zeigt wie die Formel umgesetzt werden könnte. Die Ausgabe wird mit dem Faktor 200 skaliert, damit die Zahlen besser aussehen. Die Anwendung des Kernels erfolgt natürlich ohne Skalierung.
#include <stdio.h>
#include <math.h>
double gaussian_kernel(int x, int y, double s)
{
const double pi = M_PI;
const double e = std::exp(1.0);
return exp(-(x*x+y*y)/(2.0*s*s))/(2.0*pi*s*s);
}
int main(int argc, char** argv)
{
double s = 1.0;
for( int r = 1; r < 6; r++)
{
for(int c = 1; c < 6; c++ )
{
fprintf(stderr, "% 3.0lf ", gaussian_kernel(r-3, c-3, s)*200);
}
fprintf(stderr, "\n");
}
return 0;
}
Das erzeugt die Matrix:
\begin{array}{cc}1 & 4 & 6 & 4 & 1 \\4 & 16 &26&16&4 \\6&26& 43& 26& 6\\4& 16& 26& 16& 4\\1& 4& 6& 4& 1\\\end{array}Jetzt muss man diesen Kernel nur noch mit einem Bild falten und schon hat man ein weich gezeichnetes Bild. Falten ist ein einfacher Algorithmus in dem jeder Bildpunkt nach einem bestimmten Schema mit der Matrix kombiniert wird. Dazu gibt es viele Artikel und bestimmt bekommen wir das auch hin. Doch möchte ich hier die Abkürzung gehen und diese Filterung an OpenCV delegieren. Schließlich kämen wir nie zum Ziel, wenn wir jede Kleinigkeit selbst implementieren wollten. Oben ging es mir nur darum ein Gefühl für den Begriff Kernel zu bekommen.
#include <opencv2/opencv.hpp>
int main(int argc, char** argv)
{
cv::Mat image = cv::imread("image.jpg");
// original
const char* name1 = "Original";
cv::namedWindow(name1);
cv::imshow(name1, image);
const char* name2 = "5x5 Homogen";
cv::namedWindow(name2);
cv::Mat image_homogen;
cv::blur(image, image_homogen, cv::Size(5, 5));
cv::imshow(name2, image_homogen);
// 5x5 Gauß
const char* name3 = "5x5 Gauß'sch";
cv::namedWindow(name3);
cv::Mat image_gauss;
cv::GaussianBlur(image, image_gauss, cv::Size(5, 5), 0);
cv::imshow(name3, image_gauss);
cv::waitKey(0);
cv::destroyAllWindows();
return 0;
}

Für meinen Geschmack ist das schon der echte Wahnsinn. Neben dem Gauss-Filter wird das selbe Bild auch noch mit einem homogenen Kernel gefiltert. Ein homogener Kernel entspricht einer N x N Matrix mit einem konstanten Wert in jedem Matrixelement. Hier noch ein Beispiel für einen homogenen 3×3 Kernel:
\begin{array}{cc}1&1&1\\1&1&1\\1&1&1\\\end{array}