• Community
  • Properties of a Depth Frame in Script Node

Hi,
I am using a OAK-D Pro W PoE since a few days and I have an issue when trying to calculate properties of the depth frame on the camera using the script node (I am also not a specialist in coding - therefore sorry in advance).
On the host everything works fine: So I managed to filter (only allow depth values in a certain range) and calculate some statistics (e.g. mean, variance, ...), since getFrame returns a numpy array which allows me to perform the filtering/statistics. I.e.:

depthFrame = frame.getFrame()
depthFrameSize = np.count_nonzero(~np.isnan(depthFrame))
inRange = (minDepth <= depthFrame) & (depthFrame <= maxDepth)
depthROI = depthFrame[inRange]
depthROISize = np.count_nonzero(~np.isnan(depthROI))
if depthROISize > 0:
    depthROIVar = np.var(depthROI)
    depthROIAvg = np.mean(depthROI)

In the next step I tried to move this into the script node in order to make the calculation on the camera.
So I managed to pass the depth frames to a script node. But within the script node I was not able to perform the filtering and statistics up to now. Maybe anyone give me some hints how to do the same in the script as I managed on the host using numpy functions.
Here is what I did so far:

stereo = pipeline.createStereoDepth()
script = pipeline.create(dai.node.Script)
stereo.depth.link(script.inputs['depthframes'])
script.inputs['depthframes'].setBlocking(False)
script.inputs['depthframes'].setQueueSize(1)

script.setScript("""
    import json

    while True:
        frame = node.io['depthframes'].get()
        framedata = frame.getData()   # should be a 1D byte array
        #TODO: filter the depth frame by min/max
        #TODO: calculate mean/variance of the filtered depth frame

        # write results on json dict and dump it to output
        b = Buffer(300)
        dict = {"mean": mean, "var": var} 
        b.setData(json.dumps(dict).encode('utf-8'))
        node.io['out'].send(b)
""")

xout = pipeline.create(dai.node.XLinkOut)
xout.setStreamName('scriptout')
script.outputs['out'].link(xout.input)
  • Within the script node I am even not sure how to treat the 1D byte array, i.e. I do not even know how to get a value of the depth frame on a specific coordinate, e.g. how to access for instance the value of the depth frame on pixel (0,0), since the 1D byte array has a structure I do not understand up to now.

So any comments and hints are welcome. Thanks a lot.

  • erik replied to this.

    Hi alois ,
    So at arr[0] you will have depth pixel at (x=0, y=0), at arr[1] it will be (1,0), and if you have 1280x720 depth frames, the arr[1279] will be at (1279,0) and arr[1280] will be at (0,1).
    Note that looping through 1M points inside script node will be very slow, and I would suggest offloading such computationally heavy operations to VPU through custom models, see docs here.
    Thoughts?
    Thanks, Erik

      Hi erik ,
      thanks a lot for that quick response. Yes that helps and thanks for the hints. Anyway the script node was my very first approach to get more familiar with the device. Custom models will be the second one, but might need more time to get in touch with.
      One comment/question to the array - if I have a 1280x720 depth frame the array becomes a length of 1280x720x2 (since values of the depth frame is in int16 format - as far as I understand), but still not completely sure how to access the value on a dedicated coordinate.
      Thanks, Alois

      • erik replied to this.

        Hi alois ,
        Great question, I think you are right, ImgFrame.getData() will return byte array, while ImgFrame.getFrame() should return in correct datatype (int16).
        Thanks, Erik