Monday, July 30, 2018

Cozmo, leeme


Conoces a Cozmo? El robot amigable de Anki? Bueno...aquí está...

Cozmo es un robot programable que tiene muchas características...y una de ellas incluye una camera...así que puedes hacer que Cozmo tome una foto de algo...y luego hacer algo con esa foto...

Para programar a Cozmo necesitamos utilizar Python...en realidad...Python 3 -;)

Para este blog, vamos a necesitar un par de cosas...así que vamos a instalarlas...

pip3 install ‘cozmo[camera]’

Esto va a instalar el SDK de Cozmo...y vamos a necesitar también instalar el app de Cozmo app en nuestro teléfono celular también...

Si ya tienen el SDK instalado, quizás deberían actualizarlo porque si no tienen la última versión esto no va a funcionar...

pip3 install --upgrade cozmo

Ahora, necesitamos algunas cosas adicionales...

sudo apt-get install python-pygame
pip3 install pillow
pip3 install numpy

pygame es un framework para juegos
pillow es un wrapper para la librería PIL que se usa para manipular images.
numpy nos permite manejar números complejos en Python.

Esta fué la parte sencilla...puesto que ahora debemos instalar OpenCV...el cual nos permite manipular imágenes y video...

Esta parte es un poco complicada, así que si se quedan atracados...busquen en Google o simplemente escribanme un mensaje...

Primero, debemos asegurárnos de que OpenCV no está instalado...desinstalándolo...a menos que estén seguros de que funciona correctamente...

sudo apt-get uninstall opencv

Luego, debemos instalar los siguientes pre-requisitos...

sudo apt-get install build-essential cmake pkg-config yasm python-numpy

sudo apt-get install libjpeg-dev libjpeg8-dev libtiff5-dev libjasper-dev 
libpng12-dev

sudo apt-get install libavcodec-dev libavformat-dev libswscale-dev 
libv4l-dev libdc1394-22-dev

sudo apt-get install libxvidcore-dev libx264-dev libxine-dev libfaac-dev

sudo apt-get install libgtk-3-dev libtbb-dev libqt4-dev libmp3lame-dev

sudo apt-get install libatlas-base-dev gfortran

sudo apt-get install libopencore-amrnb-dev libopencore-amrwb-dev 
libtheora-dev libxvidcore-dev x264 v4l-utils

Si por alguna razón, algo no está disponible en su sistema, simplemente remuevánlo de la lista e intenten otra vez...a menos que sean como yo y quieran pasar horas tratándo de conseguir todo...

Ahora, debemos descargar el código fuente de OpenCV para que podamos construírlo...desde el código fuente...

wget https://github.com/opencv/opencv/archive/3.4.0.zip
unzip opencv-3.4.0.zip //This should produce the folder opencv-3.4.0

Luego, debemos descargar las contribuciones porque hay cosas que no vienen incluídas con OpenCV por defecto...y quizás quieran utilizarlas en algún otro proyecto...

wget https://github.com/opencv/opencv_contrib/archive/3.4.0.zip
unzip opencv-contrib-3.4.0.zip 
//This should produce the folder opencv_contrib-3.4.0

Como tenemos las dos carpetas, podemos comenzar a compilar...

cd opencv-3.4.0
mkdir build
cd build
cmake -D CMAKE_BUILD_TYPE=RELEASE 
-D CMAKE_INSTALL_PREFIX=/usr/local 
-D INSTALL_PYTHON_EXAMPLES=OFF 
-D CMAKE_CXX_COMPILER=/usr/bin/g++ 
-D INSTALL_C_EXAMPLES=OFF 
-D OPENCV_EXTRA_MODULES_PATH=/YourPath/opencv_contrib-3.4.0/modules 
-D PYTHON_EXECUTABLE=/usr/bin/python3.6 
-D WITH_FFMPEG=OFF 
-D BUILD_OPENCV_APPS=OFF 
-D BUILD_OPENCD_TS=OFF 
-D WITH_LIBV4L=OFF 
-D WITH_CUDA=OFF 
-D WITH_V4L=ON 
-D WITH_QT=ON 
-D WITH_LAPACK=OFF 
-D WITH_OPENCV_BIOINSPIRED=OFF 
-D WITH_XFEATURES2D=ON 
-D WITH_OPENCL=OFF 
-D WITH_FACE=ON 
-D ENABLE_PRECOMPILED_HEADERS=ON 
-D WITH_OPENCL=OFF 
-D WITH_OPENCL_SVM=OFF 
-D WITH_OPENCLAMDFFT=OFF 
-D WITH_OPENCLAMDBLAS=OFF 
-D WITH_OPENCV_DNN=OFF 
-D BUILD_OPENCV_APPS=ON 
-D BUILD_EXAMPLES=OFF ..

Tengan mucho cuidado de pasar la ruta correcta para la carpeta opencv_contrib...así que es mejor pasar la ruta completa para evitar cualquier error de compilación...

Y sí...ese es un comándo bastante extenso para un build...y me tomó mucho tiempo hacerlo funcionar...puesto que hay que asegurárse de que todos los parámetros son correctos...

Una vez que hemos terminado, necesitamos compilarlo...puesto que cmake va a preparar la "receta"...

make -j2

Si hay algún error, simplemente hagan esto...y comiencen otra vez...

make clean
make

Luego, podemos finalmente instalar OpenCV con estos comandos...

sudo make install
sudo ldconfig

Para pobrar que está funcionando correctamente...simplemente debemos hacer esto...

python3
>>>import cv2


Si no tienen ningún error...entonces estamos listos para continuar -;)

Eso fué bastante trabajo...en fín...necesitamos una herramienta adicional para asegurárnos de que nuestra images es procesada de la mejor manera...

Debemos descargar textcleaner y ponerlo en la misma carpeta que nuestro script de Python...

Y...en caso de que se estén preguntándo...sí...vamos a hacer que Cozmo tome una foto...vamos a procesar la imagen...usar SAP Leonardo's OCR API y luego hacer que Cozmo nos lea el mensaje...emocionánte, no?
SAP Leonardo's OCR API aún está en la version 2Alpha1...pero fuera de eso...funciona extremadamente bien -;)

Aunque tomen en cuenta que si el resultado no es siempre el más acertado es porque la luz, la posición de la imagen, tu escritura y por el hecho de que el OCR API aún está en Alpha...

Ok...así que primero lo primero...necesitamos una pequeña pizarra...


Y claro...mi escritura a mano no es la mejor del mundo... -:(

Ahora, saltemos al código fuente...


CozmoOCR.py
import cozmo
from cozmo.util import degrees
import PIL
import cv2
import numpy as np
import os
import requests
import json
import re
import time
import pygame
import _thread

def input_thread(L):
    input()
    L.append(None)

def process_image(image_name):
 image = cv2.imread(image_name)
 
 img = cv2.resize(image, (600, 600))
 img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
 
 blur = cv2.GaussianBlur(img, (5, 5), 0)
 denoise = cv2.fastNlMeansDenoising(blur)
 thresh = cv2.adaptiveThreshold(denoise, 255, 
                 cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2)
 blur1 = cv2.GaussianBlur(thresh, (5, 5), 0)
 dst = cv2.GaussianBlur(blur1, (5, 5), 0)
 
 cv2.imwrite('imggray.png', dst)
 
 cmd = './textcleaner -g -e normalize -o 12 -t 5 -u imggray.png out.png'
 
 os.system(cmd) 

def ocr():
 url = "https://sandbox.api.sap.com/ml/ocr/ocr"
 
 img_path = "out.png"
 
 files = {'files': open (img_path, 'rb')}
 
 headers = {
     'APIKey': "APIKey",
     'Accept': "application/json",
 }
 
 response = requests.post(url, files=files, headers=headers)
 
 json_response = json.loads(response.text)
 json_text = json_response['predictions'][0]
 json_text = re.sub('\n',' ',json_text)
 json_text = re.sub('3','z',json_text)
 json_text = re.sub('0|O','o',json_text) 
 return json_text

def cozmo_program(robot: cozmo.robot.Robot):
 robot.camera.color_image_enabled = False
 L = []
 _thread.start_new_thread(input_thread, (L,))
 robot.set_head_angle(degrees(20.0)).wait_for_completed()
 while True:
  if L:
   filename = "Message" + ".png"
   pic_filename = filename
   latest_image = robot.world.latest_image.raw_image
   latest_image.convert('L').save(pic_filename)
   robot.say_text("Picture taken!").wait_for_completed()
   process_image(filename)
   message = ocr()
   print(message)
   robot.say_text(message, use_cozmo_voice=True, 
                                       duration_scalar=0.5).wait_for_completed()
   break

pygame.init()
cozmo.run_program(cozmo_program, use_viewer=True, force_viewer_on_top=True)


Analicemos un poco el código fuente...

Vamos a utilizar threads (hilos), puesto que necesitamos tener una ventana donde podamos ver lo que Cozmo está viendo y otra con Pygame donde podamos presionar "Enter" como un comando para hacer que Cozmo tome la foto.

 Basicamente, cuando ejecutamos la aplicación, Cozmo va a mover su cabeza y entrar en modo de imagen...luego, si presionamos "Enter" (En el terminal) va a tomar una foto y enviarla a nuestra función de procesamiento de OpenCV.

Esta función va a simplemente tomar la imagen, cambiar su tamaño, convertirla a escala de grises, hacer un GaussianBlur para distorcionar la imagen y remover el ruido y reducir el detalle. Luego vamos a aplicar denoising para deshacernos del polvo y el brillo...aplicar un threshold para separar los pixels blancos y negros, y aplicar un par más de distorciones...

Finalmente vamos a llamar a textcleaner para remover aún más ruido y hacer que la imagen sea más clara...

Así que, aquí está la foto original tomada por Cozmo...


Esta es la imagen luego de nuestro post-procesamiento en OpenCV...


Y finalmente, esta es nuestra imagen luego de utilizae textcleaner...

Finalmente, una vez que tenemos la imagen tal como la queremos, podemos llamar al OCR API lo cual es bastante secillo y directo...

Para obtener el API Key, simplemente vamos a  https://api.sap.com/api/ocr_api/overview y nos legeamos...

Una que obtenemos una respuesta del API, podemos hacer una pequeña limpieza con Regular Expressions solo para asegurárnos de que no hay ninguna letra que ha sido incorrectamente identificada...

Finalmente, podemos hacer que Cozmo nos lea el mensaje en voz alta -;) Y solo para propósitos de demostración...


Aquí, tuve la suerte de que la luz y todo lo demás estaban perfectos...así que obtuve una respuesta muy limpia...las pruebas sucesivas fueron bastante malas -:( Pero, nuevamente...es importante tener buena iluminación...

Por supuesto...quieren ver un video del proceso en acción, no? Bueno...aunque suene gracioso...mi primer intento fué perfecto! Aún mejor que este...pero no tome el video -:( Las prubeas sucesivas fueron bastante malas hasta que pude conseguir also razonable...y eso es lo que van a ver...el sol entrándo por la ventana no me ayudo mucho...pero de todos es bastante bueno...


Espero que les haya gustado este blog-:)

Saludos,

Blag.
SAP Labs Network.

No comments: