|
|
- #include <iostream>
- #include <cstdlib>
- #include <cmath>
- #include <mpi.h>
- #include "Ttiming.h"
- #include <opencv2/opencv.hpp>
-
- using namespace std;
- using namespace cv;
-
- #define RX 5
- #define RY 5
- int main(int argc, char *argv[])
- {
- int i,j,k,l,m,n;
- TTiming tt;
- int sumka_r, sumka_g, sumka_b;
- int suma_wag = 0;
- Mat img_out;
- int porcja_new=0;
- Mat img;
- Mat img_part_out;
-
- int ratio[RX][RY] =
- {
- {1, 4, 7, 4, 1},
- {4, 16, 26, 16, 4},
- {7, 26, 41, 26, 7},
- {4, 16, 26, 16, 4},
- {1, 4, 7, 4, 1}
- };
-
- if (argc < 3)
- {
- cerr << "Usage: " << argv[0] << " <input_image> <output_image>" << endl;
- exit(1);
- }
-
- img = cv::imread(argv[1]);
- if(!img.data )
- {
- cerr << "File " << argv[1] << " does not exist" << endl;
- exit(1);
- }
-
- for (i=0; i<RX; ++i)
- for (j=0; j<RY; ++j)
- suma_wag += ratio[i][j];
-
- MPI::Init(argc, argv);
-
- int taskid = MPI::COMM_WORLD.Get_rank();
- int ntasks = MPI::COMM_WORLD.Get_size();
-
- // porcja - ile wektorów dostaje jeden proces do liczenia
- // jeżeli liczba procesów większa od wektorów - każdy proces dostaje po jednym, niektóre wcale
- int porcja = (img.rows>=ntasks) ? (int)round(img.rows*1.0/ntasks) : 1;
- //porcja *= img.cols; //porcję mnożymy przez ilość elementów w jednym wektorze
- porcja_new = porcja;
-
- if (taskid == 0)
- img_out.create(img.rows, img.cols, img.type());
-
- int *chunk_sizes = new int[ntasks];
- int *chunk_order = new int[ntasks];
-
- //liczę tablicę z danymi - o tym ile dany chunk ma rozmiaru oraz offset w tablicy od pierwszego procesu
- for (i=0; i<ntasks; ++i)
- {
- chunk_order[i] = (i == 0) ? 0 : chunk_order[i-1] + chunk_sizes[i-1];
- chunk_sizes[i] = porcja*img.cols*3;
-
- if (i == ntasks-1)
- chunk_sizes[i] = (img.rows - porcja*(ntasks-1))*img.cols*3;
- }
-
- MPI::COMM_WORLD.Barrier();
-
- //
- // część licząca ---------------------------------------------------------------------------------
- //
-
- MPI::COMM_WORLD.Barrier();
- if (taskid == 0)
- tt.Begin();
- int start_pos = taskid*porcja;
- int stop_pos = (taskid+1)*porcja;
-
- if (taskid == ntasks -1) //przelicz porcję dla ostatniego procesu (w przypadku dzielenia z resztą)
- {
- porcja_new = img.rows - porcja*(ntasks-1);
-
- // myk jest taki, że muszę podać jakąś niezerową porcję do gathera,
- // mimo, że proces nie ma żadnych (sensownych) danych do przetworzenia
- if (porcja_new > 0)
- {
- stop_pos = img.rows;
- porcja = porcja_new;
- }
- }
- img_part_out.create(porcja, img.cols, img.type());
-
- int p=0, q=0;
-
- for (i=start_pos; i<stop_pos; ++i)
- {
- q = 0;
- for (j=0; j<img.cols; ++j)
- {
- if (i<2 || i>img.rows-3 || j<2 || j>img.cols-3)
- {
- img_part_out.at<Vec3b>(p, q)[0] = img.at<Vec3b>(i, j)[0];
- img_part_out.at<Vec3b>(p, q)[1] = img.at<Vec3b>(i, j)[1];
- img_part_out.at<Vec3b>(p, q)[2] = img.at<Vec3b>(i, j)[2];
- }
- else
- {
- sumka_r = 0;
- sumka_g = 0;
- sumka_b = 0;
- m=i-2;
- for (k=0; k<RX; ++k,++m)
- {
- n=j-2;
- for (l=0; l<RY; ++l,++n)
- {
- sumka_b += ratio[k][l] * img.at<Vec3b>(m, n)[0];
- sumka_g += ratio[k][l] * img.at<Vec3b>(m, n)[1];
- sumka_r += ratio[k][l] * img.at<Vec3b>(m, n)[2];
- }
- }
- img_part_out.at<Vec3b>(p, q).val[0] = sumka_b / suma_wag;
- img_part_out.at<Vec3b>(p, q).val[1] = sumka_g / suma_wag;
- img_part_out.at<Vec3b>(p, q).val[2] = sumka_r / suma_wag;
- }
- ++q;
- }
- ++p;
- }
-
- MPI::COMM_WORLD.Barrier();
- if (taskid == 0)
- {
- long elapsed = tt.End();
- cout << "Time: " << elapsed << " ms" << endl;
- }
- // zwróć wszystko do programu głównego
- 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);
-
- if (taskid == 0)
- imwrite(argv[2], img_out);
- MPI::Finalize();
-
- exit(0);
- }
|