Showing posts with label OpenCV. Show all posts
Showing posts with label OpenCV. Show all posts

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.

Wednesday, September 09, 2015

Fuego! (BeagleBone Black, WebCam, Missile Launcher y OpenCV)

Este post fué posteado originalmente en Firing Up (BeagleBone Black, WebCam, Missile Launcher and OpenCV).



Si eres un empleado de SAP, por favor siguenos en Jam.


Mi buen amigo John Astill vino a visitarnos al d-shop hace algún tiempo…y vió el Thunder Missile Launcher que compré como un regalo de navidad Christmas para la cena de mi equipo. El me dijo…”Blag…deberías hacer una aplicación que hace que el lanza misiles dispare cuando pones un color u objeto en frente de la camara”…eso me dejó pensándo por supuesto -;)

Así que John…este post es para ti...

Así que, vamos a comenzar…

Vamos a necesitar tener el OpenCV instalado…así que la manera regular debería funcionar…

sudo apt-get install opencv

Y OpenCV debería estar instalado y listo para usarse…

Después…necesitaba hackear el Missile Launcher para poder hacer que dispare…así que aquí es donde la diversión comienza…conecté el Missile Launcher a mi Linux en VMWare he hice un comando lsusb -vv para obtener la información del dispositivo USB…


Aquí podemos ver que el IdVendor es 0x2123 y que el idProduct es 0x1010. Esto en realidad no ayuda en nada puesto que no sabemos cual es la información que debemos pasar para hacer que esto funcione…así que el siguiente paso es "olfatear" el dispositivo para poder obtener los comandos USB…para esto utilicé el SnoopyPro un USB Sniffer para Windows…y me di cuenta de que no podía hacerlo funcionar bien en Windows 7, así que tuve que utilizar mi querido y ya viejo Windows XP en VMWare…e instalar el Dream Cheeky software...


Una vez que tuve el SnoopyPro ejecutándose, tuve que conectar el Missile Launcher y presionar en File --> Unpack Drivers…


Luego, tuve que buscar el IdVendor y IdProduct correctos y presionar click derecho y seleccionar Install and Restart.


Esto nos permite registrar todo lo que pasa cuando utilizámos el dispositivo USB. Por defecto, por lo menos para el Missile Launcher…va a hacer un log de 14 líneas que realmente no nos interesan mucho…pero cuando presionamos por el ejemplo el botón Up…entonces obtenemos información más interesánte…


Esto nos dice basicamente que para hacer que el lanza misiles se mueva para arriba, debemos pasar lo siguiente…

0x02 0x02 0x00 0x00 0x00 0x00 0x00 0x00

Ahora…la parte que nos interesa es la de disparar…así que vamos a explorarla…


Esta es

0x02 0x10 0x00 0x00 0x00 0x00 0x00 0x00

Perfecto!…ahora nos estamos acercándo…pero…hay una parte que nos está faltándo…como enviamos este comando? Fácil…solo debemos ver el comándo de transferencia…


Este comándo nos dice que debemos pasar la información así…

0x21 0x09 0 0

Seguido de la acción que queremos realizar…

Para poder utilizar este dispositivo en nuestro BeagleBone…debemos instalar algo primero…

pip install pysub

Esta librería nos permite conectárnos y más importánte, enviar comándos al dispositivo.

Como vamos a utilizar el lanza misilies y la camara, ambas al mismo tiempo…necesitamos un Hub USB con corriente externa…de otra manera, nunca va a funcionar…yo compré este de Amazon.

Así que…conectamos el Hub USB y conectamos la camara Web y el lanza misiles, conectamos el Hub al BeagleBone Black y luego conectamos el BeagleBone a nuestra laptop…

Utilicen Nano u otro editor de su preferencia y creen el archivo Thunder.py

Thunder.py
import cv2
import numpy as np
import usb.core

cam = cv2.VideoCapture(-1)
cam.set(3, 960)
cam.set(4,720)
s, img = cam.read()

dev = usb.core.find(idVendor=0x2123,idProduct=0x1010)
try:
            dev.detach_kernel_driver(0)
except Exception, e:
            pass

winName = "Thunder"
cv2.namedWindow(winName, cv2.CV_WINDOW_AUTOSIZE)
while s:
        s, img = cam.read()
        key = cv2.waitKey(10)
        if key == 27:
                cv.destroyWindow(winName)
                break
        hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
              lower_green = np.array([38, 100, 50])
              upper_green = np.array([75, 255, 255])

        mask = cv2.inRange(hsv, lower_green, upper_green)
        res = cv2.bitwise_and(img,img, mask=mask)
        cv2.imshow(winName, res)

        if cv2.countNonZero(mask) > 61000:
                dev.ctrl_transfer(0x21, 0x09, 0, 0,
                                  [0x02, 0x010, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])


Este código va a basicamente abrir la conexión de la camara, y mostrar un fondo negro para que solo el color que queremos sea mostrado. En este caso, queremos disparar el lanza misilies solamente cuando veamos algo “verde”. Como pueden ver estamos pasándo el comándo de transferecia como un parámetro simple pero el comando de fuego como un arreglo.

Ahora…el BeagleBone no tiene una pantalla…así que puedes agregar un monitor y un teclado o puedes hacer algo más interesánte y astuto…

Vamos a instalar el Tight VNC Server

sudo apt-get install tightvncserver

La primera vez que lo ejecutas, te va preguntar por un password para el usuario actual, así que proporcionale uno…

Y va a comenzar a ejecutarse…así que vamos a poder abrir una conexión de escritorio remoto para nuestro BeagleBone…ahora solo necesitamos un cliente para poder conectarnos...

Si estás utilizándo Windows puedes descargar el cleinte TightVNC de aquí…

http://www.tightvnc.com/download/2.7.10/tightvnc-2.7.10-setup-64bit.msi

http://www.tightvnc.com/download/2.7.10/tightvnc-2.7.10-setup-32bit.msi

Si estás utilizándo Linux simplemente puedes descargarlo utilizándo apt-get install así…

sudo apt-get install xtightvncviewer

Ejecútalo en el terminal...

Solo debes proporcionar el IP de tu BeagleBone que debería de ser 192.168.7.2:1 en la pequeña pantalla que va a aparecer, provee el password que creaste para el VNCServer en la pantalla siguiente y estaremos listos…




Si estás utilizándo Windows…simplemente haz doble click en el tightvnc-jviewer.jar e introduce la siguiente información…




Para poder probar esto, solo necesitamos imprimir una bonita caja verde…


Luego, podemos ejecutar la aplicación…


Y poner la caja verde en frente de la camara -;)


Disculpen por la foto media movida…pero el lanza misiles estaba disparándo y tenía mi celular en una mano y la hoja con la caja verde en la otra -;)

Saludos,

Blag.
Development Culture.