简体   繁体   中英

Catching stdout and camera frames in realtime from subprocess

I have a wireless sensor node that transmits wirelessly to a receiver connected to my computer. I use this command to see the data in real time

sudo stdbuf -o0 ./pip_sense.v2 l l | stdbuf -o0 grep -P "TX:03(376|004)

I am new to Python, but I was able to develop a piece of code as show below to capture the stdout and takes frames from a camera connected to the same computer. That is when a packet (data) is received, at that timestamp, a frame will be captured.

It is working fine, except the fact that its running slow. I am running my sensor at a rate of 10 Hz (transmitting every 0.1 sec.) but the code does what is required at a slower rate. I know that is because I am using cv2.imwrite() (I commented out this part and that helped in reducing the delay). But also, as discussed in this post and its said (as I understand) that using shell=True can invoke extra shell process and thus increase the delay.

Also, looking at this , Popen() seems to be causing delays as well. A solution is proposed in the second link, but I do not really understand how to modify it to work for me.

#!/usr/bin/env python

from subprocess import Popen, PIPE
import time
import sys
import cv2
import os
import csv
import argparse
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
from collections import OrderedDict
from datetime import datetime

PIP_CMD = 'sudo stdbuf -o0 ./pip_sense.v2 l l | stdbuf -o0 grep -P "TX:03(376|004)"'

def run(command):
    process = Popen(command, stdout=PIPE, shell=True)
    while True:
        line = process.stdout.readline().rstrip()
        if not line:
            break
        yield line
print ('Starting...')

def createFolder(directory):
    try:
        if not os.path.exists(directory):
            os.makedirs(directory)
    except OSError:
    print ('Error: Creating directory. ' + directory)

createFolder('/home/piptag/pip-test/capture_webcam/EXPERIMENTS')
file1 = open('/home/piptag/pip-test/capture_webcam/EXPERIMENTS/3376.txt','w')
file1.write("Time Stamp  \t TX ID \t RSSI  \tSEQ NO \tCAP  \tX-Axis \tY-Axis \tZ-Axis \t  X  \t  Y  \t Z \n")  # Header line 
file1.write("-------------------------------------------------------------------------------------------------------------------------------------\n")  

file2 = open('/home/piptag/pip-test/capture_webcam/EXPERIMENTS/3004.txt','w')
file2.write("Time Stamp  \t TX ID \t RSSI  \tSEQ NO  \tX-Axis \tY-Axis \tZ-Axis \t  X  \t  Y  \t Z \n")  # Header line 
file2.write("-------------------------------------------------------------------------------------------------------------------------------------\n") 

dirname = "/home/piptag/pip-test/capture_webcam/EXPERIMENTS/"

def save_webcam(dirname):
    cam = cv2.VideoCapture(-1) # was getting error (V4L: can't open camera by index 0), thus changes it to -1
    jpg_quality = 75
    frame_number = 0

    if cam.isOpened():
    ret_val, img = cam.read()
    else:
    ret_val = False

    timestamp = int(TS)

    path =  dirname + str(tx) + str("-") + str(timestamp) + ".jpg"

    cv2.imwrite(path, img, [int(cv2.IMWRITE_JPEG_QUALITY), jpg_quality])
    frame_number = frame_number + 1

##this is the end of the camera program 

def twos_comp(val, bits):
    """compute the 2's compliment of int value val"""
    if (val & (1 << (bits - 1))) != 0: # if sign bit is set e.g., 8bit: 128-255
        val = val - (1 << bits)        # compute negative value
    return val                         # return positive value as is


#########################################MAIN###################################

if __name__ == "__main__":
     for line in run(PIP_CMD):
    raw_data = line.split('\t')
        if len(raw_data) > 1:
            TS = raw_data[0][3:]
            tx = raw_data[3].split(':')[-1]
            rssi = float(raw_data[4][5:])
        crc_ok = True if (raw_data[5] != b'BAD CRC') else False
        no_drop = True if (raw_data[1] == b'Drop:0') else False

            # If CRC check is ok and no drop, process the packet
        if crc_ok and no_drop:
              data = raw_data[-1].split(':')[-1].split()
              cat = ""
              for i in data:
                   cat += str(i)

                  if tx == '03376':
              save_webcam(dirname)
                      print data
              CapStatus=data[1]
                      if CapStatus == '50':
                  Cap='0'
              elif CapStatus == '51':
                  Cap='1'
              SEQNO1=str(int((data[2]),16))
                      x_axis1=data[3]+data[4]
                      y_axis1=data[5]+data[6]
                      z_axis1=data[7]+data[8]
              TX1=tx
                      x1 = twos_comp(int(x_axis1,16), 16) * 0.0039 #* 9.80665  #the value is multiplied by 0.004 as the ADXL345                                    reports data as 4mg per 1lsb
                      y1 = twos_comp(int(y_axis1,16), 16) * 0.0039 #* 9.80665  #the value is multiplied by 0.004 as the ADXL345                                        reports data as 4mg per 1lsb
                      z1 = twos_comp(int(z_axis1,16), 16) * 0.0039 #* 9.80665  #the value is multiplied by 0.004 as the ADXL345                                    reports data as 4mg per 1lsb
              st1 = str(TS) + "\t "+ "{:<5}".format(str (TX1)) + "\t" + "{:<10}".format(str (rssi)) +                  "{:<5}".format(SEQNO1) + "\t" + "{:<5}".format(str (Cap)) + "\t" + "{:<5}".format(str (x_axis1)) +                  "\t" + "{:<5}".format(str (y_axis1)) + "\t"+ "{:<5}".format(str(z_axis1)) + "\t" + "{:<5}".format(str(x1))                  + "\t" + "{:<5}".format(str(y1)) + "\t" + "{:<5}".format(str(z1)) +"\n"
              file1.write(st1)

                  elif tx == '03004':
                save_webcam(dirname)
                    print data
                SEQNO2=str(int((data[1]),16))
                    x_axis2=data[2]+data[3]
                    y_axis2=data[4]+data[5]
                    z_axis2=data[6]+data[7]
            TX2=tx
            x2 = twos_comp(int(x_axis2,16), 16) * 0.0039 #* 9.80665  #the value is multiplied by 0.004 as the ADXL345                           reports dataas  4mg per 1lsb
                    y2 = twos_comp(int(y_axis2,16), 16) * 0.0039 #* 9.80665  #the value is multiplied by 0.004 as the ADXL345                           reports data as 4mg per 1lsb
                    z2 = twos_comp(int(z_axis2,16), 16) * 0.0039 #* 9.80665  #the value is multiplied by 0.004 as the ADXL345                           reports data as 4mg per 1lsb

            st2 = str(TS) + "\t "+ "{:<5}".format(str (TX2)) +"\t "+ "{:<10}".format(str (rssi)) +                  "{:<5}".format(SEQNO2) + "\t" + "{:<5}".format(str (x_axis2)) + "\t"+ "{:<5}".format(str (y_axis2)) +                   "\t"+ "{:<5}".format(str(z_axis2))+ "\t"+"{:<5}".format(str(x2)) + "\t" + "{:<5}".format(str(y2))+                  "\t"+ "{:<5}".format(str(z2)) +"\n"
            file2.write(st2)              
file1.close()
file2.close()

I appreciate any help

Thank you

Update: I got this advice from a friend and it worked.

Calling the cam = cv2.VideoCapture(-1) outside the save_webcam function (as a global variable) reduced the delays a lot.

In this case, the camera will be turned on one time and then capturing images will be done each time save_webcam is called...hence, turning on and off the camera was slowing the process.

However , I would like to enhance the program more, as it get stuck sometimes. So, anyone understands what is in this post and how my stdout part should be modified, then please comment here. I appreciate this.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM