首先目标的坐标信息和track id是已知的。
基本原理:记录目标上一次的坐标信息和当前的坐标信息,二者相连的线段如果与警戒线相交,那么则说明有越线的行为。因此问题就成了如何判断两条线段是否相交。
基础知识 平面向量若已知点a(x1, y1),b(x2,y2),那么向量ab为(x2 - x1, y2 - y1)
向量积如果向量a(x1, y1),向量b(x2, y2), 那么a * b = (x1*y2 - x2*y1)
若结果小于0,表示向量b在向量a的顺时针方向;若结果大于0,表示向量b在向量a的逆时针方向;若等于0,表示向量a与向量b平行
如图
向量AB(2,2),向量AC(3,0), AB*AC = (2*0 - 2*3) = -6
AB*AC < 0, 说明 AC在AB的顺时针方向
实现方案判断点与线段的关系
如图
向量AB(1, 2),AC(1,0),AD(1,-2)
AB*AC = -2 、 AD*AC = 2、 AC*AD = -2
B、D分别在线段AC的两侧,向量AC在向量AB的顺时针方向,AB×AC < 0;向量AC在向量AD的逆时针方向,AD×AC > 0,两叉乘结果异号
所以如果向量积结果异号,表示B和D分别在直线AC的两边,若向量积结果同号则表示B、D两点都在AC的一边
判断线段是否相交通过前面的铺垫我们就有了判断线段是否相交的方法
先判断C、D点在AB的两侧:AD*AB 与 AC*AB异号。
再判断A、B点在CD的两侧: CA*CD 与 CB*CD异号。
特殊情况的考虑如果线段1的端点的最大横坐标 < 线段2的端点最小横坐标,或者 如果线段1的端点的最大纵坐标 < 线段2的端点最小纵坐标,那么一定是不会相交的。我们就可以事先排除,以降低计算量。
代码实现基于以上原理实现一种越线检测算法
#include#include #include #define HOST_ANALY_MAX_TRACK_NUM (128) #define HOST_TRACK_NONE (-22) #define HOST_MIN(m, n) (((m) > (n)) ? (n) : (m)) #define HOST_MAX(m, n) (((m) > (n)) ? (m) : (n)) typedef enum { HOST_OBJ_TYPE_UNKNOW = -1, HOST_OBJ_TYPE_VEHICLE = 0, //车 HOST_OBJ_TYPE_PERSON = 1, //人 HOST_OBJ_TYPE_FACE = 2, //人脸 HOST_OBJ_TYPE_PLATE = 3, //车牌 HOST_OBJ_TYPE_BIKE = 4, //自行车 HOST_OBJ_TYPE_MOTOR = 5, // HOST_OBJ_TYPE_BOAT = 6, //船 HOST_OBJ_TYPE_SMOKE = 7, //烟 HOST_OBJ_TYPE_FIRE = 8, //火 HOST_OBJ_TYPE_FACEMASK = 9, //口罩 HOST_OBJ_TYPE_MAX }host_obj_type_e; typedef struct _host_obj_t { int track_id; //追踪ID, 用来区分目标 host_obj_type_e cls; int x; int y; int width; int height; }host_obj_t; typedef struct _host_analy_point_t { int x; int y; }host_analy_point_t; typedef struct _host_trip_wire_t { int direction;//方向 host_analy_point_t start;//起始点 host_analy_point_t end;//结束点 }host_trip_wire_t; typedef struct _host_obj_coord_t { int track_id; //追踪ID, 用来区分目标 host_obj_type_e cls; int sub; host_analy_point_t coord1; host_analy_point_t coord2; }host_obj_coord_t; typedef struct _obj_coore_info_t { unsigned int m_nIndex; //记录用到的下标 host_obj_coord_t obj_list[HOST_ANALY_MAX_TRACK_NUM]; }obj_coore_info_t; typedef struct _obj_trip_wire_t { obj_coore_info_t item; }obj_trip_wire_t; typedef struct _host_analy_t { obj_trip_wire_t trip_wire; }host_analy_t; static host_analy_t *s_host_analy_proc = NULL; int host_analy_init() { s_host_analy_proc = (host_analy_t *)malloc(sizeof(host_analy_t)); memset(s_host_analy_proc, 0, sizeof(host_analy_t)); for (int i = 0; i < HOST_ANALY_MAX_TRACK_NUM; ++i) { s_host_analy_proc->trip_wire.item.obj_list[i].track_id = HOST_TRACK_NONE; } return 0; } void host_analy_deinit() { if (s_host_analy_proc) { free(s_host_analy_proc); s_host_analy_proc = NULL; } } static int _host_find_pos(obj_coore_info_t *pParam, int track_id, host_obj_type_e cls) { int nIndex; for (int i = 0; i < HOST_ANALY_MAX_TRACK_NUM; ++i) { if ((pParam->obj_list[i].track_id == track_id) && (pParam->obj_list[i].cls == cls) && (HOST_TRACK_NONE != pParam->obj_list[i].track_id)) return i; } if (pParam->m_nIndex >= HOST_ANALY_MAX_TRACK_NUM) { pParam->m_nIndex = 0; nIndex = 0; } nIndex = pParam->m_nIndex % HOST_ANALY_MAX_TRACK_NUM; pParam->m_nIndex++; memset(&pParam->obj_list[nIndex], 0, sizeof(host_obj_coord_t)); pParam->obj_list[nIndex].track_id = HOST_TRACK_NONE; return nIndex; } static int _host_obj_update(host_obj_t &obj, host_obj_coord_t &coord) { int centre_x = obj.width/2 + obj.x; int centre_y = obj.height/2 + obj.y; coord.cls = obj.cls; coord.track_id = obj.track_id; if (0 == coord.sub) { coord.coord1.x = centre_x; coord.coord1.y = centre_y; coord.sub = 1; return -1; } else if (1 == coord.sub) { coord.coord2.x = centre_x; coord.coord2.y = centre_y; coord.sub = 2; } else { coord.coord1.x = coord.coord2.x; coord.coord1.y = coord.coord2.y; coord.coord2.x = centre_x; coord.coord2.y = centre_y; coord.sub = 2; } return 0; } int _host_compute(host_analy_point_t s, host_analy_point_t e) //计算叉乘的结果 { int ret = 0; ret = (s.x * e.y) - (s.y * e.x); return ret; } int _host_cross_line(obj_coore_info_t *trip_wire, host_obj_t &obj, host_analy_point_t line_s, host_analy_point_t line_e) { int nRet = -1; host_analy_point_t obj_s,obj_e; int nIndex = _host_find_pos(trip_wire, obj.track_id, obj.cls); nRet = _host_obj_update(obj, trip_wire->obj_list[nIndex]); if (0 != nRet) return nRet; obj_s.x = trip_wire->obj_list[nIndex].coord1.x; obj_s.y = trip_wire->obj_list[nIndex].coord1.y; obj_e.x = trip_wire->obj_list[nIndex].coord2.x; obj_e.y = trip_wire->obj_list[nIndex].coord2.y; // if ((HOST_MAX(obj_s.x, obj_e.x) <= HOST_MIN(line_s.x, line_e.x)) || (HOST_MAX(obj_s.y, obj_e.y) <= HOST_MIN(line_s.y, line_e.y)) || (HOST_MAX(line_s.x, line_e.x) <= HOST_MIN(obj_s.x, obj_e.x)) || (HOST_MAX(line_s.y, line_e.y) <= HOST_MIN(obj_s.y, obj_e.y))) { return -1; } //线段相交判断 host_analy_point_t AB,AC,AD; host_analy_point_t CD,CA,CB; AB.x = obj_e.x - obj_s.x; AB.y = obj_e.y - obj_s.y; AC.x = line_s.x - obj_s.x; AC.y = line_s.y - obj_s.y; AD.x = line_e.x - obj_s.x; AD.y = line_e.y - obj_s.y; CD.x = line_e.x - line_s.x; CD.y = line_e.y - line_s.y; CA.x = obj_s.x - line_s.x; CA.y = obj_s.y - line_s.y; CB.x = obj_e.x - line_s.x; CB.y = obj_e.y - line_s.y; int AB_AC = _host_compute(AB, AC); int AB_AD = _host_compute(AB, AD); int CD_CA = _host_compute(CD, CA); int CD_CB = _host_compute(CD, CB); printf("AB(%d, %d), AC(%d, %d), AB(%d, %d), AD(%d, %d), CD(%d, %d), CA(%d, %d), CD(%d, %d), CB(%d, %d)n", AB.x, AB.y, AC.x, AC.y, AB.x, AB.y, AD.x, AD.y, CD.x, CD.y, CA.x, CA.y, CD.x, CD.y, CB.x, CB.y); printf("AB_AC = %d, AB_AD = %d, CD_CA = %d, CD_CB = %dn", AB_AC, AB_AD, CD_CA, CD_CB); if((AB_AC > 0 && AB_AD > 0) || (AB_AC < 0 && AB_AD < 0) || (CD_CA > 0 && CD_CB > 0) || (CD_CA < 0 && CD_CB < 0)) { return -1; } //方向判断 if (CD_CA > 0)//direction = 1 { return 1; } else if (CD_CA < 0)//direction = 0 { return 2;; } else { printf("%s, %d : AB(%d, %d), AC(%d, %d), AB(%d, %d), AD(%d, %d), CD(%d, %d), CA(%d, %d), CD(%d, %d), CB(%d, %d)n", __FILE__, __LINE__, AB.x, AB.y, AC.x, AC.y, AB.x, AB.y, AD.x, AD.y, CD.x, CD.y, CA.x, CA.y, CD.x, CD.y, CB.x, CB.y); printf("AB_AC = %d, AB_AD = %d, CD_CA = %d, CD_CB = %dn", AB_AC, AB_AD, CD_CA, CD_CB); } return 0; } int host_trip_wire_analysis(host_obj_t obj, host_trip_wire_t param) { if (obj.track_id < 0) return -1; int nRet = -1; obj_coore_info_t *trip_wire = &s_host_analy_proc->trip_wire.item; host_analy_point_t line_s,line_e; line_s.x = param.start.x; line_s.y = param.start.y; line_e.x = param.end.x; line_e.y = param.end.y; nRet = _host_cross_line(trip_wire, obj, line_s, line_e); if (nRet <= 0) return -1; if (((1 == nRet) && (1 == param.direction)) || ((2 == nRet) && (0 == param.direction)) || (2 == param.direction)) nRet = 0; else nRet = -1; printf("trip_wire alarm, nRet = %d, direction = %dn", nRet, param.direction); return nRet; } int main() { host_analy_init(); host_trip_wire_t param; param.direction = 6; param.start.x = 6; param.start.y = 6; param.end.x = 6; param.end.y = 0; host_obj_t obj; obj.track_id = 100; obj.cls = HOST_OBJ_TYPE_VEHICLE; obj.x = 1; obj.y = 1; obj.width = 1; obj.height = 1; host_trip_wire_analysis(obj, param); obj.x = 3; obj.y = 3; obj.width = 1; obj.height = 1; host_trip_wire_analysis(obj, param); obj.x = 4; obj.y = 4; obj.width = 1; obj.height = 1; host_trip_wire_analysis(obj, param); obj.x = 8; obj.y = 4; obj.width = 1; obj.height = 1; host_trip_wire_analysis(obj, param); host_analy_deinit(); return 0; }



