You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

168 lines
4.2 KiB

  1. #include <iostream>
  2. #include <cstdlib>
  3. #include <cmath>
  4. #include <mpi.h>
  5. #include "Ttiming.h"
  6. #include <opencv2/opencv.hpp>
  7. using namespace std;
  8. using namespace cv;
  9. #define RX 5
  10. #define RY 5
  11. int main(int argc, char *argv[])
  12. {
  13. int i,j,k,l,m,n;
  14. TTiming tt;
  15. int sumka_r, sumka_g, sumka_b;
  16. int suma_wag = 0;
  17. Mat img_out;
  18. int buff_max=0,porcja_new=0;
  19. Mat img;
  20. Mat img_part_out;
  21. int ratio[RX][RY] =
  22. {
  23. {1, 4, 7, 4, 1},
  24. {4, 16, 26, 16, 4},
  25. {7, 26, 41, 26, 7},
  26. {4, 16, 26, 16, 4},
  27. {1, 4, 7, 4, 1}
  28. };
  29. if (argc < 3)
  30. {
  31. cerr << "Usage: " << argv[0] << " <input_image> <output_image>" << endl;
  32. exit(1);
  33. }
  34. img = cv::imread(argv[1]);
  35. if(!img.data )
  36. {
  37. cerr << "File " << argv[1] << " does not exist" << endl;
  38. MPI::Finalize();
  39. exit(1);
  40. }
  41. for (i=0; i<RX; ++i)
  42. for (j=0; j<RY; ++j)
  43. suma_wag += ratio[i][j];
  44. MPI::Init(argc, argv);
  45. int taskid = MPI::COMM_WORLD.Get_rank();
  46. int ntasks = MPI::COMM_WORLD.Get_size();
  47. // porcja - ile wektorów dostaje jeden proces do liczenia
  48. // jeżeli liczba procesów większa od wektorów - każdy proces dostaje po jednym, niektóre wcale
  49. int porcja = (img.rows>=ntasks) ? (int)round(img.rows*1.0/ntasks) : 1;
  50. //porcja *= img.cols; //porcję mnożymy przez ilość elementów w jednym wektorze
  51. porcja_new = porcja;
  52. // dla kompatybilności liczę jeszcze rozmiar bufora odbioru,
  53. // np. jeżeli chunki będą jednolitego rozmiaru, a ostatni będzie większy
  54. // to bufor odbioru musi być zwiększony (żeby go nie ucinało)
  55. buff_max = img.rows - porcja*(ntasks-1);
  56. if (porcja > buff_max)
  57. buff_max = porcja; // na wypadek, jeżeli jednak ostatni kawałek będzie mniejszy
  58. if (taskid == 0)
  59. img_out.create(img.rows, img.cols, img.type());
  60. int *chunk_sizes = new int[ntasks];
  61. int *chunk_order = new int[ntasks];
  62. for (i=0; i<ntasks; ++i)
  63. {
  64. //if (i == 0)
  65. chunk_order[i] = (i == 0) ? 0 : chunk_order[i-1] + chunk_sizes[i-1];
  66. chunk_sizes[i] = porcja*img.cols*3;
  67. if (i == ntasks-1)
  68. chunk_sizes[i] = (img.rows - porcja*(ntasks-1))*img.cols*3;
  69. //if (taskid == 0)
  70. // cout << chunk_sizes[i] << endl;
  71. }
  72. MPI::COMM_WORLD.Barrier();
  73. //
  74. // część licząca ---------------------------------------------------------------------------------
  75. //
  76. MPI::COMM_WORLD.Barrier();
  77. if (taskid == 0)
  78. tt.Begin();
  79. int start_pos = taskid*porcja;
  80. int stop_pos = (taskid+1)*porcja;
  81. if (taskid == ntasks -1) //przelicz porcję dla ostatniego procesu (w przypadku dzielenia z resztą)
  82. {
  83. porcja_new = img.rows - porcja*(ntasks-1);
  84. // myk jest taki, że muszę podać jakąś niezerową porcję do gathera,
  85. // mimo, że proces nie ma żadnych (sensownych) danych do przetworzenia
  86. if (porcja_new > 0)
  87. {
  88. stop_pos = img.rows;
  89. porcja = porcja_new;
  90. }
  91. }
  92. img_part_out.create(porcja, img.cols, img.type());
  93. int p=0, q=0;
  94. for (i=start_pos; i<stop_pos; ++i)
  95. {
  96. q = 0;
  97. for (j=0; j<img.cols; ++j)
  98. {
  99. if (i<2 || i>img.rows-3 || j<2 || j>img.cols-3)
  100. {
  101. img_part_out.at<Vec3b>(p, q)[0] = img.at<Vec3b>(i, j)[0];
  102. img_part_out.at<Vec3b>(p, q)[1] = img.at<Vec3b>(i, j)[1];
  103. img_part_out.at<Vec3b>(p, q)[2] = img.at<Vec3b>(i, j)[2];
  104. }
  105. else
  106. {
  107. sumka_r = 0;
  108. sumka_g = 0;
  109. sumka_b = 0;
  110. m=i-2;
  111. for (k=0; k<RX; ++k,++m)
  112. {
  113. n=j-2;
  114. for (l=0; l<RY; ++l,++n)
  115. {
  116. sumka_b += ratio[k][l] * img.at<Vec3b>(m, n)[0];
  117. sumka_g += ratio[k][l] * img.at<Vec3b>(m, n)[1];
  118. sumka_r += ratio[k][l] * img.at<Vec3b>(m, n)[2];
  119. }
  120. }
  121. img_part_out.at<Vec3b>(p, q).val[0] = sumka_b / suma_wag;
  122. img_part_out.at<Vec3b>(p, q).val[1] = sumka_g / suma_wag;
  123. img_part_out.at<Vec3b>(p, q).val[2] = sumka_r / suma_wag;
  124. }
  125. ++q;
  126. }
  127. ++p;
  128. }
  129. MPI::COMM_WORLD.Barrier();
  130. if (taskid == 0 && false)
  131. {
  132. long elapsed = tt.End();
  133. cout << "Time: " << elapsed << " ms" << endl;
  134. }
  135. // zwróć wszystko do programu głównego
  136. cout << porcja << endl;
  137. //MPI::COMM_WORLD.Gather(&img_part_out.data[0], buff_max*img.cols*3, MPI::CHAR, &img_out.data[0], buff_max*img.cols*3, MPI::CHAR, 0);
  138. MPI::COMM_WORLD.Gatherv(&img_part_out.data[0], porcja*img.cols*3, MPI::CHAR, &img_out.data[0], chunk_sizes, chunk_order, MPI::CHAR, 0);
  139. //cout << taskid << endl;
  140. if (taskid == 0)
  141. imwrite(argv[2], img_out);
  142. MPI::Finalize();
  143. exit(0);
  144. }