如何使用opencv python库从内存缓冲区(StringIO)或URL中读取图像

28

分享一种从内存缓冲区或URL创建OpenCV图像对象的方法,以提高性能。

有时我们从URL获取图像二进制数据,为了避免额外的文件IO,我们想从内存缓冲区或URL中imread读取该图像,但是imread只支持从文件系统路径读取图像。

2个回答

44

要使用内存缓冲区(StringIO)创建一个OpenCV图像对象,我们可以使用OpenCV API函数imdecode,参见以下代码:

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)

如果无法解码图像,则返回值为None。我不得不从字符串开头添加或删除“data:image/png;base64,这会阻止opencv进行解码。 - Charles L.
我看到了第二个类似的答案,但对我不起作用。我无法相信从URL加载图像到open-cv可能会出现这样的问题。 - CashCow
1
imread 给了我一个 TypeError: expected string or Unicode object, numpy.ndarray found 错误。 - bittterbotter

20

正如接受的答案评论中指出的那样,它已经过时且不再可用。

幸运的是,我最近使用Python 3.7和OpenCV 4.0解决了这个问题。

为了处理从URL或内存缓冲区加载图像,我定义了以下两个函数:

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)

正如您所看到的,一个函数依赖于另一个函数。

第一个函数get_opencv_img_from_buffer可用于从内存缓冲区获取图像对象。它假定缓冲区具有读取方法,并且返回实现缓冲区协议的对象实例。

第二个函数get_opencv_img_from_url直接从URL生成图像。

flags参数传递给cv2.imdecode,其中在cv2中预定义了以下常量:

  • cv2.IMREAD_ANYCOLOR - 如果设置,则以任何可能的颜色格式读取图像。
  • cv2.IMREAD_ANYDEPTH - 如果设置,则在输入具有相应深度时返回16位/32位图像,否则将其转换为8位。
  • cv2.IMREAD_COLOR - 如果设置,始终将图像转换为3通道BGR彩色图像。
  • cv2.IMREAD_GRAYSCALE - 如果设置,始终将图像转换为单通道灰度图像(编解码器内部转换)。
  • cv2.IMREAD_IGNORE_ORIENTATION - 如果设置,则不根据EXIF的方向标志旋转图像。
  • cv2.IMREAD_LOAD_GDAL - 如果设置,则使用gdal驱动程序加载图像。
  • cv2.IMREAD_REDUCED_COLOR_2 - 如果设置,始终将图像转换为3通道BGR彩色图像,并将图像大小减小1/2。
  • cv2.IMREAD_REDUCED_COLOR_4 - 如果设置,始终将图像转换为3通道BGR彩色图像,并将图像大小减小1/4。
  • cv2.IMREAD_REDUCED_COLOR_8 - 如果设置,始终将图像转换为3通道BGR彩色图像,并将图像大小减小1/8。
  • cv2.IMREAD_REDUCED_GRAYSCALE_2 - 如果设置,始终将图像转换为单通道灰度图像,并将图像大小减小1/2。
  • cv2.IMREAD_REDUCED_GRAYSCALE_4 - 如果设置,始终将图像转换为单通道灰度图像,并将图像大小减小1/4。
  • cv2.IMREAD_REDUCED_GRAYSCALE_8 - 如果设置,则始终将图像转换为单通道灰度图像,并将图像大小减小1/8。
  • cv2.IMREAD_UNCHANGED - 如果设置,则原样返回加载的图像(具有α通道,否则它会被裁剪)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接