我正在尝试像 PHP 函数一样从字符串加载图像
imagecreatefromstring
我怎样才能做到这一点?
我有 MySQL blob 字段图像。我正在使用 MySQLdb 并且不想创建临时文件来处理 PyOpenCV 中的图像。
注意:需要 cv(不是 cv2)包装函数
这是我通常用来将数据库中存储的图像转换为 Python 中的 OpenCV 图像的方法。
import numpy as np
import cv2
from cv2 import cv
# Load image as string from file/database
fd = open('foo.jpg','rb')
img_str = fd.read()
fd.close()
# CV2
nparr = np.fromstring(img_str, np.uint8)
img_np = cv2.imdecode(nparr, cv2.CV_LOAD_IMAGE_COLOR) # cv2.IMREAD_COLOR in OpenCV 3.1
# CV
img_ipl = cv.CreateImageHeader((img_np.shape[1], img_np.shape[0]), cv.IPL_DEPTH_8U, 3)
cv.SetData(img_ipl, img_np.tostring(), img_np.dtype.itemsize * 3 * img_np.shape[1])
# check types
print type(img_str)
print type(img_np)
print type(img_ipl)
我添加了从
numpy.ndarray
到 cv2.cv.iplimage
的转换,因此上面的脚本将打印:
<type 'str'>
<type 'numpy.ndarray'>
<type 'cv2.cv.iplimage'>
编辑: 从最新的 numpy
1.18.5 +
开始,np.fromstring
发出警告,因此应在该位置使用 np.frombuffer
。
我认为 this stackoverflow 问题上提供的 this 答案是这个问题的更好答案。
引用详细信息(从上面链接的答案中借用@lamhoangtung)
import base64
import json
import cv2
import numpy as np
response = json.loads(open('./0.json', 'r').read())
string = response['img']
jpg_original = base64.b64decode(string)
jpg_as_np = np.frombuffer(jpg_original, dtype=np.uint8)
img = cv2.imdecode(jpg_as_np, flags=1)
cv2.imwrite('./0.jpg', img)
我尝试使用此代码从包含原始缓冲区(纯像素数据)的字符串创建 opencv,但在这种特殊情况下它不起作用。
对于此类数据,以下是如何做到这一点:
image = np.fromstring(im_str, np.uint8).reshape( h, w, nb_planes )
(但是,你需要知道你的图像属性)
如果您的 B 和 G 通道已排列,修复方法如下:
image = cv2.cvtColor(image, cv2.cv.CV_BGR2RGB)
我正在遵循@jabaldonedo 的解决方案,但它似乎有点旧,需要一些调整。
顺便说一句,我正在使用 OpenCV 3.4.8.29。
im_path = 'path/to/foo.jpg'
with open(im_path, 'rb') as fp:
im_b = fp.read()
image_np = np.frombuffer(im_b, np.uint8)
img_np = cv2.imdecode(image_np, cv2.IMREAD_COLOR)
im_cv = cv2.imread(im_path)
print('Same image: {}'.format(np.all(im_cv == img_np)))
同一张图片:真实
imdecode的一个陷阱:
如果缓冲区太短或包含无效数据,函数返回[None]
这感觉与 OpenCV 不同寻常地宽松。这是一个可以满足此目的的函数:
import numpy as np
import cv2 as cv
def read_image(content: bytes) -> np.ndarray:
"""
Image bytes to OpenCV image
:param content: Image bytes
:returns OpenCV image
:raises TypeError: If content is not bytes
:raises ValueError: If content does not represent an image
"""
if not isinstance(content, bytes):
raise TypeError(f"Expected 'content' to be bytes, received: {type(content)}")
image = cv.imdecode(np.frombuffer(content, dtype=np.uint8), cv.IMREAD_COLOR)
if image is None:
raise ValueError(f"Expected 'content' to be image bytes")
return image