Tark_Wight

Untitled

Apr 23rd, 2023
127
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.99 KB | None | 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. //@@@@@@@@@@@@@@@@@@@@ Consistent Filter @@@@@@@@@@@@@@@@@@@@
  20.  
  21. unsigned char getMedian(std::vector<unsigned char>& values) {
  22. std::sort(values.begin(), values.end());
  23. return values[values.size() / 2];
  24. }
  25.  
  26. void applyMedianFilter(std::vector<unsigned char>& image, int width, int height, int channels, int filterSize) {
  27. std::vector<unsigned char> result(image.size());
  28.  
  29. int radius = filterSize / 2;
  30.  
  31. for (int y = 0; y < height; y++) {
  32. for (int x = 0; x < width; x++) {
  33. for (int c = 0; c < channels; c++) {
  34. std::vector<unsigned char> values;
  35.  
  36. for (int i = -radius; i <= radius; i++) {
  37. for (int j = -radius; j <= radius; j++) {
  38. int px = std::min(std::max(x + j, 0), width - 1);
  39. int py = std::min(std::max(y + i, 0), height - 1);
  40.  
  41. values.push_back(image[(py * width + px) * channels + c]);
  42. }
  43. }
  44.  
  45. result[(y * width + x) * channels + c] = getMedian(values);
  46. }
  47. }
  48. }
  49.  
  50. image = result;
  51. }
  52.  
  53. void medianFilter(const char* inputFilename, const char* outputFilename, int filterSize) {
  54. std::vector<unsigned char> image;
  55. unsigned width, height;
  56.  
  57. // Загружаем изображение
  58. unsigned error = lodepng::decode(image, width, height, inputFilename);
  59.  
  60. if (error) {
  61. std::cerr << "Error decoding image: " << lodepng_error_text(error) << std::endl;
  62. return;
  63. }
  64.  
  65. // Применяем медианный фильтр
  66. applyMedianFilter(image, width, height, 4, filterSize);
  67.  
  68. // Сохраняем изображение
  69. error = lodepng::encode(outputFilename, image, width, height);
  70.  
  71. if (error) {
  72. std::cerr << "Error encoding image: " << lodepng_error_text(error) << std::endl;
  73. return;
  74. }
  75. }
  76.  
  77.  
  78.  
  79. //@@@@@@@@@@@@@@@@@@@@ OpenMP Filter @@@@@@@@@@@@@@@@@@@@
  80.  
  81. unsigned char getMedianOMP(std::vector<unsigned char>& values) {
  82. std::sort(values.begin(), values.end());
  83. return values[values.size() / 2];
  84. }
  85.  
  86. void applyMedianFilterOMP(std::vector<unsigned char>& image, int width, int height, int channels, int filterSize) {
  87. std::vector<unsigned char> result(image.size());
  88.  
  89. int radius = filterSize / 2;
  90. #pragma omp parallel for collapse(5)
  91. for (int y = 0; y < height; y++) {
  92. for (int x = 0; x < width; x++) {
  93. for (int c = 0; c < channels; c++) {
  94. std::vector<unsigned char> values;
  95.  
  96. for (int i = -radius; i <= radius; i++) {
  97. for (int j = -radius; j <= radius; j++) {
  98. int px = std::min(std::max(x + j, 0), width - 1);
  99. int py = std::min(std::max(y + i, 0), height - 1);
  100.  
  101. values.push_back(image[(py * width + px) * channels + c]);
  102. }
  103. }
  104.  
  105. result[(y * width + x) * channels + c] = getMedianOMP(values);
  106. }
  107. }
  108. }
  109.  
  110. image = result;
  111. }
  112.  
  113. void medianFilterOMP(const char* inputFilename, const char* outputFilename, int filterSize) {
  114. std::vector<unsigned char> image;
  115. unsigned width, height;
  116.  
  117. // Загружаем изображение
  118. unsigned error = lodepng::decode(image, width, height, inputFilename);
  119.  
  120. if (error) {
  121. std::cerr << "Error decoding image: " << lodepng_error_text(error) << std::endl;
  122. return;
  123. }
  124.  
  125. // Применяем медианный фильтр
  126. applyMedianFilterOMP(image, width, height, 4, filterSize);
  127.  
  128. // Сохраняем изображение
  129. error = lodepng::encode(outputFilename, image, width, height);
  130.  
  131. if (error) {
  132. std::cerr << "Error encoding image: " << lodepng_error_text(error) << std::endl;
  133. return;
  134. }
  135. }
  136.  
  137.  
  138. //@@@@@@@@@@@@@@@@@@@@ Vectorisation Filter @@@@@@@@@@@@@@@@@@@@
  139.  
  140.  
  141. unsigned char getVectorisationMedian(std::vector<unsigned char>& values) {
  142. std::sort(values.begin(), values.end());
  143. return values[values.size() / 2];
  144. }
  145.  
  146. void applyVectorisationMedianFilter(std::vector<unsigned char>& image, int width, int height, int channels, int filterSize) {
  147. std::vector<unsigned char> result(image.size());
  148.  
  149. int radius = filterSize / 2;
  150. const int vecSize = 16; // vector size in bytes
  151.  
  152. for (int y = 0; y < height; y++) {
  153. for (int x = 0; x < width; x++) {
  154. for (int c = 0; c < channels; c++) {
  155. std::vector<unsigned char> values;
  156.  
  157. // load input values into a vector register
  158. __m128i inputVec = _mm_setzero_si128();
  159.  
  160. for (int i = -radius; i <= radius; i++) {
  161. for (int j = -radius; j <= radius; j += vecSize) {
  162. int px = std::min(std::max(x + j, 0), width - 1);
  163. int py = std::min(std::max(y + i, 0), height - 1);
  164.  
  165. // load vector of input values
  166. __m128i curVec = _mm_loadu_si128((__m128i*) & image[(py * width + px) * channels + c]);
  167.  
  168. // merge vectors into a single vector
  169. inputVec = _mm_or_si128(inputVec, curVec);
  170. }
  171. }
  172.  
  173. // extract values from the vector register
  174. unsigned char inputArr[vecSize];
  175. _mm_storeu_si128((__m128i*)inputArr, inputVec);
  176.  
  177. // add values to the vector of values
  178. for (int i = 0; i < vecSize; i++) {
  179. values.push_back(inputArr[i]);
  180. }
  181.  
  182. // calculate median and store in result
  183. result[(y * width + x) * channels + c] = getMedian(values);
  184. }
  185. }
  186. }
  187.  
  188. image = result;
  189. }
  190.  
  191. void medianVectorisationFilter(const char* inputFilename, const char* outputFilename, int filterSize) {
  192. std::vector<unsigned char> image;
  193. unsigned width, height;
  194.  
  195. // Загружаем изображение
  196. unsigned error = lodepng::decode(image, width, height, inputFilename);
  197.  
  198. if (error) {
  199. std::cerr << "Error decoding image: " << lodepng_error_text(error) << std::endl;
  200. return;
  201. }
  202.  
  203. // Применяем медианный фильтр
  204. applyVectorisationMedianFilter(image, width, height, 4, filterSize);
  205.  
  206. // Сохраняем изображение
  207. error = lodepng::encode(outputFilename, image, width, height);
  208.  
  209. if (error) {
  210. std::cerr << "Error encoding image: " << lodepng_error_text(error) << std::endl;
  211. return;
  212. }
  213. }
  214.  
  215.  
  216. //@@@@@@@@@@@@@@@@@@@@ OpenMP Vectorisation Filter @@@@@@@@@@@@@@@@@@@@
  217.  
  218.  
  219. unsigned char getMedianOMPVectorisation(std::vector<unsigned char>& values) {
  220. // Use SIMD to sort the pixel values
  221. __m128i xmm_data;
  222. unsigned char* data_ptr = values.data();
  223. int size = values.size();
  224. for (int i = 0; i < size; i += 16) {
  225. xmm_data = _mm_load_si128((__m128i*)(data_ptr + i));
  226. _mm_store_si128((__m128i*)(data_ptr + i), _mm_shuffle_epi8(xmm_data, _mm_set_epi8(
  227. 15, 14, 13, 12, 11, 10, 9, 8,
  228. 7, 6, 5, 4, 3, 2, 1, 0)));
  229. }
  230. std::sort(values.begin(), values.end());
  231. return values[values.size() / 2];
  232. }
  233.  
  234. void applyMedianFilterOMPVectorisation(std::vector<unsigned char>& image, int width, int height, int channels, int filterSize) {
  235. std::vector<unsigned char> result(image.size());
  236.  
  237. int radius = filterSize / 2;
  238.  
  239. #pragma omp parallel for collapse(5)
  240. for (int y = 0; y < height; y++) {
  241. for (int x = 0; x < width; x++) {
  242. for (int c = 0; c < channels; c++) {
  243. std::vector<unsigned char> values;
  244.  
  245. for (int i = -radius; i <= radius; i++) {
  246. for (int j = -radius; j <= radius; j++) {
  247. int px = std::min(std::max(x + j, 0), width - 1);
  248. int py = std::min(std::max(y + i, 0), height - 1);
  249.  
  250. values.push_back(image[(py * width + px) * channels + c]);
  251. }
  252. }
  253.  
  254. result[(y * width + x) * channels + c] = getMedianOMPVectorisation(values);
  255. }
  256. }
  257. }
  258.  
  259. image = result;
  260. }
  261.  
  262. void medianFilterOMPVectorisation(const char* inputFilename, const char* outputFilename, int filterSize) {
  263. std::vector<unsigned char> image;
  264. unsigned width, height;
  265.  
  266. // Загружаем изображение
  267. unsigned error = lodepng::decode(image, width, height, inputFilename);
  268.  
  269. if (error) {
  270. std::cerr << "Error decoding image: " << lodepng_error_text(error) << std::endl;
  271. return;
  272. }
  273.  
  274. // Применяем медианный фильтр
  275. applyMedianFilterOMPVectorisation(image, width, height, 4, filterSize);
  276.  
  277. // Сохраняем изображение
  278. error = lodepng::encode(outputFilename, image, width, height);
  279.  
  280. if (error) {
  281. std::cerr << "Error encoding image: " << lodepng_error_text(error) << std::endl;
  282. return;
  283. }
  284. }
  285.  
  286.  
  287. //# # # # # # # # # # # Consistent Call # # # # # # # # # # #
  288. void userConsistentMedianFilter() {
  289. clock_t start = clock();
  290. medianFilter("input.png", "outputMedian.png", 10);
  291. clock_t end = clock();
  292. double elapsed_time = double(end - start) / CLOCKS_PER_SEC;
  293. std::cout << "Время выполнения функции медианного фильтра: " << elapsed_time << " секунд." << std::endl;
  294. }
  295. void userConsistentFilters() {
  296. userConsistentMedianFilter();
  297.  
  298. }
  299.  
  300. //# # # # # # # # # # # OpenMP Call # # # # # # # # # # #
  301. void userOMPMedianFilter() {
  302. clock_t start = clock();
  303. medianFilterOMP("input.png", "outputMedianOMP.png", 10);
  304. clock_t end = clock();
  305. double elapsed_time = double(end - start) / CLOCKS_PER_SEC;
  306. std::cout << "Время выполнения функции медианного фильтра: " << elapsed_time << " секунд." << std::endl;
  307. }
  308. void userOPMFilters() {
  309. userOMPMedianFilter();
  310.  
  311. }
  312.  
  313. //# # # # # # # # # # # Vectorization Call # # # # # # # # # # #
  314. void userVectorizationMedianFilter() {
  315. clock_t start = clock();
  316. medianVectorisationFilter("input.png", "outputMedianVec.png", 10);
  317. clock_t end = clock();
  318. double elapsed_time = double(end - start) / CLOCKS_PER_SEC;
  319. std::cout << "Время выполнения функции медианного фильтра: " << elapsed_time << " секунд." << std::endl;
  320. }
  321. void userVectorizationFilters() {
  322. userVectorizationMedianFilter();
  323.  
  324. }
  325.  
  326. //# # # # # # # # # # # OpenMP Vectorization Call # # # # # # # # # # #
  327. void userOMPVectorizationMedianFilter() {
  328. clock_t start = clock();
  329. medianFilterOMPVectorisation("input.png", "outputMedianOpenMPVec.png", 10);
  330. clock_t end = clock();
  331. double elapsed_time = double(end - start) / CLOCKS_PER_SEC;
  332. std::cout << "Время выполнения функции медианного фильтра: " << elapsed_time << " секунд." << std::endl;
  333. }
  334. void userOMPVectorizationFilters() {
  335. userOMPVectorizationMedianFilter();
  336.  
  337. }
  338.  
  339.  
  340. int main() {
  341. setlocale(LC_ALL, "Russian");
  342. std::cout << "Последовательный метод:\n";
  343. userConsistentFilters();
  344. std::cout << "\n\n";
  345.  
  346. std::cout << "OpenMP:\n";
  347. userOPMFilters();
  348. std::cout << "\n\n";
  349.  
  350. std::cout << "Vectorization:\n";
  351. userVectorizationFilters();
  352. std::cout << "\n\n";
  353. std::cout << "OpenMP Vectorization:\n";
  354. userOMPVectorizationFilters();
  355. std::cout << "\n";
  356. return 0;
  357. }
Add Comment
Please, Sign In to add comment