13

I am writing simple REST API using Flask, which reads uploaded video and returns some JSON. Video is sent as file by POST request, with content type application/x-www-form-urlencoded.

I want to process it using opencv, but I do not know how to read it from raw binary string. The only solution I came up with, is to save video to file and read it using opencv VideoCapture class. However I would like to avoid IO operations, because I think it will slow down my API.

So my question is:

How can I transform video from raw bytes representation to opencv representation (list of numpy arrays)?

3 Answers3

0

If you are uploading the video as a file to the server then it sounds like you are already saving it to a file - in this case simply reading it from the file may not be that inefficient.

Videos are typically much too big to fit in memory, so one way or another it is likely going to be going to the disk and back anyway.

If you mean that you would like your openCV program to directly accept the streamed video, do the processing and then do whatever you want next (e.g. save to file, display, stream to someplace else) then its generally easiest to stream the video to the OpenCV program if possible and use OpenCV to read the stream directly:

VideoCapture cap;
cap.open(yourStreamURL);
Mick
  • 24,231
  • 1
  • 54
  • 120
  • 1
    In many ML applications the videos are short (10s) so they can easily be stored in memory. Also ML machines typically have enormous amounts of RAM 200GB+. – user3071643 May 13 '21 at 15:27
0

I know this is a little too late to answer this question. Actually I don't know how do you receive video as string. but I tried to simulate your situation. I opened an image as a bytestring

f = open('image.jpg','rb')
data = f.read()
f.close()
print(data)

The output is

b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x01\x00`\x00`\x00\x00\xff\xdb\x00C\x00\x08\x06\x06\x07\x06\x05\x08\x07\x07\x07\t\t\x08\n\x0c\x14\r\x0c\x0b\x0b\x0c\x19\x12\x13\x0f\x14\x1d\x1a\x1f\x1e\x1d\x1a\x1c\x1c $.\' ",#\x1c\x1c(7),01444\x1f\'9=82<.342\xff\xdb\x00C\x01\t\t\t\x0c\x0b\x0c\x18\r\r\x182!\x1c!22222222222222222222222222222222222222222222222222\xff\xc0\x00\x11\x08\x01q\x01n\x03\x01"\x00\x02\...

and then converted to numpy array:

img_array = np.asarray(bytearray(data), dtype=np.uint8)
im = cv2.imdecode(img_array, 0)
cv2.imshow("test", im)
cv2.waitKey()

and it shows image. hope this be helpful

Ali Ent
  • 1,420
  • 6
  • 17
0

Try "imdecode" function provided by OpenCV.

from flask import Flask, request
import numpy as np
import cv2
app = Flask(__name__)
@app.route('/process_video', methods=['POST'])
def process_video():
    video_data = request.get_data()
    nparr = np.frombuffer(video_data, np.uint8)
    frames = []
    video_stream = cv2.imdecode(nparr, cv2.IMREAD_UNCHANGED)
    if len(video_stream.shape) < 3:
        video_stream = [video_stream]
    for frame in video_stream:
        frames.append(frame)
    return 'Video processed successfully'

if __name__ == '__main__':
    app.run()
  • Answer needs supporting information Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](https://stackoverflow.com/help/how-to-answer). – moken Jul 09 '23 at 15:33