『行远见大』炼丹注意事项——以蝴蝶图像分类为例

该项目是飞桨图像分类训练营大作业,以蝴蝶图像分类为例,探究炼丹中数据增强与调参对精度的影响。包括数据集加载预处理(解压、建立路径与标签关系、自定义读取器,用Resize等增强)、构建ResNet152预训练模型,以Adam优化器训练,及预测流程,旨在分析提升分类精度的方法。

☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 DeepSeek R1 模型☜☜☜

『行远见大』炼丹注意事项——以蝴蝶图像分类为例 - 创想鸟

『行远见大』炼丹注意事项——以蝴蝶图像分类为例

本项目是『飞桨领航团图像分类零基础训练营』课程布置的大作业,项目旨在分析图像分类炼丹过程中如何做数据增强以及调参来增加精度。

『飞桨领航团图像分类零基础训练营』是由飞桨深度学习学院于2021/02/25开设的课程。

加载数据集

解压缩数据步骤:

第一步,把当前路径转换到data目录,可以使用命令!cd data。在AI studio nootbook中可以使用Linux命令,需要在命令的最前面加上英文的感叹号(!)。用&&可以连接两个命令。用号可以换行写代码。需要注意的是,每次重新打开该项目,data文件夹下除了挂载的数据集,其他文件都会被清空。因此,如果把数据保存在data目录中,每次重新启动项目时,都需要解压缩一下。如果想省事持久化保存,可以把数据保存在work目录下。

实际上,!加某命令的模式,等价于python中的get_ipython().system(‘某命令’)模式。

第二步,利用unzip命令,把压缩包解压到当前路径。unzip的-q参数代表执行时不显示任何信息。unzip的-o参数代表不必先询问用户,unzip执行后覆盖原有的文件。两个参数合起来,可以写为-qo。

第三步,用rm命令可以把一些文件夹给删掉(rm -r __MACOSX),比如,__MACOSX文件夹

In [1]

!ls /home/aistudio/data/data66509/Butterfly20.zip!ls /home/aistudio/data/data66509/Butterfly20_test.zip!unzip -q /home/aistudio/data/data66509/Butterfly20_test.zip -d work!unzip -q /home/aistudio/data/data66509/Butterfly20.zip -d work

   

准备数据

数据准备过程包括以下两个重点步骤:

一是建立样本数据读取路径与样本标签之间的关系。

二是构造读取器与数据预处理。可以写个自定义数据读取器,它继承于PaddlePaddle2.0的dataset类,在__getitem__方法中把自定义的预处理方法加载进去。

In [3]

# 以下代码用于建立样本数据读取路径与样本标签之间的关系import osimport randomimport matplotlib.pyplot as pltimport PIL.Image as Imagedata_list = [] # 用个列表保存每个样本的读取路径、标签# 由于属种名称本身是字符串,而输入模型的是数字。需要构造一个字典,把某个数字代表该属种名称。键是属种名称,值是整数。label_list=[]with open("/home/aistudio/work/species.txt") as f:    for line in f:        a,b = line.strip("n").split(" ")        label_list.append([b, int(a)-1])label_dic = dict(label_list)# 获取Butterfly20目录下的所有子目录名称,保存进一个列表之中class_list = os.listdir("/home/aistudio/work/Butterfly20")class_list.remove('.DS_Store') # 删掉列表中名为.DS_Store的元素,因为.DS_Store并没有样本。for each in class_list:    for f in os.listdir("/home/aistudio/work/Butterfly20/"+each):        data_list.append(["/home/aistudio/work/Butterfly20/"+each+'/'+f,label_dic[each]])# 按文件顺序读取,可能造成很多属种图片存在序列相关,用random.shuffle方法把样本顺序彻底打乱。random.shuffle(data_list)# 打印前十个,可以看出data_list列表中的每个元素是[样本读取路径, 样本标签]。print(data_list[0:10])# 打印样本数量,一共有1866个样本。print("样本数量是:{}".format(len(data_list)))

       

[['/home/aistudio/work/Butterfly20/011.Lamproptera_meges/011.jpg', 10], ['/home/aistudio/work/Butterfly20/016.Papilio_alcmenor/012.jpg', 15], ['/home/aistudio/work/Butterfly20/001.Atrophaneura_horishanus/152.jpg', 0], ['/home/aistudio/work/Butterfly20/013.Meandrusa_payeni/007.jpg', 12], ['/home/aistudio/work/Butterfly20/017.Papilio_arcturus/055.jpg', 16], ['/home/aistudio/work/Butterfly20/003.Byasa_alcinous/101.jpg', 2], ['/home/aistudio/work/Butterfly20/010.Lamproptera_curius/030.jpg', 9], ['/home/aistudio/work/Butterfly20/001.Atrophaneura_horishanus/129.jpg', 0], ['/home/aistudio/work/Butterfly20/007.Graphium_cloanthus/020.jpg', 6], ['/home/aistudio/work/Butterfly20/019.Papilio_dialis/043.jpg', 18]]样本数量是:1866

       In [4]

# 以下代码用于构造读取器与数据预处理# 首先需要导入相关的模块import paddlefrom paddle.vision.transforms import Compose, ColorJitter, Resize,Transpose, Normalizeimport cv2import numpy as npfrom PIL import Imagefrom paddle.io import Dataset# 使用Paddle2.0自带的数据增强方法import paddle.vision.transforms as T# 自定义的数据预处理函数,输入原始图像,输出处理后的图像,可以借用paddle.vision.transforms的数据处理功能def preprocess(img):    transform = Compose([        Resize(size=(224, 224)),                                                             # 把数据长宽像素调成224*224        T.ColorJitter(0.125,0.4,0.4,0.08),                                                   # 保持亮度、对比度、饱和度、色调等在测试集上一致        # T.BrightnessTransform(0.4),                                                        # 只对亮度调整做调整        T.RandomHorizontalFlip(0.5),                                                         # 水平翻转        T.RandomRotation(15),                                                                # 随机反转角度范围        T.RandomVerticalFlip(0.5),                                                           # 垂直翻转        T.RandomRotation(15),                                                                # 随机反转角度范围        Normalize(mean=[127.5, 127.5, 127.5], std=[127.5, 127.5, 127.5], data_format='HWC'), # 标准化        Transpose()                                                                          # 原始数据形状维度是HWC格式,经过Transpose,转换为CHW格式        ])          img = transform(img).astype("float32")    return img# 自定义数据读取器class Reader(Dataset):    def __init__(self, data, is_val=False):        super().__init__()        # 在初始化阶段,把数据集划分训练集和测试集。由于在读取前样本已经被打乱顺序,取20%的样本作为测试集,80%的样本作为训练集。        self.samples = data[-int(len(data)*0.2):] if is_val else data[:-int(len(data)*0.2)]    def __getitem__(self, idx):        # 处理图像        img_path = self.samples[idx][0]          # 得到某样本的路径        img = Image.open(img_path)        if img.mode != 'RGB':            img = img.convert('RGB')        img = preprocess(img)                    # 数据预处理--这里仅包括简单数据预处理,没有用到数据增强        # 处理标签        label = self.samples[idx][1]             # 得到某样本的标签        label = np.array([label], dtype="int64") # 把标签数据类型转成int64        return img, label    def __len__(self):        # 返回每个Epoch中图片数量        return len(self.samples)# 生成训练数据集实例train_dataset = Reader(data_list, is_val=False)# 生成测试数据集实例eval_dataset = Reader(data_list, is_val=True)# 打印一个训练样本# print(train_dataset[1136][0])print(train_dataset[1136][0].shape)print(train_dataset[1136][1])# 查看划分后的样本量print('训练集样本量: {},验证集样本量: {}'.format(len(train_dataset), len(eval_dataset)))

       

(3, 224, 224)[10]训练集样本量: 1493,验证集样本量: 373

       

ColorJitter

class paddle.vision.transforms.ColorJitter(brightness=0, contrast=0, saturation=0, hue=0, keys=None) 随机调整图像的亮度,对比度,饱和度和色调。

参数

brightness(float) – 亮度调整范围大小,会从给定参数后的均匀分布[max(0,1 – brightness), 1 + brightness]中随机选择进行实际调整,不能是负数。

contrast(float) – 对比度调整范围大小,,会从给定参数后的均匀分布[max(0,1 – contrast), 1 + contrast]中随机选择进行实际调整,不能是负数。

saturation(float) – 饱和度调整范围大小,,会从给定参数后的均匀分布[max(0,1 – saturation), 1 + saturation]中随机选择进行实际调整,不能是负数。

hue(float) – 色调调整范围大小,,会从给定参数后的均匀分布[-hue, hue]中随机选择进行实际调整,参数值需要在0到0.5之间。

keys (list[str]|tuple[str], optional) – 与 BaseTransform 定义一致。默认值: None。

RandomHorizontalFlip/RandomVerticalFlip

class paddle.vision.transforms.RandomHorizontalFlip(prob=0.5, keys=None) 基于概率来执行图片的水平翻转;

class paddle.vision.transforms.RandomVerticalFlip(prob=0.5, keys=None) 基于概率来执行图片的垂直翻转。

参数

prob (float) – 图片执行水平/垂直翻转的概率,默认值为0.5。

keys (list[str]|tuple[str], optional) – 与 BaseTransform 定义一致。默认值: None。

RandomRotate

class paddle.vision.transforms.RandomRotation(degrees, interpolation=’nearest’, expand=False, center=None, fill=0, keys=None)按指定角度范围随机旋转图像。

参数

degrees (sequence|float|int) – 旋转的角度度数范围。 如果度数是数字而不是像(min,max)这样的序列,则会根据degrees参数值生成度数范围(-degrees,+degrees)。

interpolation (str, optional): 插值的方法。 如果这个参数没有设定或者输入图像为单通道,则该参数会根据使用的后端,被设置为 PIL.Image.NEAREST 或者 cv2.INTER_NEAREST。

当使用 pil 作为后端时, 支持的插值方法如下: “nearest”: Image.NEAREST, “bilinear”: Image.BILINEAR, “bicubic”: Image.BICUBIC

当使用 cv2 作为后端时, 支持的插值方法如下: “nearest”: cv2.INTER_NEAREST, “bilinear”: cv2.INTER_LINEAR, “bicubic”: cv2.INTER_CUBIC

expand (bool,可选) – 是否要对旋转后的图片进行大小扩展,默认值: False。

当参数值为True时,会对图像大小进行扩展,让其能够足以容纳整个旋转后的图像。 当参数值为False时,会按照原图像大小保留旋转后的图像。这个扩展操作的前提是围绕中心旋转且没有平移。

center (2-tuple,可选) – 旋转的中心点坐标,原点是图片左上角,默认值是图像的中心点。

fill (int,可选) – 对图像扩展时填充的值。默认值:0。

keys (list[str]|tuple[str], optional) – 与 BaseTransform 定义一致。默认值: None。

建立模型

这里选用 ResNet 残差网络

为简便,这里直接使用残差网络ResNet,并且采用预训练模式。为什么要采用预训练模型呢?因为通常模型参数采用随机初始化,而预训练模型参数初始值是一个比较确定的值。这个参数初始值是经历了大量任务训练而得来的,比如用CIFAR图像识别任务来训练模型,得到的参数。虽然蝴蝶识别任务和CIFAR图像识别任务是不同的,但可能存在某些机器视觉上的共性。用预训练模型可能能够较快地得到比较好的准确度。

在PaddlePaddle2.0中,使用预训练模型只需要设定模型参数pretained=True。值得注意的是,预训练模型得出的结果类别是1000维度,要用个线性变换,把类别转化为20维度。

In [5]

# 定义模型class MyNet(paddle.nn.Layer):    def __init__(self):        super(MyNet,self).__init__()        # self.layer=paddle.vision.models.resnet50(pretrained=True)     # 陆平老师上课选择的模型        # self.layer=paddle.vision.models.resnet152(pretrained=True)    # 讲义中推荐的模型        self.layer=paddle.vision.models.resnet152(pretrained=True)      # 耗时长但精度相对而言高的模型        self.dropout=paddle.nn.Dropout(p=0.5)        self.fc = paddle.nn.Linear(1000, 20)    # 网络的前向计算过程    def forward(self,x):        x=self.layer(x)        x=self.dropout(x)        x=self.fc(x)        return xprint("本项目基于Paddle的版本号为:"+ paddle.__version__)

       

本项目基于Paddle的版本号为:2.0.0

       

应用高阶API训练模型

一是定义输入数据形状大小和数据类型。

二是实例化模型。如果要用高阶API,需要用Paddle.Model()对模型进行封装,如model = paddle.Model(model,inputs=input_define,labels=label_define)。

三是定义优化器。这个使用Adam优化器,学习率设置为0.0001,优化器中的学习率(learning_rate)参数很重要。要是训练过程中得到的准确率呈震荡状态,忽大忽小,可以试试进一步把学习率调低。

四是准备模型。这里用到高阶API,model.prepare()。

五是训练模型。这里用到高阶API,model.fit()。参数意义详见下述代码注释。

In [6]

# 定义输入input_define = paddle.static.InputSpec(shape=[-1,3,224,224], dtype="float32", name="img")label_define = paddle.static.InputSpec(shape=[-1,1], dtype="int64", name="label")# 实例化网络对象并定义优化器等训练逻辑model = MyNet()model = paddle.Model(model,inputs=input_define,labels=label_define)                      # 用Paddle.Model()对模型进行封装optimizer = paddle.optimizer.Adam(learning_rate=0.00005, parameters=model.parameters())# 上述优化器中的学习率(learning_rate)参数很重要。要是训练过程中得到的准确率呈震荡状态,忽大忽小,可以试试进一步把学习率调低

       

100%|██████████| 355826/355826 [00:04<00:00, 71284.76it/s]

       In [7]

# 使用Adam优化器, 学习率为0.00005, 使用交叉熵损失函数, top1与top5精准度配置Accuracy的评估指标model.prepare(optimizer=optimizer,                           # 指定优化器              loss=paddle.nn.CrossEntropyLoss(),             # 指定损失函数              metrics=paddle.metric.Accuracy(topk=(1,5)))    # 指定评估方法# 回调函数使用callback = paddle.callbacks.VisualDL(log_dir='./log_mynet_152')model.fit(train_data=train_dataset,         # 训练数据集          eval_data=eval_dataset,           # 测试数据集          batch_size=128,                   # 一个批次的样本数量(常见的有32、64、128、256)          epochs=50,                        # 迭代轮次(常见的有20、50、100、200)          save_dir="/home/aistudio/lup",    # 把模型参数、优化器参数保存至自定义的文件夹          save_freq=20,                     # 设定每隔多少个epoch保存模型参数及优化器参数          log_freq=100,                     # 打印日志的频率          verbose=1,                        # 日志展示模式          shuffle=True,                     # 是否打乱数据集顺序          callbacks=callback)               # 回调函数使用# 如果运行报错,请退出草稿版,项目栏处切换version1.0版本再运行!

   

炼丹注意事项

我这里拿batch_size=128和epochs=50为例,在20轮后acc_top1的精度在0.88和0.91之间震荡,效果还算是理想。

但如果要使acc_top1精度稳定在0.9以上,可以从调整learning_rate、batch_size、epoch的参数下手。

年轻人,拿好这本《炼丹注意事项》,前路漫漫,开启炼(爆)丹(肝)之旅事不宜迟!

应用已经训练好的模型进行预测

如果是要参加建模比赛,通常赛事组织方会提供待预测的数据集,我们需要利用自己构建的模型,来对待预测数据集合中的数据标签进行预测。也就是说,我们其实并不知道到其真实标签是什么,只有比赛的组织方知道真实标签,我们的模型预测结果越接近真实结果,那么分数也就越高。

预测流程分为以下几个步骤:

一是构建数据读取器。因为预测数据集没有标签,该读取器写法和训练数据读取器不一样,建议重新写一个类,继承于Dataset基类。

二是实例化模型。如果要用高阶API,需要用Paddle.Model()对模型进行封装,如paddle.Model(MyNet(),inputs=input_define),由于是预测模型,所以仅设定输入数据格式就好了。

三是读取刚刚训练好的参数。这个保存在/home/aistudio/work目录之下,如果指定的是final则是最后一轮训练后的结果。可以指定其他轮次的结果,比如model.load(‘/home/aistudio/work/30’),这里用到了高阶API,model.load()

四是准备模型。这里用到高阶API,model.prepare()。

五是读取待预测集合中的数据,利用已经训练好的模型进行预测。

六是结果保存。

In [9]

class InferDataset(Dataset):    def __init__(self, img_path=None):        """        数据读取Reader(推理)        :param img_path: 推理单张图片        """        super().__init__()        if img_path:            self.img_paths = [img_path]        else:            raise Exception("请指定需要预测对应图片路径")    def __getitem__(self, index):        # 获取图像路径        img_path = self.img_paths[index]        # 使用Pillow来读取图像数据并转成Numpy格式        img = Image.open(img_path)        if img.mode != 'RGB':             img = img.convert('RGB')         img = preprocess(img) #数据预处理--这里仅包括简单数据预处理,没有用到数据增强        return img    def __len__(self):        return len(self.img_paths)# 实例化推理模型model = paddle.Model(MyNet(),inputs=input_define)# 读取刚刚训练好的参数model.load('/home/aistudio/lup/final')# 准备模型model.prepare()# 得到待预测数据集中每个图像的读取路径infer_list=[]with open("/home/aistudio/work/testpath.txt") as file_pred:    for line in file_pred:        infer_list.append("/home/aistudio/work/"+line.strip())# 模型预测结果通常是个数,需要获得其对应的文字标签。这里需要建立一个字典。def get_label_dict2():    label_list2=[]    with open("/home/aistudio/work/species.txt") as filess:        for line in filess:            a,b = line.strip("n").split(" ")            label_list2.append([int(a)-1, b])    label_dic2 = dict(label_list2)    return label_dic2label_dict2 = get_label_dict2()# print(label_dict2)# 利用训练好的模型进行预测results=[]for infer_path in infer_list:    infer_data = InferDataset(infer_path)    result = model.predict(test_data=infer_data)[0]  # 关键代码,实现预测功能    result = paddle.to_tensor(result)    result = np.argmax(result.numpy())               # 获得最大值所在的序号    results.append("{}".format(label_dict2[result])) # 查找该序号所对应的标签名字# 把结果保存起来with open("work/result.txt", "w") as f:    for r in results:        f.write("{}n".format(r))

   

以上就是『行远见大』炼丹注意事项——以蝴蝶图像分类为例的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/46837.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年11月7日 20:27:12
下一篇 2025年11月7日 20:31:29

相关推荐

  • CSS mask属性无法获取图片:为什么我的图片不见了?

    CSS mask属性无法获取图片 在使用CSS mask属性时,可能会遇到无法获取指定照片的情况。这个问题通常表现为: 网络面板中没有请求图片:尽管CSS代码中指定了图片地址,但网络面板中却找不到图片的请求记录。 问题原因: 此问题的可能原因是浏览器的兼容性问题。某些较旧版本的浏览器可能不支持CSS…

    2025年12月24日
    900
  • Uniapp 中如何不拉伸不裁剪地展示图片?

    灵活展示图片:如何不拉伸不裁剪 在界面设计中,常常需要以原尺寸展示用户上传的图片。本文将介绍一种在 uniapp 框架中实现该功能的简单方法。 对于不同尺寸的图片,可以采用以下处理方式: 极端宽高比:撑满屏幕宽度或高度,再等比缩放居中。非极端宽高比:居中显示,若能撑满则撑满。 然而,如果需要不拉伸不…

    2025年12月24日
    400
  • 如何让小说网站控制台显示乱码,同时网页内容正常显示?

    如何在不影响用户界面的情况下实现控制台乱码? 当在小说网站上下载小说时,大家可能会遇到一个问题:网站上的文本在网页内正常显示,但是在控制台中却是乱码。如何实现此类操作,从而在不影响用户界面(UI)的情况下保持控制台乱码呢? 答案在于使用自定义字体。网站可以通过在服务器端配置自定义字体,并通过在客户端…

    2025年12月24日
    800
  • 如何在地图上轻松创建气泡信息框?

    地图上气泡信息框的巧妙生成 地图上气泡信息框是一种常用的交互功能,它简便易用,能够为用户提供额外信息。本文将探讨如何借助地图库的功能轻松创建这一功能。 利用地图库的原生功能 大多数地图库,如高德地图,都提供了现成的信息窗体和右键菜单功能。这些功能可以通过以下途径实现: 高德地图 JS API 参考文…

    2025年12月24日
    400
  • 如何使用 scroll-behavior 属性实现元素scrollLeft变化时的平滑动画?

    如何实现元素scrollleft变化时的平滑动画效果? 在许多网页应用中,滚动容器的水平滚动条(scrollleft)需要频繁使用。为了让滚动动作更加自然,你希望给scrollleft的变化添加动画效果。 解决方案:scroll-behavior 属性 要实现scrollleft变化时的平滑动画效果…

    2025年12月24日
    000
  • 如何为滚动元素添加平滑过渡,使滚动条滑动时更自然流畅?

    给滚动元素平滑过渡 如何在滚动条属性(scrollleft)发生改变时为元素添加平滑的过渡效果? 解决方案:scroll-behavior 属性 为滚动容器设置 scroll-behavior 属性可以实现平滑滚动。 html 代码: click the button to slide right!…

    2025年12月24日
    500
  • 为什么设置 `overflow: hidden` 会导致 `inline-block` 元素错位?

    overflow 导致 inline-block 元素错位解析 当多个 inline-block 元素并列排列时,可能会出现错位显示的问题。这通常是由于其中一个元素设置了 overflow 属性引起的。 问题现象 在不设置 overflow 属性时,元素按预期显示在同一水平线上: 不设置 overf…

    2025年12月24日 好文分享
    400
  • 网页使用本地字体:为什么 CSS 代码中明明指定了“荆南麦圆体”,页面却仍然显示“微软雅黑”?

    网页中使用本地字体 本文将解答如何将本地安装字体应用到网页中,避免使用 src 属性直接引入字体文件。 问题: 想要在网页上使用已安装的“荆南麦圆体”字体,但 css 代码中将其置于第一位的“font-family”属性,页面仍显示“微软雅黑”字体。 立即学习“前端免费学习笔记(深入)”; 答案: …

    2025年12月24日
    000
  • 如何选择元素个数不固定的指定类名子元素?

    灵活选择元素个数不固定的指定类名子元素 在网页布局中,有时需要选择特定类名的子元素,但这些元素的数量并不固定。例如,下面这段 html 代码中,activebar 和 item 元素的数量均不固定: *n *n 如果需要选择第一个 item元素,可以使用 css 选择器 :nth-child()。该…

    2025年12月24日
    200
  • 使用 SVG 如何实现自定义宽度、间距和半径的虚线边框?

    使用 svg 实现自定义虚线边框 如何实现一个具有自定义宽度、间距和半径的虚线边框是一个常见的前端开发问题。传统的解决方案通常涉及使用 border-image 引入切片图片,但是这种方法存在引入外部资源、性能低下的缺点。 为了避免上述问题,可以使用 svg(可缩放矢量图形)来创建纯代码实现。一种方…

    2025年12月24日
    100
  • 如何解决本地图片在使用 mask JS 库时出现的跨域错误?

    如何跨越localhost使用本地图片? 问题: 在本地使用mask js库时,引入本地图片会报跨域错误。 解决方案: 要解决此问题,需要使用本地服务器启动文件,以http或https协议访问图片,而不是使用file://协议。例如: python -m http.server 8000 然后,可以…

    2025年12月24日
    200
  • 旋转长方形后,如何计算其相对于画布左上角的轴距?

    绘制长方形并旋转,计算旋转后轴距 在拥有 1920×1080 画布中,放置一个宽高为 200×20 的长方形,其坐标位于 (100, 100)。当以任意角度旋转长方形时,如何计算它相对于画布左上角的 x、y 轴距? 以下代码提供了一个计算旋转后长方形轴距的解决方案: const x = 200;co…

    2025年12月24日
    000
  • 旋转长方形后,如何计算它与画布左上角的xy轴距?

    旋转后长方形在画布上的xy轴距计算 在画布中添加一个长方形,并将其旋转任意角度,如何计算旋转后的长方形与画布左上角之间的xy轴距? 问题分解: 要计算旋转后长方形的xy轴距,需要考虑旋转对长方形宽高和位置的影响。首先,旋转会改变长方形的长和宽,其次,旋转会改变长方形的中心点位置。 求解方法: 计算旋…

    2025年12月24日
    000
  • 旋转长方形后如何计算其在画布上的轴距?

    旋转长方形后计算轴距 假设长方形的宽、高分别为 200 和 20,初始坐标为 (100, 100),我们将它旋转一个任意角度。根据旋转矩阵公式,旋转后的新坐标 (x’, y’) 可以通过以下公式计算: x’ = x * cos(θ) – y * sin(θ)y’ = x * …

    2025年12月24日
    000
  • 如何让“元素跟随文本高度,而不是撑高父容器?

    如何让 元素跟随文本高度,而不是撑高父容器 在页面布局中,经常遇到父容器高度被子元素撑开的问题。在图例所示的案例中,父容器被较高的图片撑开,而文本的高度没有被考虑。本问答将提供纯css解决方案,让图片跟随文本高度,确保父容器的高度不会被图片影响。 解决方法 为了解决这个问题,需要将图片从文档流中脱离…

    2025年12月24日
    000
  • 为什么我的特定 DIV 在 Edge 浏览器中无法显示?

    特定 DIV 无法显示:用户代理样式表的困扰 当你在 Edge 浏览器中打开项目中的某个 div 时,却发现它无法正常显示,仔细检查样式后,发现是由用户代理样式表中的 display none 引起的。但你疑问的是,为什么会出现这样的样式表,而且只针对特定的 div? 背后的原因 用户代理样式表是由…

    2025年12月24日
    200
  • 如何计算旋转后长方形在画布上的轴距?

    旋转后长方形与画布轴距计算 在给定的画布中,有一个长方形,在随机旋转一定角度后,如何计算其在画布上的轴距,即距离左上角的距离? 以下提供一种计算长方形相对于画布左上角的新轴距的方法: const x = 200; // 初始 x 坐标const y = 90; // 初始 y 坐标const w =…

    2025年12月24日
    200
  • CSS元素设置em和transition后,为何载入页面无放大效果?

    css元素设置em和transition后,为何载入无放大效果 很多开发者在设置了em和transition后,却发现元素载入页面时无放大效果。本文将解答这一问题。 原问题:在视频演示中,将元素设置如下,载入页面会有放大效果。然而,在个人尝试中,并未出现该效果。这是由于macos和windows系统…

    2025年12月24日
    200
  • inline-block元素错位了,是为什么?

    inline-block元素错位背后的原因 inline-block元素是一种特殊类型的块级元素,它可以与其他元素行内排列。但是,在某些情况下,inline-block元素可能会出现错位显示的问题。 错位的原因 当inline-block元素设置了overflow:hidden属性时,它会影响元素的…

    2025年12月24日
    000
  • 为什么 CSS mask 属性未请求指定图片?

    解决 css mask 属性未请求图片的问题 在使用 css mask 属性时,指定了图片地址,但网络面板显示未请求获取该图片,这可能是由于浏览器兼容性问题造成的。 问题 如下代码所示: 立即学习“前端免费学习笔记(深入)”; icon [data-icon=”cloud”] { –icon-cl…

    2025年12月24日
    200

发表回复

登录后才能评论
关注微信