Advertisement
sacr1ficerq

blur

Mar 26th, 2022
34
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.64 KB | None | 0 0
  1. #include "blur.h"
  2.  
  3. #include <valarray>
  4. #include <chrono>
  5. #include <iostream>
  6.  
  7.  
  8. namespace {
  9.     double CalculateGaussian(size_t delta_x, size_t delta_y, double sigma) {
  10.         double coefficient = sigma * sigma * 2 * std::numbers::pi_v<double>;
  11.         double degree = (delta_x * delta_x + delta_y * delta_y) / (2 * sigma * sigma);
  12.         double result = exp(-1 * degree) / coefficient;
  13.         return result;
  14.     }
  15.  
  16.     NormalChannel CalculateGaussianMatrix(double radius, double sigma) {
  17.         auto start = std::chrono::high_resolution_clock::now();
  18.         NormalChannel matrix(2 * radius, std::vector<double>(2 * radius, 0));
  19.         for (size_t x = 0; x < 2 * radius; ++x) {
  20.             for (size_t y = 0; y < 2 * radius; ++y) {
  21.                 matrix[y][x] = CalculateGaussian(x, y, sigma);
  22.             }
  23.         }
  24.         auto stop = std::chrono::high_resolution_clock::now();
  25.         auto execution_time = duration_cast<std::chrono::milliseconds>(stop - start).count();
  26.  
  27.         std::cout << "Matrix built in " << std::round(execution_time / 10) / 100 << " seconds" << std::endl;
  28.         return matrix;
  29.     }
  30.  
  31.     NormalRGBMatrix ApplyGaussian(NormalRGBMatrix &matrix, size_t height, size_t width, double sigma) {
  32.         auto new_matrix = matrix;
  33.         static const double RADIUS = 20;
  34.         const auto gauss_matrix = CalculateGaussianMatrix(RADIUS, sigma);
  35.  
  36.         double accumulation_red;
  37.         double accumulation_green;
  38.         double accumulation_blue;
  39.  
  40.         for (size_t x0 = 0; x0 < width; ++x0) {
  41.             for (size_t y0 = 0; y0 < height; ++y0) {
  42.                 accumulation_red = 0;
  43.                 accumulation_green = 0;
  44.                 accumulation_blue = 0;
  45.  
  46.                 size_t left_border = x0 < RADIUS ? 0 : x0 - RADIUS;
  47.                 size_t top_border = y0 < RADIUS ? 0 : y0 - RADIUS;
  48.  
  49.                 if (x0 + RADIUS >= width) {
  50.                     left_border = std::max<double>(width - 2 * RADIUS, 0);
  51.                 }
  52.  
  53.                 if (y0 + RADIUS >= height) {
  54.                     top_border = std::max<double>(width - 2 * RADIUS, 0);
  55.                 }
  56.  
  57.                 size_t right_border = std::min<double>(left_border + 2 * RADIUS, width);
  58.                 size_t bottom_border = std::min<double>(top_border + 2 * RADIUS, height);
  59.  
  60.                 for (size_t x = left_border; x < right_border; ++x) {
  61.                     for (size_t y = top_border; y < bottom_border; ++y) {
  62.                         double delta_x = x0 > x ? x0 - x : x - x0;
  63.                         double delta_y = y0 > y ? y0 - y : y - y0;
  64.  
  65.                         if (delta_x > RADIUS || delta_y > RADIUS) {
  66.                             continue;
  67.                         }
  68.  
  69.                         auto gaussian = gauss_matrix[delta_x][delta_y];
  70.  
  71.                         accumulation_red += matrix.red_chanel[y][x] * gaussian;
  72.                         accumulation_green += matrix.green_chanel[y][x] * gaussian;
  73.                         accumulation_blue += matrix.blue_chanel[y][x] * gaussian;
  74.                     }
  75.                 }
  76.                 new_matrix.red_chanel[y0][x0] = std::max<double>(0, std::min<double>(accumulation_red, 1));
  77.                 new_matrix.green_chanel[y0][x0] = std::max<double>(0, std::min<double>(accumulation_green, 1));
  78.                 new_matrix.blue_chanel[y0][x0] = std::max<double>(0, std::min<double>(accumulation_blue, 1));
  79.             }
  80.         }
  81.         return new_matrix;
  82.     }
  83. }
  84.  
  85.  
  86. void Blur::Process(Image &input) {
  87.     auto rgb = input.GetNormalChannels();
  88.  
  89.     auto new_rgb = ApplyGaussian(rgb, input.height, input.width, sigma_);
  90.  
  91.     input = Image(new_rgb);
  92. }
  93.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement