負の値を取得するという問題が発生しました。問題は、反射条件に対して再計算される新しい i,j 値に属していると思います。ここにコード: 最初の部分は既に実装されており、todo で始まる部分だけが完了している必要があります。
#include <math.h>
#include <stdio.h>
#include "BilateralFilter.h"
/* Constructor creates an Bilateral filter.
* sigma is the standard deviation of the spatial weight and
* delta is the standard deviation of the grayvalue differences weight. */
BilateralFilter::BilateralFilter( const double sigma, const double delta )
{
m_Sigma = sigma;
m_Delta = delta;
}
/* Destructor (does nothing) */
BilateralFilter::~BilateralFilter()
{
}
/* Internal Method to compute the Gaussian weights
* depending on sigma (or delta) and x.
* The return value is G(sigma,x)=exp(-(x*x)/2*sigma*sigma).
*
* The factor 1/(sigma*sqrt(2*pi)) of the Gaussian distribution is
* constant and therefore not necessary to compute. */
double BilateralFilter::Gaussian( const double sigma, const double x )
{
//printf("wert: %f\n",exp( -(x * x) / (2 * sigma * sigma) ) );
return exp( -(x * x) / (2 * sigma * sigma) );
}
/* Execute the bilateral filter. */
bool BilateralFilter::Execute()
{
// First, create a valid output image
// This fails if no valid input image is available.
if( !CreateOutputImage() )
return false;
// Define some often used constant variables to speed up the computation.
const int imageSizeX = m_InputImage->GetSizeX();
const int imageSizeY = m_InputImage->GetSizeY();
// The half size of the mask is defined as three times the
// standard deviation of the spatial Gaussian function.
const int filterHalfSizeX = static_cast<int>( 3 * m_Sigma );
const int filterHalfSizeY = static_cast<int>( 3 * m_Sigma );
/*
* TODO: Aufgabe 2: Vervollstaendigen Sie die Implementierung des BilateralFilter.
* Fuer die genaue Definition des Filters beachten sie das Aufgabenblatt und die Folien
* zur Uebung.
* Die Schleifen zur Iteration ueber die Bildpixel und die Nachbarschaften, sowie die
* Ueberpruefung der Randbedingungen sind bereits vorgegeben.
*
* Sie muessen folgende Werte berechnen, um den Bilateralen Filter zu implementieren.
* Der Punkt p ist dabei der aktuelle Zentrums-Pixel und q ein Punkt in der
* Nachbarschaft von p.
*
* Die (Gauss-)Gewichtung des euklidischen Abstandes der Punkte p und q:
*
* G_sigma(||p-q||)
*
* Die (Gauss-)Gewichtung der Differenz der Grauwerte im Eingangsbild an den Punkten p und q:
*
* G_delta(I(p)-I(q))
*
* Den Normalisierungsfaktor als Summe des Produkts dieser Gewichtungen ueber alle Nachbarpunkte q:
*
* W = Sum_{q in N} G_sigma(||p-q||)*G_delta(I(p)-I(q))
*
* Die Summe der gewichteten Grauwerte in der Nachbarschaft:
*
* Sum_{q in N} G_sigma(||p-q||)*G_delta(I(p)-I(q))I(q)
*
* Hinweis 1: Verwenden Sie moeglichst double-Werte bei Ihren Berechnungen und casten Sie erst das
* fertig berechnete Ergebnis auf den Typ Image::PixelType um Typfehler zu vermeiden.
* Hinweis 2: Verwenden Sie die interne Methode Gaussian() um G_sigma bzw. G_delta zu berechnen. Uebergeben
* Sie dabei das korrekte sigma/delta!
* Hinweis 3: Vergessen sie nicht die Normalisierung 1/W !
*/
// Iterate over all pixels.
for( int y = 0; y < imageSizeY; y++ )
{
for( int x = 0; x < imageSizeX; x++ )
{
// The coordinates of point p are given by (x,y).
// Get the value of the center pixel.
double centerValue = m_InputImage->GetPixel( x, y );
// Variable to accumulate weighted greyvalues.
double sumValue = 0;
// Variable für gewichtete Gaußwerte-Abstand
double G_sigma = 0;
// Variable für gewichtete Grauwerte
double G_delta = 0;
double ende = 0;
// Variable to accumulate weights for normalization.
double sumCoeffcients = 0;
// Iterate over all points in a neighborhood of p.
for( int m = -filterHalfSizeY; m <= filterHalfSizeY; m++ )
{
// Calculate the y-coordinate of the current pixel.
int j = y + m;
// Apply reflecting boundary conditions on the current y-coordinate.
if( j < 0 )
{
j = -j - 1;
}
else if( j >= imageSizeY )
{
j = 2 * imageSizeY - j - 1;
}
for( int k = -filterHalfSizeX; k <= filterHalfSizeX; k++ )
{
// Calculate the x-coordinate of the current neighbor pixel.
int i = x + k;
// Apply reflecting boundary conditions on the current x-coordinate.
if( i < 0 )
{
i = -i - 1;
}
else if( i >= imageSizeX )
{
i = 2 * imageSizeX - i - 1;
}
// TODO The coordinates of the point q in a neighborhood of p are
// now given by (i,j). Mind that on the coordinates (i,j) the
// boundary conditions have already been applied. The distance
// ||(x,y)-(i,j)|| therefore differs from ||(x,y)-(x+k,y+m)||
// near the boundary.
//Berechnung G_sigma
G_sigma = Gaussian(m_Sigma, sqrt(static_cast<double>(((x-i)*(x-i))+((y-j)*(y-j)))));
//printf("m_Sigma: %f\nGauss: %f\n", m_Sigma, Gaussian(m_Sigma,x));
// Berechnung G_delta
G_delta = Gaussian(m_Delta, abs((centerValue-m_InputImage->GetPixel(i,j))));
// Normalisierungsfaktor W
sumCoeffcients += (G_sigma * G_delta);
//printf("hallo: %f\n", sumCoeffcients);
// Gesamtsumme
sumValue += sumCoeffcients * m_InputImage->GetPixel(i,j);
ende =(1/sumCoeffcients)*sumValue;
//printf("i: %d\nj: %d\nsumme: %f\nsumvalue: %f\nG_sigma: %f\nG_delta: %f\n", i, j, sumCoeffcients, sumValue, G_sigma, G_delta);
}
}
// TODO Set the pixel of the output image. Remember to cast the double
// values to Image::PixelType, e.g. by static_cast<double>( value ).
m_OutputImage->SetPixel(x,y,static_cast<Image::PixelType>(ende));
printf("grauwert: %d\n", ende);
}
}
return true;
}