使用VGG-16模型来对海贼王中的角色进行图像分类

动漫角色识别是计算机视觉的典型应用场景,可用于周边商品分类、动画制作辅助等。

这个案例是一个经典的深度学习应用,用于图像分类任务,它使用了一个自定义的VGG-16模型来对《海贼王》中的七个角色进行分类,演示如何将经典CNN模型应用于小规模自定义数据集。

1. 数据集准备

数据集包含7个类别的图片,每个类别对应一个《海贼王》的角色:

  • 路飞(lufei)
  • 罗宾(luobin)
  • 娜美(namei)
  • 乔巴(qiaoba)
  • 山治(shanzhi)
  • 索隆(suolong)
  • 乌索普(wusuopu)

每个角色有不同数量的图片,总共621张图片。

(1)导入必要的库和设置随机种子

import numpy as np
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers, models
import pathlib
import matplotlib.pyplot as plt
import os, PILnp.random.seed(1)
tf.random.set_seed(1)
#导入所需的Python库,并设置随机种子以确保实验的可重复性。

(2)设置数据目录和参数

data_dir = r"D:\hzw_photos"
data_dir = pathlib.Path(data_dir)
image_count = len(list(data_dir.glob('*/*.png')))
print("图片总数为:", image_count)batch_size = 32
img_height = 224
img_width = 224#作用:指定数据集路径、统计图片总数,并定义批量大小和图片尺寸。
#运行结果:输出图片总数(621张)。

(3)加载训练集和验证集

train_ds = tf.keras.preprocessing.image_dataset_from_directory(data_dir,validation_split=0.2,subset="training",seed=123,image_size=(img_height, img_width),batch_size=batch_size
)val_ds = tf.keras.preprocessing.image_dataset_from_directory(data_dir,validation_split=0.2,subset="validation",seed=123,image_size=(img_height, img_width),batch_size=batch_size
)
#作用:从指定目录加载图像数据集,并将其分为训练集和验证集。validation_split=0.2表示20%的数据用于验证,其余80%用于训练。
#运行结果:打印出找到的文件数量和类别信息。

(4)获取类别名称

class_names = train_ds.class_names
print(class_names)
#作用:获取并打印数据集中所有类别的名称。
#运行结果:输出类别名称列表:['lufei', 'luobin', 'namei', 'qiaoba', 'shanzhi', 'suolong', 'wusuopu']。

(5)可视化数据

plt.figure(figsize=(10, 5))
for images, labels in train_ds.take(1):for i in range(8):ax = plt.subplot(2, 4, i + 1)plt.imshow(images[i].numpy().astype("uint8"))plt.title(class_names[labels[i]])plt.axis("off")
plt.show()
#作用:从训练集中随机选取一批图像进行可视化展示。
#运行结果:显示8张随机选择的图像及其对应的标签。


2. 数据预处理

(1)配置数据集

AUTOTUNE = tf.data.AUTOTUNE
train_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=AUTOTUNE)
val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)
#作用:对数据集进行缓存、打乱和预取操作,以提高数据读取效率。
#运行结果:无直接输出,但优化了数据加载过程。

(2)归一化处理

normalization_layer = tf.keras.layers.Rescaling(1. / 255)
train_ds = train_ds.map(lambda x, y: (normalization_layer(x), y))
val_ds = val_ds.map(lambda x, y: (normalization_layer(x), y))image_batch, labels_batch = next(iter(val_ds))
first_image = image_batch[0]
print("归一化后数据范围:", np.min(first_image), np.max(first_image))
#作用:将图像像素值归一化到[0, 1]区间内。
#运行结果:输出归一化后的数据范围(0.0到0.9928046),表明归一化操作成功。

3. 模型构建

VGG-16 是一种经典的卷积神经网络(CNN)架构,通过堆叠多个卷积层和池化层来提取图像特征,最后通过全连接层进行分类。以其简单的结构和深度而闻名,尤其在图像分类任务中表现出色。

定义VGG-16模型

def VGG16(nb_classes, input_shape):# 构建VGG-16模型...return model
#作用:定义一个自定义的VGG-16模型,包括多个卷积层和全连接层。
#运行结果:无直接输出,但生成了一个可以使用的模型结构。

(1) 输入层

input_tensor = layers.Input(shape=input_shape)
#input_shape  输入图像的形状,通常为 (height, width, channels),例如 (224, 224, 3) 表示 224x224 像素的 RGB 图像
#Input 层定义了模型的输入张量。

(2)卷积块 1

x = layers.Conv2D(64, (3, 3), activation='relu', padding='same', name='block1_conv1')(input_tensor)
x = layers.Conv2D(64, (3, 3), activation='relu', padding='same', name='block1_conv2')(x)
x = layers.MaxPooling2D((2, 2), strides=(2, 2), name='block1_pool')(x)
#两个 Conv2D 层,每个层使用 64 个 3x3 的卷积核,激活函数为 ReLU,padding='same' 表示输出特征图的大小与输入相同。
#MaxPooling2D 层使用 2x2 的池化窗口,步幅为 2,将特征图的大小减半。
#输入图像(224×224×3)
#→ 经过64个3×3卷积核提取特征(输出224×224×64)
#→ 再次卷积增强特征(保持尺寸)
#→ 2×2最大池化(输出112×112×64)

(3)卷积块 2

x = layers.Conv2D(128, (3, 3), activation='relu', padding='same', name='block2_conv1')(x)
x = layers.Conv2D(128, (3, 3), activation='relu', padding='same', name='block2_conv2')(x)
x = layers.MaxPooling2D((2, 2), strides=(2, 2), name='block2_pool')(x)
#与第一个卷积块类似,但卷积核数量增加到 128。

(4) 卷积块 3

x = layers.Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv1')(x)
x = layers.Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv2')(x)
x = layers.Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv3')(x)
x = layers.MaxPooling2D((2, 2), strides=(2, 2), name='block3_pool')(x)
#卷积核数量增加到 256,并且有三个卷积层。

(5)卷积块 4

x = layers.Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv1')(x)
x = layers.Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv2')(x)
x = layers.Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv3')(x)
x = layers.MaxPooling2D((2, 2), strides=(2, 2), name='block4_pool')(x)
#卷积核数量增加到 512,同样有三个卷积层。

(6)卷积块 5

x = layers.Conv2D(512, (3, 3), activation='relu', padding='same', name='block5_conv1')(x)
x = layers.Conv2D(512, (3, 3), activation='relu', padding='same', name='block5_conv2')(x)
x = layers.Conv2D(512, (3, 3), activation='relu', padding='same', name='block5_conv3')(x)
x = layers.MaxPooling2D((2, 2), strides=(2, 2), name='block5_pool')(x)
#与卷积块 4 相同,卷积核数量保持为 512。

块编号CONV层数量输出尺寸通道数作用
12112×11264提取边缘/颜色等低级特征
2256×56128捕获纹理/简单形状
3328×28256识别复杂图案(如草帽轮廓)
4314×14512检测角色局部特征(娜美的头发等)
537×7512整合全局语义信息


(7) 全连接层

x = layers.Flatten()(x)
x = layers.Dense(4096, activation='relu', name='fc1')(x)
x = layers.Dense(4096, activation='relu', name='fc2')(x)
output_tensor = layers.Dense(nb_classes, activation='softmax', name='predictions')(x)
#Flatten 层将多维特征图展平为一维向量。
#两个 Dense 层,每个层有 4096 个神经元,激活函数为 ReLU。
#最后的 Dense 层输出类别概率,使用 softmax 激活函数,nb_classes 是类别数量。

(8)构建模型

model = models.Model(input_tensor, output_tensor)
#使用 Model 类将输入张量和输出张量组合成模型。

(9)初始化模型

model = VGG16(nb_classes=7, input_shape=(img_width, img_height, 3))
model.summary()
#作用:初始化VGG-16模型,并打印模型结构摘要。
#运行结果:输出模型各层的详细信息,包括层名、输出形状和参数数量等。

输入图像 → [CONV→POOL]×5 → 展平 → FC×2 → 分类输出
                        (特征提取)                           (决策)

4. 模型编译与训练

编译模型

opt = tf.keras.optimizers.Adam(learning_rate=1e-4)
model.compile(optimizer=opt,loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),metrics=['accuracy']
)
#作用:配置模型的优化器、损失函数和评估指标。

训练模型

history = model.fit(train_ds,validation_data=val_ds,epochs=epochs
)
#作用:在训练集上训练模型,并在每个epoch结束后评估验证集上的性能。
#运行结果:输出每个epoch的训练准确率、训练损失、验证准确率和验证损失。

5. 结果分析

acc = history.history['accuracy']
val_acc = history.history['val_accuracy']
loss = history.history['loss']
val_loss = history.history['val_loss']plt.figure(figsize=(12, 4))
plt.subplot(1, 2, 1)
plt.plot(range(epochs), acc, label='Training Accuracy')
plt.plot(range(epochs), val_acc, label='Validation Accuracy')
plt.legend(loc='lower right')
plt.title('Training and Validation Accuracy')plt.subplot(1, 2, 2)
plt.plot(range(epochs), loss, label='Training Loss')
plt.plot(range(epochs), val_loss, label='Validation Loss')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')
plt.show()
#作用:绘制训练和验证过程中的准确率及损失变化曲线。
#运行结果:显示两个子图,分别表示准确率和损失的变化趋势。



 

  • 训练准确率验证准确率都随着训练轮数的增加而上升,表明模型逐渐学习到了数据的特征。
  • 训练损失验证损失则逐渐下降,说明模型的预测误差在减小。
图片总数为: 621
Found 621 files belonging to 7 classes.
Using 497 files for training.
Found 621 files belonging to 7 classes.
Using 124 files for validation.
['lufei', 'luobin', 'namei', 'qiaoba', 'shanzhi', 'suolong', 'wusuopu']
归一化后数据范围: 0.0 0.9928046
Model: "functional"
┌─────────────────────────────────┬────────────────────────┬───────────────┐
│ Layer (type)                    │ Output Shape           │       Param # │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ input_layer (InputLayer)        │ (None, 224, 224, 3)    │             0 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ block1_conv1 (Conv2D)           │ (None, 224, 224, 64)   │         1,792 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ block1_conv2 (Conv2D)           │ (None, 224, 224, 64)   │        36,928 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ block1_pool (MaxPooling2D)      │ (None, 112, 112, 64)   │             0 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ block2_conv1 (Conv2D)           │ (None, 112, 112, 128)  │        73,856 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ block2_conv2 (Conv2D)           │ (None, 112, 112, 128)  │       147,584 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ block2_pool (MaxPooling2D)      │ (None, 56, 56, 128)    │             0 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ block3_conv1 (Conv2D)           │ (None, 56, 56, 256)    │       295,168 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ block3_conv2 (Conv2D)           │ (None, 56, 56, 256)    │       590,080 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ block3_conv3 (Conv2D)           │ (None, 56, 56, 256)    │       590,080 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ block3_pool (MaxPooling2D)      │ (None, 28, 28, 256)    │             0 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ block4_conv1 (Conv2D)           │ (None, 28, 28, 512)    │     1,180,160 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ block4_conv2 (Conv2D)           │ (None, 28, 28, 512)    │     2,359,808 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ block4_conv3 (Conv2D)           │ (None, 28, 28, 512)    │     2,359,808 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ block4_pool (MaxPooling2D)      │ (None, 14, 14, 512)    │             0 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ block5_conv1 (Conv2D)           │ (None, 14, 14, 512)    │     2,359,808 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ block5_conv2 (Conv2D)           │ (None, 14, 14, 512)    │     2,359,808 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ block5_conv3 (Conv2D)           │ (None, 14, 14, 512)    │     2,359,808 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ block5_pool (MaxPooling2D)      │ (None, 7, 7, 512)      │             0 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ flatten (Flatten)               │ (None, 25088)          │             0 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ fc1 (Dense)                     │ (None, 4096)           │   102,764,544 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ fc2 (Dense)                     │ (None, 4096)           │    16,781,312 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ predictions (Dense)             │ (None, 7)              │        28,679 │
└─────────────────────────────────┴────────────────────────┴───────────────┘Total params: 134,289,223 (512.27 MB)Trainable params: 134,289,223 (512.27 MB)Non-trainable params: 0 (0.00 B)
Epoch 1/20
16/16 ━━━━━━━━━━━━━━━━━━━━ 207s 13s/step - accuracy: 0.1736 - loss: 1.9444 - val_accuracy: 0.1935 - val_loss: 1.9390
Epoch 2/20
16/16 ━━━━━━━━━━━━━━━━━━━━ 216s 14s/step - accuracy: 0.1594 - loss: 1.9357 - val_accuracy: 0.1935 - val_loss: 1.9355
Epoch 3/20
16/16 ━━━━━━━━━━━━━━━━━━━━ 195s 12s/step - accuracy: 0.1656 - loss: 1.9362 - val_accuracy: 0.1935 - val_loss: 1.9293
Epoch 4/20
16/16 ━━━━━━━━━━━━━━━━━━━━ 208s 13s/step - accuracy: 0.1749 - loss: 1.9240 - val_accuracy: 0.1452 - val_loss: 1.9054
Epoch 5/20
16/16 ━━━━━━━━━━━━━━━━━━━━ 214s 13s/step - accuracy: 0.1787 - loss: 1.8650 - val_accuracy: 0.2419 - val_loss: 1.6483
Epoch 6/20
16/16 ━━━━━━━━━━━━━━━━━━━━ 202s 13s/step - accuracy: 0.3046 - loss: 1.5703 - val_accuracy: 0.3306 - val_loss: 1.6471
Epoch 7/20
16/16 ━━━━━━━━━━━━━━━━━━━━ 198s 13s/step - accuracy: 0.4451 - loss: 1.4282 - val_accuracy: 0.5403 - val_loss: 1.1161
Epoch 8/20
16/16 ━━━━━━━━━━━━━━━━━━━━ 179s 11s/step - accuracy: 0.6045 - loss: 1.0102 - val_accuracy: 0.5081 - val_loss: 1.0964
Epoch 9/20
16/16 ━━━━━━━━━━━━━━━━━━━━ 166s 11s/step - accuracy: 0.6386 - loss: 0.9255 - val_accuracy: 0.6935 - val_loss: 0.8652
Epoch 10/20
16/16 ━━━━━━━━━━━━━━━━━━━━ 162s 10s/step - accuracy: 0.7404 - loss: 0.6550 - val_accuracy: 0.6290 - val_loss: 0.9989
Epoch 11/20
16/16 ━━━━━━━━━━━━━━━━━━━━ 185s 11s/step - accuracy: 0.8052 - loss: 0.5281 - val_accuracy: 0.6855 - val_loss: 0.9217
Epoch 12/20
16/16 ━━━━━━━━━━━━━━━━━━━━ 185s 12s/step - accuracy: 0.8136 - loss: 0.4523 - val_accuracy: 0.6613 - val_loss: 1.0901
Epoch 13/20
16/16 ━━━━━━━━━━━━━━━━━━━━ 193s 12s/step - accuracy: 0.8089 - loss: 0.4674 - val_accuracy: 0.6935 - val_loss: 0.7750
Epoch 14/20
16/16 ━━━━━━━━━━━━━━━━━━━━ 192s 12s/step - accuracy: 0.8577 - loss: 0.3848 - val_accuracy: 0.7339 - val_loss: 0.8414
Epoch 15/20
16/16 ━━━━━━━━━━━━━━━━━━━━ 185s 12s/step - accuracy: 0.9164 - loss: 0.2603 - val_accuracy: 0.7419 - val_loss: 1.2181
Epoch 16/20
16/16 ━━━━━━━━━━━━━━━━━━━━ 223s 14s/step - accuracy: 0.8789 - loss: 0.4077 - val_accuracy: 0.7258 - val_loss: 0.9584
Epoch 17/20
16/16 ━━━━━━━━━━━━━━━━━━━━ 236s 15s/step - accuracy: 0.9123 - loss: 0.2405 - val_accuracy: 0.7419 - val_loss: 1.2041
Epoch 18/20
16/16 ━━━━━━━━━━━━━━━━━━━━ 236s 15s/step - accuracy: 0.9637 - loss: 0.1224 - val_accuracy: 0.7339 - val_loss: 1.9659
Epoch 19/20
16/16 ━━━━━━━━━━━━━━━━━━━━ 226s 14s/step - accuracy: 0.9677 - loss: 0.0793 - val_accuracy: 0.7339 - val_loss: 1.4271
Epoch 20/20
16/16 ━━━━━━━━━━━━━━━━━━━━ 224s 14s/step - accuracy: 0.9548 - loss: 0.1205 - val_accuracy: 0.7581 - val_loss: 1.4689
#指标	训练集变化	            验证集变化	            结论
#准确率	17.4% → 95.5% (↑78.1%)	19.4% → 75.8% (↑56.4%)	模型学习有效,但存在明显过拟合
#损失值	1.94 → 0.12 (↓93.8%)	1.94 → 1.47 (↓24.2%)	训练损失下降过快,验证损失震荡进程已结束,退出代码为 0




6.从深度学习展开分析

(1)特征学习的革命性突破

传统方法 vs 深度学习

  • 传统CV方案
    需要手工设计特征(如HOG描述子、颜色直方图),但对于动漫人物:

    草帽、发型等特征难以用数学公式描述   不同姿势/角度下特征稳定性差
  • 深度学习方案
    VGG-16通过卷积层自动学习层次化特征:

底层特征(前几层):边缘/颜色 → 识别路飞的草帽红色边缘

中层特征:纹理/部件 → 组合出索隆的三把刀轮廓

高层特征:全局语义 → 理解"娜美的橘色头发+身体比例"这种复合特征

(2)处理图像数据的先天优势

  1. 空间不变性

    • 通过卷积核共享机制,无论路飞出现在图像左上角还是右下角都能被识别

    • 池化层使模型对小幅位移/旋转具有鲁棒性(适合动漫截图角度多变的特点)

  2. 通道维度理解

    • RGB三通道自动提取色彩特征(如乔巴的粉色帽子、山治的金发)

    • 相比灰度图,保留关键颜色线索

  3. 感受野递进

    • 从3×3小窗口逐步扩大到全图感知(最终7×7的特征图对应原图约200×200像素区域)

    • 这种机制天然适配"从局部到整体"的认知逻辑

(3)端到端训练的便捷性

传统流程
图像预处理 → 特征工程 → 分类器设计 → 结果优化(需分步调试)

深度学习流程
原始图片输入 → VGG网络 → 分类结果
所有优化自动完成

(4)针对动漫数据的特殊适配能力

  1. 风格化特征处理

    • 动漫人物线条鲜明、用色大胆,与真实照片差异大

    • CNN通过多层非线性变换,能更好捕捉这种艺术化表达

  2. 跨角色泛化

    • 即使训练集没有"戴草帽的罗宾"这类异常组合,模型也能通过:

      • 低层学到的"草帽特征"

      • 高层学到的"罗宾面部特征"

    • 组合推理出未知变体(比传统方法更具泛化潜力)

(5)延伸应用场景

这套技术方案稍加调整即可用于:

  1. 动漫产业:自动标注动画分镜中的人物出场

  2. 游戏开发:玩家上传截图自动识别角色阵容

  3. 周边电商:拍照搜索手办/服饰对应的

七、总结

在本案例中,深度学习的作用本质是:
通过多层非线性变换,自动从像素中学习到海贼王角色的抽象特征表达,并建立这些特征与人物类别的映射关系。其价值不在于替代人类认知,而是将人类难以显式描述的视觉模式(比如"如何定义乔巴的可爱感")编码成可优化的数学表示。未来结合注意力机制等新技术,还可进一步接近人类的分辨能力。

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

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

相关文章

[创业之路-377]:企业战略管理案例分析-战略制定/设计-市场洞察“五看”:看宏观之社会发展趋势:数字化、智能化、个性化的趋势对初创公司的战略机会

数字化、智能化、个性化趋势为初创公司带来了捕捉长尾需求、提升运营效率、创新商业模式等战略机会,具体分析如下: 一、数字化趋势带来的战略机会 捕捉长尾需求:数字化技术能够帮助初创公司更好地捕捉市场中的长尾需求,满足那些…

macOS 安装 PostgreSQL

文章目录 安装安装信息 验证GUI 工具下载 安装 最简单的方式是通过 brew 安装 brew install postgresql17该版本在 brew 上的详情页:https://formulae.brew.sh/formula/postgresql17 你也可以根据需要,搜索 安装更新版本 如果你没有安装 brew&#xf…

安装openresty使用nginx+lua,openresty使用jwt解密

yum install -y epel-release yum update yum search openresty # 查看是否有可用包 yum install -y openresty启动systemctl start openresty验证服务状态systemctl status openresty设置开机自启systemctl enable openrestysystemctl stop openresty # 停止服务 system…

全球化 2.0 | 云轴科技ZStack助力中东智慧城市高性能智能安防云平台

在全球智慧城市加速建设的背景下,中东某大型城市通过部署云轴科技ZStack Cloud云平台,成功实现公共安全视频监控系统(CCTV)的智能化升级。该平台以弹性计算、GPU智能调度、高可用架构为核心,支撑千路高清视频流处理及人…

Day35打卡 @浙大疏锦行

知识点回顾: 三种不同的模型可视化方法:推荐torchinfo打印summary权重分布可视化进度条功能:手动和自动写法,让打印结果更加美观推理的写法:评估模式 作业:调整模型定义时的超参数,对比下效果。…

嵌入式软件-如何做好一份技术文档?

嵌入式软件-如何做好一份技术文档? 文章目录 嵌入式软件-如何做好一份技术文档?一.技术文档的核心价值与挑战二.文档体系的结构化设计三.精准表达嵌入式特有概念四. **像管理代码一样管理文档**,代码与文档的协同维护五.质量评估与持续改进5.…

css五边形

五边形 .fu{width: 172rpx;height: 204rpx;overflow: hidden;border-radius: 10rpx;clip-path: polygon(0% 0%, 100% 0%, 100% 75%, 50% 100%, 0% 75%, 0% 25%); }六边形 clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);

【Java高阶面经:微服务篇】1.微服务架构核心:服务注册与发现之AP vs CP选型全攻略

一、CAP理论在服务注册与发现中的落地实践 1.1 CAP三要素的技术权衡 要素AP模型实现CP模型实现一致性最终一致性(Eureka通过异步复制实现)强一致性(ZooKeeper通过ZAB协议保证)可用性服务节点可独立响应(支持分区存活)分区期间无法保证写操作(需多数节点可用)分区容错性…

头歌软工导论作业

一.集成测试和确认测试 第1关:集成测试 1、 集成测试的主要方法有CD A、 自顶向下集成方法 B、 自底向上集成方法 C、 渐增式测试方法 D、 非渐增式测试方法 2、 目前在进行集成测试时普遍采用非渐增式测试方法。B A、 √ B、 3、 自底向上集成策略是从主控制模…

MFC:获取所有打印机的名称(打印机模块-1)

背景: 在一个 MFC 应用程序中,列出本地系统中安装的打印机,并检测是否存在“Microsoft Print to PDF”或“Microsoft XPS Document Writer”虚拟打印机。如果有,则选择其中一个作为默认或后续操作对象;如果没有&#…

设计模式-行为型模式(详解)

模板方法 模板方法模式,它在一个抽象类中定义了一个算法(业务逻辑)的骨架,具体步骤的实现由子类提供,它通过将算法的不变部分放在抽象类中,可变部分放在子类中,达到代码复用和扩展的目的。 复用: 所有子类可以直接复…

STM32中的IIC协议和OLED显示屏

串口通信协议的缺点 串口通信通常需要至少三条线(TX、RX和GND),而 I2C 总线仅需要两条信号线(SDA和SCL); 串口通信仅支持一对一通信,而 I2C 总线支持多机通信,允许单个主机与多个从…

30个性能优化方案

1.用String.format拼接字符串 不知道你有没有拼接过字符串,特别是那种有多个参数,字符串比较长的情况。 比如现在有个需求:要用get请求调用第三方接口,url后需要拼接多个参数。 以前我们的请求地址是这样拼接的: S…

docker中部署Universal Media Server (UMS)

Universal Media Server (UMS) 本身主要是作为桌面服务程序开发的(主要面向 Java GUI DLNA 播放),但确实可以通过 Docker 进行部署。虽然官方没有提供 Docker 镜像,但社区有一些可用的方式可以在 Docker 中运行它。 下面是一个可…

配置文件,xml,json,yaml,我该选哪个?

文章目录 一、核心特性对比二、性能与生态系统三、适用场景与选型建议四、替代方案与趋势五、总结 在软件开发中,配置文件格式的选择直接影响开发效率和维护成本。XML、JSON、YAML 是目前主流的三种格式,但它们各有适用场景和局限性。本文将从语法特性、…

产品迭代与放弃的判断:MVP、PMF 与 Scale Fit 的三重验证

在创业和产品管理的世界里,一个永恒的难题是:什么时候应该继续投入资源进行产品迭代?什么时候又该果断放弃? 这是一个既关乎战略方向,又涉及资源分配的核心命题。许多初创公司或产品团队往往在错误的方向上坚持太久&a…

DAY 35 模型可视化与推理

知识点回顾: 三种不同的模型可视化方法:推荐torchinfo打印summary权重分布可视化进度条功能:手动和自动写法,让打印结果更加美观推理的写法:评估模式 作业:调整模型定义时的超参数,对比下效果。…

20250523-BUG-E1696:无法打开元数据文件“platform.winmd(已解决)

BUG:E1696:无法打开元数据文件“platform.winmd(已解决) 最近在用VisualStudio2022打开一个VisualStudio2017的C老项目后报了这个错,几经周折终于解决了,以下是我用的解决方法: 将Debug从Win32改…

Hellorobot 移动操作机器人开源实践:HPR 模型 + 全栈资源,降低家庭机器人开发门槛

Hellorobot在DobbE框架中扮演了重要的技术支柱角色。通过其尖端的模块化设计和高效算法优化,Hellorobot为家庭机器人领域注入了强大的创新动力。DobbE框架的核心技术——Home Pretrained Representations (HPR) 模型,得益于Hellorobot的技术支持&#xf…

onnx模型转入rknn3399平台上工作记录

1.rknn虚拟环境使用时报错问题 使用rknn17环境的报错: ImportError: libdc1394.so.22: cannot open shared object file: No such file or directory 参考链接:https://blog.csdn.net/2301_80032564/article/details/142316410 创作软连接: …