Sesin Prctica 1: Instalacin y Configuracin del entorno;
tratamiento de imgenes
A. Configurar EmguCV en VS2010 Nota: Compruebe que posee instalada la extensin de C#. En caso contrario, introduzca el DVD de Visual Studio 2010, seleccione la opcin de Agregar o quitar componentes y seleccione la extensin de C#. Configurar Visual Studio 2010 para poder trabajar con la librera EmguCV se reduce a hacer uso de una serie de inclusiones de libreras y referencias especficas de ella. Para llevar a cabo este proceso, seguiremos los siguientes pasos: 1. Acceda a la web de EmguCV (http://www.emgu.com/wiki/index.php/Main_Page) 2. En la seccin Latest News aparecer un listado de las ltimas versiones con sus enlaces correspondientes. Sobre cualquiera de ellas, cliqueamos en el enlace representado por la palabra sourceforge.
3. Accedemos al enlace indicado en la siguiente seccin.
4. En la pgina de SourceForge nos aparecer para descargar la ltima versin de la librera. Debido a su continua actualizacin, la ltima versin suele presentar numerosos bugs. Por ello nos descargaremos una versin testeada y en funcionamiento desde hace varios aos (para los objetivos del presente curso no se necesitar mas). La versin a descargar es la 2.2. 5. Para ello, accedemos a la pestaa Files.
6. Dentro de la carpeta emgucv aparecer un listado de todas las versiones hasta la fecha. Nos introducimos en la carpeta de la versin 2.2.0.0 y encontraremos lo siguiente:
7. Debido a varios errores (algunos sin explicacin por parte de los desarrolladores de la librera) para el caso de la versin de 64 bits, haremos uso de la versin de 32 bits. Esto no restringe que el equipo deba ser de 32 bits para su funcionamiento, solo restringe el tipo de proyecto a crear desde el Visual Studio. 8. Una vez descargado el archiv, lo descomprimiremos en una ruta conocida y a eleccin nuestra. Por simplicidad se ha escogido la ruta C:\Emgu. Tras esto, se puede pasar a configurar el proyecto de Visual Studio. 9. Arrancamos el Visual Studio 2010 y creamos un proyecto nuevo de Windows Forms.
10. En primer lugar, aadiremos las referencias necesarias del wrapper. Para ello, presionamos con el click derecho sobre la carpeta References o, sobre el nombre del proyecto, click derecho a Agregar referencia. Dentro de la pestaa Examinar navegamos hasta la ruta donde se instal EmguCV. En ella, dentro de la carpeta bin, seleccionamos las siguientes libreras dinmicas: Emgu.CV.dll, Emgu.CV.UI.dll y Emgu.Util.dll. Tras ello, le damos a aceptar.
11. En segundo lugar, tendremos que aadir las referencias pertenecientes a la librera OpenCV nativa. Al no encontrarse en el lenguaje referencia del proyecto (C#), sino en C++, no se podrn aadir de igual forma. Para ello, tendremos que introducirlas directamente a nuestro proyecto como archivos externos (al igual que cualquier elemento adicional). Hacemos click con el botn derecho sobre el nombre del proyecto y accedemos a la opcin Agregar Elemento existente. Tras ello, navegamos hasta la carpeta de instalacin de la librera y, dentro de la subcarpeta bin, seleccionamos todas las dlls relacionadas con openCV. Estas son: cvextern.dll, opencv_calib3d220.dll, opencv_contrib220.dll, opencv_core220.dll, opencv_deatures2d220.dll, opencv_ffmpeg220.dll, opencv_flann220.dll, opencv_gpu220.dll, opencv_highgui220.dll, opencv_imgproc220.dll, opencv_legacy220.dll, opencv_ml220.dll, opencv_objdetect220.dll, opencv_video220.dll y ZedGraph.dll. Quedando finalmente algo similar a lo mostrado a la derecha.
12. Como podemos recordar, estamos haciendo uso de la versin de 32 bits de la librera. Por ello, para que funcione correctamente, debemos especificar a nuestro proyecto que genere la solucin para un dispositivo x86. Hay que indicarlo en dos lugares diferentes: a. Botn secundario sobre el archivo de la solucin (el de ms arriba) Propiedades. Propiedades de Configuracin Plataforma x86. b. Botn secundario sobre el proyecto (justo debajo de la solucin) Propiedades. Generar Destino de la Plataforma x86.
13. Como programa de ejemplo, crearemos una ventana que muestre una imagen de fondo negro y con un texto en el centro. 14. Hacemos doble click en el archivo Form1.cs y nos aparecer el editor grfico del formulario en cuestin. Haremos uso de un elemento de tipo PictureBox, de forma que lo arrastraremos al formulario. De entre sus propiedades, le daremos un tamao de 400x400 pxeles, quedando algo similar a:
15. En el cdigo del formulario (sobre Form1.cs, click derechoVer cdigo), crearemos dos variables de tipos propios de EmguCV: - Image<tipo, profundidad>: almacn bsico que contiene la informacin de una imagen (o un frame en caso de vdeo), pudiendo indicarse el tipo de imagen y la profundidad del color al crearla. - MCvFont: tipo de fuente; utilizada para especificar las caractersticas de la fuente a dibujar. La imagen a crear ser a color RGB de un byte por componente. Adems, la crearemos del mismo tamao que el recipiente utilizado en el formulario para presentarla (400x400) y le indicaremos que inicialmente todos sus pxeles sern negros: Image<Bgr, Byte> im = new Image<Bgr, Byte>(400, 400, new Bgr(0, 0, 0)); A la fuente le especificaremos el tipo y las escalas (tanto horizontal como vertical): MCvFont f = new MCvFont(FONT.CV_FONT_HERSHEY_TRIPLEX, 1, 1); 16. Para que reconozcan los tipos especficos de esta librera, hay que aadir en la parte superior del fichero las referencias que se estn utilizando: using Emgu.CV; using Emgu.Util; using Emgu.CV.Structure; using Emgu.CV.CvEnum; 17. Se puede apreciar que, aparte de los atributos que acabamos de aadir a la clase, solo se encuentra visible el constructor, cuyo nico contenido es una llamada a la funcin InitializeComponent(). Tras dicha llamada, dibujaremos un determinado texto a nuestra imagen para, posteriormente, mostrarla en el pictureBox creado. 18. El mtodo Draw perteneciente a la clase Image se encuentra sobrecargado. Haremos uso de la opcin que nos permite dibujar una cadena de texto en la imagen. Le indicaremos al mtodo el texto a dibujar, la fuente a utilizar (ntese que se indica con la palabra ref delante, para denotar que se le pasa una referencia o un puntero), el lugar donde dibujar (como un punto con coordenadas x e y) y, por ltimo, el color con el que se pintar (en nuestro caso, verde). im.Draw("EMGUcv", ref f, new System.Drawing.Point(140, 200), new Bgr(0, 255, 0)); 19. Por ultimo, se mostrar el contenido de nuestra imagen sobre el pictureBox creado. Para ello, el atributo Image del pictureBox se modifica con el contenido de nuestra imagen. Como el pictureBox solo admite bitmaps, hacemos uso del mtodo interno a la clase Image que nos la convierte a bitmaps. Quedara: pictureBox1.Image = im.ToBitmap(); 20. Finalmente, quedara lo siguiente:
21. Puede compilar y ejecutar el proyecto para comprobar que funciona correctamente.
B. Plantilla de proyecto de EmguCV Partiremos del proyecto que se ha creado como ejemplo, de forma que crearemos un template a partir de dicho proyecto y lo instalaremos entre las plantillas predeterminadas de Visual Studio. As, se podr partir del programa creado de ejemplo, sin necesidad de realizar todos los pasos indicados anteriormente. Los pasos a seguir son los siguientes: 1. Con el proyecto abierto, seleccionamos la opcin Archivo Exportar plantilla. En el asistente, seleccionaremos la opcin Plantilla de proyecto. 2. A continuacin, introducimos la informacin del proyecto. Excepto el nombre, las dems opciones son opcionales. 3. IMPORTANTE desmarcar la opcin Importar la plantilla automticamente en Visual Studio.
4. Finalizamos. Se guardar la plantilla en un archivo .zip. 5. Creamos un nuevo proyecto de Visual Studio. En este caso ser un proyecto VSIX.
6. El proyecto se crear y nos aparecer el manifiesto del proyecto para rellenarlo. 7. En primer lugar, rellenaremos los campos informativos: Nombre, descripcin, autor, etc.
8. Posteriormente, en la opcin Supported VS Editions, seleccionaremos las ediciones compatibles con nuestro template. Seleccionaremos:
9. Se aadir el archivo zip (template) creado anteriormente. Dentro de la opcin Add content, seleccionamos el tipo Project Template y cargamos desde un archivo el template originado en el proyecto anterior. Opcionalmente, se podr seleccionar una subcarpeta para dicho template, que se corresponder con una subcategora dentro de las plantillas del Visual Studio. Para nuestro ejemplo:
10. Quedar finalmente:
11. Por ltimo, se generar la solucin del proyecto VSIX (Generar Generar solucin, o F7). 12. Ya se encuentra creado el complemento para aadir al Visual Studio. Cerramos el entorno y nos dirigimos a la ruta donde se ha generado la solucin del proyecto VSIX. Hacemos doble click en el archivo .vsix, que instalar el complemento en el Visual Studio. 13. Tras ello, ya se puede crear un nuevo proyecto en Visual Studio partiendo de la plantilla creada:
C. Herramientas grficas de EmguCV
Como se ha podido comprobar con el ejemplo detallado, EmguCV hace uso de una serie de clases propias para definir, almacenar y operar con imgenes. Es por ello que EmguCV contempla una serie de herramientas propias (del cuadro de herramientas de Diseo) para poder mostrar la informacin en un formulario. Si bien, en el proyecto de ejemplo, se haca uso de un pictureBox para mostrar el contenido de una imagen, se pudo apreciar que haba que realizar una conversin a bitmap para poder mostrar el contenido de dicha imagen. Es por esto, y por otros ejemplos similares, que EmguCV aporta una serie de herramientas para facilitar el trabajar con dicha librera. A continuacin se detallan los pasos a seguir para aadir esas herramientas a las predeterminadas de Visual Studio para poder trabajar con ellas. 1. Nos dirigimos a la pestaa de diseo del formulario. En el cuadro de herramientas (derecha), cliqueamos con el botn derecho y seleccionamos la opcin Elegir Elementos. 2. En la ventana que aparece, dentro de la pestaa Componentes de .NET Framework, cliqueamos en el botn de Examinar. 3. Dentro de la ubicacin de EmguCV, dentro de la carpeta bin, seleccionamos la librera Emgu.CV.UI.dll. 4. Cargar automticamente las herramientas de EmguCV y aparecern en la pestaa General del cuadro de herramientas de diseo.
D. Primer proyecto con EmguCV
Haremos uso de la plantilla creada para comenzar nuestro proyecto. A partir de l, haremos uso de las utilidades para cargar imgenes, mostrarlas y aplicarles ciertos tratamientos simples. 1. Cargar Imgenes: se realizar de dos formas diferentes.
a. Haciendo uso de una ruta esttica, se puede cargar una imagen en la propia inicializacin del objeto Image:
Image<Bgr,Byte> im = new Image<Bgr, Byte>(ruta_de_la_imagen.jpg);
b. Haciendo uso de los dilogos de apertura de archivos que posee C#:
//Creamos el objeto OpenFileDialog op = new OpenFileDialog(); //Seleccionamos el filtro utilizado (tipo de archivo) op.Filter = "Imgenes JPEG (.jpg)|*.jpg"; op.FilterIndex = 0; //Con ms de uno, as se seleccionara la posicin //Abrimos el cuadro de dilogo if (op.ShowDialog() == DialogResult.OK) { //Inicializamos la Imagen con la ruta obtenida del dilogo im = new Image<Bgr, Byte>(op.FileName); //Aqu se mostrara la imagen cargada (en el pictureBox) }
2. Mostrar Imgenes: Ya se ha visto en el proyecto de ejemplo cmo mostrar una imagen en un pictureBox, de forma que en el formulario pueda apreciarse el contenido de dicha imagen. De igual forma, podra mostrarse si se hace uso de la herramienta ImageBox, que es una de las herramientas que nos proporciona EmguCV. Esta herramienta, al estar pensada para trabajar con objetos de la clase Image, no necesita de conversiones previas. As pues, para mostrar el contenido de im en un ImageBox, se hara lo siguiente: imageBox1.Image = im;
3. Tratamientos sobre imgenes
En este apartado se expondrn una serie de tratamientos (simples y complejos) sobre imgenes, haciendo uso de las funcionalidades que aporta EmguCV. Para hacer la sesin ms interactiva y entretenida, los siguientes apartados se aportan a modo de ejercicios a realizar por el alumnado, con una breve explicacin al respecto. Ante cualquier duda puede consultar la web de EmguCV o, en ltima instancia, al profesor. a. Modifique el diseo del formulario, para mostrar 2 imageBox (elimine el pictureBox) de 512x512 de tamao, cada uno. Incluya un botn, que mostrar un cuadro de dilogo y, de esa forma, poder seleccionar la imagen correspondiente. Incluya otro botn, que servir para activar la funcionalidad correspondiente que se pida en cada apartado. Puede probar con cargar cualquier imagen que quiera pero, por motivos histricos, sera muy emotivo trabajar con la imagen clsica de visin artificial (rostro de Lena Sderberg): puede encontrarla en google imgenes, o en http://www.kitware.com/blog/files/128_1232259669.jpg. b. Redimensionar la imagen: cmo ha podido comprobar, utilizar una dimensin de 512x512 abarca buena parte de la pantalla. Intente redimensionar los dos imageBox a 256x256. Al cargar la imagen de Lena, puede apreciar que solo muestra una cuarta parte de la imagen. Haga uso del mtodo Resize de la clase Image para redimensionar la imagen a un tamao de 256x256 pxeles. Para ello tendr que indicarle como primer y segundo parmetro el ancho y alto, respectivamente, al que se redimensionar y, como ltimo parmetro, la interpolacin utilizada para ello (lineal, cbica, etc): se encuentran redefinidas dentro del enumerado INTER, de forma que podr indicar el tercer parmetro como INTER.CV_INTER_LINEAR (para interpolacin lineal). Pruebe con las otras interpolaciones, por si observa algn cambio c. Acceso directo a los pxeles de una imagen: como atributo de la clase Image se encuentra un array tridimensional denominado Data, al que se puede acceder de forma pblica y modificar el valor de las componentes de color de un determinado pxel. Pruebe a pintar de color rojo (BGR a 0,0,255) un recuadro de la imagen y aprecie el resultado. d. Extraer sub-imagen: Haga uso del mtodo GetSubRect, pasndole por parmetros un rectngulo (clase Rectangle), inicializado con cuatro parmetros: posicin x inicial, posicin y inicial, ancho y alto. e. Convertir la imagen a escala de grises. Para ello utilice el mtodo Convert de la clase Image. f. Aplique un filtro tipo blur sobre la imagen. Este tipo de filtros lineales, calcula el nuevo valor de un pxel con respecto al de sus vecinos, de forma que se suelen utilizar para eliminar el ruido de sal y pimienta. Para ello, haga uso de los mtodos: i. Blur de media: media aritmtica del valor de un pxel con el de sus vecinos. Haga uso del mtodo MedianBlur y pasndole por parmetro el tamao del kernel de convolucin a aplicar. ii. Blur Gausiano: haga uso de la funcin SmoothGaussian y pasndole por parmetro el tamao del kernel de convolucin a aplicar. Este no realiza la media aritmtica, sino una ponderada de forma que la participacin del pxel depende de la distancia con el central. g. Binarizar la imagen: convertirla en una imagen en blanco y negro. Debe partir de la imagen en escala de grises (si parte desde la imagen a color, lo que obtendr es una binarizacin en cada canal del color). En ambos casos deber indicar un valor umbral de binarizacin. Haga uso del mtodo ThresholdBinary, pasndole por parmetro el umbral y el valor mximo a utilizar en caso de superar dicho umbral. i. Inserte un control de tipo ScrollBar en su aplicacin (con un valor entre 0 y 255) y utilice el valor devuelto para binarizar la imagen con dicho valor. Utilice el evento generado por la barra de desplazamiento para aplicar la conversin en el mismo momento. De esa forma, podr apreciar cmo se modifica la imagen a medida que mueve la barra de desplazamiento. h. Transformaciones afines: giros, traslaciones, etc. i. Dar la vuelta: hacer uso del mtodo Flip, al que se le podr pasar dos parmetros: FLIP.HORIZONTAL o FLIP.VERTICAL; para efectuar el cambio horizontal o verticalmente. ii. Rotacin: hacer uso de la funcin Rotate, a la que se le pasa el ngulo de rotacin y un color (el que se utilizar para rellenar el fondo en caso de que ningn pxel coincida en una posicin concreta). iii. Inserte un control de tipo ScrollBar en su aplicacin (con un valor entre 0 y 360) y utilice el valor devuelto para utilizarlo como ngulo giro de la imagen. Utilice el evento generado por la barra de desplazamiento para aplicar el giro en el mismo momento. De esta forma, podr apreciar los cambios mientras mueve la barra. i. Operadores morfolgicos comunes: i. Erosionar una imagen: obtencin del esqueleto de la imagen. Reduce aquellos patrones gruesos de la imagen. Hacer uso del mtodo Erode, pasndole por parmetros el nmero de iteraciones utilizadas para erosionar la imagen. ii. Dilatar la imagen: justamente lo opuesto a la anterior. Hacer uso de la funcin Dilate, e indicndole por parmetros el nmero de iteraciones a realizar. j. Filtros derivativos: utilizados para detectar cambios en una imagen. i. Operador de Sobel: operador discreto que calcula, aproximadamente, el gradiente de la intensidad de la imagen. Hay que partir de la imagen monocromtica para obtener buenos resultados. Aplica el gradiente horizontal y el vertical (dependiendo de los parmetros). Puede utilizarlo, haciendo uso del mtodo Sobel, pasndole por parmetros: un entero (0 o 1) que indica si se realizar la derivada respecto a X, otro entero (0 o 1) que indica si se realizar la derivada respecto a Y, y un ltimo entero que indica el tamao del kernel. Para aplicar uno, pruebe a llamar al mtodo con los parmetros 1, 0, 3. Pruebe con otras combinaciones. Este filtro detecta variaciones significativas en la intensidad de los pxeles y las acenta. ii. Operador Laplaciano: uso de la transformada discreta de Laplace. Derivada de la intensidad de segundo orden. Se correspondera con aplicar la derivada al resultado aportado por el operador de Sobel (internamente lo llama). A las variaciones acentuadas tras aplicar Sobel, este filtro las detecta y se queda nicamente con estas variaciones para mostrar los bordes de la imagen. Haga uso de ella con el mtodo Laplace y pasndole como argumento el tamao del kernel. iii. Detector de bordes Canny: detector ptimo de bordes. Aplica filtro Gaussiano, Sobel y Laplace con unos krneles concretos, y de forma iterativa, para obtener de forma ptima los bordes. Se hace uso de l llamando al mtodo Canny, con dos parmetros que especificarn el mnimo y mximo umbral de binarizacin, respectivamente, entre los cuales el mtodo buscar el ptimo. iv. Modifique su aplicacin para que, en el detector Canny, los dos parmetros umbrales vengan aportados por dos barras de desplazamiento (as podr apreciar los resultados de hacer las modificaciones en tiempo real). k. Redimensionar utilizando pirmides: En un comienzo se ha indicado un mecanismo muy simple para redimensionar imgenes. El problema de dicho mecanismo era que se basaba en multiplicar la informacin (al aumentar el tamao) o en eliminar informacin (al disminuir el tamao). El resultado de este redimensionamiento puede ocasionar prdidas graves en el contenido de la imagen o una visualizacin muy artificial. Para ello, hay un mecanismo de redimensionamiento de la imagen que hace uso de las transformadas gaussianas y laplacianas para extrapolar el contenido de los pxeles con respecto a sus vecinos; obteniendo as un resultado mucho ms ptimo al redimensionar. Haga uso del mtodo PyrDown para reducir la imagen de forma piramidal y PyrUp para ampliar la imagen de forma piramidal. Observa algo interesante? l. Deteccin de lneas rectas: para detectar las lneas, se hace uso de un sistema de coordenadas polares, de forma que un punto viene definido por dos valores (rho y theta). Para un punto concreto con coordenadas cartesianas, al representarlo con coordenadas polares (variando ambas), se mostrara una representacin sinusoidal. Esto que quiere decir: que nuestro algoritmo aplicar estas transformaciones a polares con todos los puntos y, aquellos cuyos senos coincidan en un punto son propensos a encontrarse en la misma lnea. Obviamente, mientras ms puntos coincidan se obtendr una mayor precisin. As pues, pasando a la prctica, el mtodo encargado de buscar lneas rectas es HoughLines, al que se le pasa por parmetros: el mnimo y mximo umbral de binarizacin (para utilizarlos con Canny), la resolucin de rho (en pxeles) y de theta (en grados) en las representaciones sinusoidales (cuantizacin de dichos valores), un umbral que denotar el nmero de puntos cartesianos cuyas representaciones polares deben converger en un punto (mnimo para denotarlo como lnea), el tamao mnimo de la lnea y la distancia mnima entre puntos para ser considerados como lnea. Trabajando con la imagen en escala de grises, devuelve un LineSegment2D[][], de forma que la primera coordenada solo posee un posible valor (0), mientras que la segunda contiene todas las lneas (una por posicin y de tipo Segment2D). Para pintarlas, podemos hacer uso del mtodo Draw de la clase Image. m. Deteccin de crculos: para detectar un crculo, se lleva a cabo un proceso anlogo al de deteccin de lneas. En este caso, un crculo vendr descrito por dos coordenadas (punto central) y el radio. Para los crculos, se implementa un mtodo ms eficaz y simple que el de las lneas. Haga uso del mtodo HoughCircles, que recibe por parmetros: el umbral mayor de Canny, el umbral para la deteccin del centro del crculo, la resolucin con la que trabajar (1: 100% de la imagen), mnima distancia entre crculos, radio mnimo y radio mximo (ambos radios puedes ser 0, y se encargara el mtodo de buscar todas las posibilidades). El mtodo devuelve un CircleF[][] que, al igual que pasaba en el apartado anterior, tiene una sola fila (por ser una imagen en escala de grises) y las columnas indican los diversos crculos. Igualmente podr usar el mtodo Draw de Image. n. Operaciones con histogramas: un histograma es una representacin grfica de una variable, en forma de barras, donde la superficie de la barra es proporcional a la frecuencia de los valores representados. En visin artificial, se suele utilizar para denotar la distribucin de la luminosidad en una imagen monocromtica (frecuencia de cada posible valor de la escala de grises). Esta informacin es muy til para extraer determinadas caractersticas de la imagen, as como para aplicar diversos tratamientos sobre ella. i. Ecualizar el histograma: expande homogneamente las barras del histograma, de forma que amplia el rango de valores de la escala de grises que aparecen en la imagen, permitiendo aumentar el contraste de la misma. Haga uso del mtodo _EqualizeHist(). ii. Calcular y mostrar el histograma: Para ello, en primer lugar, hay que crear un objeto de tipo DenseHistogram, e indicarle el valor mximo y el rango de valores en su inicializacin: DenseHistogram Histo = new DenseHistogram(255, new RangeF(0, 255)); Con la imagen en escala de grises, se puede calcular su histograma hacienda uso del mtodo Calculate, que recibe por parmetros: un vector de Image (por si se quiere mostrar ms de un histograma a la vez en nuestro caso: new Image<Gray, Byte>[] {im}), el segundo y tercer parmetros se utilizan para opciones especficas a la hora de mostrar varios histogramas (en nuestro caso, valdrn false y null, respectivamente). Por ltimo, cmo lo mostramos en nuestra aplicacin?... te acuerdas del HistogramBox del cuadro de herramientas? Tendrs que crear uno y hacer uso de su mtodo AddHistogram (al que se le pasa el nombre, el color y el histograma) y, por ltimo, utilizar el mtodo Refresh para refrescar el histograma. o. Correspondencia de patrones: buscar un determinado patrn en la imagen o, lo que es lo mismo: dada una imagen, detectar las apariciones de ella en otra imagen. Aparentemente, el uso del mtodo MatchTemplate puede parecer simple (debido a que solo recibe por parmetros la imagen plantilla y el mtodo de normalizacin de los coeficientes que utilizaremos el TM_TYPE.CV_TM_CCOEFF_NORMED-) pero, tras su ejecucin hay que realizar otras tareas. Nos devuelve una imagen, pero cada posicin de esta imagen representa la probabilidad de que ese punto (x e y) sea el punto de comienzo de la plantilla pasada. As pues, lo que habr que hacer a continuacin es buscar sobre todos ellos (con un porcentaje estipulado por nosotros -normalmente mayor al 70%-) y mostrar un recuadro sobre aquellos que superen nuestro umbral. Para facilitar la tarea de buscar sobre los elementos de una imagen, la convertiremos a un array de elementos tipo float haciendo uso de float[,,] porcentajes = im.Data;. Tras ello, haremos una bsqueda secuencial por todas las filas y columnas de este array (dos primeras componentes), con la tercera componente a 0 (es una imagen en escala de grises). Para cada valor que supere 0.75 (por ejemplo) lo pintaremos. Puede hacer uso del mtodo Draw de Image o, incluso, crear un Rectangle con punto de inicio en la posicin actual y con un ancho y alto igual al de la plantilla.