My question is very close to this question: How do I gaussian blur an image without using any in-built gaussian functions?
The answer to this question is very good,
// my_test.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <cmath>
#include <vector>
#include <iostream>
#include <iomanip>
#include <string>
//https://stackoverflow.com/questions/8204645/implementing-gaussian-blur-how-to-calculate-convolution-matrix-kernel
//https://docs.opencv.org/2.4/modules/imgproc/doc/filtering.html#getgaussiankernel
//http://dev.theomader.com/gaussian-kernel-calculator/
double gaussian(double x, double mu, double sigma) {
const double a = (x - mu) / sigma;
return std::exp(-0.5 * a * a);
}
typedef std::vector<double> kernel_row;
typedef std::vector<kernel_row> kernel_type;
kernel_type produce2dGaussianKernel(int kernelRadius, double sigma) {
kernel_type kernel2d(2 * kernelRadius + 1, kernel_row(2 * kernelRadius + 1));
double sum = 0;
// compute values
for (int row = 0; row < kernel2d.size(); row++)
for (int col = 0; col < kernel2d[row].size(); col++) {
double x = gaussian(row, kernelRadius, sigma)
* gaussian(col, kernelRadius, sigma);
kernel2d[row][col] = x;
sum += x;
}
// normalize
for (int row = 0; row < kernel2d.size(); row++)
for (int col = 0; col < kernel2d[row].size(); col++)
kernel2d[row][col] /= sum;
return kernel2d;
}
char* gMatChar[10] = {
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" "
};
static int countSpace(float aValue)
{
int count = 0;
int value = (int)aValue;
while (value > 9)
{
count++;
value /= 10;
}
return count;
}
int main() {
while (1)
{
char str1[80]; // window size
char str2[80]; // sigma
char str3[80]; // coefficient
int space;
int i, ch;
printf("\n-----------------------------------------------------------------------------\n");
printf("Start generate Gaussian matrix\n");
printf("-----------------------------------------------------------------------------\n");
// input window size
printf("\nPlease enter window size (from 3 to 10) It should be odd (ksize/mod 2 = 1 ) and positive: Exit enter q \n");
for (i = 0; (i < 80) && ((ch = getchar()) != EOF)
&& (ch != '\n'); i++)
{
str1[i] = (char)ch;
}
// Terminate string with a null character
str1[i] = '\0';
if (str1[0] == 'q')
{
break;
}
int input1 = atoi(str1);
int window_size = input1 / 2;
printf("Input window_size was: %d\n", input1);
// input sigma
printf("Please enter sigma. Use default press Enter . Exit enter q \n");
str2[0] = '0';
for (i = 0; (i < 80) && ((ch = getchar()) != EOF)
&& (ch != '\n'); i++)
{
str2[i] = (char)ch;
}
// Terminate string with a null character
str2[i] = '\0';
if (str2[0] == 'q')
{
break;
}
float input2 = atof(str2);
float sigma;
if (input2 == 0)
{
// Open-CV sigma � Gaussian standard deviation. If it is non-positive, it is computed from ksize as sigma = 0.3*((ksize-1)*0.5 - 1) + 0.8 .
sigma = 0.3*((input1 - 1)*0.5 - 1) + 0.8;
}
else
{
sigma = input2;
}
printf("Input sigma was: %f\n", sigma);
// input Coefficient K
printf("Please enter Coefficient K. Use default press Enter . Exit enter q \n");
str3[0] = '0';
for (i = 0; (i < 80) && ((ch = getchar()) != EOF)
&& (ch != '\n'); i++)
{
str3[i] = (char)ch;
}
// Terminate string with a null character
str3[i] = '\0';
if (str3[0] == 'q')
{
break;
}
int input3 = atoi(str3);
int cK;
if (input3 == 0)
{
cK = 1;
}
else
{
cK = input3;
}
float sum_f = 0;
float temp_f;
int sum = 0;
int temp;
printf("Input Coefficient K was: %d\n", cK);
printf("\nwindow size=%d | Sigma = %f Coefficient K = %d\n\n\n", input1, sigma, cK);
kernel_type kernel2d = produce2dGaussianKernel(window_size, sigma);
std::cout << std::setprecision(input1) << std::fixed;
for (int row = 0; row < kernel2d.size(); row++) {
for (int col = 0; col < kernel2d[row].size(); col++)
{
temp_f = cK* kernel2d[row][col];
sum_f += temp_f;
space = countSpace(temp_f);
std::cout << gMatChar[space] << temp_f << ' ';
}
std::cout << '\n';
}
printf("\n Sum array = %f | delta = %f", sum_f, sum_f - cK);
// rounding
printf("\nRecommend use round(): window size=%d | Sigma = %f Coefficient K = %d\n\n\n", input1, sigma, cK);
sum = 0;
std::cout << std::setprecision(0) << std::fixed;
for (int row = 0; row < kernel2d.size(); row++) {
for (int col = 0; col < kernel2d[row].size(); col++)
{
temp = round(cK* kernel2d[row][col]);
sum += temp;
space = countSpace((float)temp);
std::cout << gMatChar[space] << temp << ' ';
}
std::cout << '\n';
}
printf("\n Sum array = %d | delta = %d", sum, sum - cK);
// recommented
sum_f = 0;
int cK_d = 1 / kernel2d[0][0];
cK_d = cK_d / 2 * 2;
printf("\nRecommend: window size=%d | Sigma = %f Coefficient K = %d\n\n\n", input1, sigma, cK_d);
std::cout << std::setprecision(input1) << std::fixed;
for (int row = 0; row < kernel2d.size(); row++) {
for (int col = 0; col < kernel2d[row].size(); col++)
{
temp_f = cK_d* kernel2d[row][col];
sum_f += temp_f;
space = countSpace(temp_f);
std::cout << gMatChar[space] << temp_f << ' ';
}
std::cout << '\n';
}
printf("\n Sum array = %f | delta = %f", sum_f, sum_f - cK_d);
// rounding
printf("\nRecommend use round(): window size=%d | Sigma = %f Coefficient K = %d\n\n\n", input1, sigma, cK_d);
sum = 0;
std::cout << std::setprecision(0) << std::fixed;
for (int row = 0; row < kernel2d.size(); row++) {
for (int col = 0; col < kernel2d[row].size(); col++)
{
temp = round(cK_d* kernel2d[row][col]);
sum += temp;
space = countSpace((float)temp);
std::cout << gMatChar[space] << temp << ' ';
}
std::cout << '\n';
}
printf("\n Sum array = %d | delta = %d", sum, sum - cK_d);
}
}