| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152 |
- \subsection{Blur Gaussiano}
- El filtro Blur Gaussiano consiste en, dado un radio \textbf{r} y un par\'ametro $\sigma$, \emph{generar} una matriz de convoluci\'on, la cual no depende de los valores de la imagen, por lo que puede ser calculada una sola vez. Luego con esa matriz se toma una \emph{sub-matriz} de radio \textbf{r} con centro en el p\'ixel que se quiere procesar y realizar una sumatoria de la multiplicaci\'on componente a componente de cada matriz. Esto resulta en una imagen m\'as "borrosa" (a lo que se debe el nombre del filtro).
- \subsubsection{Implementaci\'on C}
- \label{sec:blur_impc}
- Para simplificar el c\'odigo en \textbf{C} y \textbf{ASM} se cre\'o una funci\'on encargada de calcular la matriz de convoluci\'on. La matriz se almacena en el heap y se devuelve un puntero a la misma para realizar los c\'alculos. Queda a cargo del c\'odigo que utilice a dicha matriz llamar al \emph{free} para liberar la memoria.
- Para generar la matriz primeramente se calcula el largo de la misma, el cual es $(2*r + 1)^2$, al momento de llamar a la funci\'on \textbf{malloc} se multiplica dicho valor por el tama\~no de un float. \\
- Luego se realizan dos ciclos \textbf{\emph{for}} anidados, uno para recorrer las columnas y otro para recorrer las filas. Los valores van desde $-r$ a $r$. Para cada elemento realizo la ecuaci\'on gaussiana en dos dimensiones y lo almaceno en la matriz. \\
- Al finalizar queda la matriz de convoluci\'on con \emph{float}, donde cada elemento de la matriz corresponder\'ia a un p\'ixel. \\
- En el c\'odigo \ref{blurc_1} se puede ver el ejemplo del código que se ejecuta.
- \cscript{blurc_1}{blur_c}{Blur C - Ciclo princip\'al de calculo de matriz de convoluci\'on}{24}{36}
- Antes de iniciar el procesamiento se realiza un casteo de los punteros a im\'agenes recibidos para poder operar con los mismos como matrices. Tambi\'en se declaran las variables que se van a usar para recorrer la imagen y la sub-matriz. Se llama a la funci\'on para obtener la matriz de convoluci\'on y se almacena el puntero a la misma.\\
- Se procede a recorrer la imagen con dos ciclos \textbf{\emph{for}} anidados, los mismos van desde \emph{Radio} hasta $Filas-Radio"$ y $Columnas-Radio$, esto produce que no se recorran ni procecen los bordes de la im\'agen.
- Dentro del ciclo interno se reinicia (asigna $0$) al acumulador interno, se reinicia tambi\'en el contador de posici\'on de la matriz de convoluci\'on.
- \emph{NOTA: Descubrimos que el puntero de destino tiene el mismo contenido que la imagen de origen, esa es la raz\'on por la que no leemos ni escribimos en los bordes. Si llegara a cambiar esto, deber\'ia añadirse un bloque peque\~no de c\'odigo que copie los bordesde de tama\~no $Radio$ de la im\'agen de origen sin procesarlos.}
- Para cada ciclo interno, luego de reiniciars las variables se realizan otros dos ciclos \textbf{\emph{for}} anidados para calcular la sumatoria de la sub-matriz que le corresponde al p\'ixel actual. Dichos ciclos van, al igual que los ciclos que se usan para calcular la matriz de convoluci\'on, desde $-Radio$ hasta $Radio$.\\
- Luego se multiplica cada componente del p\'ixel que se recorre por la matriz de convoluci\'on en la misma posici\'on, se almacena en el acumulador y antes de terminar el ciclo se aumenta la posici\'on de la matriz de convoluci\'on. Esta operaci\'on se realiza por cada elemento de la sub-matriz (por los ciclos \emph{for}).
- Al finalizar la sumatoria de la sub-matriz se guardan los valores de la sumatoria en cada canal del pixel actual en la imagen de destino y se contin\'ua con el ciclo. En el c\'odigo \ref{blurc_2} puede verse la operaci\'on de almacenamiento de cada componente en la imagen de destino.
- \cscript{blurc_2}{blur_c}{Blur C - Ciclo princip\'al de calculo de matriz de convoluci\'on}{61}{64}
- Luego de finalizado el ciclo principal se procede a llamar a la funci\'on \textbf{free} y liberar la memoria utilizada por la matriz de convoluci\'on.
- \subsubsection{Implementaci\'on Ensamblador}
- \label{sec:blur_impasm}
- Para minimizar confusion renombramos los registros \\
- \asmscript{Defines}{blur_asm}{Define}{9}{22}
- Al iniciar el filtro, se \emph{pushean} los registros \emph{XMM0,src,dst,cols,filas,radius}, para resguardarlos al llamar a convolucion\_matrix, el resultado de esta funcion se guarda en \emph{matriz y r15} \\
- Calculamos el tama\-no correspondiente de la imagen en bytes(ancho) o pixeles(alto) y luego avanzamos \emph{radius} filas para no tener en cuenta los bordes; tambien los restamos del alto y ancho total de la imagen. \\
- El recorrido de la imagen se hace iterando a traves de cada fila de la imagen ( \emph{cols-2*radius pixeles} ), un total de \emph{filas-2radius} veces. \\
- Al inicio del recorrido de cada fila, avanzamos \emph{src} y \emph{dst} en \emph{radius} pixeles, siendo estos el borde. \\
- Una vez posicionados sobre un pixel no-borde procedemos a iterar por la matriz de convoluci\'on, esto se hace llevando la cuenta de filas y columnas restantes para terminar (sabiendo que inicialmente estas valen \emph{2*radius+1}). \\
- El procesamiento de dentro de la matriz de convoluci\'on es el siguiente:
- \begin{itemize}
- \item Leer 16 bytes de memoria desde src*
- \item Eliminar los pixeles ya procesados*
- \item Desempaquetar los pixeles, en un registro cada uno
- \item Leer 16 bytes de memoria desde matriz*
- \item Acomodar estos factores de forma que podamos multiplicarlos elemento a elemento con los pixeles
- \item Convertir los pixeles a punto flotante y multiplicarlos por los factores
- \item Acumular los productos
- \end{itemize}
- *Nunca leemos fuera de la memoria asignada, porque en caso de que nos queden menos de 16 bytes por leer, retrocedemos esta diferencia en los punteros y luego volvemos cero a los factores repetidos para evitar a\-nadirlos dos veces al resultado. \\
- \asmscript{Retroceso}{blur_asm}{Retroceso}{185}{188}
- Una vez que, para un pixel dado, recorremos completamente la matriz de convolucion, guardamos el resultado acumulado y avanzamos los punteros \emph{src y dst}. Seguimos iterando hasta recorrer la imagen de forma completa.
|