Tecnicas de Suavizado

Descargar como pdf o txt
Descargar como pdf o txt
Está en la página 1de 20

Tecnicas de

Suavizado

Benemerita Universidad Autonoma de Puebla


Lic. en ingenieria en ciencias de la
computación
CCOS608
NRC: 48136
Procesamiento digital de imagenes
Primavera 2023
Alumno: Misael Daniel Justo Silvestre
Docente: Hilario Salazar Martines
6 de marzo del 2023
Código Fuente
1. PGM
#include <stdlib.h>
#include <stdio.h>
/* Funciones: */
/* */
/* float **Imagen = pgmread(“imagen.pgm”, &Largo, &Alto); */
/* */
/* int pgmwrite(float **Imagen, “archivo.pgm”, Largo, Alto); */
/* */
/* float **Matriz(int, int, int); */
/* */
/* float *Vector(int, int); */
/* */

extern int Largo, Alto;

float *Vector(); void **Matriz(int, int, int);

unsigned char **pgmread();


int pgmwrite();
int getint(FILE *);

void **Matriz(rows, columns, elem_size)


int rows; /* number of rows */
int columns; /* number of columns */
int elem_size; /* element size */
{
int row;

void **array = (void **)malloc(rows * sizeof(void *));

if (array == NULL)

printf(“Error al asignar lineas a la matriz\n”), exit(0);

for (row = 0; row < rows; row++) {

array[row] = (void *)calloc(columns, elem_size);

if (array == NULL)

printf(“Error al asignar columnas a la matriz\n”), exit(0);


}

return array;
}
float *Vector(int i0,int i1){

float *v ;

if ((v = (float *)calloc(i1-i0+1,sizeof (float))) == NULL)

printf(“Error al asignar memoria al vector\n”) ;

return v-i0 ;
}

int getint(FILE *fd){

int c, i;

char dummy[10000];

c = getc(fd);
while (1) /* find next integer */
{
if (c==’#’) /* Descartar los comentarios */

fgets(dummy,9000,fd);

if (c==EOF){

return 0;
}
if (c>=’0’ && c<=’9’)

break; /* found what we were looking for */

c = getc(fd);
}

/* we’re at the start of a number, continue until we hit a non-number */

i = 0;
while (1) {

i = (i*10) + (c - ‘0’);
c = getc(fd);
if (c==EOF) return (i);
if (c<’0’ || c>’9’) break;
}

return (i);
}
void Free(array, rows)

void **array; /* the two-dimensional array */

int rows; /* number of rows */


{
int row;
for (row = 0; row < rows; row++) {

free(array[row]);
}
}

unsigned char **pgmread(char *filename, int *x_size, int *y_size){

FILE *fd;

char header[100];
int tmp;
int x, y,c2, Contador=0;
unsigned char **Imagen;

if ((fd=fopen(filename,”rb”)) == NULL){

printf(“No puedo abrir %s para lectura!\n”, filename);

exit(0);
}

/* Leyendo el encabezado */
header[0]=fgetc(fd);
header[1]=fgetc(fd);
if(!(header[0]==’P’ && header[1]==’5’)){

printf(“Error al leer el archivo\nLa imagen %s no es un PGM!\n”,filename);

fclose(fd);
exit(0);
}

*x_size = getint(fd);
*y_size = getint(fd);
tmp = getint(fd);

Imagen = (unsigned char **)Matriz(*x_size, *y_size, sizeof(unsigned char));

/* Toma la imagen del archivo */


for (y=0; y<*y_size; y++)

for (x=0; x<*x_size; x++, Contador++)

Imagen[x][y]=(unsigned char)fgetc(fd);

/* Verifico que se leyeron todos los bytes */

if (Contador != (*x_size * *y_size)){

printf(“Archivo con longitud incorrecta!\n”);

return 0;
}

fclose(fd);

printf(“Cargando imagen %s\n”, filename);

return Imagen;
}

int pgmwrite(unsigned char **Imagen, char *filename, int Largo, int Alto){

FILE *Out;
int x, y, Contador=0;

if ((Out=fopen(filename,”wb”)) == NULL){

printf(“No puedo escribir la imagen!\n”);

return 0;
}

/* Ponemos el encabezado de los PGM */

fprintf(Out,”P5\n”);
fprintf(Out,”%d %d\n”, Largo, Alto);
fprintf(Out,”255\n”);

/* Vacio la imagen al archivo */

printf(“****************************************************”);

for (y=0; y<Alto; y++)

for (x=0; x<Largo; x++, Contador++)

putc(Imagen[x][y], Out);
/* Verifico que se escriban todos los bytes */

if (Contador != (Largo*Alto)){

printf(“Archivo con longitud incorrecta!\n”);

return 0;
}

fclose(Out);

printf(“\nSalvando %s PGM de %ix%i\n”, filename, Largo, Alto); return 1;


}

2. Demo2.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include “PGM.c”
int Largo, Alto; /* Variables globales. Para que pasarlas
de funci�n a funci�n! */

#define MAX_ROWS 500


#define MAX_COLS 500
#define MAX 999999

/* * * * * Obtiene la copia de una imagen * * * * */

void Copia(unsigned char **Original, unsigned char **Salida){

int x, y;

for (x = 0; x < Largo; x++)

for (y = 0; y < Alto; y++)

Salida[x][y] = Original[x][y];

}
/* * * * * Obtiene el negativo de una imagen * * * * */

void Inverso(unsigned char **Original, unsigned char **Salida){

int x, y;

/* Resta el valor m�ximo (255) del valor actual de la imagen.

El resultado: el negativo de la imagen. */


/* Las matrices se accesan con los �ndices (x,y) */

for (x = 0; x < Largo; x++)

for (y = 0; y < Alto; y++)

Salida[x][y] = 255-Original[x][y];

}
void Umbral(unsigned char **Original, unsigned char **Salida, int p){

int x, y;

for (x = 0; x < Largo; x++)

for (y = 0; y < Alto; y++)

Salida[x][y] = (Original[x][y] == p ? 0 : 255);


}
void IntervaloUmbralBinario(unsigned char **Original, unsigned char **Salida, int p1, int p2){

int x, y;

for (x = 0; x < Largo; x++)

for (y = 0; y < Alto; y++)

Salida[x][y] = (Original[x][y] <= p1 || Original[x][y] >= p2) ? 355 : 0;


}
void IntervaloUmbralBinarioInvertido(unsigned char **Original, unsigned char **Salida, int
p1, int p2){

int x, y;
for (x = 0; x < Largo; x++)

for (y = 0; y < Alto; y++)

Salida[x][y] = (Original[x][y] <= p1 || Original[x][y] >= p2) ? 0 : 255;


}
void IntervaloUmbralGrises(unsigned char **Original, unsigned char **Salida, int p1, int p2){

int x, y;

for (x = 0; x < Largo; x++)

for (y = 0; y < Alto; y++)

Salida[x][y] = (Original[x][y] <= p1 || Original[x][y] >= p2) ? 255 : Original[x][y];


}
void IntervaloUmbralGrisesInvertido(unsigned char **Original, unsigned char **Salida, int p1,
int p2){
int x, y;

for (x = 0; x < Largo; x++)

for (y = 0; y < Alto; y++)

Salida[x][y] = (Original[x][y] <= p1 || Original[x][y] >= p2) ? 255 : 255-Original[x][y];


}
void Extension(unsigned char **Original, unsigned char **Salida, int p1, int p2){

int x, y;

for (x = 0; x < Largo; x++)

for (y = 0; y < Alto; y++)

Salida[x][y] = (Original[x][y] <= p1 || Original[x][y] >= p2) ? 0 : ((Original[x][y]-p1)*((255)/p2-


Original[x][y]));
}
void ReduccionNivelGris(unsigned char **Original, unsigned char **Salida, int p1, int p2, int
p3, int p4){

int x, y, p;

for (x = 0; x < Largo; x++)

for (y = 0; y < Alto; y++)

//Original[x][y] = (Salida[x][y] <= p1 || Salida[x][y] >= p2) ? 0 : ((p-p1)*((255)/p2-p));

if(Original[x][y] <= p1){

Salida[x][y] = 0;

}else if(p1 < Original[x][y] && Original[x][y] <=p2){

Salida[x][y] = p1;

}else if(p2 < Original[x][y] && Original[x][y] <=p3){

Salida[x][y] = p2;

}else if(p3 < Original[x][y] && Original[x][y] <=p4){

Salida[x][y] = p3;

}else{
Salida[x][y] = p4;
}
}
void histograma(unsigned char **Original){

int x, y, p;
for (x = 0; x < Largo; x++){

for (y = 0; y < Alto; y++){

printf(“{%d}”, Original[x][y]);
}
printf(“\n”);
}
}

void etiquetas(unsigned char **Original) {

int etiqueta = 1;
int etiquetas[MAX_ROWS * MAX_COLS] = {0}; // to keep track of labels
int filas = Largo;
int cols = Alto;
for (int i = 0; i < filas; i++) {

for (int j = 0; j < cols; j++) {

if (Original[i][j] == 255) {

// check if any neighboring elements have been labeled

int top = (i == 0) ? 0 : Original[i-1][j];

int left = (j == 0) ? 0 : Original[i][j-1];

if (top == 0 && left == 0) {

// ni los elementos de arriba ni los de la izquierda han sido etiquetados

Original[i][j] = etiqueta;

etiquetas[etiqueta] = etiqueta; // agregar etiqueta a la lista de etiquetas

etiqueta++;

} else if (top > 0 && left == 0) {

// el elemento superior ha sido etiquetado, pero el elemento izquierdo no

Original[i][j] = top;

} else if (top == 0 && left > 0) {

// el elemento izquierdo ha sido etiquetado, pero el elemento superior no

Original[i][j] = left;

} else if (top > 0 && left > 0 && top != left) {

// ambos elementos, superior e izquierdo, han sido etiquetados con diferentes etiquetas
// fusionar etiquetas

int min_label = (top < left) ? top : left;


int max_label = (top > left) ? top : left;

Original[i][j] = min_label;
etiquetas[max_label] = min_label;

} else {

// ambos elementos superior e izquierdo han sido etiquetados con la misma etiqueta

Original[i][j] = top;
}
}
}
}

// relabel elements with minimum labels

for (int i = 0; i < filas; i++) {

for (int j = 0; j < cols; j++) {

if (Original[i][j] > 0) {

int min_label = etiquetas[Original[i][j]];

Original[i][j] = min_label;
}
}
}

for (int i = 0; i < Largo; i++) {

for (int j = 0; j < Alto; j++) {

printf(“%d “, Original[i][j]);
}
printf(“\n”);
}
}

void suavizado(unsigned char **Original, unsigned char **Salida){

int submatriz[3][3]; // Declaración de la submatriz de 3x3

int sum = 0, m=0;


float promedios[MAX];
for (int i = 0; i < Largo - 2; i+=3) { // Recorrido de filas

for (int j = 0; j < Alto - 2; j+=3) { // Recorrido de columnas

// Construcción de la submatriz
for (int k = 0; k < 3; k++) {

for (int l = 0; l < 3; l++) {

submatriz[k][l] = Original[i+k][j+l];
}
}

// Cálculo de la suma de los valores de la submatriz

sum = 0;
for (int k = 0; k < 3; k++) {

for (int l = 0; l < 3; l++) {

sum += submatriz[k][l];
}
}

// Cálculo del promedio


promedios[m] = sum / 9;

// Impresión del promedio

//printf(“El promedio de la submatriz de (%d,%d) a (%d,%d) es: %f\n”, i, j, i+2, j+2,


promedios[m]);

m++;
}
}

m=0;

for (int i = 0; i < Largo - 2; i+=3) { // Recorrido de filas

for (int j = 0; j < Alto - 2; j+=3) { // Recorrido de columnas

Salida[i][j]=Original[i][j];//(int)promedios[m];

if(i < Largo)

Salida[i+1][j]=Original[i+1][j];//(int)promedios[m];

if(i < Largo)

Salida[i+2][j]=Original[i+2][j];//(int)promedios[m];
if(j < Alto)

Salida[i][j+1]=Original[i][j+1];//(int)promedios[m];

if(j < Alto && i < Largo)

Salida[i+1][j+1]=(int)promedios[m];

if(j < Alto && i < Largo)

Salida[i+2][j+1]=Original[i+2][j+1];//(int)promedios[m];

if(j < Alto)

Salida[i][j+2]=Original[i][j+2];//(int)promedios[m];

if(j < Alto && i < Largo)

Salida[i+1][j+2]=Original[i+1][j+2];//(int)promedios[m];

if(j < Alto && i < Largo)

Salida[i+2][j+2]=Original[i+2][j+2];//(int)promedios[m];

m++;
}
}

int menu(){

int op;

printf(“\t.:Menu:.\n”);

printf(“1. Operador identidad (copia)\n”);

printf(“2. Operador inverso o negativo\n”);

printf(“3. Operador umbral\n”);

printf(“4. Operador intervalo de umbral binario\n”);

printf(“5. Operador intervalo de umbral invertido\n”);

printf(“6. Operador de umbral escala de grises\n”);

printf(“7. Operador umbral de escala de grises invertido\n”);

printf(“8. Operador de extension\n”);

printf(“9. Operador reduccion de nivel de gris\n”);


printf(“10. Histograma\n”);
printf(“11. formas\n”);
printf(“12. Suavizado de una imagen\n”);
printf(“-1. Salir\n”);
printf(“Opcion : “);
scanf(“%d”, &op);
return op;
}

/* * * * * * * * * * * * * * * * * * * */
int main(int argc, char *argv[]){

unsigned char **Original = (unsigned char **)pgmread(argv[1], &Largo, &Alto);

unsigned char **Salida = (unsigned char **)Matriz(Largo, Alto, sizeof(unsigned char));

unsigned char **Salida2 = (unsigned char **)Matriz(Largo+2, Alto+1, sizeof(unsigned char));

int c;
int p, p1, p2, p3, p4;

system(“clear”);
switch (menu()){

case -1:

exit(1);
break;

case 1:

printf(“ Salida->Copia de la imagen \n \n”);

Copia(Original, Salida);

break;

case 2:

printf(“ Salida->inverso de la imagen \n \n”);

Inverso(Original, Salida);

break;
case 3:

printf(“Escriba el valor de p: “);

scanf(“%d”,&p);

printf(“ Salida->umbral de la imagen \n \n”);


Umbral(Original, Salida, p);

break;
case 4:

printf(“Escriba el valor de p1: “);

scanf(“%d”,&p1);

printf(“Escriba el valor de p2: “);

scanf(“%d”,&p2);

printf(“ Salida->umbral binario de la imagen \n \n”);

IntervaloUmbralBinario(Original, Salida, p1,p2);

break;
case 5:

printf(“Escriba el valor de p1: “);

scanf(“%d”,&p1);

printf(“Escriba el valor de p2: “);

scanf(“%d”,&p2);

printf(“ Salida->umbral invertido de la imagen \n \n”);

IntervaloUmbralBinarioInvertido(Original, Salida, p1,p2);

break;
case 6:

printf(“Escriba el valor de p1: “);

scanf(“%d”,&p1);

printf(“Escriba el valor de p2: “);

scanf(“%d”,&p2);

printf(“ Salida->umbral escala de grises de la imagen \n \n”);

IntervaloUmbralGrises(Original, Salida, p1, p2);

break;
case 7:

printf(“Escriba el valor de p1: “);

scanf(“%d”,&p1);

printf(“Escriba el valor de p2: “);


scanf(“%d”,&p2);
printf(“ Salida->umbral escala de grises invertido de la
imagen \n \n”);
IntervaloUmbralGrisesInvertido(Original, Salida, p1, p2);
break;
case 8:

printf(“Escriba el valor de p1: “);

scanf(“%d”,&p1);

printf(“Escriba el valor de p2: “);

scanf(“%d”,&p2);

printf(“ Salida->extension de la imagen \n \n”);

Extension(Original, Salida, p1, p2);

break;
case 9:

printf(“Escriba el valor de p1: “);

scanf(“%d”,&p1);

printf(“Escriba el valor de p2: “);

scanf(“%d”,&p2);

printf(“Escriba el valor de p3: “);

scanf(“%d”,&p3);

printf(“Escriba el valor de p4: “);

scanf(“%d”,&p4);

printf(“ Salida->reduccion de nivel de gris de la imagen \n \n”);

ReduccionNivelGris(Original, Salida, p1, p2, p3, p4);

break;
case 10:

printf(“ Salida->histograma de la imagen \n \n”);

histograma(Original);

break;
case 11:

printf(“ Salida->matriz xD \n \n”);

etiquetas(Original);
break;
case 12:

printf(“ Salida->suavizado de imagen”);

suavizado(Original,Salida);

break;
default:

printf(“Ups... algo salio mal”);

break;
}

pgmwrite(Salida, “suavizado.pgm”, Largo, Alto);

exit(0);
}
3. convulsión 2D
import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread(‘xd.jpg’)

#Crea el kernel
kernel = np.ones((5,5),np.float32)/25

#Filtra la imagen utilizando el kernel anterior

dst = cv2.filter2D(img,-1,kernel)

plt.subplot(121),plt.imshow(img),plt.title(‘Original’) plt.xticks([]), plt.yticks([])


plt.subplot(122),plt.imshow(dst),plt.title(‘Promediada’)

plt.xticks([]), plt.yticks([])
plt.show()

4. Difuminado de imágenes
a. Promedio
import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread(‘xd.jpg’)
blur = cv2.blur(img,(3,3))

plt.subplot(121),plt.imshow(img),plt.title(‘Original’) plt.xticks([]), plt.yticks([])


plt.subplot(122),plt.imshow(blur),plt.title(‘Difuminada’)

plt.xticks([]), plt.yticks([])
plt.show()

b. Gaussiano
import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread(‘xd.jpg’)

blur = cv2.GaussianBlur(img,(5,5),0) plt.subplot(121),plt.imshow(img),plt.title(‘Original’)


plt.xticks([]), plt.yticks([]) plt.subplot(122),plt.imshow(blur),plt.title(‘Difuminada’)

plt.xticks([]), plt.yticks([])
plt.show()

c. Mediana
import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread(‘xd.jpg’)

median = cv2.medianBlur(img,5)

plt.subplot(121),plt.imshow(img),plt.title(‘Original’) plt.xticks([]), plt.yticks([])


plt.subplot(122),plt.imshow(median),plt.title(‘Difuminada’)

plt.xticks([]), plt.yticks([])
plt.show()
Capturas de pantalla
1. Codigo en C

2. códigos en Python
La función cv2.filter2D(), disponible en OpenCV, permite aplicar una convolución entre un
kernel dado y una imagen

Como ya se ha mencionado, el difuminado de la imagen se consigue convolucionando la imagen


con un kernel de filtro pasa bajo (FPB). Los FPB eliminan el contenido de alta frecuencia (ej: ruido y
bordes) de la imagen, lo que resulta, en general, en imágenes con bordes más borrosos. No
obstante, también hay filtros que eliminan el ruido con poco efecto sobre los bordes. Tres de los
técnicas de difuminado más utlizadas, que vienen implementados en OpenCV son: el promediado,
los filtros gaussianos y los filtros de mediana. A continuación, se discutirán estos tres tipos de FPB.
1. Promedio
Una manera alternativa de hacer esto es mediante las funciones cv2.blur() o
cv2.boxFilter(). Al uilizar estas fucniones tenemos que especificar el ancho y la altura
del kernel. Un filtro de caja normalizado 3×3 se vería así
2. Filtro Gaussiano
En este enfoque, en lugar de un filtro de caja que consta de coeficientes iguales, se
utiliza un núcleo gaussiano. Esto se hace con la función, cv2.GaussianBlur(). Como
parámetros de entrada se tienen que pasar el ancho y la altura del kernel, que debe
ser positivo y impar. Además hay que especificar la desviación estándar en las
direcciones X e Y, sigmaX y sigmaY, respectivamente. Este tipo de filtrado es muy
eficaz para eliminar el ruido gaussiano de la imagen.

1. Filtro de Mediana
Este filtro calcula la mediana de todos los píxeles bajo la ventana del kernel y el píxel
central se reemplaza con este valor mediano. Esto es muy efectivo para eliminar el
ruido conocido como ruido de sal y pimienta. OpenCV dispone de la función
cv2.medianBlur() para aplicar este tipo de filtro a una imagen. Al igual que en el filtro
Gaussiano, el tamaño del kernel en el filtro de mediana tiene que ser un número
entero impar positivo.

Referencias
http://mmartin.cs.buap.mx/notas/PDI-MM-Rev.2013.pdf

https://unipython.com/suavizando-imagenes-con-opencv/

Video
https://youtu.be/TgvJEEyLBeo

También podría gustarte