Software de Procesamiento de Imágenes y Video

Anuncio
Software de Procesamiento de Imágenes y Video
Introducción
Para poder implementar el procesamiento de imágenes en el CPSI, nos vimos en la
necesidad de diseñar un software escalable que permitiese incorporar nuevas herramientas
para aplicaciones futuras.
El software se diseño a través del concepto de solución que brinda la plataforma .NET . La
solución está compuesta por los siguientes módulos: reproducción de video,
preprocesamiento de video, procesamiento de imágenes.
Descripción de los módulos
Reproducción de video: este módulo nos permite visualizar el archivo de video obtenido a
través de la adquisición de datos. A su vez, permite variar las características de la
reproducción como ser el tamaño y la velocidad.
Preprocesamiento de video: este módulo es el encargado de brindar información acerca del
video (ancho, alto, cantidad de cuadros, frame rate) y permitir la extracción de los cuadros
en imágenes. A su vez, ofrece la opción de visualizar cada uno de los cuadros en forma
individual y realizar un zoom sobre cada uno de ellos.
Procesamiento de imágenes: este módulo nos permite visualizar cada una de las imágenes
extraídas por el módulo anterior y modificar sus características. En general, las imágenes a
procesar se encuentran en escala de grises o pueden ser llevadas a esta característica como
así también lograr el efecto de pixelado.
Implementación del módulo de reproducción de video
Este módulo está basado en un ejemplo de Daniel Strigl (programador) donde se le
adiciono las opciones de controlar la velocidad y el tamaño de la reproducción. Para la
realización del módulo se utilizó DirectShow.
DirectShow es una interface que permite la captura y reproducción de video y sonido de
alta calidad. Soporta una gran cantidad de formatos incluyendo mpg, avi, mp3 y wav entre
otros.
Funciones de apertura y cierre
clipFileFilters es utilizado para obtener a través de un filtro solamente archivos de video.
ClipFile es un string que almacena el nombre del archivo que se desea abrir.
UpdatePlayBackMenu es una función que una vez abierto el archivo, habilita el uso de las
distintas acciones, como ser el tamaño o la velocidad de reproducción del video.
UpdateMainTitle es una función que muestra el nombre del archivo que se esta ejecutando.
private void archivoAbrir_Click(object sender, System.EventArgs e)
{
OpenFileDialog af = new OpenFileDialog();
af.Title = "Abrir archivo de video ...";
af.InitialDirectory = AppDomain.CurrentDomain.BaseDirectory;
af.Filter = clipFileFilters;
if( af.ShowDialog() != DialogResult.OK )
return;
archivoCerrar_Click( null, null );
clipFile = af.FileName;
if( ! PlayClip() )
archivoCerrar_Click( null, null );
UpdatePlaybackMenu();
UpdateMainTitle();
}
private void archivoCerrar_Click(object sender, System.EventArgs e)
{
clipFile = null;
clipType = ClipType.None;
CloseInterfaces();
UpdatePlaybackMenu();
UpdateMainTitle();
InitPlayerWindow();
this.Refresh();
}
Funciones de reproducción
private void controlesReproducirPausa_Click(object sender,
System.EventArgs e)
{
if( mediaCtrl == null )
return;
if( (playState == PlayState.Paused) || (playState ==
PlayState.Stopped) )
{
if( mediaCtrl.Run() == 0 )
playState = PlayState.Running;
}
else if( playState == PlayState.Running )
{
if( mediaCtrl.Pause() == 0 )
playState = PlayState.Paused;
}
UpdateMainTitle();
}
private void controlesDetener_Click(object sender, System.EventArgs e)
{
if( (mediaCtrl == null) || (mediaSeek == null) )
return;
if( (playState != PlayState.Paused) && (playState !=
PlayState.Running) )
return;
int hr = mediaCtrl.Stop();
playState = PlayState.Stopped;
DsOptInt64 pos = new DsOptInt64( 0 );
hr = mediaSeek.SetPositions( pos,
SeekingFlags.AbsolutePositioning, null, SeekingFlags.NoPositioning );
hr = mediaCtrl.Pause();
UpdateMainTitle();
}
Implementación del módulo de preprocesamiento de video
Este módulo es el encargado de procesar el archivo de video informando sobre sus
características. A su vez permite convertir el video en n imágenes. Para lo cual, se debe
seleccionar una carpeta de almacenamiento de las imágenes y especificar si la extracción
será total o parcial.
Funciones de apertura y preprocesamiento
A través de estas funciones seleccionamos el archivo de video haciendo uso de la función
GetFileName. Luego se informa sobre las características del video y permite la
visualización de los frames.
La función GetFileName hace uso de una función auxiliar para obtener el path del archivo
que seleccionamos.
private void seleccionarVideo_Click(object sender, System.EventArgs e)
{
nombreAvi.Text ="";
String fileName = GetFileName("Archivos de video (*.avi)|*.avi");
if(fileName != null)
nombreAvi.Text = fileName;
informacion();
verCuadros();
}
private String GetFileName(String filter)
{
OpenFileDialog dlg = new OpenFileDialog();
dlg.Filter = filter;
dlg.RestoreDirectory = true;
if(nombreAvi.Text.Length > 0)
{
dlg.InitialDirectory = GetCurrentFilePath();
}
if(dlg.ShowDialog(this) == DialogResult.OK)
{
return dlg.FileName;
}
else
{
return null;
}
}
private String GetCurrentFilePath()
{
return nombreAvi.Text.Substring(0, ombreAvi.Text.LastIndexOf("\\")+1);
}
Funciones de extracción total y parcial
Estas funciones basan su funcionamiento en una clase llamada AviManager que permite
manipular los archivos de video.
La clase mencionada permite llevar el archivo de video a un stream. Para lo cual se debe
abrir un stream, trabajar con él, es decir obtener su información, realizar la extracción de
imágenes y luego cerrarlo.
private void seleccionarCarpeta_Click(object sender, System.EventArgs e)
{
string folderName;
FolderBrowserDialog dlg = new FolderBrowserDialog();
if( dlg.ShowDialog(this) == DialogResult.OK )
{
folderName = dlg.SelectedPath + "\\" ;
extraerFrame(folderName);
}
}
private void extraerFrame(string folder)
{
AviManager aviManager = new AviManager(nombreAvi.Text, true);
VideoStream stream = aviManager.GetVideoStream();
stream.GetFrameOpen();
String path = @folder;
for(int n=0; n<stream.CountFrames; n++)
{
stream.ExportBitmap(n, path+n.ToString()+".bmp");
}
stream.GetFrameClose();
aviManager.Close();
}
Las funciones de extracción total y parcial se diferencian ya que en esta última se permite el
ingreso de un intervalo.
private void extraerFrameParcial(string nombreAvi, string folder, int
comenzar, int finalizar)
{
AviManager aviManager = new AviManager(nombreAvi, true);
VideoStream stream = aviManager.GetVideoStream();
stream.GetFrameOpen();
String path = @folder;
for(int i=comenzar; i<= finalizar; i++)
{
stream.ExportBitmap(i, path+i.ToString()+".bmp");
comenzar++;
}
stream.GetFrameClose();
aviManager.Close();
}
Implementación del módulo de visualización de imágenes
Este módulo permite la visualización de las imágenes extraídas previamente por el módulo
de preprocesamiento de video.
Cuenta con la posibilidad de manipular imágenes desde su apertura, pasando por una
transformación a escala de grises, regulación de brillo, contraste, guardar el archivo
modificado, etc.
Función de apertura
El archivo abierto se implementa como un bitmap. A través de AutoScrollMinSize se
regulará el tamaño de la imagen y con el método on paint se implementará el zoom.
private void ArchivoAbrir_Click(object sender, System.EventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.InitialDirectory = "c:\\" ;
openFileDialog.Filter = "Bitmap (*.bmp)|*.bmp|Jpeg
(*.jpg)|*.jpg|Todos los archivos|*.*";
openFileDialog.FilterIndex = 2 ;
openFileDialog.RestoreDirectory = true ;
if(DialogResult.OK == openFileDialog.ShowDialog())
{
m_Bitmap = (Bitmap)Bitmap.FromFile(openFileDialog.FileName,
false);
this.AutoScroll = true;
this.AutoScrollMinSize = new Size ((int)(m_Bitmap.Width *
Zoom), (int)(m_Bitmap.Height * Zoom));
this.Invalidate();
}
}
Función de zoom
private void OnZoom200(object sender, System.EventArgs e)
{
Zoom = 2.0;
this.AutoScrollMinSize = new Size ((int)(m_Bitmap.Width * Zoom),
(int)(m_Bitmap.Height * Zoom));
this.Invalidate();
}
protected override void OnPaint (PaintEventArgs e)
{
Graphics g = e.Graphics;
g.DrawImage(m_Bitmap, new Rectangle(this.AutoScrollPosition.X,
this.AutoScrollPosition.Y, (int)(m_Bitmap.Width*Zoom),
(int)(m_Bitmap.Height * Zoom)));
}
A través de la clase BitmapFilter, se implementan las funciones de escala de grises,
contraste, brillo, etc.
Esta clase trabaja con punteros para lo cual debemos utilizar el tipo de directiva unsafe.
Para trabajar con la imagen, debemos utilizar los métodos LockBits y UnlockBits.
BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height),
ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
Bitmap.LockBits es un método que bloquea un objeto Bitmap en la memoria del sistema.
Parámetros
rect : Estructura Rectangle que especifica la parte del objeto Bitmap que se va a bloquear.
flags : Enumeración ImageLockMode que especifica el nivel de acceso (lectura y escritura)
para el objeto Bitmap.
format : Enumeración PixelFormat que especifica el formato de datos de este objeto
Bitmap.
Valor devuelto
Objeto BitmapData que contiene información sobre esta operación de bloqueo.
Comentarios
El objeto BitmapData especifica los atributos del objeto Bitmap, como el tamaño, formato
de píxeles, la dirección de inicio de los datos de píxeles en la memoria y el largo de cada
línea de exploración (paso).
Función escala de grises
private void EfectosGrises_Click(object sender, System.EventArgs e)
{
m_Undo = (Bitmap)m_Bitmap.Clone();
if(BitmapFilter.GrayScale(m_Bitmap))
this.Invalidate();
}
Descargar