Creación de Imágenes sintéticas con Flip

December 1, 2020

| Ximena Carolina Andrade Vargas

Datos y modelos, dos lados de una misma moneda.

Son los datos la base de los algoritmos profundos de la Inteligencia Artificial (IA) y Machine Learning (ML), esto pone en ventaja a las empresas que los poseen. En este escenario los datos sintéticos son una gran herramienta para minimizar la brecha cuando se cuenta con pocos datos y permite a organizaciones de todos los niveles y tamaños entrar en el desarrollo de estos algoritmos. En otras palabras, democratizar el aprendizaje automático profundo.

Datos sintéticos: una breve definición

Son datos creados de forma artificial que se asemejan a los datos reales. La creación de estos suele reducir el tiempo, los costos y los riesgos derivados de la recopilación de datos, y a la vez permiten llegar a resultados similares a los obtenidos con datos reales. Así mismo pueden contribuir a mantener la confidencialidad de la información, dado que los datos creados pueden ser anonimizados.

Los datos sintéticos resultan de gran ayuda cuando se cuenta con datos desbalanceados (clases con tamaños de muestras desiguales). Haciendo uso de estos, se puede aumentar el tamaño de la muestra de la clase minoritaria (sobre-muestreo) de una forma rápida, dado que se pueden generar cientos de nuevas instancias en poco tiempo. Un ejemplo de datos desbalanceados son los provenientes de anomalías, las cuales suelen ser el grupo minoritario en comparación con su contraparte.

Otro escenario en el que los datos sintéticos pueden ser útiles, es cuando se requiere mantener la confidencialidad de la información. En este caso, los datos reales pueden ser sustituidos completamente por datos sintéticos (construidos tomando como base los datos reales) que mantienen distribuciones y correlaciones semejantes a las originales. De esta forma se puede llegar a resultados confiables sin el riesgo de perder la confidencialidad. Como ejemplo, podemos pensar en datos bancarios.

También se puede hacer uso de los datos sintéticos cuando se cuenta con pocos datos, son muy heterogéneos o difíciles de obtener. Hay varios campos que ya han empezado a trabajar con datos sintéticos, entre ellos podemos encontrar: IoT, medicina y carros autónomos, solo por nombrar algunos.

Flip

Flip es una librería de código abierto que permite generar imágenes sintéticas en pocos pasos a partir de un pequeño conjunto de imágenes compuesto por fondos y objetos (imágenes que estarían sobre el fondo). Para ello permite que el usuario pueda aplicar transformaciones sobre los objetos como girar con respecto a un eje, cambiar el tamaño o rotar. Con lo anterior definido, se realiza una composición con un conjunto de opciones para establecer el estado final del fondo y la ubicación de los objetos. Por ultimo el usuario puede generar archivos de tipo jpg, json, csv y pascal voc.

Ahora veamos como sería en la práctica. En este enlace puedes obtener un ejemplo de cómo usar la librería para crear n nuevas imágenes sintéticas por cada fondo, también puede determinar la cantidad de objetos que se agregarán.

Para el ejemplo se usaron las siguientes imágenes (que puedes encontrar en el repositorio de ejemplo):

Imágenes usadas

Objeto: pingüino en formato png con fondo transparente.
Fondo: paisaje en formato jpg.

A continuación están explicadas algunas líneas de código.

Flip: permite girar el objeto o el fondo con respecto al eje x , y o de forma random.


flip.transformers.data_augmentation.Flip(mode=’random’)
 

Flip

En las imágenes 1 y 2 se aplicó flip al fondo y en 3 y 4 al objeto. En 1 y 3 fue con respecto al eje x, mientras que en 2 y 4 con respecto al eje y.

RandomResize: cambiar el tamaño del objeto con respecto a si mismo o al fondo. Los cambios pueden ser asimétricos o simétricos con respecto al ancho o la altura, con posibilidad de definir valores máximos y mínimos.


flip.transformers.data_augmentation .RandomResize(    
mode='symmetric_w',     
relation='parent',    
w_percentage_min=0.2,     
w_percentage_max=0.7)
 

Random size

Rotate: gira los objetos en ángulos de 90º, 180º o de forma random (entre 0º y 360º). En el último modo permite determinar los valores mínimos y máximos para realizar las rotaciones.


flip.transformers.data_augmentation.Rotate(mode=’random’, min=45, max=180)
 

Rotate

En la imagen 1 se usó el modo random, en la 2 el modo upside_down o 180º y en la 3 el modo 90º.

Luego de ser definidas las transformaciones de los objetos, se realiza una composición entre estos y los fondos (a los cuales también es posible aplicarle transformaciones como por ejemplo Flip). La forma como los objetos serán puestos sobre los fondos pueden ser de dos modos: por porcentaje o de forma totalmente aleatoria. El usuario puede determinar los valores mínimos y máximos (tanto para el ancho como para el alto) donde podrían ubicarse los objetos.


flip.transformers.domain_randomization.Objects.RandomPosition(     
x_min=0.3,     
y_min=0.3,     
x_max=0.7,     
y_max=0.7,     
mode='percentage'),flip.transformers.domain_randomization.Draw()
 

Composiciones

Finalmente el usuario puede guardar las imágenes generadas en formato jpg con la siguiente línea:


flip.transformers.io.SaveImage(OUTPUT_DIR, name)
 

También puedes crear y guardar etiquetas de los objetos usados en cada composición. Para ello usa estas dos líneas:


flip.transformers.labeler.CreateBoundingBoxes(),
flip.transformers.io.CreateJson(OUTPUT_DIR, name)
 

La primer línea genera las etiquetas y la segunda lo guarda en formato JSON, también lo podrías hacer en formato csv y pascal voc. El archivo .json contiene una lista de diccionarios (uno por cada objeto en la composición), cada uno con dos keys: name y pos.

name: guarda el nombre de la imagen usada como objeto
pos: contiene la ubicación del objeto en el fondo. Los valores de x y y forman la coordenada superior izquierda, mientras w y h son el ancho y alto del objeto. Todas las unidades están en pixeles.

Para este ejemplo todos los objetos tienen el mismo nombre porque siempre se usó la misma imagen.


[{"name": "pinguino.png",  
"pos": {"x": 200, "y": 439, "w": 112, "h": 202}}, 
{"name": "pinguino.png", 
"pos": {"x": 126, "y": 449, "w": 112, "h": 245}}, 
{"name": "pinguino.png", 
"pos": {"x": 345, "y": 436, "w": 112, "h": 234}}, 
{"name": "pinguino.png", 
"pos": {"x": 621, "y": 384, "w": 112, "h": 239}}]
 

Si lo guardas en formato csv obtendrías lo siguiente:

pinguino.png   200   439   112   202
pinguino.png   126   449   112   245      
pinguino.png   345   436   112   234      
pinguino.png   621   384   112   239

En la primera columna esta el nombre de la imagen usada como objeto, luego los valores para x y y (coordenada superior izquierda), en las dos ultimas columnas los valores de ancho y alto del objeto.

Si usas el formato pascal voc generas un archivo .xml con mucha más información, como por ejemplo el nombre de la imagen generada, su ubicación, sus dimensiones (ancho, alto y el número de canales), los nombres de las imágenes usadas como objetos y los valores de las coordenadas izquierda superior (xmin, ymin) y de inferior derecha (xmax, ymax) de cada uno de los objetos puestos. A continuación puedes ver un ejemplo.

<annotation>
<folder>synthetic_images</folder>
<filename>derevya-dorogi-pejzazh-sneg-zima-26355__45763af5-a813-4f37-87d1-0bc78502fc0f.jpg</filename>
<path>synthetic_images/derevya-dorogi-pejzazh-sneg-zima-26355__45763af5-a813-4f37-87d1-0bc78502fc0f.jpg</path>
<source>
 <database>Unknown</database>
</source>
<size>
 <width>1120</width>
 <height>700</height>
 <depth>3</depth>
</size>
<segmented>0</segmented>
<object>
 <name>pinguino.png</name>
 <pose>Unspecified</pose>
 <truncated>0</truncated>
 <difficult>0</difficult>
 <bndbox>
  <xmin>200</xmin>
  <ymin>439</ymin>
  <xmax>312</xmax>
  <ymax>641</ymax>
 </bndbox>
</object>
<object>
 <name>pinguino.png</name>
 <pose>Unspecified</pose>
 <truncated>0</truncated>
 <difficult>0</difficult>
 <bndbox>
  <xmin>126</xmin>
  <ymin>449</ymin>
  <xmax>238</xmax>
  <ymax>694</ymax>
 </bndbox>
</object>
<object>
 <name>pinguino.png</name>
 <pose>Unspecified</pose>
 <truncated>0</truncated>
 <difficult>0</difficult>
 <bndbox>
  <xmin>345</xmin>
  <ymin>436</ymin>
  <xmax>457</xmax>
  <ymax>670</ymax>
 </bndbox>
</object>
<object>
 <name>pinguino.png</name>
 <pose>Unspecified</pose>
 <truncated>0</truncated>
 <difficult>0</difficult>
 <bndbox>
  <xmin>621</xmin>
  <ymin>384</ymin>
  <xmax>733</xmax>
  <ymax>623</ymax>
 </bndbox>
</object>
</annotation>

Para visualizar los cuadros delimitadores de cada objeto dentro de la composición, primero debes generar y guardar las etiquetas en formato JSON, y luego usar el notebook show_labels.ipynb que esta en los ejemplos de la librería Flip. Así se vería:

Visualización de cuadros delimitadores

Puedes revisar el código completo en Github.

Aquí puedes leer una aplicación de la librería Flip en la detección de anomalías.

Exploring Generative AI: Use Cases in Computer Vision and Beyond
Thursday, February 22, and Friday, February 23
Register Free

Follow Us

Copyright © 2024 Linked AI, Inc. All rights reserved.