0

I have a client that extracts frames from a camera then compresses and stores them in a JSON object to be sent to a Flask server. I need to display said frame images on the Flask interface. My current attempt doesn't return an error, but it just prints an np array instead of displaying the actual image.

client.py

class Camera(object):
    def __init__(self, mode, addr, id):
        self.id = id
        self.video = None
        if(mode == "file" and type(addr) == type("hi")):
            self.video = cv2.VideoCapture(addr)
        elif(mode == "live" and type(addr) == type(0)):
            self.video = cv2.VideoCapture(addr)
        else:
            print("ERROR: Camera class given either an incorrect mode or an address of the wrong type.")

    def __del__(self):
        self.video.release()

    def get_cam_id(self):
        return self.id

    def get_frame(self):
        ret, frame = self.video.read()
        if(ret == True):
            return frame
        else:
            return None

    def norm_frame(self, frame):
        frame = cv2.resize(frame, None, fx=0.6, fy=0.6)
        return frame

    def package(self, frame):
                frame = cv2.imencode('.jpg', frame, [cv2.IMWRITE_JPEG_QUALITY, 70])[1].tolist()
                frame = json.dumps(frame)
                return frame

test_config route in applications.py

@application.route('/test_config', methods = ['GET', 'POST'])
def test2():
    var = input('Enter ID: ')
    print(FEEDS[var])
    frame = FEEDS[var].package(FEEDS[var].norm_frame(FEEDS[var].get_frame()))
    print(frame)


""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
Attempt
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
    #frame = json.loads(frame)
    #frame = np.asarray(frame, np.uint8)
    #frame = cv2.imdecode(frame, cv2.IMREAD_COLOR)
    #return frame
    return "Frame will display here eventually!"

There is a /test_input route that allows the user to enter information about the cameras. Said information is used to create camera objects in client.py. The objects are stored in a dictionary in applications.py with an ID key, which when entered in test_config will determine which frame is displayed. What I'm having trouble with is displaying the image after the key for Camera object has been entered.

EllisonC
  • 23
  • 5
  • to send image (or any file) you have to send header with information what type of file you send. Normally it sends header with information that it is HTML file. – furas Apr 24 '19 at 05:42
  • instead of `type(addr) == type("hi")` you should do `isinstance(addr, str)` - it is prefered and more readable. The same with `type(addr) == type(0)` - `isinstance(addr, int)` – furas Apr 24 '19 at 05:44
  • https://stackoverflow.com/questions/11017466/flask-to-return-image-stored-in-database – furas Apr 24 '19 at 05:45
  • How would I go about using the method in the linked answer if I don't have an image filename? Sorry, I'm just not sure how to apply that solution to this problem. – EllisonC Apr 24 '19 at 16:12
  • use anything text as name - random text, "hello-world.jpg", current date and time, etc. Protocol HTTP may need it only to correctly send data. But use may need it do save image on disk with default name. It is easier when you don't have to change name when you save image. – furas Apr 24 '19 at 16:22
  • to send image (or HTML, CSS, JS or any other file) you have to respect HTTP rules. HTTP to send file to client need (1) header with filename and file type (2) body with image. If you send without header then browser will not know if it is image or HTML or CSS, etc. and it will not know what to do with this data, and it may display error message. it is like with paper mail - to send it you have to put it in envelop which has address, stamp. You can't send mail without envelop, address and stamps. HTTP protocol works as envelop for you image. – furas Apr 24 '19 at 16:26
  • probably it could be `return send_file(io.BytesIO(frame), attachment_filename='hello-world.jpg', mimetype='image/jpg')` – furas Apr 24 '19 at 16:32
  • frankly, I don't know why you keep it as JSON. You could keep it as normal JPG in memory or in file. – furas Apr 24 '19 at 16:36

1 Answers1

2

I found a solution. Thank you, @furas, for your help.

r = requests.get('http://127.0.0.1:8080/get_frame').content
frame = json.loads(r)
frame = np.asarray(frame, np.uint8)
frame = cv2.imdecode(frame, cv2.IMREAD_COLOR)
r, jpg = cv2.imencode('.jpg', frame)
return Response(b'--frame\r\n' b'Content-Type: image/jpeg\r\n\r\n' + jpg.tobytes() + b'\r\n\r\n', mimetype='multipart/x-mixed-replace; boundary=frame')
EllisonC
  • 23
  • 5