Advertisement
Guest User

Untitled

a guest
Jan 18th, 2020
97
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.29 KB | None | 0 0
  1. /*
  2.    Línea de compilación: gcc main.c pgm.c -o main
  3.  
  4.    Ejemplo del uso de:
  5.  
  6.    pgmread
  7.    pgmwrite
  8.  
  9.    Las matrices que contienen a las imágenes son declaradas como uchar
  10.  
  11.    % % % % % % % %
  12.  
  13.    Ejemplo 1:
  14.  
  15.    unsigned char Original = (unsigned char )pgmread("entrada.pgm", &Largo, &Alto);
  16.    La imagen PGM se lee de la línea de comando (argv[1]). La función
  17.    pgmread regresa tres valores:
  18.  
  19.    1. la imagen leída       (Original)
  20.    2. el largo de la imagen (Largo)
  21.    3. el alto de la imagen  (Alto)
  22.  
  23.    % % % % % % % %
  24.  
  25.    Ejemplo 2:
  26.  
  27.    pgmwrite(Salida, "salida.pgm", Largo, Alto);
  28.    La imagen Salida es escrita al disco con el nombre de negativo.pgm, la
  29.    imagen resulta en formato PGM. La imagen se escribe desde el inicio (0,0)
  30.    hasta (Largo, Alto).
  31. */
  32.  
  33. #include <stdio.h>
  34. #include <stdlib.h>
  35. #include <string.h>
  36. #include "pgm.h"
  37. #include <mpi.h>
  38. #include <tgmath.h>
  39.  
  40. typedef struct
  41. {
  42.   int start;
  43.   int size;
  44. } asignacion;
  45.  
  46. // Asigna el trabajo que hará cada proceso
  47. //      Cada proceso tendra como MÍNIMO (tamaño del array / procesos) elementos de los que encargarse y además, puede tener 0 o 1 elemento más (nunca más de 1) del que encargarse.
  48. //      empieza en (tamaño / procesos) *procesoActual+min(tamaño%procesos, i)*** El mínimo lo usamos para saber el número de elementos adicionales que se han añadido a cada proceso antes del actual
  49. //      con un tamaño de: (tamaño / procesos) + 1 si (tamaño % procesos) es > procesoActual o +0 en caso contrario
  50. asignacion reparto(int size, int workers, int i)
  51. {
  52.   return (asignacion){
  53.       .start = (size / workers) * i + fmin(size % workers, i),
  54.       .size = (size / workers) + (size % workers > i ? 1 : 0)};
  55. }
  56.  
  57. void convolucion(unsigned char *Original, int *nucleo, unsigned char *Salida, int Columnas, int Filas, int nucleoSize, int bordeNucleo)
  58. {
  59.   int x, y;
  60.   int suma;
  61.   int k = 0; // Serán los pesos para calcular la media ponderada
  62.   int i, j;
  63.   int indiceX, indiceY;
  64.   int iniSalida, finSalida;
  65.  
  66.  
  67.   for (x = 0; x < Filas; x++) {
  68.     for (y = 0; y < Columnas; y++) {
  69.       suma = 0;
  70.       k = 0;
  71.  
  72.       for (i = 0; i < nucleoSize; i++) {
  73.         for (j = 0; j < nucleoSize; j++) {
  74.           indiceX = abs(x - bordeNucleo) + i;
  75.           indiceY = abs(y - bordeNucleo) + j;
  76.           //if (indiceX >= Filas || indiceY < 0 || indiceY >= Columnas || indiceY < 0)
  77.           if (indiceY >= Columnas || indiceY < 0)
  78.             continue; // Si se sale del array, continuamos
  79.  
  80.           k = k + nucleo[i*Columnas+j];
  81.           suma = suma + Original[indiceX*Columnas+indiceY] * nucleo[i*Columnas+j];
  82.         }
  83.       }
  84.  
  85.       if (k == 0)
  86.         Salida[x*Columnas+y] = suma;
  87.       else
  88.         Salida[x*Columnas+y] = suma / k;
  89.     }
  90.   }
  91. }
  92.  
  93. /* * * * *          * * * * *          * * * * *          * * * * */
  94.  
  95. int main(int argc, char *argv[]) {
  96.   int Columnas, Filas;
  97.   int i, j;
  98.   int totalProc, proc;
  99.  
  100.   int desde, hasta;
  101.  
  102.   int nucleoFilas = 0;
  103.   int nucleoColumnas = 0;   // Tamaño de la matriz de convolución
  104.  
  105.   MPI_Init(&argc, &argv);
  106.   MPI_Comm_size(MPI_COMM_WORLD, &totalProc);
  107.   MPI_Comm_rank(MPI_COMM_WORLD, &proc);
  108.  
  109.   unsigned char **Original;
  110.   unsigned char **Salida;
  111.   // Almacenará los resultados locales (tendrá un tamaño de filas/proceso*columnas)
  112.   unsigned char *OriginalAux;
  113.   unsigned char *SalidaAux;
  114.   unsigned char *Salida1d;
  115.   int * nucleo;
  116.   int sizeNucleo;
  117.   int indices[2];
  118.   int sizeElemen;
  119.  
  120.   if (proc == 0) {
  121.     if (argc != 3) {
  122.       printf("Introduzca las filas y columnas de la matriz de convolución\n");
  123.       fflush(stdout);
  124.     }
  125.  
  126.     /*
  127.       Recogemos el tamaño de la matriz de convolución
  128.     */
  129.     nucleoFilas = atoi(argv[1]);
  130.     nucleoColumnas = atoi(argv[2]);
  131.  
  132.     /*
  133.       Lectura de la imagen
  134.     */
  135.  
  136.     Original = pgmread("lena_original.pgm", &Columnas, &Filas);
  137.     Salida = (unsigned char **)GetMem2D(Filas, Columnas, sizeof(unsigned char));
  138.  
  139.  
  140.     /*
  141.       Creación de la matriz de convolución (Actualmente funciona para matrices impares)
  142.     */
  143.    
  144.    
  145.     sizeNucleo = nucleoFilas * nucleoColumnas; // Tamaño total del nucleo
  146.      
  147.     nucleo = malloc(sizeof(int) * nucleoFilas*nucleoColumnas);
  148.    
  149.     for (i = 0; i < nucleoFilas; i++)
  150.       for (j = 0; j < nucleoColumnas; j++)
  151.         nucleo[i*nucleoColumnas+j] = -1;
  152.     nucleo[nucleoFilas/2*nucleoColumnas + nucleoColumnas/2] = 1; // Colocamos el 1 en el centro    
  153.    
  154.     // -----------------------------------------------------------------------------------------------
  155.   }
  156.  
  157.   //  Enviamos el nucleo a todos los procesos
  158.  
  159.   // Tamaño del nucleo
  160.   MPI_Bcast(&sizeNucleo, 1, MPI_INT, 0, MPI_COMM_WORLD);
  161.  
  162.   if(proc != 0) nucleo = malloc(sizeof(int) * sizeNucleo);
  163.  
  164.   // Recivimos el nucleo
  165.   MPI_Bcast(nucleo, sizeNucleo, MPI_INT, 0, MPI_COMM_WORLD);
  166.  
  167.   // Espacio desde el nucleo al borde para no salirnos de la imagen
  168.   int bordeNucleo = (int)sqrt(sizeNucleo) / 2;
  169.  
  170.   //  Enviamos el numero de columnas que tiene la imagen a todos los procesos
  171.  
  172.   MPI_Bcast(&Columnas, 1, MPI_INT, 0, MPI_COMM_WORLD);
  173.   MPI_Bcast(&Filas, 1, MPI_INT, 0, MPI_COMM_WORLD);
  174.  
  175.   //  El resto de los procesos recive su parte de imagen
  176.  
  177.   if(proc == 0) {      
  178.     //  Repartimos la imagen por filas
  179.  
  180.     asignacion a;
  181.     for (int i = totalProc-1; i >= 0; i--) { // Repartimos para los procesos
  182.       a = reparto(Columnas, totalProc, i); // Cogemos el reparto
  183.       desde = fmax(0, a.start-bordeNucleo);
  184.       hasta = fmin(Filas, (a.start + a.size)+bordeNucleo);
  185.      // printf("asignacion start=%d  fin=%d | size=%d | en rank=%d\n", a.start, a.start + a.size, a.size, i);
  186.       OriginalAux = malloc((hasta-desde)*Columnas*sizeof(unsigned char));
  187.  
  188.       // Recorremos las filas, cogiéndo un trozo más de imagen para que aplique la convolución correctamente.
  189.       for (int x = 0, fila = desde; fila < hasta; fila++, x++) {
  190.         for (int colum = 0; colum < Columnas; colum++) { // Recorremos todas las columnas
  191.           OriginalAux[x*Columnas + colum] = Original[fila][colum]; // Pasamos el contenido de la matriz 2d a una matriz 1d
  192.         }
  193.       }
  194.         // Asignamos los índices de lo que tiene que hacer cada proceso
  195.         indices[0] = a.start; // Inicio
  196.         indices[1] = a.start+a.size; // Final
  197.       if(i != 0){
  198.         // printf("rank[%d] --> desde %d | hasta %d\n",i, indices[0], indices[1]);
  199.         MPI_Send(indices, 2, MPI_INT, i, 0, MPI_COMM_WORLD); // Enviamos sus índices
  200.         MPI_Send(OriginalAux, (hasta-desde)*Columnas, MPI_UNSIGNED_CHAR, i, 0, MPI_COMM_WORLD); // Enviamos la parte que tiene que hacer cada proceso
  201.       }
  202.     }
  203.  
  204.   } else {
  205.  
  206.     //  Recivimos los indices de inicio y fin de los datos de cada proceso
  207.  
  208.     MPI_Recv(indices, 2, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);  
  209.  
  210.     desde = fmax(0, indices[0]-bordeNucleo);
  211.     hasta = fmin(Filas, (indices[1])+bordeNucleo);
  212.  
  213.     OriginalAux =  malloc((hasta-desde)*Columnas*sizeof(unsigned char));  
  214.  
  215.     // Recivimos el vector con el trozo de imagen correspondiente
  216.     MPI_Recv(OriginalAux, (hasta-desde)*Columnas, MPI_UNSIGNED_CHAR, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
  217.   }
  218.     //printf("rank[%d] --> desde %d | hasta %d\n",proc, desde, hasta);  
  219.  
  220.   // El número de elementos con los que debe trabajar cada proceso
  221.   sizeElemen = indices[1]-indices[0];
  222.   // Resultado de la convolución de cada proceso
  223.   SalidaAux = malloc(sizeElemen*Columnas*sizeof(unsigned char));
  224.        
  225.   convolucion(OriginalAux, nucleo, SalidaAux, Columnas, sizeElemen, sizeNucleo, bordeNucleo);
  226.  
  227.   Salida1d = malloc(Filas*Columnas*sizeof(unsigned char));
  228.  
  229.   MPI_Gather(SalidaAux, sizeElemen*Columnas, MPI_UNSIGNED_CHAR, Salida1d, sizeElemen*Columnas, MPI_UNSIGNED_CHAR, 0, MPI_COMM_WORLD);
  230.  
  231.  
  232.   MPI_Barrier(MPI_COMM_WORLD);
  233.   if (proc == 0) {
  234.     printf("Valor obtenido con Gather: %i ", Salida1d[1*Columnas+2]);
  235.     for (int fila = 0; fila < Filas; fila++) {
  236.       for (int col = 0; col < Columnas; col++) {
  237.         Salida[fila][col] = Salida1d[fila*Columnas+col];
  238.       }
  239.     }
  240.     pgmwrite(Salida, "lena_procesada.pgm", Filas, Columnas);
  241.   }
  242.  
  243.    
  244.  
  245.   MPI_Finalize();
  246.  
  247.  
  248.   /*free(nucleo);
  249.   free(OriginalAux);
  250.   free(SalidaAux);
  251.   free(Salida1d);
  252.  
  253.   Free2D((void **)Original, Columnas);
  254.   Free2D((void **)Salida, Columnas);*/
  255. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement