计算机视觉的应用17-利用CrowdCountNet模型解决人群数量计算问题(pytorch搭建模型)

大家好,我是微学AI,今天给大家介绍一下计算机视觉的应用17-利用CrowdCountNet模型解决人群数量计算问题(pytorch搭建模型)。本篇文章,我将向大家展示如何使用CrowdCountNet这个神奇的工具,以及它是如何利用深度学习技术来解决复杂的人群计数问题。让我们一起进入这个充满活力和创新的世界,开启图像和视频中人群数量计算的新篇章!

目录

  1. 项目介绍
  2. 应用场景
    • 人流监测和管理
    • 安全防控
    • 市场调研和决策支持
    • 城市规划和交通管理
  3. 实战项目
    • 数据准备
    • 模型构建
    • 模型训练
    • 图片检测人群数量
    • 视频检测人群数量
  4. 结论

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 OrderedDict

class CrowdCountNet(nn.Module):

    def __init__(self,
                 leaky_relu=False,
                 attn_weight=1,
                 fix_domain=1,
                 domain_center_model='',
                 **kwargs):
        super(CrowdCountNet, self).__init__()

        self.criterion_attn = torch.nn.MSELoss(reduction='sum')
        self.domain_center_model = domain_center_model
        self.attn_weight = attn_weight
        self.fix_domain = fix_domain
        self.cosine = 1

        self.conv1 = nn.Conv2d(
            3, 64, kernel_size=3, stride=2, padding=1, bias=False)
        self.bn1 = nn.BatchNorm2d(64, momentum=BN_MOMENTUM)
        self.conv2 = nn.Conv2d(
            64, 64, kernel_size=3, stride=2, padding=1, bias=False)
        self.bn2 = nn.BatchNorm2d(64, momentum=BN_MOMENTUM)
        self.relu = nn.ReLU(inplace=True)

        num_channels = 64
        block = blocks_dict['BOTTLENECK']
        num_blocks = 4
        self.layer1 = self._make_layer(block, 64, num_channels, num_blocks)
        stage1_out_channel = block.expansion * num_channels

        # -- stage 2
        self.stage2_cfg = {}
        self.stage2_cfg['NUM_MODULES'] = 1
        self.stage2_cfg['NUM_BRANCHES'] = 2
        self.stage2_cfg['BLOCK'] = 'BASIC'
        self.stage2_cfg['NUM_BLOCKS'] = [4, 4]
        self.stage2_cfg['NUM_CHANNELS'] = [40, 80]
        self.stage2_cfg['FUSE_METHOD'] = 'SUM'

        num_channels = self.stage2_cfg['NUM_CHANNELS']
        block = blocks_dict[self.stage2_cfg['BLOCK']]
        num_channels = [
            num_channels[i] * block.expansion
            for 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 3
        self.stage3_cfg = {}
        self.stage3_cfg['NUM_MODULES'] = 4
        self.stage3_cfg['NUM_BRANCHES'] = 3
        self.stage3_cfg['BLOCK'] = 'BASIC'
        self.stage3_cfg['NUM_BLOCKS'] = [4, 4, 4]
        self.stage3_cfg['NUM_CHANNELS'] = [40, 80, 160]
        self.stage3_cfg['FUSE_METHOD'] = 'SUM'

        num_channels = self.stage3_cfg['NUM_CHANNELS']
        block = blocks_dict[self.stage3_cfg['BLOCK']]
        num_channels = [
            num_channels[i] * block.expansion
            for 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)) + 256
        self.redc_layer = nn.Sequential(
            nn.Conv2d(
                in_channels=last_inp_channels,
                out_channels=128,
                kernel_size=3,
                stride=1,
                padding=1),
            nn.BatchNorm2d(128, momentum=BN_MOMENTUM),
            nn.ReLU(True),
        )

        self.aspp = nn.ModuleList(aspp(in_channel=128))

        # additional layers specfic for Phase 3
        self.pred_conv = nn.Conv2d(128, 512, 3, padding=1)
        self.pred_bn = nn.BatchNorm2d(512)
        self.GAP = nn.AdaptiveAvgPool2d(1)

        # Specially for hidden domain
        # Set the domain for learnable parameters
        domain_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 = 3

        self.G_all = torch.cat(
            [G_SHA.clone(), G_SHB.clone(),
             G_QNRF.clone()], dim=0)

        self.G_all = nn.Parameter(self.G_all)

        self.last_layer = nn.Sequential(
            nn.Conv2d(
                in_channels=128,
                out_channels=64,
                kernel_size=3,
                stride=1,
                padding=1),
            nn.BatchNorm2d(64, momentum=BN_MOMENTUM),
            nn.ReLU(True),
            nn.Conv2d(
                in_channels=64,
                out_channels=32,
                kernel_size=3,
                stride=1,
                padding=1),
            nn.BatchNorm2d(32, momentum=BN_MOMENTUM),
            nn.ReLU(True),
            nn.Conv2d(
                in_channels=32,
                out_channels=1,
                kernel_size=1,
                stride=1,
                padding=0),
        )

    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,
                                bias=False),
                            nn.BatchNorm2d(
                                num_channels_cur_layer[i],
                                momentum=BN_MOMENTUM), nn.ReLU(inplace=True)))
                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 inchannels
                    conv3x3s.append(
                        nn.Sequential(
                            nn.Conv2d(
                                inchannels, outchannels, 3, 2, 1, bias=False),
                            nn.BatchNorm2d(outchannels, momentum=BN_MOMENTUM),
                            nn.ReLU(inplace=True)))
                transition_layers.append(nn.Sequential(*conv3x3s))

        return nn.ModuleList(transition_layers)

    def _make_layer(self, block, inplanes, planes, blocks, stride=1):
        downsample = None
        if stride != 1 or inplanes != planes * block.expansion:
            downsample = nn.Sequential(
                nn.Conv2d(
                    inplanes,
                    planes * block.expansion,
                    kernel_size=1,
                    stride=stride,
                    bias=False),
                nn.BatchNorm2d(planes * block.expansion, momentum=BN_MOMENTUM),
            )

        layers = []
        layers.append(block(inplanes, planes, stride, downsample))
        inplanes = planes * block.expansion
        for i in range(1, blocks):
            layers.append(block(inplanes, planes))

        return nn.Sequential(*layers)

    def _make_stage(self,
                    layer_config,
                    num_inchannels,
                    multi_scale_output=True):
        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 module
            if not multi_scale_output and i == num_modules - 1:
                reset_multi_scale_output = False
            else:
                reset_multi_scale_output = True

            modules.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_inchannels

    def 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 = x

        x_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
        # Upsampling
        x0_h, x0_w = x[0].size(2), x[0].size(3)
        x1 = F.interpolate(
            x[1], size=(x0_h, x0_w), mode='bilinear', align_corners=False)
        x2 = F.interpolate(
            x[2], size=(x0_h, x0_w), mode='bilinear', align_corners=False)
        x = torch.cat([x[0], x1, x2, x_head_1], 1)
        # first, reduce the channel down
        x = self.redc_layer(x)

        pred_attn = self.GAP(F.relu_(self.pred_bn(self.pred_conv(x))))
        pred_attn = F.softmax(pred_attn, dim=1)
        pred_attn_list = torch.chunk(pred_attn, 4, dim=1)

        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 inside
        for 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 domains
        G_all_d = self.G_all.detach()  # use detached G_all for calulcating
        pred_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, dim=0)

            cos_dis_A = F.cosine_similarity(pred_attn_d, G_A, dim=1).view(-1)
            cos_dis_B = F.cosine_similarity(pred_attn_d, G_B, dim=1).view(-1)
            cos_dis_Q = F.cosine_similarity(pred_attn_d, G_Q, dim=1).view(-1)

            cos_dis_all = torch.stack([cos_dis_A, cos_dis_B,
                                       cos_dis_Q]).view(bz, -1)  # bz*3

            cos_dis_all = F.softmax(cos_dis_all, dim=1)

            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, dim=1, keepdim=False)  # bz * 512 * 1 * 1

            if 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), mode='bilinear', align_corners=False)

        return x, pred_attn, target_attn

    def 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, std=0.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: v
                for 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 == 2

3.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 cv2

crowd_model = pipeline(Tasks.crowd_counting,model='damo/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 OutputKeys

def 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:
            break

    cap.release()


video_path = 'test.mp4'
predict_video(video_path)

4. 结论

在这个项目中,我们成功地使用深度学习模型来计算图像和视频中的人群数量。这个模型可以被广泛地应用于人流监测和管理、安全防控、市场调研和决策支持、城市规划和交通管理等领域。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/153863.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

《增长黑客》思维导图

增长黑客这个词源于硅谷&#xff0c;简单说&#xff0c;这是一群以数据驱动营销、以迭代验证策略&#xff0c;通过技术手段实现爆发式增长的新型人才。 近年来&#xff0c;互联网公司意识到这一角色可以发挥四两拨千斤的作用&#xff0c;因此对该职位的需求也如井喷式增长。本…

营业执照识别

目录 1、制作文本检测数据集 2、导出文本检测推理模型 3、制作语义实体识别数据集 4、训练模型 5、模型预测 6、模型导出 7、模型推理 1、制作文本检测数据集 文本检测数据集格式如下&#xff1a; dataset_dir # 数据集根目录&#xff0c;目录名称可以改变 ├── im…

【广州华锐互动】VR模拟真实火灾场景,教你如何正确逃生和自救

随着科技的不断发展&#xff0c;人们对于安全教育的需求也在不断提高。在消防安全领域&#xff0c;传统的培训方式已经无法满足现代社会的需求。为了提高人们的消防安全意识&#xff0c;提升应急处理能力&#xff0c;VR火灾自救逃生体验系统应运而生。 VR火灾自救逃生体验系统是…

金蝶云星空其他出库单保存提示序列号不一致

文章目录 金蝶云星空其他出库单保存提示序列号不一致保存报错初步分析总结 金蝶云星空其他出库单保存提示序列号不一致 保存报错 显示单据数量0.序列号数量3 初步分析 输入实发数量没有触发序列号数量的计算 检查实发数量的值更新事件 实发数量和序列号数量的转换&#xff…

我把MySQL运行在Docker上,差点完了……

容器的定义&#xff1a;容器是为了解决“在切换运行环境时&#xff0c;如何保证软件能够正常运行”这一问题。 目前&#xff0c;容器和 Docker 依旧是技术领域最热门的词语&#xff0c;无状态的服务容器化已经是大势所趋&#xff0c;同时也带来了一个热点问题被大家所争论不以&…

LeetCode【41】缺失的第一个正数

题目&#xff1a; 分析&#xff1a; 第i个位置的数&#xff0c;如果再数组 0到length-1范围内&#xff0c;则将其放到对应的位置&#xff1b; 再遍历一遍数组&#xff0c;找到第一个不在位置i的正数数字&#xff0c;即为所求 思路&#xff1a;https://blog.csdn.net/weixin_45…

【docker启动的Jenkins时,遇到时区问题处理】

1、查看容器中的时区 [rootlocalhost jenkins]# docker exec -it jenkins cat /etc/timezone Etc/UTC而本地使用的是Asia/shanghai [rootlocalhost jenkins]# timedatectl | grep Time zoneTime zone: n/a (CST, 0800)###查看 [rootlocalhost jenkins]# cd /usr/share/zoneinf…

代码随想录算法训练营|五十五天

两个字符串的删除操作 583. 两个字符串的删除操作 - 力扣&#xff08;LeetCode&#xff09; 因为两个字符串都能删除&#xff0c;所以字符不匹配的话就有三个方向取最小值赋值给dp[i,j]&#xff0c;不过这里dp[i-1,j-1]2dp[i,j-1]1&#xff0c;从字面上理解 就是 当 同时删wo…

软件外包开发文档工具

有许多工具可用于生成和管理软件开发文档。这些工具可以帮助团队更有效地协作、记录和维护文档。以下是一些常用的软件开发文档生成工具&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 Javadoc&#…

软件测试面试-如何定位线上出现bug

其实无论是线上还是在测试出现bug&#xff0c;我们核心的还是要定位出bug出现的原因。 定位出bug的步骤&#xff1a; 1&#xff0c;如果是必现的bug&#xff0c;尽可能的复现出问题&#xff0c;找出引发问题的操作步骤。很多时候&#xff0c;一个bug的产生&#xff0c;很多时…

GBase8a-GDCA-第二次阶段测试

文章目录 主要内容在这里插入图片描述 ![在这里插入图片描述](https://img-blog.csdnimg.cn/1d552b9d6d204f4fb4280ccc52807ed5.png)在这里插入图片描述 总结 主要内容 GBase8a-GDCA-第二次阶段测试及答案 总结 以上是今天要讲的内容&#xff0c;GBase8a-GDCA-第二次阶段测试…

字母不重复的子串-第15届蓝桥第二次STEMA测评Scratch真题精选

[导读]&#xff1a;超平老师的《Scratch蓝桥杯真题解析100讲》已经全部完成&#xff0c;后续会不定期解读蓝桥杯真题&#xff0c;这是Scratch蓝桥杯真题解析第158讲。 第15届蓝桥第2次STEMA测评已于2023年10月29日落下帷幕&#xff0c;编程题一共有6题&#xff0c;分别如下&am…

矩阵起源到此一游:千岛湖(内含海量招聘岗位)

秋意渐浓&#xff0c;正值金秋时节&#xff0c;MO 也出去玩啦&#xff01; 海量招聘岗位&#xff0c;点击链接一键查看&#xff0c;就等您来&#xff1a; 「矩阵起源招聘」2023年矩阵起源招聘信息-BOSS直聘​www.zhipin.com/gongsi/job/59a68fecfe392c0d1nd93N-4EVU~.html​编…

放松鸭-技术支持

“放松鸭”利用苹果手表的HRV心率变异性和静息心率等数据进行分析&#xff0c;帮助您了解当前身体疲劳和心理压力程度&#xff0c;并及时提醒您的压力状态。我们的目标是让您更好地感知、管理和应对压力&#xff0c;让您的身心得到平静和放松。通过读取您的心脏数据&#xff0c…

MySQL数据库入门到大牛_基础_08__聚合函数(常用的5种聚合函数;GROUP BY分组;HAVING使用及与WHERE的对比;SELECT的执行过程)

我们上一章讲到了 SQL 单行函数。实际上 SQL 函数还有一类内置函数&#xff0c;叫做聚合&#xff08;或聚集、分组&#xff09;函数&#xff0c;它是对一组数据进行汇总的函数&#xff0c;输入的是一组数据的集合&#xff0c;输出的是单个值。即使输出多个值&#xff0c;也得作…

嵌套的iframe页面中rem字号变小问题处理

问题原因 如果 html 的 font-size: 100px&#xff0c;那字号为0.16rem的字实际为100px * 0.16 16px 故最外层的html的字号 与iframe下的html字号 不相同时&#xff0c;则会导致iframe页面内的字体字号存在问题 解决办法 先获取外层html的font-size const fontSize par…

订水商城实战教程10-宫格导航

上一篇我们介绍了跑马灯的功能&#xff0c;这一篇就进入到我们的主体部分开发。在订水商城业务中可以按照分类查询商品信息&#xff0c;这就涉及到数据源的拆分。 我们在数据源的设计中区分为主子表&#xff0c;主表呢存储唯一的记录&#xff0c;子表的记录可以重复&#xff0…

营收净利双降、市值蒸发50亿,莱克电气苦战双11

文 | 不二研究 若楠 熊生 新增长难寻&#xff0c;新故事难讲。莱克电气股份有限公司(下称“莱克电气”&#xff0c;603355.SH)承压的困局&#xff0c;都写在最新的三季报里。 今年双11前夕&#xff0c;全国吸尘器ODM龙头莱克电气公布了2023年三季报&#xff0c;其前三季度营收…

软件测试,如何月薪过万?

月薪过万这个话题&#xff0c;在现在这个百花齐放的职场里是个很流行的命题。 月薪过万对于行业大佬来说&#xff0c;可能是个不屑一顾的追求&#xff0c;但对于职场新人而言通常是个很实际的人生目标。 我怎么样能达到月薪过万呢&#xff0c;其实严格来说&#xff0c;要找到…

酸性设计——它的独特性和特点都在这里了

酸性设计,一个出乎意料且奇特的概念&#xff0c;实则蕴藏着丰富的创意设计思维和科学内涵。这一术语首次被引入设计领域&#xff0c;是为了探索化学元素在设计中的独特魅力和无限可能。现在&#xff0c;让我们一起进入酸性设计的世界&#xff0c;揭示其独特之处&#xff0c;理解…