如何针对特定Object ID关联性别检测以实现精准男女计数?
实现思路与代码修改方案
核心目标是将每个跟踪到的Object ID与对应的性别信息绑定,仅在人员首次被检测到(新ID注册)时执行性别检测,在人员离开(ID注销)时更新男女总计数,彻底避免逐帧重复统计的问题。
1. 初始化必要的状态变量
在循环开始前,定义几个关键变量来存储跟踪状态和统计数据:
# 存储每个Object ID对应的性别信息 id_gender_map = {} # 记录上一帧的跟踪ID集合,用于对比新增/注销的ID previous_ids = set() # 男女总计数 total_male = 0 total_female = 0 # 统计会话内出现的总唯一人数(替代原来的totalppl) total_unique_ppl = set()
2. 识别新增与注销的Object ID
每次调用ct.update(rects)后,对比当前帧和上一帧的ID集合,找出新增(人员进入)和注销(人员离开)的ID:
objects, intervals = ct.update(rects) current_ids = set(objects.keys()) # 计算新增ID(当前有但上一帧没有的)和注销ID(上一帧有但当前没有的) new_ids = current_ids - previous_ids removed_ids = previous_ids - current_ids
3. 为新增ID绑定性别并更新计数
对于新增的ID,我们需要找到它对应的人脸区域,执行一次性别检测,然后将结果存入映射表,并更新男女计数:
# 先计算当前所有人脸rect的质心,方便和新增ID的质心匹配 rect_centroids = [] for (x1, y1, x2, y2) in rects: cx = (x1 + x2) // 2 cy = (y1 + y2) // 2 rect_centroids.append( ((x1, y1, x2, y2), (cx, cy)) ) # 处理新增ID for obj_id in new_ids: obj_centroid = objects[obj_id] # 找到距离当前ID质心最近的人脸rect(匹配跟踪到的ID对应的人脸) min_dist = float('inf') matched_rect = None for rect, rect_c in rect_centroids: dist = ((obj_centroid[0] - rect_c[0])**2 + (obj_centroid[1] - rect_c[1])**2)**0.5 if dist < min_dist: min_dist = dist matched_rect = rect if matched_rect and run_age_gender: x, y, x2, y2 = matched_rect w = x2 - x h = y2 - y cropped_image = frame[y:y+h, x:x+w] if cropped_image.size > 0: age_inference.infer(cropped_image) age, gender = age_inference.get_age_gender_data() # 将性别与ID绑定 id_gender_map[obj_id] = gender # 更新总计数 if gender == 'Male': total_male += 1 elif gender == 'Female': total_female += 1 # 更新总唯一人数 total_unique_ppl.add(obj_id) # 更新UI显示 self.ui.male_count.setText(str(total_male)) self.ui.female_count.setText(str(total_female)) self.ui.ppltextbox.setPlainText(str(len(total_unique_ppl)))
4. 处理注销ID并更新计数
当ID被注销(人员离开)时,从映射表中移除该ID的性别信息,并相应减少对应性别的计数:
# 处理注销ID for obj_id in removed_ids: if obj_id in id_gender_map: gender = id_gender_map.pop(obj_id) # 更新总计数 if gender == 'Male': total_male -= 1 elif gender == 'Female': total_female -= 1 # 更新UI显示 self.ui.male_count.setText(str(total_male)) self.ui.female_count.setText(str(total_female))
5. 更新上一帧ID集合
最后,在每帧结束前更新previous_ids,为下一次对比做准备:
previous_ids = current_ids.copy()
额外优化建议
- 避免重复检测:除非跟踪到的人脸出现大幅偏移或丢失后重新识别,否则不需要对已绑定性别的ID重复执行性别检测,这样能减少推理开销。
- 性别检测容错:如果某次性别检测失败(比如人脸区域过小),可以在后续帧中尝试重新检测该ID对应的人脸,直到成功绑定性别。
- 修正总时长统计:原来的
totaltime统计逻辑会逐帧累加每个ID的时间,导致重复计算。建议在Centroid Tracker中为每个ID维护单独的停留时长,当ID注销时,将其时长累加到总时长中。
内容的提问来源于stack exchange,提问作者Shweta Katti
相关产品推荐
相关产品推荐

