How to use the GST-nvdsanalytics plugin in Deepstream to count different categories across lines

• Hardware Platform (Jetson)
• DeepStream Version 6.3
• JetPack Version (valid for Jetson only) 5.1.2

I am using the GST-nvdsanalytics plugin of DeepStream version 6.3 for cross-line counting, but I find that it seems unable to perform cross-line counting for different categories in the same detection video.

For example, I want to count cars (class-id=1) and trucks (class-id=2) across lines in the video. I am using my own model, so their category label numbers are correct.

I drew two lines to count cars and trucks separately, but I did not get the results I wanted. Why is that?

So my configuration parameters are:

[line-crossing-stream-0]
enable=1
line-crossing-CarEntry=566;611;428;914;258;637;843;629
line-crossing-CarExit=1407;880;1227;620;883;625;1539;629
class-id=1
extended=0
mode=loose

[line-crossing-stream-0]
enable=1
line-crossing-TruckEntry=566;611;428;914;202;686;849;679
line-crossing-TruckExit=1407;880;1227;620;889;678;1595;673
class-id=2
extended=0
mode=loose

But it doesn’t seem to work, so how should I implement it?

I found someone had asked the same question before, but there didn’t seem to be this function at that time. Is it implemented now?

> NVDS Analytics Multiple Class Line Crossing Issue

I saw it seemed to support multi-category counting, but I tried it and it didn’t work. Why?

[line-crossing-stream-0]
enable=1
line-crossing-CarEntry=566;611;428;914;258;637;843;629
line-crossing-CarExit=1407;880;1227;620;883;625;1539;629
line-crossing-TruckEntry=566;611;428;914;202;686;849;679
line-crossing-TruckExit=1407;880;1227;620;889;678;1595;673
class-id=1;2
extended=0
mode=loose

Or should I go like this:

[line-crossing-stream-0]
enable=1
line-crossing-CarEntry=566;611;428;914;258;637;843;629
line-crossing-CarExit=1407;880;1227;620;883;625;1539;629
line-crossing-TruckEntry=566;611;428;914;202;686;849;679
line-crossing-TruckExit=1407;880;1227;620;889;678;1595;673
class-id=1;1;2;2
extended=0
mode=loose

These don’t work as well as I’d like them to. They’re for cars, not trucks, but I set id = 2

Is it not possible to count across lines for different categories with different lines?
Who can help me?

Please provide complete information as applicable to your setup.

• Hardware Platform (Jetson / GPU)

• DeepStream Version

• JetPack Version (valid for Jetson only)

• TensorRT Version

• NVIDIA GPU Driver Version (valid for GPU only)

• Issue Type( questions, new requirements, bugs)

• How to reproduce the issue ? (This is for bugs. Including which sample app is using, the configuration files content, the command line used and other details for reproducing)

• Requirement details( This is for new requirement. Including the module name-for which plugin or for which sample application, the function description)

• Hardware Platform (Jetson)

• DeepStream Version 6.3

• JetPack Version (5.12)

• TensorRT Version 8.5

please find the explanation of class-id in the guide. you may try class-id=-1 first, then try class-id=1;2. In your configuration class-id=1;1;2;2" , please make sure the colon is correct.

please refer to this faq.

Well, I don’t think you understand what I mean, I already know it doesn’t support
It seems that I need to modify the source code

I said line-crossing-stream-0, and you gave me roi-filtering-stream-0

I think what it supports is to set class-id = 1; 2 on one line to count the two categories together, and I want to say that one line counts class-id = 1 and the other line counts class-id = 2

The faq above is just a sample to modify the code to customize. Similarly you can set different properties for each line-crossing line.

I tried to modify the code, but the effect I got was still wrong, I don’t know if there was a problem with my modification, but I made the modification according to the example, and copied the compiled file, but it still doesn’t seem to be ideal!
Here’s my modified file:
nvdsanalytics_property_parser.txt (32.4 KB)
以下是我的修改部分:

for (LineCrossingInfo & lc:lc_vec) {
    lc.enable = enable;
    lc.extended = extended;
    lc.operate_on_class = operate_on_class_vec;
    lc.mode = eMd;
  }

// new code 2025.3.21
for (LineCrossingInfo & lc:lc_vec) {
    int i=0;
	if (i == 0) {
	        lc.operate_on_class[0] = 0;
    	} else if (i == 1) {
	        lc.operate_on_class[0] = 1;
    	} else if (i == 2) {
	        lc.operate_on_class[0] = 2;
    	} else if (i == 3) {
	        lc.operate_on_class[0] = 6;
    	} else if (i == 4) {
	        lc.operate_on_class[0] = 7;
    	}else if (i == 5) {
	        lc.operate_on_class[0] = 8;
    }
    i++;
}
//--new code

Since I have 9 categories: I want to draw a line for 0, 1, 2, 6, 7, and 8 to count the number of them after crossing the line

1. car
2. person
3. motorcycle
4. red light
5. green light
6. yellow light
7. bus
8. truck
9. bicycle

But when I use the following configuration for video detection, what appears is that both lines are statistics of cars and pedestrians.
These two lines are the sum of cars and pedestrians. It doesn’t reach the CarEntry counts the number of cars, and PersonEntry counts the number of pedestrians, why is that?

[line-crossing-stream-0]
enable=1
line-crossing-CarEntry=566;611;428;914;258;637;843;629
line-crossing-PersonEntry=566;611;428;914;202;686;849;679
class-id=0;1
extended=0
mode=loose

Can you give me further guidance? I very much hope that it can be achieved! Thank you very much!

the code is not correct. please put “i” outside of “for” loop.

Yes, you are right, so I revised it early

// new code 2025.3.21
int i=0;
for (LineCrossingInfo & lc:lc_vec) {
        if (i == 0) {
                lc.operate_on_class[0] = 0;
        } else if (i == 1) {
                lc.operate_on_class[1] = 1;
        } else if (i == 2) {
                lc.operate_on_class[2] = 2;
        } else if (i == 3) {
                lc.operate_on_class[3] = 6;
        } else if (i == 4) {
                lc.operate_on_class[4] = 7;
        }else if (i == 5) {
                lc.operate_on_class[5] = 8;
    }
    i++;
}
//--new code

But then it doesn’t compile

sudo make
g++ -c -o nvdsanalytics_property_parser.o -fPIC -std=c++11 -DDS_VERSION=\"6.3.0\" -I ../../includes -I ../../libs/nvds_analytics -DNDEBUG -pthread -I/usr/include/gstreamer-1.0 -I/usr/include/orc-0.4 -I/usr/include/gstreamer-1.0 -I/usr/include/glib-2.0 -I/usr/lib/aarch64-linux-gnu/glib-2.0/include nvdsanalytics_property_parser.cpp
nvdsanalytics_property_parser.cpp: In function ‘gboolean nvdsanalytics_parse_linecrossing_group(GstNvDsAnalytics*, gchar*, GKeyFile*, gchar*, guint64)’:
nvdsanalytics_property_parser.cpp:571:1: error: jump to label ‘done’
  571 | done:
      | ^~~~
nvdsanalytics_property_parser.cpp:41:10: note:   from here
   41 |     goto done; \
      |          ^~~~
nvdsanalytics_property_parser.cpp:526:5: note: in expansion of macro ‘PARSE_ERROR’
  526 |     PARSE_ERROR ("%s not specified in group '%s'",
      |     ^~~~~~~~~~~
nvdsanalytics_property_parser.cpp:538:5: note:   crosses initialization of ‘int i’
  538 | int i=0;
      |     ^
nvdsanalytics_property_parser.cpp:571:1: error: jump to label ‘done’
  571 | done:
      | ^~~~
nvdsanalytics_property_parser.cpp:41:10: note:   from here
   41 |     goto done; \
      |          ^~~~
nvdsanalytics_property_parser.cpp:58:7: note: in expansion of macro ‘PARSE_ERROR’
   58 |       PARSE_ERROR ("%s %s", errvalue.c_str(), error->message); \
      |       ^~~~~~~~~~~
nvdsanalytics_property_parser.cpp:425:7: note: in expansion of macro ‘CHECK_ERROR’
  425 |       CHECK_ERROR (error, group);
      |       ^~~~~~~~~~~
nvdsanalytics_property_parser.cpp:538:5: note:   crosses initialization of ‘int i’
  538 | int i=0;
      |     ^
nvdsanalytics_property_parser.cpp:571:1: error: jump to label ‘done’
  571 | done:
      | ^~~~
nvdsanalytics_property_parser.cpp:41:10: note:   from here
   41 |     goto done; \
      |          ^~~~
nvdsanalytics_property_parser.cpp:58:7: note: in expansion of macro ‘PARSE_ERROR’
   58 |       PARSE_ERROR ("%s %s", errvalue.c_str(), error->message); \
      |       ^~~~~~~~~~~
nvdsanalytics_property_parser.cpp:420:3: note: in expansion of macro ‘CHECK_ERROR’
  420 |   CHECK_ERROR (error, group);
      |   ^~~~~~~~~~~
nvdsanalytics_property_parser.cpp:538:5: note:   crosses initialization of ‘int i’
  538 | int i=0;
      |     ^
make: *** [Makefile:52: nvdsanalytics_property_parser.o] Error 1

Finally I relocated the initialization:

enum::eMode eMd = eMode::loose;
std::unordered_map < int, StreamInfo > *stream_analytics_info =
    (nvdsanalytics->stream_analytics_info);
lc_info.stream_id = stream_id;

// new code 2025.3.21
int i = 0; // ✅ Move the variable definition to the top of the function
//--new code

keys = g_key_file_get_keys (key_file, group, nullptr, &error);
CHECK_ERROR (error, group);

It compiles successfully, but the end result is not what I wanted

[line-crossing-stream-0]
enable=1
line-crossing-CarEntry=566;611;428;914;258;637;843;629
line-crossing-PersonEntry=566;611;428;914;202;686;849;679
line-crossing-MotorcycleEntry=566;611;428;914;159;740;855;731
class-id=0;1;2
extended=0
mode=balanced

After a long time of observation, I found out
‘CarEntry’ counts Cars, Pedestrians and Motorcycles quantity
‘PersonEntry’ counts the number of pedestrians and motorcycles
‘MotorcycleEntry’ counts the number of pedestrians and motorcycles

Why Is This?

lc.operate_on_class is a vector. could you try the following code?

lc.operate_on_class.clear();
operate_on_class_vec.push_back (0);

Can you explain further? Where should I put it?

for (LineCrossingInfo & lc:lc_vec) {
    lc.enable = enable;
    lc.extended = extended;
    lc.operate_on_class = operate_on_class_vec;
    lc.mode = eMd;
  }

// new code 2025.3.21
for (LineCrossingInfo & lc:lc_vec) {
	if (i == 0) {
	        lc.operate_on_class[0] = 0;
    	} else if (i == 1) {
	        lc.operate_on_class[0] = 1;
    	} else if (i == 2) {
	        lc.operate_on_class[0] = 2;
    	} else if (i == 3) {
	        lc.operate_on_class[0] = 6;
    	} else if (i == 4) {
	        lc.operate_on_class[0] = 7;
    	}else if (i == 5) {
	        lc.operate_on_class[0] = 8;
    }
    i++;
}
//--new code

Is that so?

Very Sorry, I just touched this plug-in, there are still many places to learn from you!

please refer to the following code.
code.txt (352 Bytes)


I revised it according to this, and the result is still wrong

This makes a bigger mistake, it is totally wrong statistics

one correction. please change operate_on_class_vec.push_back (0); to lc.operate_on_class.push_back (0);

I’m very sorry, it’s my problem, according to your guidance

It’s finally come to pass, and so far, so good

Thank you very much! Thank you very much! Thank you very much!