NeRF神经辐射场渲染过程详解,三维重建渲染过程基本原理_光线采样sample_pdf()和光线渲染render_rays ()代码详解

news2024/11/24 16:59:30

目录

1 神经辐射场

1.1 基本原理

1.2 基本流程

 1.3 数学解释

2 三维场景图像渲染详解

2.1射线采样

2.2 NeRF 模型预测

2.3 体积渲染

3 采样与渲染代码详解 (rending.py)

3.1 神经体积渲染代码解析

3.2 sample_pdf 函数

3.3 render_rays 函数


1 神经辐射场

        神经辐射场(Neural Radiance Fields,NeRF)是一种用于生成三维场景的方法,其核心概念是使用神经网络来学习场景中光线的辐射属性。NeRF 通过学习场景中密度和颜色随着光线方向的变化而变化的函数来实现。

1.1 基本原理

        NeRF 试图学习将三维场景中每个点(或每个空间方向)处的颜色和密度映射到对应的 RGB 颜色值和密度值。NeRF 假设场景中的辐射函数(radiance function)是光线方向的连续函数,它描述了从特定方向观察场景时,光线的颜色和密度如何随着距离而变化。

1.2 基本流程

  1. 场景表示: NeRF用场景中的点来表示三维物体。每个点包括其三维位置(空间坐标)和对应的颜色。而场景中的每个点都对应于射线空间的采样点,即相机到场景中某一点的射线上的所有采样点。

  2. 神经网络建模: NeRF使用神经网络来表示场景中的辐射场,将这个场景建模为一个密集的、连续的辐射场。这个场景可以被看作是一个从空间坐标到颜色和密度的函数映射。

  3. 采样和渲染: NeRF利用相机射线对场景进行采样,即对射线上的点进行密集采样。通过神经网络,为每个采样点估计其颜色和密度。这些信息被用于计算渲染图像时,即从相机视点沿射线渲染的过程。


 1.3 数学解释

  1. 场景表示: NeRF将场景表示为一个由空间坐标 �x 到颜色和密度的函数映射,即 f:x→(C(x),σ(x)),其中C(x) 表示颜色,σ(x) 表示密度。对于一个场景中的点 x,这个函数会返回该点的颜色和密度。

  2. 辐射场建模: NeRF采用了一个深度神经网络,这个网络被称为 NeRF。这个网络输入场景中的点 x,输出其颜色和密度。这种函数表示法是一个用于密集、连续辐射场的表示。这个神经网络采用了 MLP(多层感知器)的结构。

  3. 采样和渲染: 对于每个相机射线上的点 x,NeRF会对其进行密集采样,获得该点的颜色和密度估计值。这些估计值被用于渲染图像,计算从相机视点沿射线到达的颜色值。通过对采样点进行体积渲染和光线投射,得到了最终的渲染图像。

总的来说,NeRF利用神经网络对场景中的辐射场进行建模,然后对相机射线进行采样和渲染,以生成逼真的三维场景渲染图像。


2 三维场景图像渲染详解

2.1射线采样

对于每个像素,NeRF会沿着相机视点到场景中的某一点的射线进行采样。这些采样点代表了相机到场景中特定点的视线路径。

  • 射线表示:对于每个像素 (i,j),相机位置为 o,在图像平面上的点到场景中的某一点 p 的射线由其方向向量 d=normalize(p−o) 表示。这个射线由射线的原点 o 和方向 d 表示。

    • NeRF 在每个像素处发出一条射线,从相机通过像素位置发出。这些光线在场景中传播,并与场景中的物体相交。每条光线由其起点和方向向量定义。

  • 采样点:每条射线由一系列采样点组成,这些采样点位于射线上,表示为 x=o+t⋅d,其中 t 为射线方向上的距离。

    • 对于每条光线,NeRF 需要在其路径上进行均匀的样本点采样。采样点通常在光线路径的连续空间中,比如在光线上等距离采样或根据场景深度进行采样。

2.2 NeRF 模型预测

对于每个采样点,NeRF 模型给出了该点的颜色和密度估计值。

  • NeRF 函数:场景中的每个点 x 都对应着颜色 C(x) 和密度σ(x)。这些值由神经网络表示的函数预测得出。
  • 在每个采样点,NeRF 的神经网络会根据该点的三维位置 x 来预测两个关键参数:颜色值 C(x) 和密度值 σ(x)。

  • 这个预测是由观察光线经过该点处的场景属性得出的,这包括光线经过的位置 x 以及光线的方向。

  • 颜色和密度预测:沿着光线的采样点预测颜色和密度,神经网络输出颜色和密度值。

2.3 体积渲染

NeRF 使用采样点的颜色和密度估计值进行体积渲染,计算最终的像素值。

  • 体积渲染方程:对于每个像素(i,j),体积渲染方程是一个积分,表示了从相机视点沿着射线看到的颜色值。

  • 这里,C 是颜色值,σ 是密度,δt 是采样点之间的距离,T 是射线长度。这个方程基于体积渲染的基本原理,根据颜色和密度的累积,计算出最终的颜色值。

    • NeRF 使用渲染方程进行体积渲染(Volume Rendering)。渲染方程描述了沿光线的传播,考虑了光线传播路径上的各个采样点的颜色和密度,以估算最终的像素颜色值。

    • NeRF 通过沿光线对预测的颜色值 C(x) 和密度值 σ(x) 进行蒙特卡洛积分来近似渲染方程。这个积分的结果将近似光线路径上所有采样点的光线传播和场景颜色的影响。

  • 权重计算:NeRF 根据颜色和密度估计值计算每个采样点的权重。权重表示了沿着射线的能量传输情况。

  • 颜色积分:NeRF 将每个采样点的颜色和权重进行积分,然后加权求和,得出了最终的像素颜色值。

总结:基于颜色和密度值,NeRF 使用体积渲染方程进行积分,计算最终的像素颜色值。这个过程类似于光线追踪中的反射和折射计算,但是是通过神经网络来近似和预测。


3 采样与渲染代码详解 (rending.py)

3.1 神经体积渲染代码解析

        rending.py 主要用于神经体积渲染(NeRF)方面的工作。它实现了光线在空间中的渲染和采样,结合了深度学习模型和光线投射技术,用于从数据中合成逼真的三维场景。代码主要包含两个主要函数:

  1. sample_pdf 函数用于根据权重(weights)的分布从 bins 中采样 N_importance 个样本。此函数用于在体积渲染中对rending.py光线采样进行处理。

  2. render_rays 函数是执行光线渲染的主函数。它接受NeRF模型、嵌入模型、光线的起始点和方向等参数,然后执行光线的采样、模型推断和体积渲染。

这些函数涉及到的主要步骤包括:

  • 解析光线的起始点和方向。
  • 在深度空间或视差空间中对光线进行采样。
  • 调用 inference 函数,该函数执行模型推断,获取 RGB 和原始 sigma 等值。
  • 使用体积渲染算法对这些值进行处理,计算光线的颜色和深度。
  • 如果需要精细模型的采样,还会对精细模型进行类似的操作。

3.2 sample_pdf () 光线采样

  • 这个函数从 bins 和 weights 中根据给定的分布,抽取 N_importance 个样本。
  • 参数 bins 是射线的采样点(N_rays, N_samples_+1),其中 N_samples_ 是每条射线的粗略样本数减去 2。
  • 参数 weights 是权重(N_rays, N_samples_)。
  • 函数首先计算归一化的概率密度函数(PDF),然后计算累积分布函数(CDF),用于采样。
  • 如果是确定性采样(det=True),则等间隔采样 N_importance 个点;否则在 [0, 1] 范围内随机采样。
  • 通过 CDF 和随机数采样的结果得到实际采样的位置 samples。
def sample_pdf(bins, weights, N_importance, det=False, eps=1e-5):
    """
    从 @weights 定义的分布中采样 @N_importance 个样本。
    输入:
        bins: 形状为 (N_rays, N_samples_+1),其中 N_samples_ 是“每条射线的粗糙样本数 - 2”
        weights: 形状为 (N_rays, N_samples_)
        N_importance: 从分布中抽取的样本数量
        det: 是否确定性采样
        eps: 用于防止除以零的小数值
    输出:
        samples: 采样的样本
    """
    N_rays, N_samples_ = weights.shape
    weights = weights + eps  # 防止除零错误(不要进行就地操作!)
    pdf = weights / reduce(weights, 'n1 n2 -> n1 1', 'sum')  # 形成概率密度函数 (N_rays, N_samples_)
    cdf = torch.cumsum(pdf, -1)  # 累积分布函数 (N_rays, N_samples),累积概率
    cdf = torch.cat([torch.zeros_like(cdf[:, :1]), cdf], -1)  # (N_rays, N_samples_+1),填充至 0~1 区间

    if det:
        u = torch.linspace(0, 1, N_importance, device=bins.device)
        u = u.expand(N_rays, N_importance)
    else:
        u = torch.rand(N_rays, N_importance, device=bins.device)
    u = u.contiguous()

    inds = torch.searchsorted(cdf, u, right=True)
    below = torch.clamp_min(inds - 1, 0)
    above = torch.clamp_max(inds, N_samples_)

    inds_sampled = rearrange(torch.stack([below, above], -1), 'n1 n2 c -> n1 (n2 c)', c=2)
    cdf_g = rearrange(torch.gather(cdf, 1, inds_sampled), 'n1 (n2 c) -> n1 n2 c', c=2)
    bins_g = rearrange(torch.gather(bins, 1, inds_sampled), 'n1 (n2 c) -> n1 n2 c', c=2)

    denom = cdf_g[..., 1] - cdf_g[..., 0]
    denom[denom < eps] = 1  # 如果 denom 为 0,表示某个区间的权重为 0,不会被采样,因此可以将其设为任何值(此处设为 1)

    samples = bins_g[..., 0] + (u - cdf_g[..., 0]) / denom * (bins_g[..., 1] - bins_g[..., 0])
    return samples

  1. 输入参数解释

    • bins: 形状为 (N_rays, N_samples_+1),描述了采样区间的边界。
    • weights: 形状为 (N_rays, N_samples_),表示每个区间的权重值。
    • N_importance: 要从分布中抽取的样本数量。
    • det: 布尔值,确定是否进行确定性采样。
    • eps: 用于防止除零错误的小数值。
  2. 步骤

    a. 对权重值应用一个微小的修正(eps),以防止权重为零导致的除零错误。

    b. 通过对权重值进行归一化,生成概率密度函数(PDF)。这是通过将权重值除以所有权重值的总和得到的。

    c. 计算累积分布函数(CDF),将概率密度函数进行累积求和,得到每个区间的累积概率。

    d. 生成均匀分布的随机数 u,以便对每条光线进行重要性采样。根据 det 的取值,选择确定性采样或随机采样。

    e. 根据生成的随机数 u,在累积分布函数中寻找对应的位置。这是通过 torch.searchsorted 函数实现的。

    f. 确定采样点所在的区间。根据得到的索引,选择下界和上界的采样点,以便进行线性插值采样。

    g. 计算采样点的位置。通过线性插值,从区间的边界值中计算出采样点的实际位置。

    h. 返回生成的样本。

这段代码主要用于神经渲染中对概率分布进行采样,以获取重要的样本点,以便更准确地估算光线在场景中的传播和颜色变化。

3.3 render_rays()光线渲染

  • 这个函数执行渲染操作,将给定的射线渲染成图像。
  • 参数 models 是 NeRF 模型字典(粗糙和细致模型)。
  • 参数 embeddings 是原点和方向的嵌入模型字典。
  • 参数 rays 是射线的起始点和方向。
  • 参数 ts 是射线时间作为嵌入索引。
  • N_samples 是每条射线的粗略样本数。
  • use_disp 表示是否在视差空间中采样。
  • perturb 是对粗糙模型射线采样位置的扰动因子。
  • noise_std 是扰动模型 sigma 预测的因子。
  • N_importance 是每条射线的细致样本数。
  • chunk 是批处理推断中的块大小。
  • white_back 表示背景颜色是否为白色。
  • test_time 表示是否为测试(只进行推断)。
  • 函数输出结果存储在 result 字典中,包含粗糙模型和细致模型的最终 RGB 和深度图。
def render_rays(models,
                embeddings,
                rays,
                ts,
                N_samples=64,
                use_disp=False,
                perturb=0,
                noise_std=1,
                N_importance=0,
                chunk=1024*32,
                white_back=False,
                test_time=False,
                **kwargs
                ):
    """
    渲染光线,通过对 @model 应用在 @rays 和 @ts 上计算输出
    Inputs:
        models: 在 nerf.py 中定义的 NeRF 模型的字典(粗糙模型和精细模型)
        embeddings: 在 nerf.py 中定义的原点和方向嵌入模型的字典
        rays: (N_rays, 3+3),光线的起始点和方向
        ts: (N_rays),作为嵌入索引的光线时间
        N_samples: 每条光线的粗糙采样数量
        use_disp: 是否在视差空间(逆深度)中采样
        perturb: 对光线上采样位置的扰动因子(仅适用于粗糙模型)
        noise_std: 扰动模型预测 sigma 的因子
        N_importance: 每条光线的精细采样数量
        chunk: 批量推断的块大小
        white_back: 背景是否为白色(依赖于数据集)
        test_time: 是否为测试(仅推断),如果为 True,将不进行粗糙 RGB 的推断以节省时间
    Outputs:
        result: 包含粗糙模型和精细模型的最终 RGB 和深度图的字典
    """

    def inference(results, model, xyz, z_vals, test_time=False, **kwargs):
        """
        辅助函数,执行模型推断
        Inputs:
            results: 存储所有结果的字典
            model: NeRF 模型(粗糙或精细)
            xyz: (N_rays, N_samples_, 3) 采样位置
                  N_samples_ 是每条光线上采样点的数量;
                             对于粗糙模型,N_samples_ = N_samples
                             对于精细模型,N_samples_ = N_samples + N_importance
            z_vals: (N_rays, N_samples_) 采样位置的深度
            test_time: 是否为测试时间
        """
        typ = model.typ
        N_samples_ = xyz.shape[1]
        xyz_ = rearrange(xyz, 'n1 n2 c -> (n1 n2) c', c=3)

        # 执行模型推断以获取 RGB 和原始 sigma
        B = xyz_.shape[0]
        out_chunks = []
        if typ == 'coarse' and test_time:
            for i in range(0, B, chunk):
                xyz_embedded = embedding_xyz(xyz_[i:i+chunk])
                out_chunks += [model(xyz_embedded, sigma_only=True)]
            out = torch.cat(out_chunks, 0)
            static_sigmas = rearrange(out, '(n1 n2) 1 -> n1 n2', n1=N_rays, n2=N_samples_)
        else:  # 推断 RGB、sigma 和其他值
            dir_embedded_ = repeat(dir_embedded, 'n1 c -> (n1 n2) c', n2=N_samples_)
            # 创建其他必要的输入
            if model.encode_appearance:
                a_embedded_ = repeat(a_embedded, 'n1 c -> (n1 n2) c', n2=N_samples_)
            if model.encode_random:
                a_embedded_random_ = repeat(a_embedded_random, 'n1 c -> (n1 n2) c', n2=N_samples_)
            for i in range(0, B, chunk):
                # 原始 NeRF 的输入
                inputs = [embedding_xyz(xyz_[i:i+chunk]), dir_embedded_[i:i+chunk]]
                # NeRF-W 的额外输入
                if model.encode_appearance:
                    inputs += [a_embedded_[i:i+chunk]]
                if model.encode_random:
                    inputs += [a_embedded_random_[i:i+chunk]]
                out_chunks += [model(torch.cat(inputs, 1), output_random=output_random)]
            out = torch.cat(out_chunks, 0)
            out = rearrange(out, '(n1 n2) c -> n1 n2 c', n1=N_rays, n2=N_samples_)
            static_rgbs = out[..., :3]  # (N_rays, N_samples_, 3)
            static_sigmas = out[..., 3]  # (N_rays, N_samples_)
            ################################################################
            if output_random:
                static_rgbs_random = out[..., 4:]
            ################################################################
        # 使用体积渲染转换这些值
        deltas = z_vals[:, 1:] - z_vals[:, :-1]  # (N_rays, N_samples_-1)
        delta_inf = 1e2 * torch.ones_like(deltas[:, :1])  # (N_rays, 1) 最后一个 delta 是无穷大
        deltas = torch.cat([deltas, delta_inf], -1)  # (N_rays, N_samples_)

        noise = torch.randn_like(static_sigmas) * noise_std
        alphas = 1 - torch.exp(-deltas * torch.relu(static_sigmas + noise))

        alphas_shifted = torch.cat([torch.ones_like(alphas[:, :1]), 1 - alphas], -1)  # [1, 1-a1, 1-a2, ...]
        transmittance = torch.cumprod(alphas_shifted[:, :-1], -1)  # [1, 1-a1, (1-a1)(1-a2), ...]

        weights = alphas * transmittance
        weights_sum = reduce(weights, 'n1 n2 -> n1', 'sum')

        results[f'weights_{typ}'] = weights
        results[f'opacity_{typ}'] = weights_sum

        if test_time and typ == 'coarse':
            return

        rgb_map = reduce(rearrange(weights, 'n1 n2 -> n1 n2 1') * static_rgbs,
                         'n1 n2 c -> n1 c', 'sum')
        if white_back:
            rgb_map += 1 - rearrange(weights_sum, 'n -> n 1')
        results[f'rgb_{typ}'] = rgb_map

        if output_random:
            rgb_map_random = reduce(rearrange(weights, 'n1 n2 -> n1 n2 1') * static_rgbs_random,
                                    'n1 n2 c -> n1 c', 'sum')
            if white_back:
                rgb_map_random += 1 - rearrange(weights_sum, 'n -> n 1')
            results[f'rgb_{typ}_random'] = rgb_map_random

        results[f'depth_{typ}'] = reduce(weights * z_vals, 'n1 n2 -> n1', 'sum')
        return

    embedding_xyz, embedding_dir = embeddings['xyz'], embeddings['dir']

    # 拆解输入
    N_rays = rays.shape[0]
    rays_o, rays_d = rays[:, 0:3], rays[:, 3:6]  # 都是 (N_rays, 3)
    near, far = rays[:, 6:7], rays[:, 7:8]  # 都是 (N_rays, 1)
    # 嵌入方向
    dir_embedded = embedding_dir(kwargs.get('view_dir', rays_d))

    rays_o = rearrange(rays_o, 'n1 c -> n1 1 c')
    rays_d = rearrange(rays_d, 'n1 c -> n1 1 c')

    # 采样深度点
    z_steps = torch.linspace(0, 1, N_samples, device=rays.device)
    if not use_disp:  # 在深度空间中进行线性采样
        z_vals = near * (1 - z_steps) + far * z_steps
    else:  # 在视差空间中进行线性采样
        z_vals = 1 / (1 / near * (1 - z_steps) + 1 / far * z_steps)

    z_vals = z_vals.expand(N_rays, N_samples)

    if perturb > 0:  # 扰动采样深度(z_vals)
        z_vals_mid = 0.5 * (z_vals[:, :-1] + z_vals[:, 1:])  # (N_rays, N_samples-1) 间隔中点
        # 获取采样点之间的间隔
        upper = torch.cat([z_vals_mid, z_vals[:, -1:]], -1)
        lower = torch.cat([z_vals[:, :1], z_vals_mid], -1)

        perturb_rand = perturb * torch.rand_like(z_vals)
        z_vals = lower + (upper - lower) * perturb_rand

    xyz_coarse = rays_o + rays_d * rearrange(z_vals, 'n1 n2 -> n1 n2 1')

    results = {}
    output_random = False
    inference(results, models['coarse'], xyz_coarse, z_vals, test_time, **kwargs)

    if N_importance > 0:  # 为精细模型采样点
        z_vals_mid = 0.5 * (z_vals[:, :-1] + z_vals[:, 1:])  # (N_rays, N_samples-1) 间隔中点
        z_vals_ = sample_pdf(z_vals_mid, results['weights_coarse'][:, 1:-1].detach(),
                             N_importance, det=(perturb == 0))
        # detach,使得梯度不会从此处传播到 weights_coarse
        z_vals = torch.sort(torch.cat([z_vals, z_vals_], -1), -1)[0]
        xyz_fine = rays_o + rays_d * rearrange(z_vals, 'n1 n2 -> n1 n2 1')

        model = models['fine']
        if model.encode_appearance:
            if 'a_embedded_from_img' in kwargs:
                a_embedded = kwargs['a_embedded_from_img'].repeat(xyz_fine.size(0), 1)
            elif 'a_embedded' in kwargs:
                a_embedded = kwargs['a_embedded']
            else:
                a_embedded = embeddings['a'](ts)

        if model.encode_random:
            a_embedded_random = kwargs['a_embedded_random'].repeat(xyz_fine.size(0), 1)

        output_random = kwargs.get('output_random', True) and model.encode_random

        inference(results, model, xyz_fine, z_vals, test_time, **kwargs)

    return results

以上代码是一个用于光线追踪的函数,主要执行的是将模型应用在给定的光线和时间上,输出包含了粗糙和精细模型的最终 RGB 和深度图。

这个函数 render_rays 返回一个结果字典 result,包含了渲染的各种输出:

  • result['weights_coarse']: 粗糙模型每个采样点的权重。
  • result['opacity_coarse']: 粗糙模型的每条光线的总透明度。
  • result['rgb_coarse']: 粗糙模型的最终颜色图。
  • result['depth_coarse']: 粗糙模型的深度图。

如果启用了精细模型:

  • result['weights_fine']: 精细模型每个采样点的权重。
  • result['opacity_fine']: 精细模型的每条光线的总透明度。
  • result['rgb_fine']: 精细模型的最终颜色图。
  • result['depth_fine']: 精细模型的深度图。

此外,如果存在额外的随机信息输出:

  • result['rgb_coarse_random']: 粗糙模型的随机信息的颜色图。
  • result['rgb_fine_random']: 精细模型的随机信息的颜色图。

这些输出提供了对光线渲染过程中每个模型的计算结果。weights 表示每个采样点的权重,opacity 是每条光线的总透明度,rgb 包含颜色信息,而 depth 是渲染的深度信息。

如果指定了 white_backTrue,背景将被假定为白色(依赖于数据集)。

这些输出对于可视化渲染结果非常有用,提供了每条光线上的颜色、透明度和深度信息,可以在场景渲染中用于后续处理和可视化。

  • 函数render_rays接收一些模型、嵌入、光线、时间、以及一些其他参数,例如N_samplesuse_dispperturbnoise_std等。这些参数会影响光线追踪的采样和推断。

  • 函数中嵌套了一个名为inference的子函数。这个子函数用于执行模型推断。它接收了模型、采样位置的坐标(xyz)、深度信息(z_vals)等参数,并根据模型类型进行推断。对于粗糙模型(typ=='coarse')在测试时间(test_time)下,只推断出sigma值。而对于其他情况,它会通过模型计算RGB、sigma以及其他值。

  • 针对模型的输出,它通过体积渲染的方式进行转换,计算光线的透明度、权重等,最终得到最终的RGB图和深度值。这些结果存储在名为results的字典中。

  • 函数的其余部分用于处理输入数据,对光线、采样的深度点等进行处理和采样。

总体而言,这些函数的目标是根据给定的射线、时间和模型数据渲染出图像和深度信息。渲染是通过对射线进行采样并应用神经网络模型来获取颜色和深度信息。

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

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

相关文章

号牌模拟数据生成

说明 自己开发的测试数据生成工具&#xff0c;用于生成数据训练对应模型。 项目 效果

微带线的ABCD矩阵的推导、转换与级联-Matlab计算实例

微带线的ABCD矩阵的推导、转换与级联-Matlab计算实例 散射参数矩阵有实际的物理意义&#xff0c;但是其无法级联计算&#xff0c;但是ABCD参数和传输散射矩阵可以级联计算&#xff0c;在此先简单介绍ABCD参数矩阵的基本用法。 1、微带线的ABCD矩阵的推导 其他的一些常用的二端…

【教程】多进程下载百度旋转验证码图片-制作数据集

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhang.cn] 效果展示&#xff1a; 直接上代码&#xff0c;开箱即用&#xff08;当然selenium库自己装一下&#xff09;&#xff1a; import os import time import requests from selenium import webdriver from selenium.…

为什么HTTP用得很好的,开始普及HTTPS呢?

显而易见&#xff0c;现在的HTTP早已不安全&#xff0c;当我们在浏览各个网站时会发现HTTP前面都会显示不安全&#xff0c;因为HTTP是明文传输&#xff0c;一旦电脑被植入了木马&#xff0c;木马程序就会主动周期性发消息给Internet的控制终端&#xff0c;这样NAT小洞会一直敞开…

Markdown写作应用推荐

MWeb Pro 是一款适用于macOS的专业Markdown写作、笔记本应用软件。喜欢写博客的朋友&#xff0c;那你一定会需要 MWeb Pro 这款软件。为您提供最佳的写作体验。 Markdown 语法支持&#xff1a; 使用 Github Flavored Markdown 语法&#xff0c;简称 GFM 语法。支持表格、TOC、…

2023年云计算发展趋势:生活的智能未来

目录 引言1 智能家居的崭新时代2 无人驾驶的崭新时代3 虚拟现实的扩展与改进4 人工智能的综合应用5 云计算的可持续性结语 引言 时光荏苒&#xff0c;科技的飞速发展已经成为当今社会的标志之一。在这个数字化时代&#xff0c;云计算已经成为推动技术革新和生活方式改变的关键…

【深度学习】Python爬取豆瓣实现影评分析

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、任务描述二、使用步骤1.数据爬取1.2.对爬取的页面数据进行解析&#xff0c;并保存为JSON文件2、数据分析2.1数据分析之评论时间分布图2.2角色评分 前言 爬…

雷神学习---视音频数据处理入门:RGB、YUV像素数据处理

原文地址&#xff1a;https://blog.csdn.net/leixiaohua1020/article/details/50534150 ​​​​​​​​从代码可以看出&#xff0c;如果想把YUV格式像素数据变成灰度图像&#xff0c;只需要将U、V分量设置成128即可。 这是因为U、V是图像中的经过偏置处理的色度分量。色度分…

Python继承和多态:基础继承、方法重写、多态的基本概念

文章目录 基础继承方法重写多态在编程语言中,特别是在面向对象编程(OOP)中,继承和多态是两个核心概念,它们提供了代码重用和接口设计的强大工具。Python 作为一种支持 OOP 的语言,也具备这些特性。 基础继承 继承是面向对象编程的一个基本概念,它允许我们定义一个类(…

Angew. Chem. Int. Ed.:Co-1T-MoS2-bpe碱性介质中电催化HER

高效析氢反应&#xff08;HER&#xff09;电催化剂决定氢动力清洁技术的质量分布&#xff0c;但仍面临着巨大的挑战。基于此&#xff0c;中国石油大学&#xff08;华东&#xff09;董斌副教授等人报道了通过CoMo -金属-有机骨架前驱体对1T-MoS2催化剂进行了配体调制和Co掺杂的协…

前端图片压缩上传,减少等待时间!优化用户体检

添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 这里有两张图片&#xff0c;它们表面看上去是一模一样的&#xff0c;但实际上各自所占用的内存大小相差了180倍。 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 添加图片注释&…

JumpServer 打开RDP客户端出现由于在客户端检测到一个协议错误 错误代码 0x2104

环境: Win10 专业版 JumpServer Version v2.25.4 问题描述: JumpServer 打开RDP客户端出现由于在客户端检测到一个协议错误 错误代码 0x2104 个别电脑又是正常可以连接 解决方案: 检查网络连接:确保您的计算机和JumpServer之间的网络连接正常。尝试使用其他网络连接…

操作系统基础知识1

1、用户态和内核态的区别&#xff1f; a、访问权限。用户态下&#xff0c;应用程序只能访问受限的的资源和执行受限的程序&#xff1b;而在内核态下&#xff0c;操作系统具有完全的访问权限&#xff0c;可以访问系统的所有资源和执行所有操作&#xff1b; b、CPU指令集。用户态…

拍摄中的信息表达者---镜头语言!

炫我科技在影视动画行业为众多影片提供了渲染支持。涉及到的业务有云渲染系统、实时渲染系统、XR虚拟拍摄系统&#xff0c;强势赋能元宇宙。在影视动画创作过程中提供了多种解决方案&#xff0c;例如集群渲染、私有云渲染解决方案、虚拟拍摄等。 今天我们来聊一些不一样的东西…

学习pytorch15 优化器

优化器 官网如何构造一个优化器优化器的step方法coderunning log出现下面问题如何做反向优化&#xff1f; 官网 https://pytorch.org/docs/stable/optim.html 提问&#xff1a;优化器是什么 要优化什么 优化能干什么 优化是为了解决什么问题 优化模型参数 如何构造一个优化器…

【Proteus仿真】【51单片机】水质监测报警系统设计

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真51单片机控制器&#xff0c;使用按键、LED、蜂鸣器、LCD1602、PCF8591 ADC、PH传感器、浑浊度传感器、DS18B20温度传感器、继电器模块等。 主要功能&#xff1a; 系统运行后&…

链表经典面试题之一讲

什么是链表&#xff1f; 链表是一种物理存储结构上非连续、非顺序的存储结构&#xff0c;数据元素的逻辑顺序是通过链表中的指针链接次序实现的 。 今天给大家分享一道经典的单链表面试题 力扣题目——反转链表https://leetcode.cn/problems/reverse-linked-list/ 只给了头…

Wsl2 Ubuntu在不安装Docker Desktop情况下使用Docker

目录 1. 前提条件 2.安装Distrod 3. 常见问题 3.1.docker compose 问题无法使用问题 3.1. docker-compose up报错 参考文档 1. 前提条件 win10 WSL2 Ubuntu(截止202308最新版本是20.04.xx) 有不少的博客都是建议直接安装docker desktop&#xff0c;这样无论在windows…

实体属性映射框架mapstruct

1. 框架介绍 mapstruct框架是一种实体类间的映射框架&#xff0c;能够通过JAVA注解的形式将一个实体类的属性安全的赋值给另一个实体类。通过一系列注解可以定义实体类属性之间的映射关系&#xff0c;mapstruct会在编译期间生成映射实现类&#xff0c;而非通过反射的方式进行实…

Dcoker学习笔记(一)

Dcoker学习笔记一 一、 初识Docker1.1 简介1.2 虚拟机和docker的区别1.3 Docker架构1.4 安装Docker&#xff08;Linux&#xff09; 二、 Dcoker基本操作2.1 镜像操作2.2 容器操作练习 2.3 数据卷volume&#xff08;容器数据管理&#xff09;简介数据卷语法数据卷挂载 2.4 自定义…