南通网站建设系统电话,德国网站的后缀名,如何建论坛网站,宁夏建设网站的公司大家好#xff0c;我是微学AI#xff0c;今天给大家介绍一下计算机视觉的应用17-利用CrowdCountNet模型解决人群数量计算问题(pytorch搭建模型)。本篇文章#xff0c;我将向大家展示如何使用CrowdCountNet这个神奇的工具#xff0c;以及它是如何利用深度学习技术来解决复杂…大家好我是微学AI今天给大家介绍一下计算机视觉的应用17-利用CrowdCountNet模型解决人群数量计算问题(pytorch搭建模型)。本篇文章我将向大家展示如何使用CrowdCountNet这个神奇的工具以及它是如何利用深度学习技术来解决复杂的人群计数问题。让我们一起进入这个充满活力和创新的世界开启图像和视频中人群数量计算的新篇章
目录
项目介绍应用场景 人流监测和管理安全防控市场调研和决策支持城市规划和交通管理 实战项目 数据准备模型构建模型训练图片检测人群数量视频检测人群数量 结论
1. 项目介绍
本文我将利用深度神经网络来解决一个现实中普遍存在的问题如何准确计算图像和视频中的人群数量。当您走进拥挤的城市街头或繁忙的公共场所时人群数量经常让人难以置信。然而现在有了深度学习模型的帮助我们可以轻松地通过计算机视觉来解决这个挑战。
CrowdCountNet是我们的主角它是一种被广泛应用于图像识别和处理领域的深度学习模型。它背后的原理十分精巧利用了神经网络的强大能力来理解和分析图像中的人群分布。这个模型通过学习大量的图像数据自动捕捉到了各种人群密集度的模式和特征。
想象一下当你看着一张摄像头拍摄的城市街景时CrowdCountNet正在忙碌地工作着。它会逐像素地扫描整个图像并识别每个像素点上是否存在人群。从细微的行人到人群聚集的区域CrowdCountNet都能准确地捕捉到每个人的存在。
使用这个强大的深度学习模型我们可以实现许多令人惊叹的功能。无论是为城市规划提供人流热图、帮助安保人员监控拥挤场所还是为交通管理提供实时的交通流量信息CrowdCountNet都能在不同领域发挥巨大作用。
2. 应用场景
2.1 人流监测和管理
在公共场所例如商场、机场、火车站等监测和管理人流量是至关重要的。我们的模型可以用于实时监测人流量帮助管理者做出更有效的决策比如调整人流方向预防拥挤等。
在一个繁忙的购物中心通过我们的人流监测系统可以实时显示各个商店的人流量。商场管理员可以在控制中心的大屏幕上看到不同区域的人流状况比如一楼的时尚区人流量饱和而二楼的电子产品区人流相对稀少。管理员立即作出反应调整楼梯和电梯的方向引导顾客流向较空闲的区域以缓解拥挤。
2.2 安全防控
在大型活动或集会中通过实时监测人群数量可以预防和控制安全事故的发生及时制定疏散计划提高人员安全。
想象一个音乐节现场数以万计的观众聚集在一个开放的场地上。通过我们的人流监测系统主办方能够实时获得观众的数量和密度数据。突然系统发出警报显示某个区域的人流超过了安全限制。主办方立刻启动紧急预案引导人群有序撤离避免发生踩踏事故。
2.3 市场调研和决策支持
商家可以通过监测店铺或某个区域的人流量来评估其营销策略的效果或者进行更准确的市场调研。
一家新开业的百货公司想要评估其广告宣传效果和吸引力。通过人流监测系统他们可以统计每天进入商场的人数并与营销活动的时间和内容进行对比。他们发现当进行打折促销时入场人数骤增而在没有促销的日子里人流量相对稀少。这为他们提供了有价值的市场调研数据帮助他们更准确地评估促销策略的成效。
2.4 城市规划和交通管理
在城市规划和交通管理中通过人群数量的监测可以更好地理解和预测城市中的人流动态从而更科学地进行城市规划和交通管理。
想象一座拥挤的大都市上班高峰期大批人涌入地铁站。通过我们的人流监测系统地铁管理部门可以实时了解不同地铁站的客流情况并根据需求增加或减少列车班次。当一个地铁站即将达到容纳上限时系统会自动发出警报引导乘客选择其他线路或利用公共交通换乘以减少人流压力。
2.5 相册与毕业生人数统计
通常毕业合影中有大批的人一起合作我们要统计人数的话基本都是人工去一个一个数出来这样费时费力。现在利用模型直接统计合照人数统计合照人数判断是否学生来齐了。
3. 实战项目
在这个项目中我们将首先讨论如何准备数据然后构建和训练我们的模型并最后使用我们的模型来检测人群数量。
3.1 数据准备
首先我们需要准备一个包含大量标注人群数量的图像数据集。这可以是公开的人群数量数据集也可以是自己收集并标注的数据集。
3.2 模型构建
然后我们需要构建一个CrowdCountNet模型来学习如何从图像中预测人群数量。
import torch.nn as nn
import torch
import torch.nn.functional as F
from torch.autograd import Variable
from torch.nn.utils.weight_norm import weight_norm
import math
from collections import OrderedDictclass CrowdCountNet(nn.Module):def __init__(self,leaky_reluFalse,attn_weight1,fix_domain1,domain_center_model,**kwargs):super(CrowdCountNet, self).__init__()self.criterion_attn torch.nn.MSELoss(reductionsum)self.domain_center_model domain_center_modelself.attn_weight attn_weightself.fix_domain fix_domainself.cosine 1self.conv1 nn.Conv2d(3, 64, kernel_size3, stride2, padding1, biasFalse)self.bn1 nn.BatchNorm2d(64, momentumBN_MOMENTUM)self.conv2 nn.Conv2d(64, 64, kernel_size3, stride2, padding1, biasFalse)self.bn2 nn.BatchNorm2d(64, momentumBN_MOMENTUM)self.relu nn.ReLU(inplaceTrue)num_channels 64block blocks_dict[BOTTLENECK]num_blocks 4self.layer1 self._make_layer(block, 64, num_channels, num_blocks)stage1_out_channel block.expansion * num_channels# -- stage 2self.stage2_cfg {}self.stage2_cfg[NUM_MODULES] 1self.stage2_cfg[NUM_BRANCHES] 2self.stage2_cfg[BLOCK] BASICself.stage2_cfg[NUM_BLOCKS] [4, 4]self.stage2_cfg[NUM_CHANNELS] [40, 80]self.stage2_cfg[FUSE_METHOD] SUMnum_channels self.stage2_cfg[NUM_CHANNELS]block blocks_dict[self.stage2_cfg[BLOCK]]num_channels [num_channels[i] * block.expansionfor i in range(len(num_channels))]self.transition1 self._make_transition_layer([stage1_out_channel],num_channels)self.stage2, pre_stage_channels self._make_stage(self.stage2_cfg, num_channels)# -- stage 3self.stage3_cfg {}self.stage3_cfg[NUM_MODULES] 4self.stage3_cfg[NUM_BRANCHES] 3self.stage3_cfg[BLOCK] BASICself.stage3_cfg[NUM_BLOCKS] [4, 4, 4]self.stage3_cfg[NUM_CHANNELS] [40, 80, 160]self.stage3_cfg[FUSE_METHOD] SUMnum_channels self.stage3_cfg[NUM_CHANNELS]block blocks_dict[self.stage3_cfg[BLOCK]]num_channels [num_channels[i] * block.expansionfor i in range(len(num_channels))]self.transition2 self._make_transition_layer(pre_stage_channels,num_channels)self.stage3, pre_stage_channels self._make_stage(self.stage3_cfg, num_channels)last_inp_channels np.int(np.sum(pre_stage_channels)) 256self.redc_layer nn.Sequential(nn.Conv2d(in_channelslast_inp_channels,out_channels128,kernel_size3,stride1,padding1),nn.BatchNorm2d(128, momentumBN_MOMENTUM),nn.ReLU(True),)self.aspp nn.ModuleList(aspp(in_channel128))# additional layers specfic for Phase 3self.pred_conv nn.Conv2d(128, 512, 3, padding1)self.pred_bn nn.BatchNorm2d(512)self.GAP nn.AdaptiveAvgPool2d(1)# Specially for hidden domain# Set the domain for learnable parametersdomain_center_src np.load(self.domain_center_model)G_SHA torch.from_numpy(domain_center_src[G_SHA]).view(1, -1, 1, 1)G_SHB torch.from_numpy(domain_center_src[G_SHB]).view(1, -1, 1, 1)G_QNRF torch.from_numpy(domain_center_src[G_QNRF]).view(1, -1, 1, 1)self.n_domain 3self.G_all torch.cat([G_SHA.clone(), G_SHB.clone(),G_QNRF.clone()], dim0)self.G_all nn.Parameter(self.G_all)self.last_layer nn.Sequential(nn.Conv2d(in_channels128,out_channels64,kernel_size3,stride1,padding1),nn.BatchNorm2d(64, momentumBN_MOMENTUM),nn.ReLU(True),nn.Conv2d(in_channels64,out_channels32,kernel_size3,stride1,padding1),nn.BatchNorm2d(32, momentumBN_MOMENTUM),nn.ReLU(True),nn.Conv2d(in_channels32,out_channels1,kernel_size1,stride1,padding0),)def _make_transition_layer(self, num_channels_pre_layer,num_channels_cur_layer):num_branches_cur len(num_channels_cur_layer)num_branches_pre len(num_channels_pre_layer)transition_layers []for i in range(num_branches_cur):if i num_branches_pre:if num_channels_cur_layer[i] ! num_channels_pre_layer[i]:transition_layers.append(nn.Sequential(nn.Conv2d(num_channels_pre_layer[i],num_channels_cur_layer[i],3,1,1,biasFalse),nn.BatchNorm2d(num_channels_cur_layer[i],momentumBN_MOMENTUM), nn.ReLU(inplaceTrue)))else:transition_layers.append(None)else:conv3x3s []for j in range(i 1 - num_branches_pre):inchannels num_channels_pre_layer[-1]outchannels num_channels_cur_layer[i] \if j i - num_branches_pre else inchannelsconv3x3s.append(nn.Sequential(nn.Conv2d(inchannels, outchannels, 3, 2, 1, biasFalse),nn.BatchNorm2d(outchannels, momentumBN_MOMENTUM),nn.ReLU(inplaceTrue)))transition_layers.append(nn.Sequential(*conv3x3s))return nn.ModuleList(transition_layers)def _make_layer(self, block, inplanes, planes, blocks, stride1):downsample Noneif stride ! 1 or inplanes ! planes * block.expansion:downsample nn.Sequential(nn.Conv2d(inplanes,planes * block.expansion,kernel_size1,stridestride,biasFalse),nn.BatchNorm2d(planes * block.expansion, momentumBN_MOMENTUM),)layers []layers.append(block(inplanes, planes, stride, downsample))inplanes planes * block.expansionfor i in range(1, blocks):layers.append(block(inplanes, planes))return nn.Sequential(*layers)def _make_stage(self,layer_config,num_inchannels,multi_scale_outputTrue):num_modules layer_config[NUM_MODULES]num_branches layer_config[NUM_BRANCHES]num_blocks layer_config[NUM_BLOCKS]num_channels layer_config[NUM_CHANNELS]block blocks_dict[layer_config[BLOCK]]fuse_method layer_config[FUSE_METHOD]modules []for i in range(num_modules):# multi_scale_output is only used last moduleif not multi_scale_output and i num_modules - 1:reset_multi_scale_output Falseelse:reset_multi_scale_output Truemodules.append(HighResolutionModule(num_branches, block, num_blocks,num_inchannels, num_channels, fuse_method,reset_multi_scale_output))num_inchannels modules[-1].get_num_inchannels()return nn.Sequential(*modules), num_inchannelsdef forward(self, x):x self.conv1(x)x self.bn1(x)x self.relu(x)x self.conv2(x)x self.bn2(x)x self.relu(x)x self.layer1(x)x_head_1 xx_list []for i in range(self.stage2_cfg[NUM_BRANCHES]):if self.transition1[i] is not None:x_list.append(self.transition1[i](x))else:x_list.append(x)y_list self.stage2(x_list)x_list []for i in range(self.stage3_cfg[NUM_BRANCHES]):if self.transition2[i] is not None:x_list.append(self.transition2[i](y_list[-1]))else:x_list.append(y_list[i])x self.stage3(x_list)# Replace the classification heaeder with custom setting# Upsamplingx0_h, x0_w x[0].size(2), x[0].size(3)x1 F.interpolate(x[1], size(x0_h, x0_w), modebilinear, align_cornersFalse)x2 F.interpolate(x[2], size(x0_h, x0_w), modebilinear, align_cornersFalse)x torch.cat([x[0], x1, x2, x_head_1], 1)# first, reduce the channel downx self.redc_layer(x)pred_attn self.GAP(F.relu_(self.pred_bn(self.pred_conv(x))))pred_attn F.softmax(pred_attn, dim1)pred_attn_list torch.chunk(pred_attn, 4, dim1)aspp_out []for k, v in enumerate(self.aspp):if k % 2 0:aspp_out.append(self.aspp[k 1](v(x)))else:continue# Using Aspp add, and relu insidefor i in range(4):x x F.relu_(aspp_out[i] * 0.25) * pred_attn_list[i]bz x.size(0)# -- Besides, we also need to let the prediction attention be close to visable domain# -- Calculate the domain distance and get the weights# - First, detach domainsG_all_d self.G_all.detach() # use detached G_all for calulcatingpred_attn_d pred_attn.detach().view(bz, 512, 1, 1)if self.cosine 1:G_A, G_B, G_Q torch.chunk(G_all_d, self.n_domain, dim0)cos_dis_A F.cosine_similarity(pred_attn_d, G_A, dim1).view(-1)cos_dis_B F.cosine_similarity(pred_attn_d, G_B, dim1).view(-1)cos_dis_Q F.cosine_similarity(pred_attn_d, G_Q, dim1).view(-1)cos_dis_all torch.stack([cos_dis_A, cos_dis_B,cos_dis_Q]).view(bz, -1) # bz*3cos_dis_all F.softmax(cos_dis_all, dim1)target_attn cos_dis_all.view(bz, self.n_domain, 1, 1, 1).expand(bz, self.n_domain, 512, 1, 1) * self.G_all.view(1, self.n_domain, 512, 1, 1).expand(bz, self.n_domain, 512, 1, 1)target_attn torch.sum(target_attn, dim1, keepdimFalse) # bz * 512 * 1 * 1if self.fix_domain:target_attn target_attn.detach()else:raise ValueError(Have not implemented not cosine distance yet)x self.last_layer(x)x F.relu_(x)x F.interpolate(x, size(x0_h * 2, x0_w * 2), modebilinear, align_cornersFalse)return x, pred_attn, target_attndef init_weights(self,pretrained,):logger.info( init weights from normal distribution)for m in self.modules():if isinstance(m, nn.Conv2d):nn.init.normal_(m.weight, std0.01)if m.bias is not None:nn.init.constant_(m.bias, 0)elif isinstance(m, nn.BatchNorm2d):nn.init.constant_(m.weight, 1)nn.init.constant_(m.bias, 0)if os.path.isfile(pretrained):pretrained_dict torch.load(pretrained)logger.info(f loading pretrained model {pretrained})model_dict self.state_dict()pretrained_dict {k: vfor k, v in pretrained_dict.items() if k in model_dict.keys()}for k, _ in pretrained_dict.items():logger.info(f loading {k} pretrained model {pretrained})model_dict.update(pretrained_dict)self.load_state_dict(model_dict)else:assert 1 23.3 图片检测人群数量
接下来我们加载已经训练好的模型进行预测这里省略了中间复杂的过程大家可以一键调用预测。
from modelscope.pipelines import pipeline
from modelscope.utils.constant import Tasks
from modelscope.outputs import OutputKeys
from modelscope.utils.cv.image_utils import numpy_to_cv2img
import cv2crowd_model pipeline(Tasks.crowd_counting,modeldamo/cv_hrnet_crowd-counting_dcanet)imgs 111.png
results crowd_model(imgs)print(人数为, int(results[OutputKeys.SCORES]))vis_img results[OutputKeys.OUTPUT_IMG]
vis_img numpy_to_cv2img(vis_img)
cv2.imwrite(result1.jpg, vis_img)预测生成图 毕业合照人群计数 预测生成图
3.4 视频检测人群数量
对于视频我们可以将其分解为一系列的图像帧然后使用我们的模型来检测每一帧中的人群数量。
import cv2
from modelscope.outputs import OutputKeysdef predict_video(video_path):cap cv2.VideoCapture(video_path)while (cap.isOpened()):ret, frame cap.read()if ret:gray cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)preds crowd_model(gray)print(preds[OutputKeys.SCORES])else:breakcap.release()video_path test.mp4
predict_video(video_path)4. 结论
在这个项目中我们成功地使用深度学习模型来计算图像和视频中的人群数量。这个模型可以被广泛地应用于人流监测和管理、安全防控、市场调研和决策支持、城市规划和交通管理等领域。