Principios del algoritmo involucrado en el cálculo del avance en los carriles.

Principios del algoritmo involucrado en el cálculo del avance en los carriles.

árbol de directorios
--__chetoushiju230315
----json    # 文件夹,读取json文件需要调用相关函数
--------include
--------lib_json
----CmakeLists.txt                 # 编译文件所需
----TimeHeadway.cpp             # 源文件
----TimeHeadway.h               # 头文件
----main_demo.cpp                  # demo文件,包含main入口函数
----TimeHeadway_config.json     # 读取的配置文件
----车道内计算车头时距涉及的算法原理.md     # 此文件
definición

Avance: El intervalo de tiempo entre las cabezas de vehículos adyacentes de una flota que viajan en la misma dirección.

Avance promedio: el avance promedio de todos los vehículos en el segmento de carretera observado.

La fórmula de cálculo es: la distancia entre los dos vehículos dividida por la velocidad del siguiente vehículo.

Para escenarios de intersección semaforizada, el tiempo que tardan dos vehículos en pasar continuamente por la línea de parada se puede obtener como avance.

Referencia: "Ingeniería de tráfico" Prensa de transporte popular de Li Zuomin

Si tiene alguna pregunta o sugerencia, agregue V (xuanze500) para obtener más detalles.

----TimeHeadway_config.json # Leer el archivo de configuración
{
	"src1" : {
		"camera_src":"5_1",
		"cameraFPS": 23,
		"configRegion": {
			"lane1": [[405, 590],[498, 613],[888, 444],[858, 407]],
		    "lane2": [[498, 613],[888, 444],[989, 441],[583,626]],
			"lane3": [[1032, 455],[989, 441],[583, 626],[671, 645]]	
		},
	    "describe": "Time HeadWay",
	    "enable": true
	},
	
	"src2" : {
		"camera_src":"5_1",
		"cameraFPS": 25,
		"configRegion": {
			"lane1": []
		},
	    "describe": "Time HeadWay",
	    "enable": true
	}
}
Análisis del contenido del archivo de configuración.

No se permite modificar las claves del diccionario en el archivo de configuración. "camera_src" se refiere a la fuente de la cámara. "cameraFPS" se refiere a la velocidad de cuadros de la cámara, el valor predeterminado es 25 fps. "configRegion" es el área del carril calibrado. Cuando los vehículos se alinean en esta área, se debe calcular el avance del vehículo detrás del vehículo que va delante. El método de cálculo es: la distancia entre los dos vehículos dividida por la velocidad del siguiente vehículo. La distancia entre dos vehículos se calcula en función de los valores de longitud y latitud de los dos vehículos.

Leer método de archivo json
int EventTimeHeadWay::getConfig(const char* strPath, std::map<std::string, vector<ConfigInfos>>& config_)
{
	// cout << "=====》》》 getConfig()" << endl;
	// 1  read json config file
	char* text = readConfig(strPath);
	if (text == nullptr)  {  return 0;  }	
	//cout << "text:\n" <<text<< endl;

	// 2  The following 10 lines or so are the operations required to parse the file
	string str(text);
	Json::Value root;
    JSONCPP_STRING errs;
    Json::CharReaderBuilder build;

    unique_ptr<Json::CharReader> const jsonReader(build.newCharReader());
    bool jsonRet = jsonReader->parse(str.c_str(), str.c_str() + str.length(), &root, &errs);
    if ((jsonRet != true) || (errs.size() != 0)) {
        return false;
    }
    
	// 3 parse
	// cout << "root:\n" << root << endl;
	// cout  << "root.size() : " << root.size() << endl;
	ConfigInfos config;
	vector<ConfigInfos> configInfos; 
	for(int i = 1; i <= root.size(); ++i) {
		std::string src = "src" + std::to_string(i);
		// cout << "\n" << "camera source: " << src << endl;
		auto srci = root[src];
		
		// (1)  camera src
		string camera_src = srci["camera_src"].asString();		
		// cout << "camera_src = " << camera_src << endl;		
		
		// (2)  fps
		int sfps = srci["cameraFPS"].asInt();
		// cout << "sfps = " << sfps << endl;		
		
		// (3)  read config region inform. and save to map
		// cout << "configlaneNum = " << srci["configRegion"].size() << endl;		
        for (int l = 1; l <= srci["configRegion"].size(); ++l)
		{
			// srci["configRegion"]
			std::string laneNamel = "lane" + std::to_string(l);
			//cout << "laneNamel ???= " << laneNamel << endl;
		    if( srci["configRegion"][laneNamel].isArray() )
			{
				int laneNamelSize = srci["configRegion"][laneNamel].size();
				//cout << laneNamel << ": " << laneNamelSize << endl;
				for (int m = 0; m < laneNamelSize; ++m) 
				{					
					//cout << "........." << srci["configRegion"][laneNamel][m][0] << endl;
					int x = srci["configRegion"][laneNamel][m][0].asInt();
					int y = srci["configRegion"][laneNamel][m][1].asInt();
					cv::Point pt;
					pt.x = x; pt.y = y;
					config.region.push_back(pt);
					config.laneName = laneNamel;
					config.fps = sfps;
					// cout << laneNamel  <<  ": " << pt.x << ", " << pt.y << endl;
				}

			}
			configInfos.push_back(config);
			config.region.clear();
		}

	config_.insert(std::make_pair(camera_src, configInfos));
	}
	return 1;
}
Proceso de implementación de cálculo relevante:

1. Contar los tipos de vehículos de motor en el carril;

2 Ordena tus objetivos:

2.1 Considere si ordenar según la dirección x o la dirección y de las posiciones de píxeles correspondientes de los vehículos de motor;

2.2 Considere si ordenar x o y de pequeño a grande o de grande a pequeño.

2.3 La clasificación anterior debe ser la clasificación del índice correspondiente, porque la asignación final del atributo de avance del objetivo debe asignarse al objetivo del cuadro de imagen correspondiente.

3 Calcule el avance de los vehículos en el carril según los resultados de la clasificación (excepto el primer vehículo en la cola)

Los algoritmos clave involucrados en el proceso anterior son: (1) Ordenar y devolver el índice objetivo

bool EventTimeHeadWay::compareAs(sort_st a, sort_st b)
{
	return a.value < b.value; //Ascending order
}

bool EventTimeHeadWay::compareDs(sort_st a, sort_st b)
{
	return a.value > b.value; //Descending order
}


int EventTimeHeadWay::sortReturnIndex(vector<int>& vectors, vector<int>& sortindex)
{
	vector <sort_st> sort_array(vectors.size());
	for(int i=0; i<vectors.size(); ++i){
		sort_array[i].index = i;
		sort_array[i].value = vectors[i];
	}
	if (sortOrder){
		sort(sort_array.begin(), sort_array.end(), compareAs);
	}
	else{
		sort(sort_array.begin(), sort_array.end(), compareDs);
	}

	for(int i=0;i<vectors.size();++i){
		// cout<<sort_array[i].value<<' '<<sort_array[i].index<<endl;
		sortindex.push_back(sort_array[i].index);
	}
	
	return 0;    
}

Los algoritmos clave involucrados en el proceso anterior son: (2) Calcular la distancia del objetivo en función de la longitud y la latitud.

// Calculate the distance between two positions
float EventTimeHeadWay::cal_distance(double lat1, double lon1, double lat2, double lon2)
{
	double lat1Deg = (lat1*PI/180);
	double lon1Deg = (lon1*PI/180);
	double lat2Deg = (lat2*PI/180);
	double lon2Deg = (lon2*PI/180);
	double COS = cos(lat1Deg)*cos(lat2Deg)*cos(lon1Deg - lon2Deg) + (sin(lat1Deg)*sin(lat2Deg));
	return earthR * acos(COS);   // 单位:米(meters)
}
El constructor de la clase es el siguiente.
EventTimeHeadWay::EventTimeHeadWay() 
{
	queue_ = new Queue<vector<TargetAttribute>>(100);

	getConfig(strPath, config_);	
	
	std::thread th1([=](){
		while (true) 
		{
			// (1)  queue size
			if (queue_->size() <= 0) {
				this_thread::sleep_for(std::chrono::milliseconds(1));
				continue;
			}
			auto frame = queue_->pop();
			
			// (2)  frame size
			// cout<<"frame.size() = "<<frame.size()<<endl;
			if (frame.size() <= 0) continue;
			
			// (3)  config info
			auto config = config_.find(frame[0].source);
			if (config == config_.end()) {
				//cout<<"config == config_.end()"<<endl;
				continue;
			}			

			// (4)  juge envent
			calTimeHeadWay(frame, config->second);
			callback_(frame);
		}
	});
	th1.detach();
}
La función de entrada es
	// 1  初始化类
    EventTimeHeadWay* timeheadway = new EventTimeHeadWay();
	
	// 2  获取一帧图像的目标信息(demo为自己创造的数据)
	vector<TargetAttribute> frame1, frame2, frame3;   // 外部传进来的多帧图像的信息
    creat_frame(frame1, frame2, frame3);

	// 3  回调
	DetectorCallback callback([=](const std::vector<TargetAttribute>& infos){
    printf("\nget target info:\n");
		for (int i = 0; i < infos.size(); ++i) {
			printTargetInfo(infos[i]);
		}
    });
	timeheadway->setCallback(callback);

	
	// 4  for 是为了模拟多源,测试单源就可以。
	for (int i = 0; i < 1; ++i) {
		std::thread th([=](){
			while (1) {
				timeheadway->push(frame1);
				usleep(40 * 1000);
				timeheadway->push(frame2);
				usleep(40 * 1000);
				timeheadway->push(frame3);
				usleep(40 * 1000);
			}
		});
		th.detach();
	}

	while (true)
	{
		sleep(10000);
	}	
	
	return 0;
Ubicación del código fuente
链接:https://pan.baidu.com/s/1gkUsNRGoPah0jQNBlLghmQ 

Supongo que te gusta

Origin blog.csdn.net/qq_42835363/article/details/130223000
Recomendado
Clasificación