Implementing Gaussian Blur - How to calculate convolution matrix (kernel)

后端 未结 7 2011
予麋鹿
予麋鹿 2020-12-22 21:14

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,

相关标签:
7条回答
  • 2020-12-22 22:04
    // 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);
    
        }
    }
    
    0 讨论(0)
提交回复
热议问题