How to access Re-ID tensor for cross camera re-id

There are Re-ID index in each object of each source. It is fine for multiple streams.

@kesong

Hi, thank you for your response.

Where is that index? Since we are writing the binding ourselves.
I actually can’t even access the tensor in this way:

if user_meta and user_meta.base_meta.meta_type == pyds.NVDS_TRACKER_OBJ_REID_META and user_meta.user_meta_data:
    tensor_meta = pyds.NvDsInferTensorMeta.cast(user_meta.user_meta_data)
    layer = pyds.get_nvds_LayerInfo(tensor_meta, 0)
    ptr = ctypes.cast(pyds.get_ptr(layer.buffer),
                        ctypes.POINTER(ctypes.c_float))
    features = np.ctypeslib.as_array(ptr, shape=(512,))
    print(features.shape)

Am I doing it correct?

Please use these updated bindings for tracker meta while compiling deepstream python apps.

bindtrackermeta.cpp.txt (6.7 KB)
trackermetadoc.h.txt (10.5 KB)
nvdsmetadoc.h.txt (23.7 KB)
bindnvdsmeta.cpp.txt (27.5 KB)

Example Usage:
                ::

                gst_buffer = info.get_buffer()
                if not gst_buffer:
                    print("Unable to get GstBuffer ")
                    return
                batch_meta = pyds.gst_buffer_get_nvds_batch_meta(hash(gst_buffer))

                l_batch_user=batch_meta.batch_user_meta_list #
                while l_batch_user is not None:
                    try:
                        user_meta= pyds.NvDsUserMeta.cast(l_batch_user.data)
                    except StopIteration:
                        break
                    if user_meta and user_meta.base_meta.meta_type == pyds.NVDS_TRACKER_BATCH_REID_META:
                        pReidTensor = pyds.NvDsReidTensorBatch.cast(user_meta.user_meta_data)
                    try:
                        l_batch_user=l_batch_user.next
                    except StopIteration:
                        break
                
                
                l_frame = batch_meta.frame_meta_list
                while l_frame is not None:
                    try:
                        frame_meta = pyds.NvDsFrameMeta.cast(l_frame.data)
                    except StopIteration:
                        break
                
                    if not pReidTensor:
                        continue

                    l_obj = frame_meta.obj_meta_list
                    while l_obj is not None:
                        try:
                            obj = pyds.NvDsObjectMeta.cast(l_obj.data)
                        except StopIteration:
                            break
                        id = obj.object_id
                        l_obj_user = obj.obj_user_meta_list
                        obj_user_meta = pyds.NvDsUserMeta.cast(l_obj_user.data)
                        if obj_user_meta and obj_user_meta.base_meta.meta_type == pyds.NVDS_TRACKER_OBJ_REID_META and obj_user_meta.user_meta_data:

                            reidInd_ptr = ctypes.cast(pyds.get_ptr(obj_user_meta.user_meta_data), ctypes.POINTER(ctypes.c_int32))                
                            reidInd = reidInd_ptr.contents.value

                            # Check the conditions
                            if 0 <= reidInd < pReidTensor.numFilled:
                                features = pReidTensor.ptr_host[reidInd]
                                features[id] = features.tolist()                    #This will be the Re-ID feature for the obj. id
                        try:
                            l_obj = l_obj.next
                        except StopIteration:
                            break

This is the example usage code you can use to get reid feature. @JoeShz

@kesong Please help update the repo if you find the bindingd are correct. Will be useful for other developers in future.

Regards

Thanks for your sharing. We will review it.

I built the binding using Cmake. It was built successfully. But, I get this error:

if user_meta and user_meta.base_meta.meta_type == pyds.NVDS_TRACKER_BATCH_REID_META:
AttributeError: module 'pyds' has no attribute 'NVDS_TRACKER_BATCH_REID_META'

I am sure that there’s another file to be edited since It was working before xD but I don’t remember which file I had to edit.
@st123439

1 Like
copy the files:

.cpp files to: opt/nvidia/deepstream/deepstream-6.3/sources/deepstream_python_apps/bindings/src/
.h files to : opt/nvidia/deepstream/deepstream-6.3/sources/deepstream_python_apps/bindings/docstrings/

Then :

cd /opt/nvidia/deepstream/deepstream/sources/deepstream_python_apps/bindings && \
    rm -rf build && \
    mkdir build && \
    cd build && \
    cmake .. -DPYTHON_MAJOR_VERSION=3 -DPYTHON_MINOR_VERSION=8 -DPIP_PLATFORM=linux_x86_64 -DDS_PATH=/opt/nvidia/deepstream/deepstream/ && \
    make -j$(nproc) && \
    echo "###########################" && \
    echo "Installing built PyDS wheel" && \
    echo "###########################" && \
    pip3 install ./pyds-1.1.8-py3-none*.whl

This is how you can compile the bindings.

Best luck!

1 Like

Oh, I had to force-reinstall the wheel.
Now it works!!

Thank you @st123439 @kesong

Thanks a lot for sharing binding related files. I followed your instruction and I used sample code you provided. However, when I run the code, it says: “if not pReidTensor:
UnboundLocalError: local variable ‘pReidTensor’ referenced before assignment”

So I tried to declare pReidTensor, but it just freezes.

def pgie_src_pad_buffer_probe(pad, info, u_data):
    frame_number = 0
    pReidTensor = None
    
    num_rects = 0
    gst_buffer = info.get_buffer()
    if not gst_buffer:
        print("Unable to get GstBuffer ")
        return
    batch_meta = pyds.gst_buffer_get_nvds_batch_meta(hash(gst_buffer))
    
    l_batch_user=batch_meta.batch_user_meta_list #
    while l_batch_user is not None:
        try:
            user_meta= pyds.NvDsUserMeta.cast(l_batch_user.data)
        except StopIteration:
            break
        if user_meta and user_meta.base_meta.meta_type == pyds.NVDS_TRACKER_BATCH_REID_META:
            pReidTensor = pyds.NvDsReidTensorBatch.cast(user_meta.user_meta_data)
        try:
            l_batch_user=l_batch_user.next
        except StopIteration:
            break
    
    
    l_frame = batch_meta.frame_meta_list
    while l_frame is not None:
        try:
            frame_meta = pyds.NvDsFrameMeta.cast(l_frame.data)
        except StopIteration:
            break

        if pReidTensor is None:
        # if not pReidTensor:
            continue
    
        l_obj = frame_meta.obj_meta_list
        while l_obj is not None:
            try:
                obj = pyds.NvDsObjectMeta.cast(l_obj.data)
            except StopIteration:
                break
            id = obj.object_id
            l_obj_user = obj.obj_user_meta_list
            obj_user_meta = pyds.NvDsUserMeta.cast(l_obj_user.data)
            if obj_user_meta and obj_user_meta.base_meta.meta_type == pyds.NVDS_TRACKER_OBJ_REID_META and obj_user_meta.user_meta_data:
    
                reidInd_ptr = ctypes.cast(pyds.get_ptr(obj_user_meta.user_meta_data), ctypes.POINTER(ctypes.c_int32))                
                reidInd = reidInd_ptr.contents.value
    
                # Check the conditions
                if 0 <= reidInd < pReidTensor.numFilled:
                    features = pReidTensor.ptr_host[reidInd]
                    features[id] = features.tolist()                    #This will be the Re-ID feature for the obj. id
            try:
                l_obj = l_obj.next
            except StopIteration:
                break

    
    return Gst.PadProbeReturn.OK
Warning: gst-stream-error-quark: No decoder available for type 'application/x-rtp, media=(string)application, payload=(int)107, clock-rate=(int)90000, encoding-name=(string)VND.ONVIF.METADATA, a-tool=(string)"LIVE555\ Streaming\ Media\ v2022.01.21", a-type=(string)broadcast, x-qt-text-nam=(string)"RTSP/RTP\ stream\ from\ Encoder", x-qt-text-inf=(string)cam0_0, npt-start=(guint64)0, play-speed=(double)1, play-scale=(double)1, ssrc=(uint)2647244233'. (6): gsturidecodebin.c(920): unknown_type_cb (): /GstPipeline:pipeline0/GstBin:source-bin-01/GstURIDecodeBin:uri-decode-bin
Decodebin child added: h264parse1 

Decodebin child added: capsfilter1 

Decodebin child added: nvv4l2decoder1 

In cb_newpad

gstname= video/x-raw
features= <Gst.CapsFeatures object at 0x7f39d0f8f580 (GstCapsFeatures at 0x7f38b002b460)>

Best Regards

I think its because of the probe. I see that the probe function you have used is after the pgie. But we need to use this probe after the tracker if i understand the issue correctly in your case.

And in case of the freezing, i think its because you have not iterated the frame as :

try:
l_frame = l_frame.next
except StopIteration:
break

So once you go inside the probe, the logic was able to go in the first frame and couldnt iterate over the other frames.

1 Like

Also, make sure that outputReidTensor equals 1 in your tracker.

Thanks for your reply.

Using probe after the track solved the problem.

Now I can access to Re-ID features.

I have a new question regarding the code below

# Check the conditions
                if 0 <= reidInd < pReidTensor.numFilled:
                    features = pReidTensor.ptr_host[reidInd]
                    features[id] = features.tolist()                    #This will be the Re-ID feature for the obj. id

I don’t understand why you added the last part.
Is there any specific reason you changed features to list? And is the type of features Dictionary?

In addition, if possible, could you provide me any insights to track objects with those features on different camera (with different view, not at the same time.)

Best Regards,

The features are the list of array. So i want to save it as an array.

the id is the obj id for which the features are calculated.

So if you want to do reid in another camera, you need to save these features in the buffer and reuse it. Depends on what you want to do.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.