fbpixel
Reconocimiento de textos con Python

Reconocimiento de textos con Python

En este tutorial veremos cómo reconocer texto de una imagen utilizando Python y Tesseract. Tesseract es una herramienta para reconocer caracteres, y por tanto texto, contenidos en una imagen (OCR, Optical Character Recognition).

Instalación de Tesseract

  • En Linux

Para instalar tesseract, introduzca los siguientes comandos en un terminal

sudo apt install tesseract-ocr
sudo apt install libtesseract-dev
  • Para Windows

puede descargar y ejecutar el instalador para su sistema operativo

Una vez finalizada la instalación, añada C:\Archivos de programa\Tesseract-OCR a su variable de entorno Path.

Ahora puede ejecutar tesseract y comprobar el resultado con el siguiente comando

tesseract <path_to_image> <path_to_result_file> -l <language>

ex:

tesseract prueba.png resultado -l fra

Tesseract reconocerá el texto contenido en la imagen test.png y escribirá el texto sin procesar en el archivo result.txt.

Nota: Tesseract puede tener dificultades con la puntuación y la alineación del texto.

Reconocimiento de textos con Pytesseract

A continuación, puede instalar el paquete pytesseract

pip install pytesseract

La ventaja de utilizar Python, y OpenCV en particular, es que puedes procesar imágenes e implementar la herramienta en paquetes de software más grandes. He aquí una lista de algunas de las ventajas:

  • detección de texto en un vídeo
  • Tratamiento y filtrado de imágenes para caracteres obstruidos, por ejemplo
  • Detectar texto de un archivo PDF
  • Escribir los resultados en un archivo Word o Excel

En el siguiente script, cargamos la imagen con OpenCV y dibujamos rectángulos alrededor del texto detectado. Los datos de posición se obtienen utilizando la función image_to_data. El texto en bruto se obtiene utilizando la función image_to_string

from PIL import Image
import pytesseract
from pytesseract import Output
import cv2
 
source = 'test.png'
img = cv2.imread(source)
text=pytesseract.image_to_string(img)
print(text)

d = pytesseract.image_to_data(img, output_type=Output.DICT)
 
NbBox = len(d['level'])
print ("Number of boxes: {}".format(NbBox))

for i in range(NbBox):
	(x, y, w, h) = (d['left'][i], d['top'][i], d['width'][i], d['height'][i])
	# display rectangle
	cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
 
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

El script también funciona con fotos de documentos

Bonus: Reconocimiento de textos con Python à partir d’un fichier PDF

Instalación de la biblioteca pdf2image

pip install pdf2image

pdf2image requiere la instalación de poppler

Bastante sencillo en Linux

sudo apt-get install poppler-utils

Para Windows

  • Descargar el archivo zip
  • Extraiga los archivos donde desee (C:
  • Añade la carpeta bin a la variable de entorno Path (C:³³Users³ADMIN³Documents³poppler³Library³bin)
  • prueba con el comando pdftoppm -h

Script para recuperar texto de un PDF

from pdf2image import convert_from_path, convert_from_bytes
from PIL import Image
import pytesseract
from pytesseract import Output

images = convert_from_path('invoice.pdf')

# get text
print("Number of pages: {}".format(len(images)))
for i,img in enumerate(images):
    print ("Page N°{}\n".format(i+1))
    print(pytesseract.image_to_string(img))

Script para mostrar rectángulos en un PDF

from pdf2image import convert_from_path, convert_from_bytes
from PIL import Image
import pytesseract
from pytesseract import Output
import cv2
import numpy

images = convert_from_path('invoice.pdf')
for i,source in enumerate(images):
	print ("Page N°{}\n".format(i+1))
	
	#convert PIL to opencv
	pil_image = source.convert('RGB') 
	open_cv_image = numpy.array(pil_image) 
	# Convert RGB to BGR 
	img = open_cv_image[:, :, ::-1].copy() 
	#img = cv2.imread(source)

	d = pytesseract.image_to_data(img, output_type=Output.DICT)
	 
	NbBox = len(d['level'])
	print ("Number of boxes: {}".format(NbBox))

	for j in range(NbBox):
		(x, y, w, h) = (d['left'][j], d['top'][j], d['width'][j], d['height'][j])
		# display rectangle
		cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
	 
	cv2.imshow('img', img)
	cv2.waitKey(0)
	cv2.destroyAllWindows()

Aplicaciones

  • Lectura de documentos escaneados
  • Reconocimiento de texto en tiempo real a partir de vídeo

Fuentes

Visualización de una imagen OpenCV en una interfaz PyQt

Visualización de una imagen OpenCV en una interfaz PyQt

Para ciertas aplicaciones, puede resultarte útil incrustar OpenCV en una interfaz PyQt. En este tutorial, veremos cómo integrar y gestionar correctamente un vídeo capturado por OpenCV en una aplicación PyQt.

N.B.: Utilizamos Pyside, pero la conversión a PyQt es bastante sencilla.

Requisitos previos:

  • Instalación de Python
  • Instalación de OpenCV (pip install opencv-python)
  • PySide o PyQt (pip install pyside6 o pip install PyQt5)

Código para capturar un vídeo con OpenCV

Este es el código básico para visualizar un vídeo de webcam con openCV

import sys
import cv2

def main(args):

	cap = cv2.VideoCapture(0) #default camera

	while(True):
		ret, frame = cap.read()
		if ret:
			frame=cv2.resize(frame, (800, 600)) 
			cv2.imshow("Video",frame)
			
		if cv2.waitKey(1) &amp; 0xFF == ord('q'): #click q to stop capturing
			break

	cap.release()
	cv2.destroyAllWindows()
	return 0

if __name__ == '__main__':
    
    sys.exit(main(sys.argv))

Para integrarlo en una aplicación PyQt, crearemos un objeto QThread que se encargará de reproducir el vídeo sin bloquear la aplicación.

  • La función run es la función que contiene el código openCV que se ejecutará en un bucle cuando se llame a la función QThread.start.
  •  La función stop se utiliza para detener limpiamente el hilo
  • La señal changePixmap se utiliza para indicar a la aplicación que hay una nueva imagen disponible
class Thread(QThread):
	changePixmap = pyqtSignal(QImage)

	def run(self):
		self.isRunning=True
		cap = cv2.VideoCapture(0)
		while self.isRunning:
			ret, frame = cap.read()
			if ret:
				rgbImage = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
				h, w, ch = rgbImage.shape
				bytesPerLine = ch * w
				convertToQtFormat = QImage(rgbImage.data, w, h, bytesPerLine, QImage.Format_RGB888)
				p = convertToQtFormat.scaled(640, 480, Qt.KeepAspectRatio)
				self.changePixmap.emit(p)
				
	def stop(self):
		self.isRunning=False
		self.quit()
		self.terminate()

Creación de la aplicación PyQt

Para la aplicación, crearemos una QLabel en un simple QWidget que contendrá la imagen de video e instanciaremos el QThread. El video se actualizará automáticamente usando la función setImage, que es llamada cuando se recibe la señal changePixmap.

  • Función setImage
	@pyqtSlot(QImage)
	def setImage(self, image):
		#update image	
		self.label.setPixmap(QPixmap.fromImage(image))
  • señal changePixmap
		self.th.changePixmap.connect(self.setImage)
class VideoContainer(QWidget):
	def __init__(self):
		super().__init__()
		self.title = 'PySide Video'
		self.left = 100
		self.top = 100
		self.fwidth = 640
		self.fheight = 480
		self.initUI()

	@pyqtSlot(QImage)
	def setImage(self, image):
		#update image	
		self.label.setPixmap(QPixmap.fromImage(image)) 
	
	def initUI(self):
		self.setWindowTitle(self.title)
		self.setGeometry(self.left, self.top, self.fwidth, self.fheight)
		self.resize(1200, 800)
		
		# create a label
		self.label = QLabel(self)		
		self.label.resize(640, 480)
		self.th = Thread(self)
		self.th.changePixmap.connect(self.setImage)
		self.th.start()
		self.show()

Código completo para mostrar un vídeo en una ventana PyQt

import cv2
import sys
#from PyQt5.QtWidgets import  QWidget, QLabel, QApplication
#from PyQt5.QtCore import QThread, Qt, pyqtSignal, pyqtSlot
#from PyQt5.QtGui import QImage, QPixmap

from PySide6.QtWidgets import  QWidget, QLabel, QApplication
from PySide6.QtCore import QThread, Qt, Signal, Slot
from PySide6.QtGui import QImage, QPixmap
pyqtSignal = Signal
pyqtSlot = Slot

class Thread(QThread):
	changePixmap = pyqtSignal(QImage)

	def run(self):
		self.isRunning=True
		cap = cv2.VideoCapture(0)
		while self.isRunning:
			ret, frame = cap.read()
			if ret:
				# https://stackoverflow.com/a/55468544/6622587
				rgbImage = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
				h, w, ch = rgbImage.shape
				bytesPerLine = ch * w
				convertToQtFormat = QImage(rgbImage.data, w, h, bytesPerLine, QImage.Format_RGB888)
				p = convertToQtFormat.scaled(640, 480, Qt.KeepAspectRatio)
				self.changePixmap.emit(p)
				
	def stop(self):
		self.isRunning=False
		self.quit()
		self.terminate()

class VideoContainer(QWidget):
	def __init__(self):
		super().__init__()
		self.title = 'Video'
		self.left = 100
		self.top = 100
		self.fwidth = 640
		self.fheight = 480
		self.initUI()

	@pyqtSlot(QImage)
	def setImage(self, image):
		#update image	
		self.label.setPixmap(QPixmap.fromImage(image)) 
	
	def initUI(self):
		self.setWindowTitle(self.title)
		self.setGeometry(self.left, self.top, self.fwidth, self.fheight)
		self.resize(1200, 800)
		
		# create a label
		self.label = QLabel(self)		
		self.label.resize(640, 480)
		self.th = Thread(self)
		self.th.changePixmap.connect(self.setImage)
		self.th.start()
		self.show()

if __name__ == '__main__':
	
		app = QApplication(sys.argv)
		ex = VideoContainer()
		sys.exit(app.exec())

Aparece una ventana “Vídeo” con la imagen de la webcam.

Puedes adaptar este sencillo código para integrar un vídeo en una interfaz gráfica que te permita modificar las opciones del vídeo o trabajar con filtros, por ejemplo.

Bonificación: interfaz de cierre mejorada

El código funciona bien y puede ser suficiente, pero hay algunos problemas con esta implementación:

  • La aplicación no se puede cerrar con Ctrl+C (KeyboardInterrupt)
  • Al cerrar la ventana, el Qthread no se detiene
  • Si cambia el tamaño de la ventana, el tamaño del vídeo no cambia

Para cerrar la aplicación con Ctrl+C, puedes utilizar la señal de interrupción añadiendo el siguiente código antes de llamar a la aplicación (existen métodos más limpios)

import signal #close signal with Ctrl+C
signal.signal(signal.SIGINT, signal.SIG_DFL)

Para finalizar el QThread cuando se cierra la ventana, puede utilizar la señal aboutToQuit de la aplicación para llamar a la función stop del QThread

app.aboutToQuit.connect(ex.th.stop) #stop qthread when closing window

Por último, para redimensionar el vídeo con la ventana cada vez que se actualiza, utilizamos el tamaño de la ventana para calcular el tamaño de la imagen y la posición de la etiqueta, de modo que quede centrada y el vídeo conserve sus proporciones.

	@pyqtSlot(QImage)
	def setImage(self, image):
		#resize image with window and center
		imWidth=self.width()-2*self.padding
		imHeight=self.height()-2*self.padding
		image = image.scaled(imWidth, imHeight, Qt.KeepAspectRatio) # remove Qt.KeepAspectRatio if not needed
		self.label.resize(image.width(), image.height()) #(640, 480)
		self.label.move((self.width()-image.width())/2, (self.height()-image.height())/2)
			
		#update image	
		self.label.setPixmap(QPixmap.fromImage(image)) 

Aquí está el código completo con las mejoras

import cv2
import sys
#from PyQt5.QtWidgets import  QWidget, QLabel, QApplication
#from PyQt5.QtCore import QThread, Qt, pyqtSignal, pyqtSlot
#from PyQt5.QtGui import QImage, QPixmap

from PySide6.QtWidgets import  QWidget, QLabel, QApplication
from PySide6.QtCore import QThread, Qt, Signal, Slot
from PySide6.QtGui import QImage, QPixmap
pyqtSignal = Signal
pyqtSlot = Slot

class Thread(QThread):
	changePixmap = pyqtSignal(QImage)

	def run(self):
		self.isRunning=True
		cap = cv2.VideoCapture(0)
		while self.isRunning:
			ret, frame = cap.read()
			if ret:
				# https://stackoverflow.com/a/55468544/6622587
				rgbImage = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
				h, w, ch = rgbImage.shape
				bytesPerLine = ch * w
				convertToQtFormat = QImage(rgbImage.data, w, h, bytesPerLine, QImage.Format_RGB888)
				p = convertToQtFormat.scaled(640, 480, Qt.KeepAspectRatio)
				self.changePixmap.emit(p)
				
	def stop(self):
		self.isRunning=False
		self.quit()
		self.terminate()

class VideoContainer(QWidget):
	def __init__(self):
		super().__init__()
		self.title = 'PySide Video'
		self.left = 100
		self.top = 100
		self.fwidth = 640
		self.fheight = 480
		self.padding = 10
		self.initUI()

	@pyqtSlot(QImage)
	def setImage(self, image):
		#resize image with window and center
		imWidth=self.width()-2*self.padding
		imHeight=self.height()-2*self.padding
		image = image.scaled(imWidth, imHeight, Qt.KeepAspectRatio) # remove Qt.KeepAspectRatio if not needed
		self.label.resize(image.width(), image.height()) #(640, 480)
		self.label.move((self.width()-image.width())/2, (self.height()-image.height())/2)
			
		#update image	
		self.label.setPixmap(QPixmap.fromImage(image)) 
		
	def initUI(self):
		self.setWindowTitle(self.title)
		self.setGeometry(self.left, self.top, self.fwidth, self.fheight)
		self.resize(1200, 800)
		
		# create a label
		self.label = QLabel(self)		
		self.label.resize(self.width()-2*self.padding,self.height()-2*self.padding) #(640, 480)
		self.th = Thread(self)
		self.th.changePixmap.connect(self.setImage)
		self.th.start()
		self.show()

import signal #close signal with Ctrl+C
signal.signal(signal.SIGINT, signal.SIG_DFL)

if __name__ == '__main__':
	
		app = QApplication(sys.argv)
		ex = VideoContainer()
		app.aboutToQuit.connect(ex.th.stop) #stop qthread when closing window
		
		sys.exit(app.exec())

Fuentes

Reconocimiento de formas y colores con Python

Reconocimiento de formas y colores con Python

,

La biblioteca OpenCV se utiliza para el procesamiento de imágenes, en particular el reconocimiento de formas y colores. La biblioteca tiene funciones de adquisición y algoritmos de procesamiento de imágenes que hacen que el reconocimiento de imágenes sea bastante sencillo sin necesidad de inteligencia artificial. Eso es lo que veremos en este tutorial.

Este tutorial se puede aplicar a cualquier ordenador con una instalación de Python con OpenCV y una Cámara. En particular la Raspberry Pi.

Hardware

  • Ordenador con una instalación de python3

Preparar el entorno de trabajo

Para crear el script de reconocimiento de formas, instalamos los módulos OpenCV, numpy e imutils para manipular y procesar las imágenes.

pip3 install opencv-python numpy imutils

La detección de colores se realiza mediante los módulos webcolors y scipy (KDTree)

pip3 install webcolors scipy

Para probar y validar el algoritmo, creamos una imagen que contiene objetos de diferentes formas y colores. Puedes crear tu propia imagen con Paint o utilizar ésta:

Principio de funcionamiento

En el siguiente código, vamos a crear una clase de detección de formas que nos permitirá seleccionar una forma basada en el número de contornos encontrados. A continuación, vamos a definir una función para encontrar el nombre del color basado en su código RGB. Por último, vamos a utilizar OpenCV para cargar, filtrar y enmascarar la imagen con el fin de detectar las formas y los colores contenidos en la imagen.

Código completo para el reconocimiento sencillo de formas y colores

Es necesario crear el archivo python ObjectDetection.py en la misma carpeta que la imagen que se desea analizar.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# import the necessary packages
import cv2
import numpy as np
import imutils

#colors
from webcolors import rgb_to_name,CSS3_HEX_TO_NAMES,hex_to_rgb #python3 -m pip install webcolors
from scipy.spatial import KDTree

def convert_rgb_to_names(rgb_tuple):
    # a dictionary of all the hex and their respective names in css3
    css3_db = CSS3_HEX_TO_NAMES#css3_hex_to_names
    names = []
    rgb_values = []    
    for color_hex, color_name in css3_db.items():
        names.append(color_name)
        rgb_values.append(hex_to_rgb(color_hex))
    
    kdt_db = KDTree(rgb_values)    
    distance, index = kdt_db.query(rgb_tuple)
    return names[index]
    
class ShapeDetector:
	def __init__(self):
		pass
	def detect(self, c):
		# initialize the shape name and approximate the contour
		shape = "unidentified"
		peri = cv2.arcLength(c, True)
		approx = cv2.approxPolyDP(c, 0.04 * peri, True)

		# if the shape is a triangle, it will have 3 vertices
		if len(approx) == 3:
			shape = "triangle"
		# if the shape has 4 vertices, it is either a square or
		# a rectangle
		elif len(approx) == 4:
			# compute the bounding box of the contour and use the
			# bounding box to compute the aspect ratio
			(x, y, w, h) = cv2.boundingRect(approx)
			ar = w / float(h)
			# a square will have an aspect ratio that is approximately
			# equal to one, otherwise, the shape is a rectangle
			shape = "square" if ar &gt;= 0.95 and ar &lt;= 1.05 else "rectangle"
		# if the shape is a pentagon, it will have 5 vertices
		elif len(approx) == 5:
			shape = "pentagon"
		elif len(approx) == 6:
			shape = "hexagon"
		elif len(approx) == 10 or len(approx) == 12:
			shape = "star"
		# otherwise, we assume the shape is a circle
		else:
			shape = "circle"
		# return the name of the shape
		return shape	

if __name__ == '__main__':
	# load the image and resize it to a smaller factor so that
	# the shapes can be approximated better
	image = cv2.imread('python_shapes_detection_base.PNG')
	resized = imutils.resize(image, width=300)
	ratio = image.shape[0] / float(resized.shape[0])
	
	# convert the resized image to grayscale, blur it slightly,
	# and threshold it
	gray = cv2.cvtColor(resized, cv2.COLOR_BGR2GRAY)
	blurred = cv2.GaussianBlur(gray, (5, 5), 0)
	thresh = cv2.threshold(blurred, 60, 255, cv2.THRESH_BINARY)[1]
	
	# find contours in the thresholded image and initialize the
	# shape detector
	cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
		cv2.CHAIN_APPROX_SIMPLE)
	cnts = imutils.grab_contours(cnts)
	sd = ShapeDetector()

	# loop over the contours
	for c in cnts:
		# compute the center of the contour
		M = cv2.moments(c)
		cX = int((M["m10"] / M["m00"]) * ratio)
		cY = int((M["m01"] / M["m00"]) * ratio)  
		
		#detect shape from contour
		shape = sd.detect(c)
		
		# resize the contour
		c = c.astype("float")
		c *= ratio
		c = c.astype("int")
		cv2.drawContours(image, [c], -1, (0, 255, 0), 2)
		
		#draw contour with mask
		mask = np.zeros(image.shape[:2], np.uint8)
		cv2.drawContours(mask, [c], -1, 255, -1)
		img = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
		
		#Convert to RGB and get color name
		imgRGB = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
		mean=cv2.mean(imgRGB, mask=mask)[:3]
		named_color = convert_rgb_to_names(mean)
		
		#get complementary color for text
		mean2 = (255-mean[0],255-mean[1],255-mean[2])
		
		#display shape name and color
		objLbl=shape+" {}".format(named_color)
		textSize = cv2.getTextSize(objLbl,cv2.FONT_HERSHEY_SIMPLEX,0.5,2)[0]
		cv2.putText(image, objLbl, (int(cX-textSize[0]/2),int(cY+textSize[1]/2)), cv2.FONT_HERSHEY_SIMPLEX,0.5,mean2, 2)
		
		#show image
		cv2.imshow("Image", image)
		#cv2.waitKey(0)
	cv2.waitKey(0)		

Resultados

Para ejecutar el script, puede ejecutarlo desde su editor de código (como Geany) o ejecutar el siguiente comando en un terminal de comandos abierto en su carpeta de trabajo.python3 ObjectDetection.py

Una vez ejecutado el código, se mostrará la imagen con cada una de las formas rodeadas de verde y un texto en el centro de la forma que contiene el nombre y el color de la forma.

N.B.: Este algoritmo no funcionará para todas las formas. Para detectar otras formas debe adaptar la función detect de la clase ShapeDetector para identificar todos los casos posibles o utilizar inteligencia artificial.

Aplicaciones

Fuentes

Crear un banco de imágenes con Python

Crear un banco de imágenes con Python

, ,

Para entrenar una red neuronal en detección y reconocimiento de objetos, se necesita un banco de imágenes con el que trabajar. Veremos cómo descargar un gran número de imágenes de Google utilizando Python. Para entrenar una red neuronal, necesitas una gran cantidad de datos. Cuantos más datos, mejor será el entrenamiento. En nuestro caso, queremos entrenar una red neuronal para que reconozca un objeto concreto. Para ello, creamos un script en Python que descargará los archivos de Internet y los colocará en una carpeta.

Configuración de Python3

Descargar las bibliotecas Selenium y OpenCV (opcional)

python3 -m pip install selenium
python3 -m pip install opencv-python

descargar archivo geckodriver

N.B.: Sólo utilizamos la librería OpenCV para comprobar que OpenCV puede abrir y utilizar las imágenes, para no saturar innecesariamente la carpeta.

Script en Python para descargar imágenes

Este script lanza una búsqueda en Google Image y guarda las imágenes encontradas en la carpeta especificada para el banco de imágenes.

N.B.: No olvide especificar la ruta al archivo GECKOPATH de geckodriver, la ruta a la carpeta de destino y las palabras clave para la búsqueda en Google.

import sys
import os
import time 

#Imports Packages
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.common.exceptions import TimeoutException,WebDriverException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

import cv2

########################################################################
GECKOPATH = "PATH-TO-GECKODRIVER"
parent_dir = "PATH-TO-FOLDER"
search='coffee mug'
########################################################################

# path 
folderName=search.replace(" ","_")
directory = os.path.join(parent_dir, folderName,'img') 
   
# Create the directory 
try: 
	if not os.path.exists(directory):
		os.makedirs(directory) #os.mkdir(directory)
except OSError as error: 
	print("ERROR : {}".format(error)) 


sys.path.append(GECKOPATH)  
#Opens up web driver and goes to Google Images
browser = webdriver.Firefox()#Firefox(firefox_binary=binary)

#load google image
browser.get('https://www.google.ca/imghp?hl=en')

delay = 10 # seconds
try:
	btnId="L2AGLb"
	myElem = WebDriverWait(browser, delay).until(EC.presence_of_element_located((By.ID , btnId))) #id info-address-place-wrapper 
	elm=browser.find_element_by_id(btnId)
	elm.click()
	print("Popup is passed!")
except TimeoutException as e:
	print("Loading took too much time!")



# get and fill search bar
box = browser.find_element_by_xpath('//*[@id="sbtc"]/div/div[2]/input')
box.send_keys(search)
box.send_keys(Keys.ENTER)


#Will keep scrolling down the webpage until it cannot scroll no more
last_height = browser.execute_script('return document.body.scrollHeight')
while True:
	browser.execute_script('window.scrollTo(0,document.body.scrollHeight)')
	time.sleep(5)
	new_height = browser.execute_script('return document.body.scrollHeight')
	try:
		browser.find_element_by_xpath('//*[@id="islmp"]/div/div/div/div/div[5]/input').click()
		time.sleep(5)
	except:
		print("button not found")
		pass
		
	if new_height == last_height:
		break
	last_height = new_height
	
imgList=[]
for i in range(1, 1000):
	try:
		browser.find_element_by_xpath('//*[@id="islrg"]/div[1]/div['+str(i)+']/a[1]/div[1]/img').screenshot(directory+'\{}.png'.format(i))
		imgList.add(directory+'\{}.png'.format(i))
		
	except:
		pass
browser.quit()
 
#Test images with OpenCV
for img in imgList:
	try:   
		cv2.imread(img)
	except Exception as e:
		os.remove(img)
		print("remove {}".format(img))

BONUS: Gestión de una ventana emergente

En el código he añadido un comando para gestionar la ventana emergente que aparece al abrir la página web. Esperará a que se cargue el botón con el identificador correcto para pulsarlo.

delay = 10 # seconds
try:
	btnId="L2AGLb"
	myElem = WebDriverWait(browser, delay).until(EC.presence_of_element_located((By.ID , btnId))) #id info-address-place-wrapper 
	elm=browser.find_element_by_id(btnId)
	elm.click()
	print("Popup is passed!")
except TimeoutException as e:
	print("Loading took too much time!")

Resultados

El script recorrerá los resultados de Google y tomará capturas de pantalla de cada imagen para colocarlas en nuestra base de datos y formar un banco de imágenes.

Aplicaciones

  • Desarrollar algoritmos de tratamiento de imágenes
  • Entrenamiento de redes neuronales para la detección y el reconocimiento de objetos

Fuentes

Detección de una línea con Python y OpenCV

Detección de una línea con Python y OpenCV

Una aplicación interesante en robótica es el reconocimiento de patrones. En este tutorial vamos a utilizar la librería OpenCV en un código Python que nos permitirá detectar el centro de un cable. Para lograr este seguimiento de la línea haremos un poco de procesamiento de imágenes con OpenCV.

¡Esto le permitirá entonces hacer su regulación para mantener siempre el centro del cable en el centro de la cámara y así seguir la trayectoria! Decidimos hacer este tutorial en Raspberry Pi ya que este tutorial es sobre el procesamiento de imágenes para un robot utilizando la cámara Pi.

Material

Configuración

Código

Para empezar, para poder reutilizar la detección de una línea o un cable en un vídeo (sucesión de imágenes), implementaremos una Clase. Esta clase tomará como parámetro la ruta de la imagen. Por defecto, si la imagen está en la misma carpeta que el código, bastará con poner el nombre de la imagen, por ejemplo: “cam.jpg”).

A continuación, guarde el código python siguiente en un archivo llamado: suivi_ligne.py

# -*- coding: utf-8 -*-
"""
@author: AranaCorp
"""
import cv2
import time
import numpy as np
import matplotlib.pyplot as plt


class LineTracking():
	"""
	Classe permettant le traitement d'image, la délimitation d'un contour et permet de trouver le centre de la
	forme detectée
	"""
	def __init__(self,img_file):
		"""The constructor."""
		self.img = cv2.imread(img_file)
		self.img_inter = self.img
		self.img_final = self.img
		self.cendroids = []
		self.mean_centroids = [0,0]

	def processing(self):
		"""Méthode permettant le traitement d'image"""
		#self.img=cv2.resize(self.img,(int(self.img.shape[1]*0.2),int(self.img.shape[0]*0.2))) #redimensionner l'image d'origine
		print(self.img.shape)
		#self.img = self.img[199:391, 149:505] #on recentre l'image en excluant les zones extérieures afin d'avoir une plus grande précision pour la suite
		gray = cv2.cvtColor(self.img, cv2.COLOR_BGR2GRAY) #on passe l'image en nuances de gris
		blur = cv2.GaussianBlur(gray,(5,5),0) #on floute l'image
		ret,thresh = cv2.threshold(blur,60,255,cv2.THRESH_BINARY_INV) #on binarise l'image

		self.img_inter=thresh
		"""Une ouverture permet d'enlever tous les élements qui sont plus petits que l'élement structurant (ou motif)
		Une fermeture permet de "combler" les trous qui ont une taille inférieur à l'élement structurant """
		kernel_open = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5)) #on créé l'élement structurant de l'ouverture
		kernel_close = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(10,10)) #on créé l'élement structurant de la fermeture

		thresh = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel_open) #on fait une ouverture suivant un motif
		thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel_close) #on fait une fermeturesuivant un motif

		connectivity = 8

		output = cv2.connectedComponentsWithStats(thresh, connectivity, cv2.CV_32S) #permet de délimiter une forme
		num_labels = output[0]
		labels = output[1]
		stats = output[2]
		self.centroids = output[3] #donne les centres de la ou des formes de l'image

		for c in self.centroids :
			"""Permet de faire la moyenne des centres de la forme, en effet sur l'image test,
			   il y a deux centres qui sont très proches et la moyenne de deux convient.
			   On pourra imaginer que dans un cas général on modifie cela
			"""
			self.mean_centroids[0] += c[0]/len(self.centroids)
			self.mean_centroids[1] += c[1]/len(self.centroids)

		self.img_final = cv2.cvtColor(thresh, cv2.COLOR_GRAY2BGR)

		#permet de rajouter un carré rouge à l'endroit du centre de la forme
		#self.img_final[int(self.mean_centroids[1])-10 : int(self.mean_centroids[1])+20, int(self.mean_centroids[0])-10 : int(self.mean_centroids[0])+20] = [0,0,255]
		for c in self.centroids :
			self.img_final[int(c[1])-5 : int(c[1])+10, int(c[0])-5 : int(c[0])+10] = [0,255,0]

Por último, cree un nuevo script python, por ejemplo: test_tracking.py

if __name__ == '__main__' :
	test = LineTracking('cam.png') #créer un objet LineTracking qui est la Classe créée au dessus .png ou .jpg
	test.processing() #lance le traitement d'image
	while True :
		cv2.imshow('image',test.img) #affiche l'image original après redimensionnement
		#cv2.imshow('process',test.img_inter ) #affiche l'image après traitement
		cv2.imshow('cable',test.img_final) #affiche l'image après traitement
		key= cv2.waitKey(1);
		if  key == ord(' '): #pour fermer les fenêtres appuyer sur la barre 'espace'
			break
	cv2.destroyAllWindows()

Ahora tiene todos los códigos para probar el procesamiento de imágenes. Ejecute el comando :

python3 test_tracking.py

Resultado

Se abren dos ventanas con la imagen original y la imagen procesada. Puedes ver que un cuadrado verde marca la posición del cable. Este punto puede utilizarse para dirigir un robot o una cámara móvil.

Para detener la visualización, pulse la barra espaciadora.

Para terminar, el tratamiento se acaba de hacer sobre una imagen. Ahora puedes implementarlo en un bucle de procesamiento para un vídeo.

Aplicaciones

Ahora puedes usar la clase LineTracking en tu archivo principal que abre la cámara de la Raspberry. Para más información sobre cómo instalar una PiCam en una Raspberry Pi puedes seguir nuestro tutorial

Fuentes