我想从字符串中加载图像,就像PHP函数imagecreatefromstring
一样。
我该怎么做?
我有一个MySQL blob字段图像。我正在使用MySQLdb,不想为在PyOpenCV中处理图像而创建临时文件。
注意:需要cv(而不是cv2)包装函数
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
。
我认为在这个stackoverflow问题中提供的这个答案是更好的答案。
引用细节(借用自上面链接的@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
cv2.IMREAD_COLOR
代替cv2.CV_LOAD_IMAGE_COLOR
。 - uglidebase64.b64decode(string)
。最后,我认为这个答案(https://dev59.com/j1gR5IYBdhLWcg3wu_f4#58406222)更适合这个问题。 - Anugraha Sinha