深度学习100例 | 第31天-卷积神经网络(DenseNet)识别生活物品

news2024/11/15 11:00:50

🚀 我的环境:

  • 语言环境:Python3.6.5
  • 编译器:jupyter notebook
  • 深度学习环境:TensorFlow2.4.1
  • 显卡(GPU):NVIDIA GeForce RTX 3080
  • 数据:📌【传送门】

🚀 本文选自专栏:《深度学习100例》

🚀 深度学习新人必看:《小白入门深度学习》

  1. 小白入门深度学习 | 第一篇:配置深度学习环境
  2. 小白入门深度学习 | 第二篇:编译器的使用-Jupyter Notebook
  3. 小白入门深度学习 | 第三篇:深度学习初体验
  4. 小白入门深度学习 | 第四篇:配置PyTorch环境
  5. 小白入门深度学习 | 第五篇:数据不均衡的处理方法

🚀 往期精彩-卷积神经网络篇:

  1. 深度学习100例-卷积神经网络(CNN)实现mnist手写数字识别 | 第1天
  2. 深度学习100例-卷积神经网络(CNN)彩色图片分类 | 第2天
  3. 深度学习100例-卷积神经网络(CNN)服装图像分类 | 第3天
  4. 深度学习100例-卷积神经网络(CNN)花朵识别 | 第4天
  5. 深度学习100例-卷积神经网络(CNN)天气识别 | 第5天
  6. 深度学习100例-卷积神经网络(VGG-16)识别海贼王草帽一伙 | 第6天
  7. 深度学习100例-卷积神经网络(VGG-19)识别灵笼中的人物 | 第7天
  8. 深度学习100例-卷积神经网络(ResNet-50)鸟类识别 | 第8天
  9. 深度学习100例-卷积神经网络(AlexNet)手把手教学 | 第11天
  10. 深度学习100例-卷积神经网络(CNN)识别验证码 | 第12天
  11. 深度学习100例-卷积神经网络(Inception V3)识别手语 | 第13天
  12. 深度学习100例-卷积神经网络(Inception-ResNet-v2)识别交通标志 | 第14天
  13. 深度学习100例-卷积神经网络(CNN)实现车牌识别 | 第15天
  14. 深度学习100例-卷积神经网络(CNN)识别神奇宝贝小智一伙 | 第16天
  15. 深度学习100例-卷积神经网络(CNN)注意力检测 | 第17天
  16. 深度学习100例-卷积神经网络(LeNet-5)深度学习里的“Hello Word” | 第22天
  17. 深度学习100例-卷积神经网络(CNN)3D医疗影像识别 | 第23天
  18. 深度学习100例 | 第24天-卷积神经网络(Xception):动物识别
  19. 深度学习100例 | 第25天-卷积神经网络(CNN):中文手写数字识别
  20. 深度学习100例 | 第26天-卷积神经网络(CNN):乳腺癌识别
  21. 深度学习100例 | 第27天-卷积神经网络(CNN):艺术作品识别
  22. 深度学习100例 | 第28天:水果的识别与分类(准确率99.9%)
  23. 深度学习100例 | 第29天-ResNet50模型:船型识别
  24. 深度学习100例 | 第30天-MobileNetV2算法:动物识别(90类)
  25. 深度学习100例 | 第33天:迁移学习-实战案例教程(必须掌握的一个点)
  26. 深度学习100例 | 第34天:如何进行数据增强?
  27. 深度学习100例 | 第35天:脑肿瘤识别

🚀 往期精彩-循环神经网络篇:

  1. 深度学习100例-循环神经网络(RNN)实现股票预测 | 第9天
  2. 深度学习100例-循环神经网络(LSTM)实现股票预测 | 第10天
  3. 深度学习100例 | 第32天-GRU模型:算法生成小说

🚀 往期精彩-生成对抗网络篇:

  1. 深度学习100例-生成对抗网络(GAN)手写数字生成 | 第18天
  2. 深度学习100例-生成对抗网络(DCGAN)手写数字生成 | 第19天
  3. 深度学习100例-生成对抗网络(DCGAN)生成动漫小姐姐 | 第20天

我们的代码流程图如下所示:

一、设置GPU

import tensorflow as tf
gpus = tf.config.list_physical_devices("GPU")

if gpus:
    gpu0 = gpus[0] #如果有多个GPU,仅使用第0个GPU
    tf.config.experimental.set_memory_growth(gpu0, True) #设置GPU显存用量按需使用
    tf.config.set_visible_devices([gpu0],"GPU")
    
import matplotlib.pyplot as plt
import os,PIL,pathlib
import numpy as np
import pandas as pd
import warnings
from tensorflow import keras

warnings.filterwarnings("ignore")#忽略警告信息
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号

二、导入数据

1. 查看数据情况

import pathlib

data_dir = "./31-data/"
data_dir = pathlib.Path(data_dir)
image_count = len(list(data_dir.glob('*/*')))
print("图片总数为:",image_count)
图片总数为: 30608
# 统计每一个类别的数目
class_name = []
class_sum  = []

for i in data_dir.glob('*'):

    one_dir = ".\\" + str(i)
    one_dir = pathlib.Path(one_dir)
    
    class_name.append(str(i).split(".")[1])
    class_sum.append(len(list(one_dir.glob('*'))))

class_dict = {'class_name':class_name,'class_sum':class_sum}
class_df   = pd.DataFrame(class_dict,columns=['class_name', 'class_sum'])
# 按照图片数量进行降序排序
class_df = class_df.sort_values(by="class_sum" , ascending=False)
class_df.head()
class_nameclass_sum
256clutter827
250airplanes-101800
144motorbikes-101798
252faces-easy-101435
231t-shirt358
def draw_bar(X,Y):
    
    plt.figure(figsize=(6, 4))

    plt.barh(X, Y, align='center',color=['r','g','b','c','y','m'],alpha=0.7)
    plt.xticks(fontsize=12)    # 设置刻度字体大小
    plt.yticks(fontsize=12)   
    plt.xlabel('图片数量',size=12)  #设置x轴标签
#     plt.ylabel('y轴',size=12)  #设置y轴标签
    plt.title('数据集数量top-5与bottom-5对比分析',size=14)
    
    plt.show()

top_5_X    = list(class_df["class_name"][  :5])
top_5_Y    = list(class_df["class_sum"][  :5])

bottom_5_X = list(class_df["class_name"][-5: ])
bottom_5_Y = list(class_df["class_sum"][-5: ])

X= top_5_X+bottom_5_X
Y =top_5_Y+bottom_5_Y

draw_bar(X,Y)

在实验开始时查看数据集分布情况,部分类别图片数量过少时,需要及时补充数据。

2. 加载数据

batch_size = 16
img_height = 224
img_width  = 224
"""
关于image_dataset_from_directory()的详细介绍可以参考文章:https://mtyjkh.blog.csdn.net/article/details/117018789

通过该方法导入数据时,会同时打乱数据
"""
train_ds = tf.keras.preprocessing.image_dataset_from_directory(
    data_dir,
    validation_split=0.2,
    subset="training",
    seed=12,
    image_size=(img_height, img_width),
    batch_size=batch_size)
Found 30607 files belonging to 257 classes.
Using 24486 files for training.
"""
关于image_dataset_from_directory()的详细介绍可以参考文章:https://mtyjkh.blog.csdn.net/article/details/117018789

通过该方法导入数据时,会同时打乱数据
"""
val_ds = tf.keras.preprocessing.image_dataset_from_directory(
    data_dir,
    validation_split=0.2,
    subset="validation",
    seed=12,
    image_size=(img_height, img_width),
    batch_size=batch_size)
Found 30607 files belonging to 257 classes.
Using 6121 files for validation.
class_names = list(class_df["class_name"])
# print("数据类别有:",class_names)
print("需要识别的物体一共有%d类"%len(class_names))
需要识别的物体一共有257类
for image_batch, labels_batch in train_ds:
    print(image_batch.shape)
    print(labels_batch.shape)
    break
(16, 224, 224, 3)
(16,)

3. 配置数据集

  • shuffle() : 打乱数据。
  • prefetch() : 预取数据,加速运行,其详细介绍可以参考我前两篇文章,里面都有讲解。
  • cache() : 将数据集缓存到内存当中,加速运行
AUTOTUNE = tf.data.AUTOTUNE

def train_preprocessing(image,label):
    return (image/255.0,label)

train_ds = (
    train_ds#.cache()              # 如果数据量过大,尽量不要缓存,不然电脑会卡死
    .map(train_preprocessing)      # 这里可以设置预处理函数
    .prefetch(buffer_size=AUTOTUNE)
)

val_ds = (
    val_ds#.cache()                # 如果数据量过大,尽量不要缓存,不然电脑会卡死
    .map(train_preprocessing)      # 这里可以设置预处理函数
    .prefetch(buffer_size=AUTOTUNE)
)

4. 数据可视化

plt.figure(figsize=(10, 8))  # 图形的宽为10高为5
plt.suptitle("数据展示")

for images, labels in train_ds.take(1):
    for i in range(15):
        plt.subplot(4, 5, i + 1)
        plt.xticks([])
        plt.yticks([])
        plt.grid(False)

        # 显示图片
        plt.imshow(images[i])
        # 显示标签
        # plt.xlabel(class_names[labels[i]-1])

plt.show()

三、构建DenseNet模型

from tensorflow.keras.models import Model
from tensorflow.keras import layers
from tensorflow.keras import backend 

def dense_block(x, blocks, name):
    for i in range(blocks):
        x = conv_block(x, 32, name=name + '_block' + str(i + 1))
    return x

def conv_block(x, growth_rate, name):
    bn_axis = 3 
    x1 = layers.BatchNormalization(axis=bn_axis,
                                   epsilon=1.001e-5,
                                   name=name + '_0_bn')(x)
    x1 = layers.Activation('relu', name=name + '_0_relu')(x1)
    x1 = layers.Conv2D(4 * growth_rate, 1,
                       use_bias=False,
                       name=name + '_1_conv')(x1)
    x1 = layers.BatchNormalization(axis=bn_axis, epsilon=1.001e-5,
                                   name=name + '_1_bn')(x1)
    x1 = layers.Activation('relu', name=name + '_1_relu')(x1)
    x1 = layers.Conv2D(growth_rate, 3,
                       padding='same',
                       use_bias=False,
                       name=name + '_2_conv')(x1)
    x = layers.Concatenate(axis=bn_axis, name=name + '_concat')([x, x1])
    return x

def transition_block(x, reduction, name):
    bn_axis = 3
    x = layers.BatchNormalization(axis=bn_axis, epsilon=1.001e-5,
                                  name=name + '_bn')(x)
    x = layers.Activation('relu', name=name + '_relu')(x)
    x = layers.Conv2D(int(backend.int_shape(x)[bn_axis] * reduction), 1,
                      use_bias=False,
                      name=name + '_conv')(x)
    x = layers.AveragePooling2D(2, strides=2, name=name + '_pool')(x)
    return x

def DenseNet(blocks, input_shape=None, classes=1000, **kwargs):

    img_input = layers.Input(shape=input_shape)

    bn_axis = 3

    # 224,224,3 -> 112,112,64
    x = layers.ZeroPadding2D(padding=((3, 3), (3, 3)))(img_input)
    x = layers.Conv2D(64, 7, strides=2, use_bias=False, name='conv1/conv')(x)
    x = layers.BatchNormalization(
        axis=bn_axis, epsilon=1.001e-5, name='conv1/bn')(x)
    x = layers.Activation('relu', name='conv1/relu')(x)
    
    # 112,112,64 -> 56,56,64
    x = layers.ZeroPadding2D(padding=((1, 1), (1, 1)))(x)
    x = layers.MaxPooling2D(3, strides=2, name='pool1')(x)

    # 56,56,64 -> 56,56,64+32*block[0]
    # Densenet121 56,56,64 -> 56,56,64+32*6 == 56,56,256
    x = dense_block(x, blocks[0], name='conv2')

    # 56,56,64+32*block[0] -> 28,28,32+16*block[0]
    # Densenet121 56,56,256 -> 28,28,32+16*6 == 28,28,128
    x = transition_block(x, 0.5, name='pool2')

    # 28,28,32+16*block[0] -> 28,28,32+16*block[0]+32*block[1]
    # Densenet121 28,28,128 -> 28,28,128+32*12 == 28,28,512
    x = dense_block(x, blocks[1], name='conv3')
    
    # Densenet121 28,28,512 -> 14,14,256
    x = transition_block(x, 0.5, name='pool3')

    # Densenet121 14,14,256 -> 14,14,256+32*block[2] == 14,14,1024
    x = dense_block(x, blocks[2], name='conv4')

    # Densenet121 14,14,1024 -> 7,7,512
    x = transition_block(x, 0.5, name='pool4')

    # Densenet121 7,7,512 -> 7,7,256+32*block[3] == 7,7,1024
    x = dense_block(x, blocks[3], name='conv5')
    
    x = layers.BatchNormalization(axis=bn_axis, epsilon=1.001e-5, name='bn')(x)
    x = layers.Activation('relu', name='relu')(x)

    x = layers.GlobalAveragePooling2D(name='avg_pool')(x)
    x = layers.Dense(classes, activation='softmax', name='fc1000')(x)

    inputs = img_input

    if blocks == [6, 12, 24, 16]:
        model = Model(inputs, x, name='densenet121')
    elif blocks == [6, 12, 32, 32]:
        model = Model(inputs, x, name='densenet169')
    elif blocks == [6, 12, 48, 32]:
        model = Model(inputs, x, name='densenet201')
    else:
        model = Model(inputs, x, name='densenet')
    return model

def DenseNet121(input_shape=[224,224,3], classes=len(class_names), **kwargs):
    return DenseNet([6, 12, 24, 16], input_shape, classes, **kwargs)

def DenseNet169(input_shape=[224,224,3], classes=len(class_names), **kwargs):
    return DenseNet([6, 12, 32, 32], input_shape, classes, **kwargs)

def DenseNet201(input_shape=[224,224,3], classes=len(class_names), **kwargs):
    return DenseNet([6, 12, 48, 32], input_shape, classes, **kwargs)

四、编译

model = DenseNet121()

optimizer = tf.keras.optimizers.Adam(lr=1e-3)

model.compile(optimizer=optimizer,
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

五、训练模型

from tensorflow.keras.callbacks import ModelCheckpoint, Callback, EarlyStopping, ReduceLROnPlateau, LearningRateScheduler

NO_EPOCHS = 40
PATIENCE  = 5
VERBOSE   = 1

# 设置动态学习率
# annealer = LearningRateScheduler(lambda x: 1e-4 * 0.98 ** x)

# 设置早停
# earlystopper = EarlyStopping(monitor='loss', patience=PATIENCE, verbose=VERBOSE)

# 设置回调函数
checkpointer = ModelCheckpoint('best_model.h5',
                                monitor='val_accuracy',
                                verbose=VERBOSE,
                                save_best_only=True,
                                save_weights_only=True)
train_model  = model.fit(train_ds,
                  epochs=NO_EPOCHS,
                  verbose=1,
                  validation_data=val_ds,
                  callbacks=[checkpointer])
Epoch 1/40
1531/1531 [==============================] - 155s 94ms/step - loss: 5.1739 - accuracy: 0.0677 - val_loss: 19.6963 - val_accuracy: 0.0601

Epoch 00001: val_accuracy improved from -inf to 0.06012, saving model to best_model.h5
Epoch 2/40
1531/1531 [==============================] - 140s 92ms/step - loss: 4.7255 - accuracy: 0.1058 - val_loss: 4.7597 - val_accuracy: 0.1132

Epoch 00002: val_accuracy improved from 0.06012 to 0.11322, saving model to best_model.h5
Epoch 3/40
1531/1531 [==============================] - 139s 91ms/step - loss: 4.3067 - accuracy: 0.1527 - val_loss: 4.2869 - val_accuracy: 0.1626

 ......

Epoch 00036: val_accuracy did not improve from 0.44257
Epoch 37/40
1531/1531 [==============================] - 140s 91ms/step - loss: 0.1387 - accuracy: 0.9556 - val_loss: 4.4015 - val_accuracy: 0.4468

Epoch 00037: val_accuracy improved from 0.44257 to 0.44682, saving model to best_model.h5
Epoch 38/40
1531/1531 [==============================] - 140s 91ms/step - loss: 0.1244 - accuracy: 0.9622 - val_loss: 4.2792 - val_accuracy: 0.4485

Epoch 00038: val_accuracy improved from 0.44682 to 0.44846, saving model to best_model.h5
Epoch 39/40
1531/1531 [==============================] - 136s 89ms/step - loss: 0.1210 - accuracy: 0.9627 - val_loss: 4.3829 - val_accuracy: 0.4511

Epoch 00039: val_accuracy improved from 0.44846 to 0.45107, saving model to best_model.h5
Epoch 40/40
1531/1531 [==============================] - 138s 90ms/step - loss: 0.1113 - accuracy: 0.9668 - val_loss: 4.4362 - val_accuracy: 0.4527

Epoch 00040: val_accuracy improved from 0.45107 to 0.45270, saving model to best_model.h5

六、评估模型

1. Accuracy与Loss图

acc = train_model.history['accuracy']
val_acc = train_model.history['val_accuracy']

loss = train_model.history['loss']
val_loss = train_model.history['val_loss']

epochs_range = range(len(acc))

plt.figure(figsize=(12, 4))
plt.subplot(1, 2, 1)

plt.plot(epochs_range, acc, label='Training Accuracy')
plt.plot(epochs_range, val_acc, label='Validation Accuracy')
plt.legend(loc='lower right')
plt.title('Training and Validation Accuracy')

plt.subplot(1, 2, 2)
plt.plot(epochs_range, loss, label='Training Loss')
plt.plot(epochs_range, val_loss, label='Validation Loss')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')
plt.show()

加入Dropout层后过拟合现象得到了缓解,没有那么明显了。

2. 各项指标评估

from sklearn import metrics

def test_accuracy_report(model):
#     print(metrics.classification_report(val_label, val_pre, target_names=class_names)) 
    score = model.evaluate(val_ds, verbose=0)
    print('Loss : %s, accuracy:' % score[0], score[1])
    
test_accuracy_report(model)
Loss : 4.436242580413818, accuracy: 0.4527038037776947



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

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

相关文章

Gradle和Maven的区别

Gradle和Maven 当涉及到构建和管理项目时,Gradle和Maven是两个非常流行的选项。本文将讨论Gradle和Maven之间的区别以及它们的配置信息差异。 1. Gradle和Maven的区别 1.1 构建脚本语言 Maven使用XML作为构建脚本语言,而Gradle使用基于Groovy的DSL&…

HashMap查找

文章目录 1 哈希表的基本概念1.1 两个例子1.2 如何查找1.3 若干术语 2 哈希函数的构造方法2.1 直接定址法2.2 除留余数法 3 处理冲突的方法3.1 开放地址法3.1.1 线性探测法3.1.2 二次探测法3.1.3 伪随机探测法 3.2 链地址法(拉链法)3.2.1 创建步骤3.2.2 …

STM32-风速传感器(ADC)

目录 0 说明 1 传感器介绍 2 代码说明 2.1 ADC.c 2.2 adc.h 2.3 main.c 0 说明 本篇文章主要是说明怎么使用STM32单片机读取风速传感器采集到的数据,读取方式是ADC,并且附带着STM32所需要的全部代码,所使用的风速传感器如下图所示。 附&am…

Redis—相关背景

Redis—相关背景 🔎Redis—特性In-memory data structures—在内存中存储数据Programmability—可编程性Extensibility—可扩展性Persistence—持久化Clustering—集群High availability—高可用 🔎Redis 为什么快🔎Redis 的使用场景Real-tim…

看看ChatGPT的Embedding接口都完成哪些任务

调用Embedding接口完成文本分类 前面博客介绍了如何调用ChatGPT的Embedding接口完成文本聚类任务,实现过程入下图所示: 除了完成文本分类,调用Embedding接口还可完成聚类任务。 调用Embedding接口完成聚类任务 聚类任务是一种无监督学习任…

tinymce实现将word中内容(文字图片等)直接粘贴至编辑器中——利用插件tinymce-powerpaste-plugin

TinyMCE是一款易用、且功能强大的所见即所得的富文本编辑器。同类程序有:UEditor、Kindeditor、Simditor、CKEditor、wangEditor、Suneditor、froala等等。 TinyMCE的优势: 开源可商用,基于LGPL2.1 插件丰富,自带插件基本涵盖日常…

活字格性能优化技巧——如何利用数据库主键提升访问性能

大家都知道,活字格作为企业级低代码开发平台,拥有6大引擎,3大能力,能够高效落地企业级应用。在每年的应用大赛中也能看到很多格友利用活字格做了很多复杂的应用,例如2021年企业级低代码应用大赛中宁波聚轩利用活字格做…

vue使用qrcodejs2-fix或者qrcodejs2插件生成二维码

1. vue2安装 npm i qrcodejs2 1.1. vue3安装 npm install qrcodejs2-fix 2. 组件中引入并封装成公共组件&#xff0c;vue3版 <template><!-- 二维码生成 --><div class"body-div"><div style"width: 100%;height: 100%;" :id&quo…

誉天程序员-2301-3-day05

文章目录 知识回归1、单点登录SSO single sign on&#xff08;面试必考&#xff0c;10分&#xff09;2、Vue重大的扩展&#xff0c;Vue框架越来越完善&#xff0c;Vuex状态管理&#xff08;共享数据&#xff09; 全局守卫嵌套路由 知识回归 1、单点登录SSO single sign on&…

Vue2基础七、refnextTick自定义指令

零、文章目录 Vue2基础七、ref&nextTick&自定义指令 1、ref **作用&#xff1a;**利用 ref 和 $refs 可以用于 获取 dom 元素, 或 组件实例**特点&#xff1a;**查找范围 → 当前组件内 (更精确稳定)&#xff0c;用document.querySelect(‘.box’) 获取的是整个页面…

Ubuntu Server版 之 mysql 系列(-),安装、远程连接,mysql 创建用户、授权等

Ubuntu 分 桌面版 和 服务版 桌面版 &#xff1a;有额外的简易界面 服务版&#xff1a;是纯黑框的。没有任何UI界面的可言 安装mysql 安装位置 一般按照的位置存放在 /usr/bin 中 sudo apt-get install mysql-server查看mysql的状态 service mysql status mysql 安全设置…

【C语言课程设计】图书管理系统

引言&#xff1a; 图书管理系统是一个重要的信息管理系统&#xff0c;对于图书馆和书店等机构来说&#xff0c;它能够方便地管理图书的录入、显示、查询、修改和删除等操作。本实验基于C语言开发了一个简单的图书管理系统&#xff0c;通过账户名和密码进行系统访问和权限控制&a…

java数组对象初始化分析

分析代码 public static void main(String[] args) {int a10,b20,c30,d 40,e 50,f60;int aa[] {a,b,c,d,e,f};aa[2] 100;}代码的字节码 图解分析 refs https://docs.oracle.com/javase/specs/jvms/se19/html/jvms-6.html#jvms-6.5.aloadhttps://docs.oracle.com/javase/sp…

WebServer

socket是啥&#xff1f; 网络套接字&#xff08;Socket&#xff09;通常被表示为一个类或类似于类的数据结构。网络套接字类封装了网络通信的细节&#xff0c;并提供了用于建立、发送和接收网络数据的方法和属性。常见的成员有源端口&#xff0c;目标端口&#xff0c;源IP,目…

C语言:结构体,联合体

文章目录 一、结构体1.结构体的声明和结构体变量的定义2.结构体变量初始化3. 访问结构体成员4.结构体的内存对齐 二、联合(共用体)总结 一、结构体 结构体是一组元素类型不同的元素的集合 1.结构体的声明和结构体变量的定义 结构体的声明包含三个部分&#xff0c;标记名(tag…

uniapp 微信小程序:页面+组件的生命周期顺序

uniapp 微信小程序&#xff1a;页面组件的生命周期顺序 首页页面父组件子组件完整顺序参考资料 这个uniapp的微信小程序项目使用的是 VUE2 首页 首页只提供了一个跳转按钮。 <template><view><navigator url"/pages/myPage/myPage?namejerry" hov…

Vue中使用Typescript及Typescript基础

准备工作 新建一个基于ts的vue项目 通过官方脚手架构建安装 # 1. 如果没有安装 Vue CLI 就先安装 npm install --global vue/cli最新的Vue CLI工具允许开发者 使用 TypeScript 集成环境 创建新项目。 只需运行vue create my-app 然后选择选项&#xff0c;箭头键选择 Manuall…

国产芯片架构再下一城,ARM或被彻底抛弃,外媒:自作自受

有消息指出特定厂商的5G手机芯片将采用RISC-V架构&#xff0c;这是国产芯片彻底抛弃ARM的标志&#xff0c;毕竟ARM如今对中国芯片越来越不友好&#xff0c;最新款的ARM V9架构就未对多家中国芯片企业授权&#xff0c;抛弃ARM在情理之中。 据悉特定企业的5G手机芯片为RISC-V架构…

Vue项目中强制刷新页面的方法

我们在动态切换组件的过程中&#xff0c;导航栏和底栏不动&#xff0c;动态切换中间区域的情况&#xff0c;在首页可以进行跳转任意组件&#xff0c;在组件与组件之间不能相互跳转&#xff0c;路由发生了变化&#xff0c;但是页面未改变&#xff0c;这时我们就需要强制刷新页面…

窗口透明丨窗口透明度设置控件透明以及窗体透明源码

透明窗口&#xff08;窗口上面文字图片等内容不透明&#xff09;的实现&#xff08;使用SetLayeredWindowAttributes API函数&#xff09; SetLayeredWindowAttributes的实现必须将窗口设置为WS_EX_LAYERED的扩展风格。 然而&#xff0c;只有WS_POPUP窗口才能设置WS_EX_LAYER…