【2023年第十三届APMCM亚太地区大学生数学建模竞赛】A题 水果采摘机器人的图像识别 Python代码解析

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 本文介绍了2023年第十三届APMCM亚太地区大学生数学建模竞赛A题的Python代码实现,详细阐述了水果采摘机器人图像识别问题的分析与解决策略,包括图像特征提取、数学模型建立、目标检测算法使用,以及苹果数量统计、位置估计、成熟度评估和质量估计等任务的编程实践。

【2023年第十三届APMCM亚太地区大学生数学建模竞赛】A题 水果采摘机器人的图像识别

1 题目

水果采摘机器人的图像识别

中国是世界上最大的苹果生产国,年产量约为3500万吨。与此同时,中国也是世界上最大的苹果出口国,世界上每两个苹果中就有一个来自中国,全球出口的苹果中有六分之一以上来自中国。中国提出了“一带一路”倡议,这是构建人类命运共同体的重要支柱。得益于这一倡议,越南、孟加拉国、菲律宾、印度尼西亚等沿线国家已成为中国苹果的主要出口目的地。

在这里插入图片描述

图1 所示摘果机器人对苹果的图像识别示意图。

苹果采摘主要依靠手工采摘。苹果成熟后,几天内苹果产区就需要大量的采摘工人。但当地的农民大多在自己的果园里种苹果。此外,农业工人的老龄化和年轻人离乡打工的现象,也导致了苹果采摘季节的劳动力短缺。为了解决这一问题,中国从2011年前后开始研究能够摘苹果的机器人,并取得了重大进展。然而,由于果园环境与受控实验的不同,各种苹果采摘机器人在世界范围内的普及和应用与理想相差甚远设置。在复杂和非结构化的果园环境中,现有的大多数机器人都无法准确识别“树叶遮挡”、“树枝遮挡”、“果实遮挡”、“混合遮挡”等障碍物。如果没有根据实际场景做出精确的判断就直接采摘苹果,那么水果受损的风险很高,甚至会对采摘手和机械臂造成伤害。这对采收效率和果实品质造成不利影响,导致更大的损失。此外,对不同收获水果的识别和分类也非常重要,如分类、加工、包装、运输等程序。然而,许多水果的颜色、形状和大小与苹果非常相似,这给苹果的采收后鉴定带来了很大的困难。

本次比赛旨在通过对标记的水果图像进行特征分析和提取,建立一个识别率高、速度快、准确率高的苹果图像识别模型,并对图像进行数据分析,如自动计算图像中苹果的数量、位置、成熟度等级、质量估计等。具体任务如下:

(1)问题1:数苹果

基于附件1提供的收获苹果图像数据集,提取图像特征,建立数学模型,统计每张图像中的苹果数量,绘制附件1中所有苹果分布的直方图。

(2)问题2:估计苹果的位置

根据附件1中提供的成熟苹果图像数据集,以图像左下角为坐标原点,确定每张图像中苹果的位置,绘制附件1中所有苹果几何坐标的二维散点图。

(3)问题3:估计苹果的成熟状态

基于附件1提供的成熟苹果图像数据集,建立数学模型,计算每张图像中苹果的成熟度,并绘制附件1中所有苹果成熟度分布的直方图。

(4)问题4:估计苹果的质量

基于附件1提供的成熟苹果图像数据集,计算每张图像中苹果的二维面积,图像左下角为坐标原点,估计苹果的质量,并绘制附件1中所有苹果质量分布的直方图。

(5)问题5:对苹果的识别

基于附件2提供的收获水果图像数据集,提取图像特征,训练苹果识别模型,识别附件3中的苹果,并绘制附件3中所有苹果图像的ID号分布直方图。

附件:

Attachment.zip,下载网址:https://share.weiyun.com/T6FKbjLf

附件1:

文件夹中包含200张收获苹果的图片,每张图片的大小为270 180像素。附件1的部分截图如下:

在这里插入图片描述

附件2:

文件夹中包含20705张已知标签和分类的不同收获水果图片,每张图片大小为270 180像素。附件2的部分截图如下:

苹果数据集:

在这里插入图片描述
在这里插入图片描述

附件3:

文件夹中包含20705张不同收获水果的图片,标签和分类未知,每张图片大小为270 180像素。附件3的部分截图如下:

在这里插入图片描述

2 问题分析

2.1 问题一

图像中的苹果数量较多,可以考虑使用目标检测算法进行苹果的检测和计数。常见的目标检测算法有Haar特征级联分类器、HOG(Histograms of Oriented Gradients)算法以及深度学习中的Faster R-CNN、YOLO等算法。

从图像中提取特征可能会用到的算法有边缘检测算法(如Canny算法、Sobel算法)、色彩特征提取算法(如HSV颜色空间的色调、饱和度、亮度特征提取)以及纹理特征提取算法(如Gabor滤波器)等。

2.2 问题二

由于需要确定每张图像中苹果的位置,需要将图像上的坐标转换为实际坐标。可能会用到的算法有仿射变换以及透视变换等。

2.3 问题三

图片中的苹果颜色分类,可能用到的算法有

(1)颜色空间转换与阈值分割: 首先,将图像从RGB颜色空间转换为HSV(或其它颜色空间)。然后,选择合适的阈值来分割图像,将成熟和未成熟的苹果分开。

(2)颜色特征提取: 提取图像中苹果区域的颜色特征。可以使用颜色直方图等方法来描述颜色分布情况。

(3)机器学习分类算法: 使用机器学习算法,如支持向量机(SVM)或深度学习神经网络,训练一个分类器。将提取的颜色特征作为输入,将训练好的分类器应用到新的图像上,预测苹果的成熟度。

(4)图像分割算法: 使用图像分割算法,如基于边缘检测的方法(如Canny边缘检测算法)或基于区域生长的方法,将苹果从背景中分离出来,然后进行后续的成熟度估计。

(5)深度学习目标检测算法: 使用深度学习目标检测算法,如Faster R-CNN或YOLO等,来检测和定位图像中的苹果区域,然后进行成熟度估计。

2.4 问题四

在以上两个问题的基础上

(1)轮廓检测和面积计算算法: 对分离出来的苹果轮廓进行检测和处理,并计算出其像素点的个数或计算轮廓面积,即苹果的二维面积。

(2)物理学质量计算方法: 根据苹果的密度和二维面积来计算苹果的质量。苹果的密度大约在0.6-0.8g/cm³之间。可以通过实验测量得到密度的平均值,然后根据面积和密度的关系进行计算。

2.5 问题五

分类问题,在问题一和问题二的基础上,提取特征后,训练分类模型。常用的算法:

(1)卷积神经网络 (CNN):经典的 CNN 架构,如 LeNet、AlexNet、VGG、ResNet 等。

(2)循环神经网络 (RNN):长短期记忆网络(LSTM)、门控循环单元(GRU)等。

(3)迁移学习:迁使用在大规模图像数据集上预训练的 CNN 模型(如 ImageNet 数据集)作为特征提取器,然后根据水果图像的特定数据集进行微调或添加全连接层进行新的分类。

(4)改进的深度学习算法和架构

3 Python代码实现

2.1 问题一

使用了OpenCV库来实现图像的预处理、特征提取和目标检测等操作


import cv2
import torch
import torchvision
import numpy as np
from torchvision import transforms, utils
from matplotlib import pyplot as plt

CLASS_NAMES = ['background', 'apple']
COLORS = np.random.uniform(0, 255, size=(len(CLASS_NAMES), 3))

def load_model():
    model = torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=True)
    model.eval()
    return model

def load_and_process_image(image_path):
    image = cv2.imread(image_path)
    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    transformed = transforms.Compose([
        transforms.ToTensor(),
        transforms.Resize((800, 800)),
    ])
    image = transformed(image)
    return image.unsqueeze(0)

model = load_model()

import glob
import os
def visualize(image, boxes, labels, title,i):
    image = image.permute(1, 2, 0).numpy()
    fig = plt.figure(figsize=(8, 8))
    plt.imshow(image)
    ax = plt.gca()
    for i in range(len(boxes)):
        xmin, ymin, xmax, ymax = boxes[i]
        color = 'r'
        rect = plt.Rectangle((xmin, ymin), xmax - xmin, ymax - ymin, fill=False, edgecolor=color, linewidth=2)
        ax.add_patch(rect)
        text = '{:.2f}'.format(scores[i])
        plt.text(xmin, ymin-5, text, fontsize=8, bbox=dict(facecolor=color, alpha=0.5, pad=1), color='white')
    plt.axis('off')
    plt.title(title)
    plt.savefig('img/Q1_{}.png'.format(i),dpi=100)
    plt.show()

# 循环读取图片
image_paths = sorted(glob.glob(os.path.join('Attachment/Attachment 1', '*.jpg')))
i=0
test = []
count_list = []
for image_path in image_paths:
    image = load_and_process_image(image_path)
    det_pred = model(image)
    boxes = det_pred[0]['boxes'].detach().numpy()
    scores = det_pred[0]['scores'].detach().numpy()
    labels = det_pred[0]['labels'].detach().numpy()

    threshold = 0.5
    idx = scores > threshold
    boxes = boxes[idx]
    scores = scores[idx]
    labels = labels[idx]

    num_apples = len(boxes)
    count_list.append(num_apples)
    print('第{}张图片中苹果的数量为{}个'.format(i, num_apples))
    apple_locs = []
    for j in range(num_apples):
        xmin, ymin, xmax, ymax = boxes[j]
        apple_loc = (xmin, ymin, xmax, ymax)
        apple_locs.append(apple_loc)
    if i <= 3:
        visualize(image[0], boxes, labels, 'Image {}'.format(i),i)
    i+=1
# 绘制直方图
plt.hist(count_list, bins=range(max(count_list) + 2))
plt.xlabel("Apple count")
plt.ylabel("Image count")
plt.savefig('img/Q_苹果数量分布.png',dpi=300)
plt.show()

每张图像中苹果的数量: [2, 0, 0, 0, 0, 1, 1, 0, 0, 3, 0, 1, 3, 0, 0, 1, 0, 1, 3, 0, 0, 0, 5, 0, 0, 2, 0, 0, 2, 0, 3, 0, 0, 0, 2, 3, 0, 1, 0, 0, 0, 3, 0, 2, 2, 0, 2, 0, 0, 0, 1, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 2, 1, 2, 3, 4, 1, 5, 0, 3, 0, 1, 0, 0, 0, 0, 2, 2, 1, 1, 4, 1, 3, 0, 2, 4, 0, 3, 1, 0, 1, 2, 2, 0, 4, 1, 4, 3, 0, 0, 0, 1, 2, 3, 0, 0, 0, 2, 2, 1, 0, 1, 3, 2, 3, 1, 1, 1, 2, 0, 0, 0, 3, 0, 3, 5, 0, 5, 0, 4, 3, 0, 4, 0, 0, 0, 0, 0, 2, 3, 2, 0, 1, 0, 1, 3, 1, 2, 0, 0, 1, 3, 0, 0, 0, 5, 1, 1, 0, 0, 2, 2, 2, 2, 5, 0, 2, 0, 3, 1, 0, 1, 0, 1, 0, 1, 0, 0, 2, 0, 3, 7, 0, 2, 4, 0, 0, 2, 0, 0, 0, 2, 0, 2, 2]

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

2.2 问题二

列表apple_locs_all,用于存储所有图像中苹果的位置信息。在每个图像的处理中,在确定每个苹果的位置时将其添加到apple_locs_all中。在处理完所有图像后,绘制apple_locs_all中所有苹果位置信息的散点图。具体方法是根据坐标数据分别将x、y值组成两个列表,然后使用Matplotlib中的scatter函数进行绘制。


import cv2
import torch
import torchvision
import numpy as np
from torchvision import transforms, utils
from matplotlib import pyplot as plt
import glob
import os

CLASS_NAMES = ['background', 'apple']
COLORS = np.random.uniform(0, 255, size=(len(CLASS_NAMES), 3))

def load_model():
    model = torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=True)
    model.eval()
    return model

def load_and_process_image(image_path):
    image = cv2.imread(image_path)
    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    transformed = transforms.Compose([
        transforms.ToTensor(),
        transforms.Resize((800, 800)),
    ])
    image = transformed(image)
    return image.unsqueeze(0)

def visualize(image, boxes, labels, title,i):
    image = image.permute(1, 2, 0).numpy()
    fig = plt.figure(figsize=(8, 8))
    plt.imshow(image)
    ax = plt.gca()
    for i in range(len(boxes)):
        xmin, ymin, xmax, ymax = boxes[i]
        color = 'r'
        rect = plt.Rectangle((xmin, ymin), xmax - xmin, ymax - ymin, fill=False, edgecolor=color, linewidth=2)
        ax.add_patch(rect)
        text = '{:.2f}'.format(scores[i])
        plt.text(xmin, ymin-5, text, fontsize=8, bbox=dict(facecolor=color, alpha=0.5, pad=1), color='white')
    plt.axis('off')
    plt.title(title)
    plt.savefig('img/Q1_{}.png'.format(i),dpi=100)
    plt.show()

model = load_model()
# 循环读取图片
image_paths = sorted(glob.glob(os.path.join('Attachment/Attachment 1', '*.jpg')))
i=0
test = []
count_list = []
apple_locs_all = []  # 存储所有苹果的位置
for image_path in image_paths:
    image = load_and_process_image(image_path)
    det_pred = model(image)
    boxes = det_pred[0]['boxes'].detach().numpy()
    scores = det_pred[0]['scores'].detach().numpy()
    labels = det_pred[0]['labels'].detach().numpy()

    threshold = 0.5
    idx = scores > threshold
    boxes = boxes[idx]
    scores = scores[idx]
    labels = labels[idx]

    num_apples = len(boxes)
    count_list.append(num_apples)
    print('第{}张图片中苹果的数量为{}个'.format(i, num_apples))
    apple_locs = []
    for j in range(num_apples):
        xmin, ymin, xmax, ymax = boxes[j]
        # 转换坐标原点到左下角
        ymin = image.shape[1] - ymax
        ymax = image.shape[1] - ymin
        apple_loc = (xmin, ymin, xmax, ymax)
        apple_locs.append(apple_loc)
        apple_locs_all.append(apple_loc)
    # 只可视化前4张图片
    # if i <= 3:
        # visualize(image[0], boxes, labels, 'Image {}'.format(i),i)
    i += 1

# 绘制所有苹果的散点图
x = [loc[0] for loc in apple_locs_all]
y = [loc[1] for loc in apple_locs_all]
fig, ax = plt.subplots()
ax.scatter(x, y)
ax.set_xlabel('x')
ax.set_ylabel('y')
plt.title('All Apples in Dataset')
plt.savefig('img/Q1_all_apples.png')
plt.show()

在这里插入图片描述

2.3 问题三

在问题一和问题二的基础上,获取苹果位置,并截取苹果部分的图片
将图片转换为HSV色彩空间,然后根据苹果在该色彩空间中的颜色范围,将苹果分为成熟和未成熟两类。

import cv2
import torch
import torchvision
import numpy as np
from torchvision import transforms, utils
from matplotlib import pyplot as plt
import glob
import os
def load_model():
    model = torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=True)
    model.eval()
    return model

def load_and_process_image(image_path):
    image = cv2.imread(image_path)
    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    transformed = transforms.Compose([
        transforms.ToTensor(),
        transforms.Resize((800, 800)),
    ])
    image = transformed(image)
    return image.unsqueeze(0)

def plot_ripeness_distribution(labels):
    # 统计成熟和未成熟苹果的数量
    num_ripe = labels.count(1)
    num_unripe = labels.count(0)
    num_total = num_ripe + num_unripe

    # 绘制成熟度分布的直方图
    fig, ax = plt.subplots()
    ax.bar([0, 1], [num_unripe, num_ripe], color=['g', 'r'])
    ax.set_xlim(-0.5, 1.5)
    ax.set_xticks([0, 1])
    ax.set_xticklabels(['Unripe', 'Ripe'])
    ax.set_xlabel('Ripeness')
    ax.set_ylabel('Count')
    plt.title('Ripeness Distribution of {} Apples'.format(num_total))
    plt.savefig('img/Q1_ripeness_distribution.png')
    plt.show()

def calculate_apple_ripeness(image, boxes, scores):
    ...请下载完整资料
    return apple_labels

def visualize(image, boxes, scores, title, i, apple_labels=None):
    image = image.permute(1, 2, 0).numpy()
    fig = plt.figure(figsize=(8, 8))
    plt.imshow(image)
    ax = plt.gca()
    if apple_labels is not None:
        for j in range(len(apple_labels)):
            xmin, ymin, xmax, ymax = boxes[j]
            color = 'g' if apple_labels[j] == 0 else 'r'
            rect = plt.Rectangle((xmin, ymin), xmax - xmin, ymax - ymin, fill=False, edgecolor=color, linewidth=2)
            ax.add_patch(rect)
    else:
        for j in range(len(boxes)):
            xmin, ymin, xmax, ymax = boxes[j]
            color = 'r'
            rect = plt.Rectangle((xmin, ymin), xmax - xmin, ymax - ymin, fill=False, edgecolor=color, linewidth=2)
            ax.add_patch(rect)
            text = '{:.2f}'.format(scores[j])
            plt.text(xmin, ymin-5, text, fontsize=8, bbox=dict(facecolor=color, alpha=0.5, pad=1), color='white')
    plt.axis('off')
    plt.title(title)
    plt.savefig('img/Q3_{}.png'.format(i),dpi=100)
    plt.show()

model = load_model()
# 循环读取图片
image_paths = sorted(glob.glob(os.path.join('Attachment/test', '*.jpg')))
i = 0
test = []
count_list = []
apple_locs_all = []  # 存储所有苹果的位置
apple_labels_all = []  # 存储所有苹果标签
for image_path in image_paths:
    image = load_and_process_image(image_path)
    det_pred = model(image)
    boxes = det_pred[0]['boxes'].detach().numpy()
    scores = det_pred[0]['scores'].detach().numpy()
    labels = det_pred[0]['labels'].detach().numpy()

    threshold = 0.5
    idx = scores > threshold
    boxes = boxes[idx]
    scores = scores[idx]
    labels = labels[idx]

    num_apples = len(boxes)
    count_list.append(num_apples)
    print('第{}张图片中苹果的数量为{}个'.format(i, num_apples))
    apple_locs = []
    if num_apples > 0:
        apple_labels = calculate_apple_ripeness(image[0].numpy().astype(np.uint8), boxes, scores)
        # apple_labels = calculate_apple_ripeness(image.numpy(), boxes, scores)
        apple_labels_all.extend(apple_labels)
        for j in range(num_apples):
            xmin, ymin, xmax, ymax = boxes[j]
            # 转换坐标原点到左下角
            ymin = image.shape[2] - ymax
            ymax = image.shape[2] - ymin
            apple_loc = (xmin, ymin, xmax, ymax)
            apple_locs.append(apple_loc)
            apple_locs_all.append(apple_loc)
        visualize(image[0], boxes, scores, 'Image {}'.format(i), i, apple_labels=apple_labels)
    else:
        visualize(image[0], [], [], 'Image {}'.format(i), i)
        apple_labels_all.extend([])
    i += 1

# 绘制苹果成熟度分布直方图
plot_ripeness_distribution(apple_labels_all)

在这里插入图片描述

2.4 问题四

在这里插入图片描述

2.5 问题五

请下载完整资料,请加我扣扣

目录
相关文章
|
17天前
|
搜索推荐 UED Python
实现一个带有昼夜背景切换的动态时钟:从代码到功能解析
本文介绍了一个使用Python和Tkinter库实现的动态时钟程序,具有昼夜背景切换、指针颜色随机变化及整点和半点报时功能。通过设置不同的背景颜色和随机变换指针颜色,增强视觉吸引力;利用多线程技术确保音频播放不影响主程序运行。该程序结合了Tkinter、Pygame、Pytz等库,提供了一个美观且实用的时间显示工具。欢迎点赞、关注、转发、收藏!
128 94
|
6天前
|
存储 算法 安全
控制局域网上网软件之 Python 字典树算法解析
控制局域网上网软件在现代网络管理中至关重要,用于控制设备的上网行为和访问权限。本文聚焦于字典树(Trie Tree)算法的应用,详细阐述其原理、优势及实现。通过字典树,软件能高效进行关键词匹配和过滤,提升系统性能。文中还提供了Python代码示例,展示了字典树在网址过滤和关键词屏蔽中的具体应用,为局域网的安全和管理提供有力支持。
34 17
|
9天前
|
运维 Shell 数据库
Python执行Shell命令并获取结果:深入解析与实战
通过以上内容,开发者可以在实际项目中灵活应用Python执行Shell命令,实现各种自动化任务,提高开发和运维效率。
42 20
|
1月前
|
传感器 人工智能 自然语言处理
RDT:清华开源全球最大的双臂机器人操作任务扩散基础模型、代码与训练集,基于模仿能力机器人能够自主完成复杂任务
RDT(Robotics Diffusion Transformer)是由清华大学AI研究院TSAIL团队推出的全球最大的双臂机器人操作任务扩散基础模型。RDT具备十亿参数量,能够在无需人类操控的情况下自主完成复杂任务,如调酒和遛狗。
137 22
RDT:清华开源全球最大的双臂机器人操作任务扩散基础模型、代码与训练集,基于模仿能力机器人能够自主完成复杂任务
|
16天前
|
SQL Java 数据库连接
如何在 Java 代码中使用 JSqlParser 解析复杂的 SQL 语句?
大家好,我是 V 哥。JSqlParser 是一个用于解析 SQL 语句的 Java 库,可将 SQL 解析为 Java 对象树,支持多种 SQL 类型(如 `SELECT`、`INSERT` 等)。它适用于 SQL 分析、修改、生成和验证等场景。通过 Maven 或 Gradle 安装后,可以方便地在 Java 代码中使用。
137 11
|
1月前
|
自然语言处理 搜索推荐 数据安全/隐私保护
鸿蒙登录页面好看的样式设计-HarmonyOS应用开发实战与ArkTS代码解析【HarmonyOS 5.0(Next)】
鸿蒙登录页面设计展示了 HarmonyOS 5.0(Next)的未来美学理念,结合科技与艺术,为用户带来视觉盛宴。该页面使用 ArkTS 开发,支持个性化定制和无缝智能设备连接。代码解析涵盖了声明式 UI、状态管理、事件处理及路由导航等关键概念,帮助开发者快速上手 HarmonyOS 应用开发。通过这段代码,开发者可以了解如何构建交互式界面并实现跨设备协同工作,推动智能生态的发展。
154 10
鸿蒙登录页面好看的样式设计-HarmonyOS应用开发实战与ArkTS代码解析【HarmonyOS 5.0(Next)】
|
22天前
|
数据采集 供应链 API
Python爬虫与1688图片搜索API接口:深度解析与显著收益
在电子商务领域,数据是驱动业务决策的核心。阿里巴巴旗下的1688平台作为全球领先的B2B市场,提供了丰富的API接口,特别是图片搜索API(`item_search_img`),允许开发者通过上传图片搜索相似商品。本文介绍如何结合Python爬虫技术高效利用该接口,提升搜索效率和用户体验,助力企业实现自动化商品搜索、库存管理优化、竞品监控与定价策略调整等,显著提高运营效率和市场竞争力。
62 3
|
1月前
|
数据采集 JSON API
如何利用Python爬虫淘宝商品详情高级版(item_get_pro)API接口及返回值解析说明
本文介绍了如何利用Python爬虫技术调用淘宝商品详情高级版API接口(item_get_pro),获取商品的详细信息,包括标题、价格、销量等。文章涵盖了环境准备、API权限申请、请求构建和返回值解析等内容,强调了数据获取的合规性和安全性。
|
1月前
|
数据挖掘 vr&ar C++
让UE自动运行Python脚本:实现与实例解析
本文介绍如何配置Unreal Engine(UE)以自动运行Python脚本,提高开发效率。通过安装Python、配置UE环境及使用第三方插件,实现Python与UE的集成。结合蓝图和C++示例,展示自动化任务处理、关卡生成及数据分析等应用场景。
137 5
|
1月前
|
存储 缓存 Python
Python中的装饰器深度解析与实践
在Python的世界里,装饰器如同一位神秘的魔法师,它拥有改变函数行为的能力。本文将揭开装饰器的神秘面纱,通过直观的代码示例,引导你理解其工作原理,并掌握如何在实际项目中灵活运用这一强大的工具。从基础到进阶,我们将一起探索装饰器的魅力所在。

热门文章

最新文章