/* in input image size size of filter kernel spatial true if convolution shall be performed in spatial domain, false otherwise return smoothed image */ Mat Dip3::mySmooth(Mat& in, int size, bool spatial){ // create filter kernel Mat kernel = createGaussianKernel(size); // perform convoltion if (spatial) return spatialConvolution(in, kernel); else return frequencyConvolution(in, kernel); }
void Dip3::test_createGaussianKernel(void){ Mat k = createGaussianKernel(11); if ( abs(sum(k).val[0] - 1) > 0.0001){ cout << "ERROR: Dip3::createGaussianKernel(): Sum of all kernel elements is not one!" << endl; return; } if (sum(k >= k.at<float>(5,5)).val[0]/255 != 1){ cout << "ERROR: Dip3::createGaussianKernel(): Seems like kernel is not centered!" << endl; return; } cout << "Message: Dip3::createGaussianKernel() seems to be correct" << endl; }
pixel3f *Image::createGaussian(float sigma) { pixel3f *gaussian = new pixel3f[_width * _height](); // Precompute constants. float variance = sigma * sigma; float denomiator = 2 * M_PI * variance; // Radius of filter. int r = 2.0f * sigma; float *kernel = createGaussianKernel(r + 1, variance); // Seperable x component of Gaussian filter. for (int x = 0; x < _width; x++) { for (int y = 0; y < _height; y++) { float sum = 0; for (int i = -r; i <= r; i++) { sum += pixelAt(_pixels, x + i, y)->L * kernel[abs(i)]; } // Do not divide by the regular denominator. pixelAt(_copy, x, y)->L = sum; } } // Seperable y component of Gaussian filter. for (int x = 0; x < _width; x++) { for (int y = 0; y < _height; y++) { float sum = 0; for (int j = -r; j <= r; j++) { sum += pixelAt(_copy, x, y + j)->L * kernel[abs(j)]; } // Divided by the denominator squared only once rather than twice. pixelAt(gaussian, x, y)->L = sum / denomiator; } } // Free temporary data. delete[] kernel; return gaussian; }
void Image::bilateral() { // Gaussian kernel used to model geometric similarity. float *kernel = createGaussianKernel(RADIUS + 1, VARIANCE); for (int x = 0; x < _width; x++) { for (int y = 0; y < _height; y++) { pixel3f *center = pixelAt(_pixels, x, y); float numerator = 0; float denominator = 0; for (int i = -RADIUS; i <= RADIUS; i++) { pixel3f *neighbor = pixelAt(_pixels, x + i, y); // Compute euclidean distance between Lab colors to determine photometric similarity. float dL = center->L - neighbor->L; float da = center->a - center->a; float db = center->b - center->b; float distance = dL * dL + da * da + db * db; float photometric = expf(distance / PHOTOMETRIC); float similarity = photometric * kernel[abs(i)]; // Denominator serves to normalize values. denominator += similarity; numerator += similarity * neighbor->L; } // Copy a and b data over as well to use for the y-filter pass. pixel3f *target = pixelAt(_copy, x, y); target->L = numerator / denominator; target->a = center->a; target->b = center->b; } } for (int x = 0; x < _width; x++) { for (int y = 0; y < _height; y++) { pixel3f *center = pixelAt(_copy, x, y); float numerator = 0; float denominator = 0; for (int j = -RADIUS; j <= RADIUS; j++) { pixel3f *neighbor = pixelAt(_copy, x, y + j); float dL = center->L - neighbor->L; float da = center->a - center->a; float db = center->b - center->b; float distance = dL * dL + da * da + db * db; float photometric = expf(distance / PHOTOMETRIC); float similarity = photometric * kernel[abs(j)]; denominator += similarity; numerator += similarity * neighbor->L; } pixelAt(_pixels, x, y)->L = numerator / denominator; } } delete[] kernel; }