Je travaille sur une application qui permet de faire une reconnaissance faciale à partir d'un flux webcam. J'obtiens des uri de données encodées en base64 du canevas et je veux l'utiliser pour faire quelque chose comme ceci:
cv2.imshow('image',img)
L'URI de données ressemble à ceci:
data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7
Donc, pour plus de clarté, j'ai montré à quoi ressemble l'image afin que la chaîne base64 ne soit pas cassée.
<img src="data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7">
Le doc officiel dit que imread
accepte un chemin de fichier comme argument. De this SO answer, si je fais quelque chose comme:
import base64
imgdata = base64.b64decode(imgstring) #I use imgdata as this variable itself in references below
filename = 'some_image.jpg'
with open(filename, 'wb') as f:
f.write(imgdata)
L'extrait de code ci-dessus fonctionne et le fichier image est généré correctement. Cependant, je ne pense pas que tant d'opérations File IO sont possibles étant donné que je ferais cela pour chaque trame du flux. Je veux pouvoir lire l'image dans la mémoire en créant directement l'objet img
.
J'ai essayé deux solutions qui semblent fonctionner pour certaines personnes.
En utilisant PIL référence :
pilImage = Image.open(StringIO(imgdata))
npImage = np.array(pilImage)
matImage = cv.fromarray(npImage)
J'obtiens cv
non défini car j'ai installé openCV3 qui est disponible pour moi en tant que module cv2
. J'ai essayé img = cv2.imdecode(npImage,0)
, cela ne renvoie rien.
Obtenir les octets de la chaîne décodée et la convertir en un tableau numpy de toutes sortes
file_bytes = numpy.asarray(bytearray(imgdata), dtype=numpy.uint8)
img = cv2.imdecode(file_bytes, 0) #Here as well I get returned nothing
La documentation ne mentionne pas vraiment ce que la fonction imdecode
renvoie. Cependant, d'après les erreurs que j'ai rencontrées, je suppose qu'il attend un numpy array
Ou un scalar
comme premier argument. Comment puis-je obtenir une poignée sur cette image en mémoire afin que je puisse faire cv2.imshow('image',img)
et toutes sortes de trucs sympas par la suite.
J'espère avoir pu me clarifier.
Vous pouvez simplement utiliser à la fois cv2 et oreiller comme ceci:
import base64
from PIL import Image
import cv2
from StringIO import StringIO
import numpy as np
def readb64(base64_string):
sbuf = StringIO()
sbuf.write(base64.b64decode(base64_string))
pimg = Image.open(sbuf)
return cv2.cvtColor(np.array(pimg), cv2.COLOR_RGB2BGR)
cvimg = readb64('R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7')
cv2.imshow(cvimg)
Cela a fonctionné pour moi, et ne nécessite pas de PIL/oreiller ou d'autres dépendances (sauf cv2):
import cv2
import numpy as np
def data_uri_to_cv2_img(uri):
encoded_data = uri.split(',')[1]
nparr = np.fromstring(encoded_data.decode('base64'), np.uint8)
img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
return img
data_uri = "data:image/jpeg;base64,/9j/4AAQ..."
img = data_uri_to_cv2_img(data_uri)
cv2.imshow(img)
Ceci est ma solution pour python 3.7 et sans utiliser PIL
import base64
def readb64(uri):
encoded_data = uri.split(',')[1]
nparr = np.fromstring(base64.b64decode(encoded_data), np.uint8)
img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
return img
j'espère que cette solution fonctionne pour tous