For the Code-Catas I'm organizing in the company, I found this site, which allows the users not only to choose a language among a lot of languages, but also to work with projects and files.
This was a "must have" because in the catas we wanted also to try design patterns, and good programming techniques, what sometimes means to use more than just one file.
The idea of using an online tool came because of licensing issues by installing some languages in the laptops. There were not supposed to be used to develop productive code (code that will be sold) so buying a license just for that was a lot of money and time installing all the languages.
The page I found is:
https://www.tutorialspoint.com/codingground.htm
Let's see how it work for our purposes!
Blog about Software Architecture, Patterns, Practices, Principles and a lot of software issues that I find interesting. Blog sobre Arquitectura de Software, Patrones de Diseño, Principios y otros asuntos de software que me interesan.
Buscar en este blog....
Mostrando entradas con la etiqueta algoritmos. Mostrar todas las entradas
Mostrando entradas con la etiqueta algoritmos. Mostrar todas las entradas
lunes, 22 de mayo de 2017
miércoles, 9 de marzo de 2016
C# - Obtener canales RGB de un Bitmap
Vamos a trabajar con el siguiente bitmap tomado de internet para trabajar:
Para descomponer un Bitmap de tres canales (RGB) en tres Bitmaps que representen cada uno, un canal del Bitmap original, podemos hacer lo siguiente:
De esta forma, obtenemos 3 bitmaps, cada uno en blanco y negro y representando la tonalidad de cada canal:
Esto se ve así, porque ocupamos cada canal, de cada imagen, con el canal que obtuvimos previamente. Es decir, extrajimos el canal rojo de la imagen original, y grabamos todos los canales de channelRed con ese componente. Al tener cada canal el mismo valor, se ve gris. Si quisieramos que cada imagen contenga únicamente el valor del canal que extraemos, tendríamos que dejar los otros dos canales en cero. Cambiemos entonces la parte del código que asigna los colores:
Y lo que obtenemos es esto:
Si bien el resultado es el esperado, esta forma no es precisamente rápida. En caso de imágenes más grandes, el proceso tarda más, y más. Y ni hablar si queremos operar con estos valores. Hay, claro, formas de trabajar con esto mucho más rápido, en otro momento las veremos.
Para descomponer un Bitmap de tres canales (RGB) en tres Bitmaps que representen cada uno, un canal del Bitmap original, podemos hacer lo siguiente:
rgb = new Bitmap("imagen.bmp");
int width = rgb.Width;
int height = rgb.Height;
Bitmap channelRed = new Bitmap(width, height);
Bitmap channelGreen = new Bitmap(width, height);
Bitmap channelBlue = new Bitmap(width, height);
for(int x = 0; x < width; x++)
{
for(int y = 0; y < height; y++)
{
Color color = rgb.GetPixel(x, y);
Color colorRed = Color.FromArgb(color.R, color.R, color.R);
Color colorGreen = Color.FromArgb(color.G, color.G, color.G);
Color colorBlue = Color.FromArgb(color.B, color.B, color.B);
channelRed.SetPixel(x, y, colorRed);
channelGreen.SetPixel(x, y, colorGreen);
channelBlue.SetPixel(x, y, colorBlue);
}
}
De esta forma, obtenemos 3 bitmaps, cada uno en blanco y negro y representando la tonalidad de cada canal:
Esto se ve así, porque ocupamos cada canal, de cada imagen, con el canal que obtuvimos previamente. Es decir, extrajimos el canal rojo de la imagen original, y grabamos todos los canales de channelRed con ese componente. Al tener cada canal el mismo valor, se ve gris. Si quisieramos que cada imagen contenga únicamente el valor del canal que extraemos, tendríamos que dejar los otros dos canales en cero. Cambiemos entonces la parte del código que asigna los colores:
Color color = rgb.GetPixel(x, y); Color colorRed = Color.FromArgb(color.R, 0, 0); Color colorGreen = Color.FromArgb(0, color.G, 0); Color colorBlue = Color.FromArgb(0, 0, color.B);
Y lo que obtenemos es esto:
Si bien el resultado es el esperado, esta forma no es precisamente rápida. En caso de imágenes más grandes, el proceso tarda más, y más. Y ni hablar si queremos operar con estos valores. Hay, claro, formas de trabajar con esto mucho más rápido, en otro momento las veremos.
viernes, 7 de enero de 2011
¿Convolución? ¡Pero si es muy fácil! (Parte 3/3)
Buenas. Hoy voy a terminar con la última parte que había comentado sobre el tema de convolución. Básicamente voy a presentar un pequeño código que hice en C, y que muestra dos formas de realizar la convolución. En la primera de ellas, llamada (Input Side Algorithm) y denominada como input_side_conv() en el código, se puede observar que se obtiene la convolución de una forma muy simple: se recorren todos los puntos de la señal x[n] y h[n], y en base a esto se calcula el y[n] correspondiente.
La segunda función, llamada output_side_conv(), obtiene la convolución con el Output Side Algorithm, la cual varía de la anterior en un punto muy importante. Antes de ver cual es la diferencia importante, veamos el código, ya que es muy simple de entender:
Vemos que he definido 3 constantes simbólicas con #define. Las mismas son PUNTOS_X, PUNTOS_H y PUNTOS_Y. Cada uno denota la cantidad de puntos que tiene cada señal involucrada. En el caso de PUNTOS_Y se puede obtener con la operación que puse, según la fórmula que expliqué en la primera parte de esta serie de artículos.
Luego siguen las definiciones de las funciones que calculan la convolución. Ambas dan el mismo resultado, pero cada una lo calcula de forma distinta.
Finalmente, tenemos un main() que lo unico que hace es fijar valores para x[n] y h[n] y luego realiza la convolución de las mismas en dos señales de salida, y1[n] e y2[n] y muestra en forma "de tabla" el resultado de ambas para simplificar la comparación y ver que dan el mismo resultado.
La diferencia importante de la que hablé recién, es la siguiente: si observamos con detalle cómo se calcula cada convolución, podemos notar que la segunda forma, output_side_conv() tiene una ventaja importante, y ésta es que permite calcular un valor específico de y[n] sin que sea necesario conocer todos los puntos de x[n], sino solo los necesarios. En cambio, en la otra función necestiamos conocer todos los puntos de x[n] de antemano, ya que los recorremos uno a uno, y en base a esto vamos calculando cada valor de y[n]. ¿Por qué esto es tan importante? Porque generalmente, no contamos con todos los puntos de x[n] ya que muchas veces se necesita obtener la convolución a medida que se va obteniendo la señal x[n], es decir, obtener y[n] en tiempo real.
Acá les dejo el código en C para que no tengan que copiarlo a mano: bajar código en C .
Bueno, con esto doy por finalizados los artículos de convolución, espero que les haya resultado interesante, divertido.. o al menos práctico!
La segunda función, llamada output_side_conv(), obtiene la convolución con el Output Side Algorithm, la cual varía de la anterior en un punto muy importante. Antes de ver cual es la diferencia importante, veamos el código, ya que es muy simple de entender:
#include <stdio.h>
#include <stdlib.h>
#define PUNTOS_X (6)
#define PUNTOS_H (4)
#define PUNTOS_Y ((PUNTOS_X) + (PUNTOS_H) - 1)
/* Los metodos tienen la misma interfaz:
x, h ---> son las señales de entrada
y ---> es la señal de salida */
void input_side_conv(int *x, int *h, int *y)
{
int i,j;
for(i=0;i<PUNTOS_X; i++)
for(j=0;j<PUNTOS_H;j++)
y[i+j]=y[i+j]+x[i]*h[j];
}
void output_side_conv(int *x, int *h, int *y)
{
int i,j;
for(i=0;i<PUNTOS_Y; i++) {
y[i]=0;
for(j=0;j<PUNTOS_H;j++) {
if(i-j<0 || i-j>=PUNTOS_X) continue;
y[i] = y[i]+h[j]*x[i-j];
}
}
}
int main()
{
int x[PUNTOS_X] = {0,-1,-1,2,1,1};
int h[PUNTOS_H] = {1,0,-1,1};
int y1[PUNTOS_Y] = {0,0,0,0,0,0,0,0,0};
int y2[PUNTOS_Y] = {0,0,0,0,0,0,0,0,0};
int i;
//calculamos la convolucion por el primer metodo
input_side_conv(x, h, y1);
//calculamos la convolucion por el otro metodo
output_side_conv(x, h, y2);
//mostramos las dos respuestas
printf("Input Side Output Side\n");
for(i=0;i<PUNTOS_Y;i++)
printf("[%2d] [%d]\n", y1[i], y2[i]);
return 0;
}
Vemos que he definido 3 constantes simbólicas con #define. Las mismas son PUNTOS_X, PUNTOS_H y PUNTOS_Y. Cada uno denota la cantidad de puntos que tiene cada señal involucrada. En el caso de PUNTOS_Y se puede obtener con la operación que puse, según la fórmula que expliqué en la primera parte de esta serie de artículos.
Luego siguen las definiciones de las funciones que calculan la convolución. Ambas dan el mismo resultado, pero cada una lo calcula de forma distinta.
Finalmente, tenemos un main() que lo unico que hace es fijar valores para x[n] y h[n] y luego realiza la convolución de las mismas en dos señales de salida, y1[n] e y2[n] y muestra en forma "de tabla" el resultado de ambas para simplificar la comparación y ver que dan el mismo resultado.
La diferencia importante de la que hablé recién, es la siguiente: si observamos con detalle cómo se calcula cada convolución, podemos notar que la segunda forma, output_side_conv() tiene una ventaja importante, y ésta es que permite calcular un valor específico de y[n] sin que sea necesario conocer todos los puntos de x[n], sino solo los necesarios. En cambio, en la otra función necestiamos conocer todos los puntos de x[n] de antemano, ya que los recorremos uno a uno, y en base a esto vamos calculando cada valor de y[n]. ¿Por qué esto es tan importante? Porque generalmente, no contamos con todos los puntos de x[n] ya que muchas veces se necesita obtener la convolución a medida que se va obteniendo la señal x[n], es decir, obtener y[n] en tiempo real.
Acá les dejo el código en C para que no tengan que copiarlo a mano: bajar código en C .
Bueno, con esto doy por finalizados los artículos de convolución, espero que les haya resultado interesante, divertido.. o al menos práctico!
lunes, 2 de agosto de 2010
Algoritmos Genéticos Paralelos (I)
Voy a tirar algunos conceptos básicos sobre lo que son los algoritmos genéticos paralelos.
Había escrito el primer post sobre el tema, pero lo eliminé porque me pareció molesto tenerlo en dos blogs. Directamente dejo el otro lugar donde tengo las dos partes del informe ya terminadas y además porque es más elegante y te parsea codigo fuente.
Bien, estos son los temas que trato:
1. Una introducción a los Algoritmos Genéticos.
2. Explicación del Algoritmo Genético Simple.
3. Los algoritmos genéticos paralelos.
Los temas 1 y 2 se ven acá: Algoritmos Genéticos Paralelos (Parte 1)
El tema 3, se puede ver acá: Algoritmos Genéticos Paralelos (Parte 2)
Esta serie de artículos se trata de un informe que escribí para la cátedra de Computación Paralela de la facultad a la que asisto. Acepto sugerencias y críticas. Salute!
Suscribirse a:
Entradas (Atom)


