#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);
|
|
}
|