Tark_Wight

Median + Vectorisation

Apr 23rd, 2023 (edited)
133
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.06 KB | Source Code | 0 0
  1. #include <algorithm>
  2. #include <intrin.h>
  3. #include <iostream>
  4. #include <fstream>
  5. #include <string>
  6. #include <vector>
  7. #include <ctime>
  8. #include <cstring>
  9. #include <omp.h>
  10. #include <xmmintrin.h>
  11. #include <immintrin.h>
  12. #include "lodepng.cpp"
  13. #include "lodepng.h"
  14.  
  15.  
  16. using namespace std;
  17.  
  18.  
  19. //@@@@@@@@@@@@@@@@@@@@      Vectorisation Filter     @@@@@@@@@@@@@@@@@@@@
  20.  
  21.  
  22. unsigned char getVectorisationMedian(std::vector<unsigned char>& values) {
  23.     std::sort(values.begin(), values.end());
  24.     return values[values.size() / 2];
  25. }
  26.  
  27. void applyVectorisationMedianFilter(std::vector<unsigned char>& image, int width, int height, int channels, int filterSize) {
  28.     std::vector<unsigned char> result(image.size());
  29.  
  30.     int radius = filterSize / 2;
  31.     const int vecSize = 16; // vector size in bytes
  32.  
  33.     for (int y = 0; y < height; y++) {
  34.         for (int x = 0; x < width; x++) {
  35.             for (int c = 0; c < channels; c++) {
  36.                 std::vector<unsigned char> values;
  37.  
  38.                 // load input values into a vector register
  39.                 __m128i inputVec = _mm_setzero_si128();
  40.  
  41.                 for (int i = -radius; i <= radius; i++) {
  42.                     for (int j = -radius; j <= radius; j += vecSize) {
  43.                         int px = std::min(std::max(x + j, 0), width - 1);
  44.                         int py = std::min(std::max(y + i, 0), height - 1);
  45.  
  46.                         // load vector of input values
  47.                         __m128i curVec = _mm_loadu_si128((__m128i*) & image[(py * width + px) * channels + c]);
  48.  
  49.                         // merge vectors into a single vector
  50.                         inputVec = _mm_or_si128(inputVec, curVec);
  51.                     }
  52.                 }
  53.  
  54.                 // extract values from the vector register
  55.                 unsigned char inputArr[vecSize];
  56.                 _mm_storeu_si128((__m128i*)inputArr, inputVec);
  57.  
  58.                 // add values to the vector of values
  59.                 for (int i = 0; i < vecSize; i++) {
  60.                     values.push_back(inputArr[i]);
  61.                 }
  62.  
  63.                 // calculate median and store in result
  64.                 result[(y * width + x) * channels + c] = getMedian(values);
  65.             }
  66.         }
  67.     }
  68.  
  69.     image = result;
  70. }
  71.  
  72. void medianVectorisationFilter(const char* inputFilename, const char* outputFilename, int filterSize) {
  73.     std::vector<unsigned char> image;
  74.     unsigned width, height;
  75.  
  76.     // Загружаем изображение
  77.     unsigned error = lodepng::decode(image, width, height, inputFilename);
  78.  
  79.     if (error) {
  80.         std::cerr << "Error decoding image: " << lodepng_error_text(error) << std::endl;
  81.         return;
  82.     }
  83.  
  84.     // Применяем медианный фильтр
  85.     applyVectorisationMedianFilter(image, width, height, 4, filterSize);
  86.  
  87.     // Сохраняем изображение
  88.     error = lodepng::encode(outputFilename, image, width, height);
  89.  
  90.     if (error) {
  91.         std::cerr << "Error encoding image: " << lodepng_error_text(error) << std::endl;
  92.         return;
  93.     }
  94. }
  95.  
  96.  
Advertisement
Add Comment
Please, Sign In to add comment