Cómo leer la imagen desde el búfer de memoria(StringIO) o desde url con la biblioteca opencv python
numpy urllib2 (2)
Como se señaló en los comentarios a la respuesta aceptada, está desactualizada y ya no funciona.
Por suerte, tuve que resolver este problema usando Python 3.7 con OpenCV 4.0 recientemente.
Para manejar la carga de imágenes desde una URL o un búfer en memoria, definí las siguientes dos funciones:
import urllib.request
import cv2
import numpy as np
def get_opencv_img_from_buffer(buffer, flags):
bytes_as_np_array = np.frombuffer(buffer.read(), dtype=np.uint8)
return cv2.imdecode(bytes_as_np_array, flags)
def get_opencv_img_from_url(url, flags):
req = urllib.request.Request(url)
return get_opencv_img_from_buffer(urllib.request.urlopen(req), flags)
Como puedes ver una depende de la otra.
El primero, get_opencv_img_from_buffer, se puede usar para obtener un objeto de imagen de un búfer en memoria. Se supone que el búfer tiene un método de lectura y que devuelve una instancia de un objeto que implementa el protocolo del búfer
El segundo, get_opencv_img_from_url, genera una imagen directamente desde una URL.
El argumento flags se pasa a cv2.imdecode, que tiene las siguientes constantes predefinidas en cv2:
- cv2.IMREAD_ANYCOLOR - Si se establece, la imagen se lee en cualquier formato de color posible.
- cv2.IMREAD_ANYDEPTH: si se establece, devuelve una imagen de 16 bits / 32 bits cuando la entrada tiene la profundidad correspondiente; de lo contrario, conviértala a 8 bits.
- cv2.IMREAD_COLOR - Si está configurado, siempre convierta la imagen a la imagen de color BGR de 3 canales.
- cv2.IMREAD_GRAYSCALE - Si está configurado, siempre convierta la imagen a la imagen en escala de grises de un solo canal (conversión interna del códec).
- cv2.IMREAD_IGNORE_ORIENTATION - Si está configurado, no gire la imagen de acuerdo con la bandera de orientación de EXIF.
- cv2.IMREAD_LOAD_GDAL: si está configurado, use el controlador gdal para cargar la imagen.
- cv2.IMREAD_REDUCED_COLOR_2 - Si está configurado, siempre convierta la imagen a la imagen de color BGR de 3 canales y el tamaño de la imagen se redujo 1/2.
- cv2.IMREAD_REDUCED_COLOR_4 - Si está configurado, siempre convierta la imagen a la imagen de color BGR de 3 canales y el tamaño de la imagen se redujo 1/4.
- cv2.IMREAD_REDUCED_COLOR_8 - Si está configurado, siempre convierta la imagen a la imagen de color BGR de 3 canales y el tamaño de la imagen se redujo 1/8.
- cv2.IMREAD_REDUCED_GRAYSCALE_2 - Si está configurado, siempre convierta la imagen a la imagen en escala de grises de un solo canal y el tamaño de la imagen se redujo 1/2.
- cv2.IMREAD_REDUCED_GRAYSCALE_4 - Si está configurado, siempre convierta la imagen a la imagen en escala de grises de un solo canal y el tamaño de la imagen se redujo 1/4.
- cv2.IMREAD_REDUCED_GRAYSCALE_8 - Si está configurado, siempre convierta la imagen a la imagen en escala de grises de un solo canal y el tamaño de la imagen se redujo 1/8.
- cv2.IMREAD_UNCHANGED - Si se establece, devuelve la imagen cargada tal como está (con el canal alfa, de lo contrario, se recorta).
Simplemente comparta una forma de crear un objeto de imagen opencv desde el búfer de memoria o desde la url para mejorar el rendimiento.
A veces obtenemos imágenes binarias de url, para evitar la E / S de archivos adicionales, queremos analizar esta imagen desde el búfer de memoria o desde url, pero imread solo admite la lectura de imágenes del sistema de archivos con ruta.
Para crear un objeto de imagen OpenCV con un búfer de memoria (StringIO), podemos usar el código de la API de OpenCV, vea el código a continuación:
import cv2
import numpy as np
from urllib2 import urlopen
from cStringIO import StringIO
def create_opencv_image_from_stringio(img_stream, cv2_img_flag=0):
img_stream.seek(0)
img_array = np.asarray(bytearray(img_stream.read()), dtype=np.uint8)
return cv2.imdecode(img_array, cv2_img_flag)
def create_opencv_image_from_url(url, cv2_img_flag=0):
request = urlopen(url)
img_array = np.asarray(bytearray(request.read()), dtype=np.uint8)
return cv2.imdecode(img_array, cv2_img_flag)