I'm using Microsoft Azure's Face API to detect the emotions of a person in a video. I have a Python program working correctly with local images, and now I'm trying to take a local video and send each frame to the API, and store the result of each analysis.
The data sent to Azure's Face API needs to be a PNG/JPG file read as bytes:
image_data=open(image_source, "rb").read()
OpenCV seems to be the standard for going frame by frame through a video with Python, but the frames are of the type Numpy array. You can take each frame of a video and save it as a JPG to disk like so:
import cv2 # OpenCV
vidcap = cv2.VideoCapture('vid.mp4')
success, image = vidcap.read()
count = 1
while success:
cv2.imwrite("video_data/frame_%d.jpg" % count, image)
success, frame = vidcap.read() # frame is a Numpy array
print('Saved frame ', count)
count += 1
But this isn't exactly what I want. Is there anyway to do this Numpy array to JPG conversion without saving a file to disk? I just want to convert it to JPG, then send that image as bytes to the Azure API.
Any and all advice and guidance is appreciated, thanks!
Edit: I've got a working work-around by converting the Numpy array frame to a PIL Image object and converting it to a PNG through the BytesIO library module. If anyone has any more efficient/nicer/cleaner/better solutions, I would still love to hear them!
You just need cv2.imencode()
like this:
success, frame = vidcap.read()
_, JPEG = cv2.imencode('.jpeg', frame)
JPEG
will now be a Numpy array containing a JPEG-encoded image. If you want to send it to Azure as bytes, you can send:
JPEG.tobytes()