Skip to content

ivandres73/Convolution

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

34 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🌆 FILTRO DE IMÁGENES

El siguiente proyecto prueba el algoritmo para aplicar filtros a imágenes por medio de la convolución


Qué es un filtro?

Es la alteración digital de una fotografía

Filtro de desenfoque

Existen varios tipos, pero todos consisten en suavizar los bordes de los objetos dentro de una imagen

Original Borde suavizado
drawing drawing

Para mas información ver referencia


📘 Librería CImg

Es una librería que ofrece utilidades para el procesamiento de imágenes, la librería es capaz de leer/escribir imágenes y aplicar filtros en ella. La librería perse ya utiliza paralelismo com lpthreads, pero para mi implementación solo la utilicé para leer los datos de una imagen

Lectura de una imagen

Las imágenes, son interpretadas como matrices, donde cada posición de la matriz tiene un valor del 0-255. Y existe una matriz para cada uno los canales RGB (jpg/jpeg). Para una imagen en formato PNG se utilizan 4 canales (RGBA).

Cimg crea un arreglo donde las primeras posiciones son los datos del color R, luego todos los G y por ultimo los B. i.e. char* imagen = {R, R, R, G, G, G, B, B, B}

Explicación de como CImg maneja los pixeles aquí


Ejemplo de lectura de imagen con CImg

Dada la siguiente imagen:

drawing


CImg nos dará los siguientes datos:

Rojos

drawing


Verdes

drawing


Azules

drawing

Notese que los negros son valores bajos (cercanos a 0) y los blancos son los 3 canales de colores en sus valores mas altos


Resultado del filtro

Original After filter
drawing drawing

Implementación

Se crearon 2 funciones principales

La siguiente función utiliza 2 for loops para mover el kernel en toda la superficie de la imagen y luego escribe en la matriz result, la cual tiene los datos de la imagen con el filtro ya aplicado

template <size_t N>
void convolution(const short* ptr, const array<short, KERNEL_SIZE>& kernel, array<short, N>& result) {
    ushort x_moves = IMG_SIZX - KERNEL_X + 1;
    ushort y_moves = IMG_SIZY - KERNEL_Y + 1;

    double start, finish;
    GET_TIME(start);
    #pragma omp parallel for num_threads(thread_count) schedule(static, 2)
    for (ushort i=0; i < y_moves; i++) {
        for (ushort v=0; v < x_moves; v++) {
            result[i*x_moves + v] = kernel_calc(ptr, i, v, kernel);
        }
    }
    GET_TIME(finish);
    total_time += finish-start;
}

La siguiente función hara los cálculos de los datos del kernel con cierta parte de la imagen y devolviendo el resultado de los cálculos

short kernel_calc(const short* ptr, short x_offset, short y_offset, const array<short, KERNEL_SIZE>& kernel) {
    ushort total_sum = 0;
    ushort row_sum;
    for (ushort i=0; i < KERNEL_X; i++) {
        row_sum = 0;
        for (ushort v=0; v < KERNEL_Y; v++) {
            row_sum += kernel[v*3 + i] *  ptr[(i+x_offset)*IMG_SIZX + (v+y_offset)];//operacion es columna x fila
        }
        total_sum += row_sum;
    }
    return total_sum / KERNEL_TOTAL;
}

PERO QUE ES ESO DEL KERNEL !?

El kernel es una pequeña matriz (usualmente 3x3 o 5x5) que recorre toda la imagen para aplicar los cálculos sobre un pixel pero tomando en cuenta los pixeles adyacentes.

kernelGif


Ejemplos de kernels

Detección de bordes:

const array<short, 9> kernel = { 0, -1,  0,
                                -1,  5, -1,
                                 0, -1,  0 };

Desenfoque:

const array<short, 9> kernel = {1, 2, 1,
                                2, 4, 2,
                                1, 2, 1 };

📊 Paralelización

Uno de los objetivos principales ademas de resolver el problema era aplicar paralelización a este y probar que podía ser mas rápido (o mas lento) que una implementación en secuencial. La implementación fue con OpenMP y se probaron diversas configuraciones con los threads.

Los resultados promedio fueron los siguientes (100 imagenes 1080x720):

(static, 2) con 4 threads Secuencial (dynamic, 1) con 4 threads (static, 1) con 2 threads
Tiempo (seg) 0.13470515 0.22241637 0.16348029 0.21238093

💻 Compilación y Ejecución (linux)

Si deseas ejecutar la aplicación en tu computadora debes:

  • Descargar el repositorio
  • Compilar con ./compile.sh
  • Crear una carpeta output (porque el programa guarda las imagenes filtradas en ese folder, y si no existe dará error)
  • Correr ./run_tests.sh (tambien crea un archivo times.txt que guarda cuanto tiempo tardo el algoritmo, no mide todo el programa, solo el algoritmo)
  • Ya puedes ver las imagenes filtradas en la carpeta output/!

About

Convolucion de imagenes

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages