论文及代码详解——可变形卷积(DCNv2)

news2024/11/15 17:52:32

文章目录

  • 论文详解
    • Stacking More Deformable Conv Layers
    • Modulated Deformable Modules
    • R-CNN Feature Mimicking
  • 代码详解

DCNv2 是在DCNv1的基础上的改进版。
理解DCNv2之前,建议先读 《论文及代码详解——可变形卷积(DCNv1)》

论文详解

DCNv2的改进主要包括如下三点

  • Stacking More Deformable Conv Layers (使用更多的可变形卷积)
  • Modulated Deformable Modules
  • R-CNN Feature Mimicking

Stacking More Deformable Conv Layers


原文翻译:
由于观察到可变形卷积网络可以在具有挑战性的基准上有效地模拟几何变换,我们大胆地用它们的可变形的对应层替换更规则的转换层。我们期望通过叠加更多可变形的转换层,可以进一步增强整个网络的几何变换建模能力。

本文在ResNet-50中,将可变形卷积应用于所有的3 × 3卷积层,在阶段conv3、conv4和conv5中。因此,网络中有12层可变形的卷积。相比之下,[8]只使用了三层可变形卷积,都在conv5阶段。在[8]中可以观察到,对于相对简单和小规模的PASCAL VOC基准,当叠加超过三层时,性能达到饱和。此外,在COCO上的误导偏移可视化可能会阻碍在更有挑战性的基准上的进一步探索。在实验中,我们观察到在conv3-conv5阶段利用可变形层实现了COCO上的目标检测的精度和效率之间的最佳权衡。详见5.2节。


个人理解:
改进点1: 使用更多的可变形卷积

  • DCNv1:ResNet-50 Conv5里边的3×3的卷积层都使用可变形卷积替换。Aligned RoI pooling 由 Deformable RoI Pooling取代。
  • DCNv2:在Conv3, Conv4, Conv5中所有的3×3的卷积层全部被替换掉。

Modulated Deformable Modules


原文翻译:
为了进一步增强可变形卷积神经网络对空间支持区域的控制能力,引入了一种调制机制。利用该方法,可变形卷积神经网络模块不仅可以调节感知输入特征的偏移量,还可以调节来自不同空间位置/ bin的输入特征幅值。在极端情况下,模块可以通过将其特征振幅设置为零来决定不接收来自特定位置/ bin的信号。因此,来自相应空间位置的图像内容将大大减少或不会对模块输出产生影响。因此,调制机制为网络模块提供了另一个自由维度来调整其空间支持区域。

给定 K K K 个采样位置的卷积核,令 w k w_k wk p k p_k pk分别表示第K个位置的权值和预先指定的偏移量。例如, K = 9 K=9 K=9 并且 p k ∈ { ( − 1 , − 1 ) , ( − 1 , 0 ) , … , ( 1 , 1 ) } p_k \in\{(-1,-1),(-1,0), \ldots,(1,1)\} pk{(1,1),(1,0),,(1,1)} 定义了一个dilation=1 的 3 × 3 3\times 3 3×3的卷积,让设 x ( p ) x(p) x(p) y ( p ) y(p) y(p)分别表示输入特征映射x和输出特征映射y中位置p的特征。调制的可变形卷积可以表示为 :

y ( p ) = ∑ k = 1 K w k ⋅ x ( p + p k + Δ p k ) ⋅ Δ m k y(p)=\sum_{k=1}^K w_k \cdot x\left(p+p_k+\Delta p_k\right) \cdot \Delta m_k y(p)=k=1Kwkx(p+pk+Δpk)Δmk

其中 ∆ p k ∆p_k pk ∆ m k ∆m_k mk分别是第 k k k个位置的可学习偏移量和调制标量。调制标量 ∆ m k ∆m_k mk在[0,1]范围内, ∆ p k ∆p_k pk为实数,范围不受约束。由于 p + p k + ∆ p k p + p_k +∆p_k p+pk+pk为分数,在计算 x ( p + p k + ∆ p k ) x(p + p_k +∆p_k) x(p+pk+pk)时,采用[8]中的双线性插值。 ∆ p k ∆p_k pk ∆ m k ∆m_k mk都是通过在相同的输入特征图 x x x上应用一个单独的卷积层得到的。这个卷积层与当前的卷积层具有相同的空间分辨率和扩张。输出是3K通道,其中前2K通道对应于学习偏移 { ∆ p k } k = 1 K \{∆p_k\}^K_{k=1} {pk}k=1K ,剩下的K通道进一步馈送到sigmoid层以获得调制标量 { ∆ m k } k = 1 K \{∆m_k\}^K_{k=1} {mk}k=1K。在这个独立的卷积层中,内核权值被初始化为零。因此, ∆ p k ∆p_k pk ∆ m k ∆m_k mk的初始值分别为0和0.5。增加的偏移和调制学习的转换层的学习速率设置为现有层的0.1倍。

modulated deformable RoIpooling的设计与此类似。给定一个输入RoI, RoIpooling将其划分为K个spatial bins(例如7 × 7)。在每个bin中,应用均匀空间间隔的采样网格(例如2 × 2)。网格上的采样值取平均值,计算bin的输出。设 ∆ p k ∆p_k pk ∆ m k ∆m_k mk为第k个bin的可学习偏移和调制标量。输出分块特征 y ( k ) y(k) y(k)计算为 :

y ( k ) = ∑ j = 1 n k x ( p k j + Δ p k ) ⋅ Δ m k / n k y(k)=\sum_{j=1}^{n_k} x\left(p_{k j}+\Delta p_k\right) \cdot \Delta m_k / n_k y(k)=j=1nkx(pkj+Δpk)Δmk/nk

其中 P k j P_{kj} Pkj为第 k k k个bin中第 j j j个网格单元的采样位置, n k n_k nk为采样的网格单元数。采用双线性插值得到特征 x ( p k j + ∆ p k ) x(p_{kj} +∆p_k) x(pkj+pk) ∆ p k ∆p_k pk ∆ m k ∆m_k mk的值由输入特征图上的一个兄弟分支产生。

在这个分支中,RoIpooling生成RoI上的特征,然后是1024-D的两个fc层(初始化为标准推导的高斯分布0.01)。在此之上,一个额外的fc层产生了3K通道的输出(权值初始化为0)。前2K通道是归一化的可学习偏移,其中计算与RoI的宽度和高度的元素级乘法,得到 ∆ p k K = 1 K {∆p_k}^K_{K =1} pkK=1K。剩余的K通道通过sigmoid层归一化产生 ∆ m k K = 1 K {∆m_k}^K_{K=1} mkK=1K。增加的偏移学习fc层的学习速率与现有层的学习速率相同。


个人理解
改进点2:添加幅值参数

  • 在DCNV1里,Deformable Conv只学习offset:

y ( p ) = ∑ k = 1 K w k ⋅ x ( p + p k + Δ p k ) y(p)=\sum_{k=1}^K w_k \cdot x\left(p+p_k+\Delta p_k\right) y(p)=k=1Kwkx(p+pk+Δpk)

  • 在DCNV2里,加入了对每个采样点的权重:

y ( p ) = ∑ k = 1 K w k ⋅ x ( p + p k + Δ p k ) ⋅ Δ m k y(p)=\sum_{k=1}^K w_k \cdot x\left(p+p_k+\Delta p_k\right) \cdot \Delta m_k y(p)=k=1Kwkx(p+pk+Δpk)Δmk

其中 Δ p k Δp_k Δpk是学到的offset, Δ m k Δm_k Δmk是学到的权重。

为了解决引入了一些无关区域的问题,在DCN v2中我们不只添加每一个采样点的偏移,还添加了一个权重系数,来区分我们引入的区域是否为我们感兴趣的区域,假如这个采样点的区域我们不感兴趣,则把权重学习为0

具体做法:

  1. Δ p k Δp_k Δpk Δ m k Δm_k Δmk都是通过在相同的输入feature map 上应用的单独卷积层获得的。 该卷积层具有与当前卷积层相同的空间分辨率。 输出为3K通道,其中前2K通道对应于学习的偏移剩余的K通道进一步馈送到sigmoid层以获得调制量

  2. 对于deformable RoIPooling,DCNV2的修改类似:

    y ( k ) = ∑ j = 1 n k x ( p k j + Δ p k ) ⋅ Δ m k / n k y(k)=\sum_{j=1}^{n_k} x\left(p_{k j}+\Delta p_k\right) \cdot \Delta m_k / n_k y(k)=j=1nkx(pkj+Δpk)Δmk/nk

    Δ p k Δp_k Δpk Δ m k Δm_k Δmk的值由输入特征图上的分支产生。 在这个分支中,RoIpooling在RoI上生成特征,然后是两个1024-D的fc层。 额外的fc层产生3K通道的输出(权重被初始化为零)。 前2K通道是可学习偏移 Δ p k Δp_k Δpk, 剩余的K个通道由sigmoid层标准化以产生 Δ m k Δm_k Δmk

R-CNN Feature Mimicking


原文翻译:
如图2所示,对于Regular ConvNets和Deformable ConvNets,每个RoI分类节点的error-bounded saliency region都可以延伸到RoI之外。因此,RoI以外的图像内容可能会影响提取的特征,从而降低最终的目标检测结果。

在[6]中,作者发现冗余上下文是Faster R-CNN检测误差的一个来源。结合其他动机(例如,在分类和边界框回归分支之间共享更少的特征),作者提出将Faster R-CNN和R-CNN的分类分数相结合,得到最终的检测分数。由于R-CNN分类分数是针对从输入的RoI中裁剪出来的图像内容进行的,将它们进行合并有助于缓解上下文冗余问题,提高检测精度。然而,由于fast - rcnn和R-CNN分支在训练和推理中都需要用到,因此该组合系统的速度较慢。

同时,可变形卷积神经网络在调整空间支持区域方面具有很强的能力。特别是对于Deformable ConvNets v2,调制的Deformable RoIpooling模块可以简单地设置bins的调制标量,以排除冗余上下文。然而,我们在第5.3节中的实验表明,即使使用调制的可变形模块,这种表示也不能通过标准的Faster R-CNN训练过程很好地学习。我们怀疑这是因为传统的Faster RCNN训练缺失不能有效地驱动这种表征的学习。需要额外的指导来指导培训。

受最近的特征模拟工作的激励[2,22,28],我们在每个roi的变形更快的R-CNN特征中加入了一个特征模拟损失,以迫使它们与从裁剪图像中提取的R-CNN特征相似。这个辅助训练目标的目的是驱动可变形更快的R-CNN学习更多像R-CNN一样的“聚焦”特征表示。我们注意到,基于图2中可视化的空间支持区域,对于图像背景上的负roi,聚焦的特征表示可能不是最优的。对于背景区域,可能需要考虑更多的上下文信息,以避免产生假阳性检测。因此,特征模拟损失只在与地真物体充分重叠的正roi上实施。

训练可变形的Faster R-CNN的网络架构如图3所示。除了 Faster R-CNN网络,添加了一个额外的R-CNN分支去feature mimicking。给定用于特征模拟的RoI b,裁剪与之对应的图像patch,并将其大小调整为224 × 224像素。在R-CNN分支中,主干网对缩放后的图像patch进行操作,生成14 × 14空间分辨率的特征图。在特征图的上方应用一个(调制的)可变形的RoIpooling层,其中输入的RoI覆盖整个缩放后的图像patch(左上角为(0,0),高度和宽度为224像素)。 然后,应用1024-D的2个fc层,得到输入图像patch的R-CNN特征表示,用 f R C N N ( b ) f_{RCNN}(b) fRCNN(b)表示。采用A (C+1)-way Softmax分类器进行分类,其中C表示前景类别的数量,1表示背景类别。在R-CNN特征表征 f R C N N ( b ) f_{RCNN}(b) fRCNN(b)和Faster R-CNN中的对应特征表征 f F R C N N ( b ) f_{FRCNN}(b) fFRCNN(b)之间实施了feature mimic loss,后者也是1024-D,由Fast R-CNN头部的2 fc层产生。feature mimic loss定义为fRCNN(b)与fFRCNN(b)的余弦相似度,计算为 :

L mimic  = ∑ b ∈ Ω [ 1 − cos ⁡ ( f R C N N ( b ) , f F R C N N ( b ) ) ] L_{\text {mimic }}=\sum_{b \in \Omega}\left[1-\cos \left(f_{\mathrm{RCNN}}(b), f_{\mathrm{FRCNN}}(b)\right)\right] Lmimic =bΩ[1cos(fRCNN(b),fFRCNN(b))]

其中Ω表示用于feature mimic training 的采样roi集合。在SGD训练中,给定一个输入图像,将RPN生成的32个positive region proposal 随机采样到Ω中。cross-entropy classification loss在R-CNN分类头上执行,也在Ω中的roi上计算。网络训练是由feature miimc loss和R-CNN分类损失以及Faster R-CNN中原始损失项驱动的。新引入的两个损失项的损失权是原来Faster R-CNN损失项的0.1倍。R-CNN和Faster R-CNN分支中相应模块之间的网络参数共享,包括骨干网、(modulated) deformable RoIpooling 和2个fc头(两个分支的分类头不共享)。在推理阶段,测试图像只使用Faster R-CNN网络,不使用辅助的R-CNN分支。因此,在推理中,R-CNN feature mimicking没有引入额外的计算。

在这里插入图片描述


个人理解:
改进点3: 提出了特征模拟方案指导网络培训

  • 《Revisiting RCNN: On Awakening the Classification Power of Faster RCNN》发现把R-CNN和Faster RCNN的classification score结合起来可以提升performance,说明R-CNN学到的focus在物体上的feature可以解决redundant context(上下文无关)的问题。但是增加额外的R-CNN会使inference速度变慢很多。
  • DCNV2里的解决方法是把R-CNN当做teacher network,让DCNV2的ROIPooling之后的feature去模拟R-CNN的feature。
  • 左边的网络为主网络(Faster RCNN),右边的网络为子网络(RCNN)。实现上大致是用主网络训练过程中得到的RoI去裁剪原图,然后将裁剪到的图resize到224×224大小作为子网络的输入,这部分最后提取的特征和主网络输出的1024维特征作为feature mimicking loss的输入,用来约束这2个特征的差异(通过一个余弦相似度计算)
  • 同时子网络通过一个分类损失进行监督学习,因为并不需要回归坐标,所以没有回归损失。在inference阶段仅有主网络部分,因此这个操作不会在inference阶段增加计算成本。
  • 因为RCNN这个子网络的输入就是RoI在原输入图像上裁剪出来的图像,因此不存在RoI以外区域信息的干扰,这就使得RCNN这个网络训练得到的分类结果更加可靠,以此通过一个损失函数监督主网络Faster RCNN的分类支路训练就能够使网络提取到更多RoI内部特征,而不是自己引入的外部特征。

代码详解

DCNv2的代码就是在DCNv1( DCNv1代码的详细讲解)的基础上加了权重项sigmoid。
此处代码不再详细注释,只标注和V1不同的地方

import torch
from torch import nn


class DeformConv2d(nn.Module):
    def __init__(self, inc, outc, kernel_size=3, padding=1, stride=1, bias=None, modulation=False):
        """
        新增modulation 参数: 是DCNv2中引入的调制标量
        """
        super(DeformConv2d, self).__init__()
        self.kernel_size = kernel_size
        self.padding = padding
        self.stride = stride
        self.zero_padding = nn.ZeroPad2d(padding)
        self.conv = nn.Conv2d(inc, outc, kernel_size=kernel_size, stride=kernel_size, bias=bias) 

        self.p_conv = nn.Conv2d(inc, 2*kernel_size*kernel_size, kernel_size=3, padding=1, stride=stride)
        # 输出通道是2N
        nn.init.constant_(self.p_conv.weight, 0) #权重初始化为0
        self.p_conv.register_backward_hook(self._set_lr)
        
        self.modulation = modulation
        if modulation: # 如果需要进行调制
        	# 输出通道是N
            self.m_conv = nn.Conv2d(inc, kernel_size*kernel_size, kernel_size=3, padding=1, stride=stride)
            nn.init.constant_(self.m_conv.weight, 0)
            self.m_conv.register_backward_hook(self._set_lr) # 在指定网络层执行完backward()之后调用钩子函数

    @staticmethod
    def _set_lr(module, grad_input, grad_output): # 设置学习率的大小
        grad_input = (grad_input[i] * 0.1 for i in range(len(grad_input)))
        grad_output = (grad_output[i] * 0.1 for i in range(len(grad_output)))

    def forward(self, x): # x: (b,c,h,w)
        offset = self.p_conv(x) # (b,2N,h,w) 学习到的偏移量 2N表示在x轴方向的偏移和在y轴方向的偏移
        if self.modulation: # 如果需要调制
            m = torch.sigmoid(self.m_conv(x))  # (b,N,h,w) 学习到的N个调制标量

        dtype = offset.data.type()
        ks = self.kernel_size
        N = offset.size(1) // 2

        if self.padding:
            x = self.zero_padding(x)

        # (b, 2N, h, w)
        p = self._get_p(offset, dtype)

        # (b, h, w, 2N)
        p = p.contiguous().permute(0, 2, 3, 1)
        q_lt = p.detach().floor()
        q_rb = q_lt + 1

        q_lt = torch.cat([torch.clamp(q_lt[..., :N], 0, x.size(2)-1), torch.clamp(q_lt[..., N:], 0, x.size(3)-1)], dim=-1).long()
        q_rb = torch.cat([torch.clamp(q_rb[..., :N], 0, x.size(2)-1), torch.clamp(q_rb[..., N:], 0, x.size(3)-1)], dim=-1).long()
        q_lb = torch.cat([q_lt[..., :N], q_rb[..., N:]], dim=-1)
        q_rt = torch.cat([q_rb[..., :N], q_lt[..., N:]], dim=-1)

        # clip p
        p = torch.cat([torch.clamp(p[..., :N], 0, x.size(2)-1), torch.clamp(p[..., N:], 0, x.size(3)-1)], dim=-1)

        # bilinear kernel (b, h, w, N)
        g_lt = (1 + (q_lt[..., :N].type_as(p) - p[..., :N])) * (1 + (q_lt[..., N:].type_as(p) - p[..., N:]))
        g_rb = (1 - (q_rb[..., :N].type_as(p) - p[..., :N])) * (1 - (q_rb[..., N:].type_as(p) - p[..., N:]))
        g_lb = (1 + (q_lb[..., :N].type_as(p) - p[..., :N])) * (1 - (q_lb[..., N:].type_as(p) - p[..., N:]))
        g_rt = (1 - (q_rt[..., :N].type_as(p) - p[..., :N])) * (1 + (q_rt[..., N:].type_as(p) - p[..., N:]))

        # (b, c, h, w, N)
        x_q_lt = self._get_x_q(x, q_lt, N)
        x_q_rb = self._get_x_q(x, q_rb, N)
        x_q_lb = self._get_x_q(x, q_lb, N)
        x_q_rt = self._get_x_q(x, q_rt, N)

        # (b, c, h, w, N)
        x_offset = g_lt.unsqueeze(dim=1) * x_q_lt + \
                   g_rb.unsqueeze(dim=1) * x_q_rb + \
                   g_lb.unsqueeze(dim=1) * x_q_lb + \
                   g_rt.unsqueeze(dim=1) * x_q_rt

        # 如果需要调制
        if self.modulation: # m: (b,N,h,w)
            m = m.contiguous().permute(0, 2, 3, 1) # (b,h,w,N)
            m = m.unsqueeze(dim=1) # (b,1,h,w,N)
            m = torch.cat([m for _ in range(x_offset.size(1))], dim=1) # (b,c,h,w,N)
            x_offset *= m # 为偏移添加调制标量

        x_offset = self._reshape_x_offset(x_offset, ks)
        out = self.conv(x_offset)

        return out

    def _get_p_n(self, N, dtype):
        p_n_x, p_n_y = torch.meshgrid(
            torch.arange(-(self.kernel_size-1)//2, (self.kernel_size-1)//2+1),
            torch.arange(-(self.kernel_size-1)//2, (self.kernel_size-1)//2+1))
        # (2N, 1)
        p_n = torch.cat([torch.flatten(p_n_x), torch.flatten(p_n_y)], 0)
        p_n = p_n.view(1, 2*N, 1, 1).type(dtype)

        return p_n

    def _get_p_0(self, h, w, N, dtype):
        p_0_x, p_0_y = torch.meshgrid(
            torch.arange(1, h*self.stride+1, self.stride),
            torch.arange(1, w*self.stride+1, self.stride))
        p_0_x = torch.flatten(p_0_x).view(1, 1, h, w).repeat(1, N, 1, 1)
        p_0_y = torch.flatten(p_0_y).view(1, 1, h, w).repeat(1, N, 1, 1)
        p_0 = torch.cat([p_0_x, p_0_y], 1).type(dtype)

        return p_0

    def _get_p(self, offset, dtype):
        N, h, w = offset.size(1)//2, offset.size(2), offset.size(3)

        # (1, 2N, 1, 1)
        p_n = self._get_p_n(N, dtype)
        # (1, 2N, h, w)
        p_0 = self._get_p_0(h, w, N, dtype)
        p = p_0 + p_n + offset
        return p

    def _get_x_q(self, x, q, N):
        b, h, w, _ = q.size()
        padded_w = x.size(3)
        c = x.size(1)
        # (b, c, h*w)
        x = x.contiguous().view(b, c, -1)

        # (b, h, w, N)
        index = q[..., :N]*padded_w + q[..., N:]  # offset_x*w + offset_y
        # (b, c, h*w*N)
        index = index.contiguous().unsqueeze(dim=1).expand(-1, c, -1, -1, -1).contiguous().view(b, c, -1)

        x_offset = x.gather(dim=-1, index=index).contiguous().view(b, c, h, w, N)

        return x_offset

    @staticmethod
    def _reshape_x_offset(x_offset, ks):
        b, c, h, w, N = x_offset.size()
        x_offset = torch.cat([x_offset[..., s:s+ks].contiguous().view(b, c, h, w*ks) for s in range(0, N, ks)], dim=-1)
        x_offset = x_offset.contiguous().view(b, c, h*ks, w*ks)

        return x_offset

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据结构单链表

单链表 1 链表的概念及结构 概念:链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链 接次序实现的 。 在我们开始讲链表之前,我们是写了顺序表,顺序表就是类似一个数组的东西&#xff0…

651页23万字智慧教育大数据信息化顶层设计及建设方案WORD

导读:原文《651页23万字智慧教育大数据信息化顶层设计及建设方案WORD》(获取来源见文尾),本文精选其中精华及架构部分,逻辑清晰、内容完整,为快速形成售前方案提供参考。 目录 一、 方案背景 1.1 以教育…

三、数据类型

1、数值类型 (1)分类: (2)注意: 存储某一类数据,如果只想要表示整数,则在其后加unsigned即可; 在表示小数时,需要指明该小数的总长度和小数部分的长度&…

PostgreSQL空值的判断

PostgreSQL空值的判断 空值判断非空判断总结 空值判断 -- 查询为空的 is null,sql简写isnull select * from employees where manager_id isnull;select * from employees where manager_id is null;非空判断 -- 查询不为空的 is not null;sql简写notnull select * from empl…

c++基本语法

c基础语法 由于长时间没有使用过c&#xff0c;因此c的语法已经忘得差不多了&#xff0c;这篇文章主要是快读地过一遍c的基本语法。之前也写过一篇从c过渡到c的文章&#xff0c;有兴趣地可以看看。 文章链接 1.c的安装 mingw64的安装配置环境变量 2.语法 #include<iostre…

leetcode 力扣刷题 两数/三数/四数之和 哈希表和双指针解题

两数/三数/四数之和 题目合集 哈希表求解1. 两数之和454. 四数相加Ⅱ 双指针求解15.三数之和18. 四数之和 这个博客是关于&#xff1a;找出数组中几个元素&#xff0c;使其之和等于题意给出的target 这一类题目的&#xff0c;但是各个题之间又有些差异&#xff0c;使得需要用不…

网络及其计算的重点知识及回顾

概述 1.1 计算机网络的分类 按照网络的作用范围&#xff1a;广域网&#xff08;WAN&#xff09;、城域网&#xff08;MAN&#xff09;、局域网&#xff08;LAN&#xff09;&#xff1b; 按照网络使用者&#xff1a;公用网络、专用网络。 1.2 计算机网络的层次结构 应用层&a…

谷歌云平台替代超级计算机?助力心脏病学研究,省心智能还省钱

哈佛大学的研究团队在使用谷歌云平台代替超级计算机进行心脏病研究方面取得了重大突破。通常情况下&#xff0c;进行模拟人体循环系统中血块和肿瘤细胞的疗法需要强大的计算能力才能提供准确的结果。然而&#xff0c;超级计算机的高昂成本和有限的可用性成为这项研究面临的巨大…

Qt+Pyhton实现麒麟V10系统下word文档读写功能

目录 前言1.C调用python1.1 安装Python开发环境1.2 修改Qt工程配置1.3 初始化Python环境1.4 C 调用Python 函数1.5 常用的Python接口 2.python虚拟环境2.1Python虚拟环境简介2.2 virtualenv 安装及使用2.3 在C程序中配置virtualenv 虚拟环境 3.python-docx库的应用4.总结 前言 …

【计算机网络篇】UDP协议

✅作者简介&#xff1a;大家好&#xff0c;我是小杨 &#x1f4c3;个人主页&#xff1a;「小杨」的csdn博客 &#x1f433;希望大家多多支持&#x1f970;一起进步呀&#xff01; UDP协议 1&#xff0c;UDP 简介 UDP&#xff08;User Datagram Protocol&#xff09;是一种无连…

集成DTM实现跨语言分布式事务V1.0

集成DTM实现跨语言分布式事务V1.0 简介 DTM是一款开源的分布式事务管理器&#xff0c;解决跨数据库、跨服务、跨语言栈更新数据的一致性问题。 通俗一点说&#xff0c;DTM提供跨服务事务能力&#xff0c;一组服务要么全部成功&#xff0c;要么全部回滚&#xff0c;避免只更新…

Qt编程基础 | 第六章-窗体 | 6.5、QTableWidget 使用过程注意的问题

一、QTableWidget 使用过程注意的问题 1、添加行时要先设置行数 往表格重添加行时&#xff0c;要先设置行数&#xff0c;不然添加的内容看不到&#xff0c;如下&#xff1a; void QCustomWidget::InitTableContent() {for (int row 0; row < m_rowData.size(); row ){// 注…

DAY4,ARM(用c语言点亮LED灯,封装库代码,软件编程控制硬件)

---gpio.h头文件--- #ifndef __LED_H__ #define __LED_H__//1RCC_MP_AHB4ENSETR寄存器封装 #define RCC_MP_AHB4ENSETR (*(volatile unsigned int*)0x50000a28)//2GPIO封装结构体 typedef struct {volatile unsigned int MODER;volatile unsigned int OTYPER;volatile unsigne…

Python系统学习1-9-类二之MVC框架

一、模型说明 View视图:处理界面逻辑,输入输出 Controller控制器:处理核心逻辑,存储计算 Model模型:将多个变量组合为一种类型 二、注意事项 类外通过自定义对象名调用 类中通过self调用 """疫情信息管理系统学习MVC的软件架构View Controller Model视…

汇川脉冲伺服SV630P常用参数设置(博途PLC脉冲输出控制)

有关博途PLC脉冲输出控制功能块详细介绍,请查看下面博客链接: 博途1200PLC轴控功能块(脉冲轴)_博图 轴控块_RXXW_Dor的博客-CSDN博客STRUCT// 轴使能// 轴正向点动// 轴反向点动// 轴回原// 轴复位// 轴暂停// 轴快速停机// 轴绝对定位// 轴相对定位// 轴匀速运行// 修改轴参…

Dubbo基础学习

目录 第一章、概念介绍1.1&#xff09;什么是RPC框架1.2&#xff09;什么是分布式系统1.3&#xff09;Dubbo概述1.3&#xff09;Dubbo基本架构 第二章、服务提供者(直连)2.1&#xff09;目录结构和依赖2.2&#xff09;model层2.3&#xff09;service层2.4&#xff09;resources…

Java课题笔记~ 日期处理

2.8 日期处理 2.8.1 日期注入 日期类型不能自动注入到方法的参数中。需要单独做转换处理。 使用DateTimeFormat注解&#xff0c;需要在springmvc.xml文件中添加mvc:annotation-driven/标签。 &#xff08;1&#xff09;在方法的参数上使用DateTimeFormat注解 RequestMappi…

浅谈SPA

1. 基本概念 ● SPA(single-page application) 单页应用,默认情况下我们编写Vue,React都只有一个html页面并且提供一个挂载点,最终打包后会在此页面中引入对应的资源.(页面渲染全部由js动态进行渲染).切换页面时通过监听路由变化,渲染对应的页面(client side rendering,客户端…

探秘分布式大数据:融合专业洞见,燃起趣味火花,启迪玄幻思维

文章目录 一 数据导论二 大数据的诞生三 大数据概论3.1 大数据的5V特征3.2 大数据的工作核心 四 大数据软件生态4.1 数据存储软件4.2 数据计算软件4.3 数据传输软件 五 Apache Hadoop概述5.1 Apache Hadoop框架5.2 Hadoop的功能5.3 Hadoop的发展5.4 Hadoop发行版本 一 数据导论…