Home > Software design >  How do I pass a frame read from a camera using opencv from a python script to another python script?
How do I pass a frame read from a camera using opencv from a python script to another python script?

Time:11-04

I'm trying to pass a frame read from a camera using opencv as an argument to another python script but I cannot get it to work.

Running the following script stores a camera frame on my network every 5 seconds:


#!/usr/bin/python

import cv2
import threading
import subprocess
import time
import datetime

def camera():
    camera = cv2.VideoCapture("/dev/video0")
    if not camera.isOpened():
        print("Cannot open camera.")
        raise SystemExit
    camera.set(cv2.CAP_PROP_FRAME_WIDTH, 320)
    camera.set(cv2.CAP_PROP_FRAME_HEIGHT, 320)
    camera.set(cv2.CAP_PROP_FPS, 15)
    return camera

try:
    camera = camera()
    while True:
        frame = camera.read()[1]
        #subprocess.call(["python", "/home/user/test2.py", frame])
        server = "/net/192.168.4.51/mnt/LAN4Storage/EC/Camera/"
        cv2.imwrite(server   "temp.jpg", frame)
        timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        cv2.imwrite(server   timestamp   ".jpg", frame)
        time.sleep(5)

except Exception as error:
    print(error)

finally:
    camera.release()

If I uncomment the subprocess.call line and comment the next 4 lines I expect the frame to be passed to my test2.py script:

`

    #/usr/bin/env python

    import cv2
    import sys
    import os
    import time
    import datetime

    try:
        frame = cv2.imread(sys.argv[1])
        server = "/net/192.168.4.51/mnt/LAN4Storage/EC/Camera/"
        cv2.imwrite(server   "temp.jpg", frame)
        timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        cv2.imwrite(server   timestamp   ".jpg", frame)

    except Exception as error:
        print(error)

    finally:
        pass

` But on starting test1.py, I get the following error:

`expected str, bytes or os.PathLike object, not ndarray`

CodePudding user response:

There seem to be a couple of misconceptions here that are leading things astray...

  • You can't sensibly pass images (i.e. their complete pixel data) as command-line arguments/parameters. They are generally too long and may contain nulls.

  • It is grossly inefficient to think about writing an image for every frame of a video. That's actually why we have video - because we can difference and do motion vectors between frames to enable better compression.

  • You can write an image file to RAM without causing wear to an SD card.

In light of what I understand so far, I would suggest either:

  • writing your image to a tmpfs filesystem, a.k.a. RAM drive, or
  • look at this answer, and write the images to Redis where you can pick them up from any machine or process in your network, using Python, C/C , Ruby or bash scripts.

Note that if you use the file-based approach and unsynchronised access from multiple processes, you may get corruption if a file is overwritten during a read. One way to avoid this is to leverage the fact that renames are atomic. So, write the image to a file called something like InProgress.jpg and when complete, rename InProgress.jpg as Latest.jpg and let readers always read Latest.jpg. That way readers will always get one of the two files and never two inconsistent halves of different versions.

Also, bear in mind Dan's comment about buffering. More material here.

CodePudding user response:

the frame object is a ndarray, you need to convert to string. if you do:

subprocess.call(["python", "/home/user/test2.py", frame.tostring()]) should work.

but you shouldn't use cv2.imread, because you are not reading the image from a file, you are reading froma string in command

So you should use

frame = np.fromstring(sys.argv[1])

i'm not sure if the conversion from ndarray to string and in the other way work fine, probabbly you need to adjust the parameters

  • Related