Jueves 14 de Noviembre de 2024, 16:53
SoloCodigo
Bienvenido(a),
Visitante
. Por favor,
ingresa
o
regístrate
.
¿Perdiste tu
email de activación?
Inicio
Foros
Chat
Ayuda
Buscar
Ingresar
Registrarse
SoloCodigo
»
Foros
»
CLR: .Net / Mono / Boo / Otros CLR
»
Otros CLR
»
Aplicar Una Máscara A Una Imagen
« anterior
próximo »
Imprimir
Páginas: [
1
]
Autor
Tema: Aplicar Una Máscara A Una Imagen (Leído 4355 veces)
KAYSS
Nuevo Miembro
Mensajes: 19
Aplicar Una Máscara A Una Imagen
«
en:
Miércoles 7 de Noviembre de 2007, 10:27 »
0
Alguno sabéis de una forma rápida de aplicar una máscara a una imagen en mapa de bits.
Yo primero creo la máscara (matriz nxn), recorro pixel a pixel la imagen, sitúo la máscara y recorro la máscara posición por posición para dicho pixel, y así con todos los demás pixels de la imagen. Pero esto es muy lento.
Os muestro el código que he desarrollado por si es causa de que no está bien planteado:
Código: Text
Bitmap^ AplicarMascara(Bitmap ^Imagen, Array^ Mascara, int Tamanio){
Bitmap ^ImagenFiltrada=gcnew Bitmap (Imagen->Width, Imagen->Height);
int IncX, IncY, X, Y;
int TamanioNxN=Tamanio*Tamanio;
double Sumatorio;
Color color;
// Aplicamos la máscara para cada uno de los pixels de la imagen
for(int i=0; i<Imagen->Width; i++){
for (int j=0; j<Imagen->Height; j++){
IncY=Tamanio/2;
Sumatorio=0;
// Recorremos los valores de la máscara para aplicarlos a la imagen
for (int k=0; k<Tamanio; k++){
Y=j+IncY;
IncX=Tamanio/2;
for (int q=0; q<Tamanio; q++){
X=i+IncX;
if ((X>=0&&X<Imagen->Width) && (Y>=0&&Y<Imagen->Height))
Sumatorio=Sumatorio + Mascara->GetValue(Tamanio/2+IncX, Tamanio/2+IncY)) * Imagen->GetPixel(X,Y).R;
IncX--;
}
IncY--;
}
// El valor del pixel será el valor del sumatorio obtenido
color=Color::FromArgb(Sumatorio, Sumatorio, Sumatorio);
ImagenFiltrada->SetPixel(i, j, color);
}
}
return ImagenFiltrada;
}
Gracias, un saludo
Tweet
JuanK
Miembro de ORO
Mensajes: 5393
Nacionalidad:
Re: Aplicar Una Máscara A Una Imagen
«
Respuesta #1 en:
Miércoles 7 de Noviembre de 2007, 14:12 »
0
No es muy rápido, lo mejor es que uses trabajo a nivel de bytes. El objeto bitmap te permite acceder directamente a todos los bytes de la imagen usando los metodos de lockbitmap, y una vez allli puedes trabajar todo de una sola vez con operaciones binarias y/o con arreglos. Eso si es muy rápido.
si necesitas ayuda me cuentas... aunque no deberias...
[size=109]Juan Carlos Ruiz Pacheco
[/size]
Microsoft Technical Evangelist
@JuanKRuiz
http://juank.io
KAYSS
Nuevo Miembro
Mensajes: 19
Re: Aplicar Una Máscara A Una Imagen
«
Respuesta #2 en:
Jueves 8 de Noviembre de 2007, 01:19 »
0
Muchas gracias por la ayuda, Juan Carlos.
He aplicado lo que me propones y he conseguido reducir de 2 minutos y medios a 1 minuto y medio el tiempo empleado en aplicar una máscara 3x3 a una imagen, que aunque sigue siendo mucho tiempo pero mejora el anterior.
Te muestro el código resultante:
Código: Text
Bitmap^ AplicarMascara2(System::Drawing::Bitmap ^Imagen, cli::array<int>^ Mascara, int Tamanio){
this->ImagenFiltrada=gcnew System::Drawing::Bitmap (Imagen);
int i, j, k, q, IncX, IncY, X, Y, ValorPixel, PosVectorRGB;
int TamanioNxN=Tamanio*Tamanio;
double Sumatorio;
Color color;
int Cte1=Tamanio/2;
// formato de pixel
PixelFormat pxf = PixelFormat::Format24bppRgb;
// Bloqueamos los pixels de la imagen original y la filtrada
Rectangle rect = System::Drawing::Rectangle(0, 0, Imagen->Width, Imagen->Height);
BitmapData ^bmpDatosOriginal = Imagen->LockBits(rect, ImageLockMode::ReadWrite, pxf);
BitmapData ^bmpDatosFiltrada = ImagenFiltrada->LockBits(rect, ImageLockMode::ReadWrite, pxf);
// Obtenemos la direcciones de comienzo
IntPtr ptrOriginal = bmpDatosOriginal->Scan0;
IntPtr ptrFiltrada = bmpDatosFiltrada->Scan0;
// Declaramos los arrays para almacenar los bytes de los bitmaps
int numBytes = Imagen->Width * Imagen->Height * 3;
array<Byte> ^valoresRGBOriginal = gcnew array<Byte>(numBytes);
array<Byte> ^valoresRGBFiltrada = gcnew array<Byte>(numBytes);
// Copiamos los valores RGB a los arrays
Marshal::Copy(ptrOriginal, valoresRGBOriginal, 0, numBytes);
Marshal::Copy(ptrFiltrada, valoresRGBFiltrada, 0, numBytes);
// Recorremos la imagen
for(i=0; i<Imagen->Width; i++){
for (j=0; j<Imagen->Height; j++){
IncY=Cte1;
Sumatorio=0;
// Recorremos la máscara
for (k=0; k<Tamanio; k++){
Y=j+IncY;
IncX=Cte1;
for (q=0; q<Tamanio; q++){
X=i+IncX;
if ((X>=0&&X<Imagen->Width)&&(Y>=0&&Y<Imagen->Height)){
Sumatorio=Sumatorio+
Convert::ToDouble(Mascara[(Cte1+IncX)*3 + (Cte1+IncY)])*
Convert::ToDouble(valoresRGBOriginal[(Y*Imagen->Width+X)*3]);
}
IncX--;
}
IncY--;
}
// El valor del pixel será el valor del sumatorio obtenido
if (Sumatorio>0)ValorPixel=Convert::ToInt32(Sumatorio)%255;
else ValorPixel=0;
PosVectorRGB=(j*Imagen->Width+i)*3;
valoresRGBFiltrada[PosVectorRGB]=ValorPixel;
valoresRGBFiltrada[PosVectorRGB+1]=ValorPixel;
valoresRGBFiltrada[PosVectorRGB+2]=ValorPixel;
}
}
// Copiamos de nuevo los valores del array al bitmap
Marshal::Copy(valoresRGBFiltrada, 0, ptrFiltrada, numBytes);
// Desbloqueamos los bytes
ImagenFiltrada->UnlockBits(bmpDatosFiltrada);
Imagen->UnlockBits(bmpDatosOriginal);
return ImagenFiltrada;
}
Gracias, un saludo
JuanK
Miembro de ORO
Mensajes: 5393
Nacionalidad:
Re: Aplicar Una Máscara A Una Imagen
«
Respuesta #3 en:
Jueves 8 de Noviembre de 2007, 02:52 »
0
Bueno no ando con mucho tiempo para revisar la logica completa del programa y hacer una optimizacion agresiva, pero si por encima estos son los tips:
1- Trata de deshacerte de todo lo que implique conversion de tipos de dato, ejemplo
Código: Text
Convert::ToDouble
Seguramente deberas replantear la mayoria de las operaciones aritmeticas que tienes para trabajar sin convertir tipos de datos por lo menos mientras estes dentro de los bucles.
2- Optimiza de acuerdo a la plataforma, si vas a trabajar para plataforma de 32 bot utiliza tipos de dato de 32 bit o si es plataforma de 64 utiliza tipos de dato de 64 bit, el punto es que si usas plataforma de 32 bit maneja tipos de dato Int32 en contadores ciclos etc, y utiliza todas las operaciones sobre unidades de 32 bit, inclusive las operaciones de corrimiento.
Seguramente la logica de tu programa sera un poco mas elaborada pero creeme que justificara.
3- Minimiza la mayor cantidad de operaciones posibles a operaciones a nivel binario.
En todo caso de todo lo que te mencione lo mas importante es lo de las conversiones de tipo de dato.
Ahh si, trata de reducirlos bucles, entre menos vueltas mejor.
saludos,
[size=109]Juan Carlos Ruiz Pacheco
[/size]
Microsoft Technical Evangelist
@JuanKRuiz
http://juank.io
KAYSS
Nuevo Miembro
Mensajes: 19
Re: Aplicar Una Máscara A Una Imagen
«
Respuesta #4 en:
Jueves 8 de Noviembre de 2007, 11:23 »
0
Muchas gracias de nuevo, todos tus consejos me han sido de gran ayuda.
Aplicaré todo lo que me dices
Un saludo
JuanK
Miembro de ORO
Mensajes: 5393
Nacionalidad:
Re: Aplicar Una Máscara A Una Imagen
«
Respuesta #5 en:
Jueves 8 de Noviembre de 2007, 14:27 »
0
bueno ok.
Se me olvidaba otro muy buen tip:
1- no hagas las pruebas de velocidad compilando el programa en modo debug siempre hazlas compilando en modo Release
2- no hagas las pruebas de velocidad ejecutando el programa desde visual studio o el ide que uses, hazlo siempre de manera independiente.
3- En la compilación en modo release selecciona optimizar codigo y no selecciones definir DEBUG ni definir TRACE.
4- En destino plataforma selecciona la plataforma a donde quieres que se ejeccute el programa salvo que quieras que corra tanto en x86 como en x64
bye.
[size=109]Juan Carlos Ruiz Pacheco
[/size]
Microsoft Technical Evangelist
@JuanKRuiz
http://juank.io
KAYSS
Nuevo Miembro
Mensajes: 19
Re: Aplicar Una Máscara A Una Imagen
«
Respuesta #6 en:
Viernes 9 de Noviembre de 2007, 20:18 »
0
Muchas gracias por todo!!!
Un saludo
Imprimir
Páginas: [
1
]
« anterior
próximo »
SoloCodigo
»
Foros
»
CLR: .Net / Mono / Boo / Otros CLR
»
Otros CLR
»
Aplicar Una Máscara A Una Imagen