版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
数据爬取-标注-可视化实验手册实验手册【项目目标】(1)掌握使用行业主流的API技术,根据指定主题(关键词)批量获取图像数据的方法。(2)学习并实践使用LabelMe工具对获取的图像数据进行基础的人工标注(如目标检测框)。(3)学习使用Matplotlib库对获取的数据集进行初步的特征分析与可视化。(4)完整体验人工智能项目中“数据获取->数据标注->数据分析”的核心流程。任务一基于API的通用图像数据获取(1)使用浏览器访问/zh-cn/api/。(2)点击“加入”,按照提示注册一个Pexels账号。(3)登录后,进入个人主页,找到API相关的菜单,根据提示填写相关信息,申请API密钥。(4)申请成功后,会得到一串由数字和字母组成的字符串,即API密钥。请妥善保管,后续代码中会用到。在向Pexels服务器发送请求之前,首先要搭建好代码的基本框架。本步骤代码实现的功能主要有:导入将要使用的requests、os和time库。定义函数download_images_from_pexels,并将所有需要的参数(如API密钥、搜索关键词等)作为函数的输入。在函数内部,先检查用于保存图片的文件夹是否存在,如果不存在,就自动创建一个。新建一个名为download_data_single_page.py的Python文件,将下列代码复制至文件中。#代码块1:准备工作与函数框架importrequestsimportosimporttime#导入time模块用于添加延迟defdownload_images_from_pexels(api_key,query,per_page=15,save_path='downloaded_images_single_page'):"""使用PexelsAPI根据关键词下载图片,带有上限控制。参数:api_key(str):你的PexelsAPI密钥。query(str):你想搜索的图片关键词。per_page(int):你期望下载的图片数量,但不会超过设定的最大上限MAX_DOWNLOAD_LIMIT。save_path(str):图片保存的文件夹名称。"""#设定一个全局的下载上限(根据Pexels网站API限制,单页返回结果数最大值为80,故此处数值应≤80)MAX_DOWNLOAD_LIMIT=50#确定本次实际要请求下载的数量#在用户期望的数量和上限之间取较小值num_to_download=min(per_page,MAX_DOWNLOAD_LIMIT)#检查并创建保存图片的文件夹ifnotos.path.exists(save_path):os.makedirs(save_path)print(f"创建文件夹:{save_path}")框架搭好后,需要填充核心的“网络请求”部分。本步骤代码实现的功能主要有:定义好PexelsAPI的网址、请求头(包含身份认证APIKey)和请求参数(告诉API我们想搜索什么)。使用requests.get()函数将该请求发送出去。接收服务器返回的响应,并将其从JSON格式解析为Python可以理解的字典和列表格式,从中提取出包含所有图片信息的列表photos。在params中,我们使用了上一步计算出的num_to_download作为per_page的值。从返回的data中解析出total_results字段,并将其打印出来。这样就能清楚地知道,虽然我们只下载一部分,但网站上总共有多少资源。请将以下代码继续添加至函数download_images_from_pexels内。#代码块2:配置并发送API请求#PexelsAPI的URL地址api_url='/v1/search'#设置请求头headers={'Authorization':api_key}#设置请求参数,使用计算好的下载数量params={'query':query,'per_page':num_to_download,'locale':'zh-CN'}try:#发起GET请求print("正在向Pexels服务器发送请求...")response=requests.get(api_url,headers=headers,params=params,timeout=10)#添加超时response.raise_for_status()#检查API请求是否成功#解析返回的JSON数据data=response.json()#读取并打印符合条件的总图片数total_results=data.get('total_results',0)print(f"Pexels网站上共找到{total_results}张关于'{query}'的图片。")photos=data.get('photos',[])ifnotphotos:print("未能找到相关图片,请尝试更换关键词。")returnprint(f"根据上限设定,准备下载其中的{len(photos)}张...")在获取了所有图片的信息之后需要遍历该信息列表(上一步中得到的photo),从中提取出每张图片真正的下载地址(img_url),然后再次使用requests库将图片一张张下载并保存到本地文件夹中。注意在下载过程中添加短暂延迟,避免对服务器的请求过于频繁。最后添加程序的“主入口”(if__name__=='__main__':),设置好API密钥和搜索词,并调用我们刚刚完成的函数。在主函数中通过变量EXPECTED_AMOUNT控制预期的下载量,而函数内部的逻辑会保证最终下载量不会超出代码块1中MAX_DOWNLOAD_LIMIT变量所规定的数值。#代码块3:循环下载图片与程序主入口#遍历图片列表并下载fori,photoinenumerate(photos):try:img_url=photo['src']['original']print(f"({i+1}/{len(photos)})准备下载图片URL:{img_url}")#发起图片下载请求,添加超时img_response=requests.get(img_url,stream=True,timeout=30)img_response.raise_for_status()#检查图片下载请求是否成功file_name=f"{query}_{i+1}.jpg"file_path=os.path.join(save_path,file_name)print(f"保存路径:{file_path}")#以二进制写入模式打开文件并写入图片内容withopen(file_path,'wb')asf:forchunkinimg_response.iter_content(8192):ifchunk:#过滤掉keep-alive新块f.write(chunk)print(f"已下载:{file_name}")#添加短暂延迟,避免请求过于频繁(例如0.2秒)time.sleep(0.2)exceptrequests.exceptions.RequestExceptionase:print(f"下载图片{img_url}时发生网络错误:{e}")exceptIOErrorase:print(f"保存图片{file_path}时发生文件错误:{e}")exceptExceptionase:print(f"下载图片{img_url}时发生未知错误:{e}")print("\n所有图片下载完成!")exceptrequests.exceptions.RequestExceptionase:print(f"请求PexelsAPI时发生网络错误:{e}")exceptExceptionase:print(f"发生未知错误:{e}")#主程序入口if__name__=='__main__':#********************需要修改的区域********************#请在这里粘贴你从Pexels获取的有效API密钥MY_API_KEY="Nki0RSycdk28Zl10uzPcuQdo1fGTx0EF6g3H2irST0yk6bIdk6ahYCgY"#请在这里修改你想搜索的关键词SEARCH_QUERY="长城"#你期望下载多少张?(但最多不会超过MAX_DOWNLOAD_LIMIT变量所规定的数值)EXPECTED_AMOUNT=10#你可以根据需要修改这个数量#**********************************************************ifMY_API_KEY=="在这里粘贴你的API密钥":print("错误:请先在代码中填入你的PexelsAPI密钥!")else:#调用函数开始下载download_images_from_pexels(api_key=MY_API_KEY,query=SEARCH_QUERY,per_page=EXPECTED_AMOUNT)将步骤二、三、四的代码块按顺序整合到一个完整的Python文件(例如download_data_single_page.py)中。找到代码中“需要修改的区域”,填入在步骤一中获取的API密钥和想搜索的关键词(例如“故宫”、“小狗”、“机器人”等)。运行该Python文件。程序会自动创建一个名为downloaded_images_single_page的文件夹,并将下载的图片保存在里面。打开文件夹,检查图片是否已成功下载。图2-12在目标文件夹中下载的图片在Pexels网站上有数量庞大的图片数据资源,当我们以某个关键词进行搜索时可能会得到成千上万的返回结果。根据PexelsAPI文档中的描述,当结果较多时,会以分页的形式返回结果,每页最多80个数据。在任务一的代码中,我们未考虑结果分页的情形,因此最大的下载量即为单页数据的最大值(80)。在实际应用中,如果希望下载更多数量的结果,就需要根据API文档的指示,在代码中加入分页处理的功能,逐页下载数据,直至达到我们需要的数量。读者可以自行尝试修改代码增加分页下载的功能,或运行配套资源中的示例代码(download_data_multi_pages.py),查看大数量情景下的图片数据爬取结果。在应用中需要注意遵守目标网站的相关规定,合法合规的下载数据,杜绝滥用的情况。任务二图像场景目标标注Labelme是一个图形界面的图像标注软件。它是用Python语言编写的,图形界面使用的是Qt(PyQt)。其Python的源代码在GitHub的位置:/wkentaro/labelme。Labelme能够进行多种形式的图像数据标注,其以JSON文件存储标注信息,主要功能如下:(1)对图像进行多边形,矩形,圆形,多段线,线段,点形式的标注(可用于目标检测,图像分割,等任务);(2)对图像进行进行flag形式的标注(可用于图像分类和清理任务);(3)生成VOC、COCO等格式的数据集;(4)自定义图片+标签的自定义数据集。本任务具体实施步骤如下。启动anaconda3中的anacondaprompt,运行如下代码安装labelme。pipinstallpyqt5pipinstalllabelme因最新版本的labelme需要python3.9以上的环境,若使用的环境是python3.8,则需使用如下命令安装旧版本的labelme:pipinstalllabelme==4.6.0在anacondaprompt中,运行如下代码激活project2环境,并启动labelme。condaactivateproject2labelme在LabelMe界面中,点击左侧菜单的“OpenDir”按钮。在弹出的对话框中,选择我们刚才在任务一中创建并保存图片的downloaded_images_single_page文件夹。图2-13labelme软件导入待标注图片上一步选择文件夹后,LabelMe将自动加载文件夹中的第一张图片。点击左侧菜单的“CreatePolygons”进行描点标注,或点击上方的“Edit”选择标注工具。对于目标检测任务,通常使用矩形框(Rectangle)。在图片上,用鼠标左键点击与拖拽操作,框出你想要标注的目标。例如,如果下载的是“长城”的图片,就框出图片中的城墙、烽火台等。框选完成后,会弹出一个对话框让你输入标签(Label)。输入对应的名称,例如chengqiang(城墙),然后点击OK。可以对一张图片中的多个目标进行标注。图2-14标注图片完成一张图片的标注后,点击左侧菜单的“Save”按钮。LabelMe会在原图片所在的文件夹下,生成一个同名的.json文件。该文件就包含了所有的标注信息(框的位置、标签等)。点击“NextImage”处理下一张图片,重复步骤三和四,直至所有图片都标注完成。图2-15原始图片及标注后生成的json文件任务三数据可视化在拥有数据集后,我们不仅可以对其进行标注,还可以对数据本身进行分析。一个优秀的人工智能工程师需要具备从数据中发现模式和特点的能力。可视化是实现这一目标最直观的手段。在本次任务中,我们将从两个不同的维度对下载的图片数据集进行分析:个体特征:每张图片的具体尺寸是怎样的?我们将使用散点图来展示宽度和高度的分布。宏观特征:数据集中横向、纵向和方形的图片各有多少?我们将使用柱状图来进行分类统计和对比。完成这一任务所使用的工具是matplotlib,它是Python中最常用、最著名的数据可视化模块,该模块的子模块pyplot包含大量用于绘制各类图表的函数,例如柱状图、折线图、散点图、饼图、气泡图等。任务实施具体步骤如下。本步骤代码将导入所有必需的工具库(os,PIL,matplotlib),然后遍历我们下载的图片文件夹,读取每一张图片的宽度和高度,并将这些尺寸数据存储在两个列表(widths和heights)中,为后续的绘图做好数据准备。新建一个名为visualize_data.py的Python文件,将以下代码复制至文件中。#代码块1:数据准备importosfromPILimportImageimportmatplotlib.pyplotaspltdefanalyze_and_visualize_image_sizes(folder_path='downloaded_images_single_page'):"""分析指定文件夹中所有图片的特征,并生成可视化图表。"""image_files=[fforfinos.listdir(folder_path)iff.lower().endswith(('.jpg','.jpeg','.png'))]ifnotimage_files:print(f"在文件夹'{folder_path}'中没有找到图片文件。")returnwidths=[]heights=[]#遍历所有图片,获取尺寸print("开始读取图片尺寸...")forfilenameinimage_files:try:withImage.open(os.path.join(folder_path,filename))asimg:width,height=img.sizewidths.append(width)heights.append(height)exceptExceptionase:print(f"无法读取图片{filename}:{e}")print("所有图片尺寸读取完毕!")在步骤一获取了所有图片的宽度和高度数据后,我们现在可以利用这些数据绘制第一张图表——散点图。每一张图片都将作为图上的一个点,其横坐标是图片的宽度,纵坐标是图片的高度。这可以帮助我们直观地看到数据集中所有图片尺寸的分布情况。#代码块2:绘制散点图#设置Matplotlib支持中文显示plt.rcParams['font.sans-serif']=['MicrosoftYaHei','SimHei']plt.rcParams['axes.unicode_minus']=False#绘制散点图plt.figure(figsize=(10,6))#创建一个新的图形窗口plt.scatter(widths,heights,alpha=0.6,edgecolors='w',s=80)plt.title('下载图片尺寸分布图(散点图)',fontsize=16)plt.xlabel('宽度(像素)',fontsize=12)plt.ylabel('高度(像素)',fontsize=12)plt.grid(True)除了观察每个数据点的个体情况,我们还关心数据集的整体特征。本步骤将对已获取的尺寸数据进行一次简单的统计:计算“横向”、“纵向”和“方形”的图片各有多少张。然后,利用统计结果绘制第二张图表——柱状图,以清晰地对比不同朝向图片的数量。#代码块3:绘制柱状图并显示#首先,根据宽高数据统计图片朝向orientations={'横向':0,'纵向':0,'方形':0}forw,hinzip(widths,heights):ifw>h:orientations['横向']+=1elifh>w:orientations['纵向']+=1else:orientations['方形']+=1categories=list(orientations.keys())counts=list(orientations.values())#绘制柱状图plt.figure(figsize=(8,5))#创建第二个新的图形窗口bars=plt.bar(categories,counts,color=['skyblue','salmon','lightgreen'])#在柱状图顶部显示具体数值forbarinbars:yval=bar.get_height()plt.text(bar.get_x()+bar.get_width()/2.0,yval,int(yval),va='bottom',ha='center')plt.title('图片朝向统计(柱状图)',fontsize=16)plt.xlabel('图片朝向',fontsize=12)plt.ylabel('数量(张)',fontsize=12)#最后,显示所有图表plt.show()#主程序入口if__name__=='__main__':analyze_and_visualize_image_sizes()确保visualize_data.py文件与downloaded_images文件夹在同一个目录下。运行该文件,程序会依次执行数据读取、散点图绘制和柱状图绘制,最终弹出两个独立的窗口,分别显示散点图和柱状图。图2-16图片尺寸分布散点图图2-17图片朝向统计柱状图本项目实现了数据采集、数据标注和数据可视化。通过python中requests、lableme和matplotlib等库的实践应用,使读者了解数据采集、数据标注和数据可视化的一般流程,掌握其基础原理与基本技能。完成项目实训后,读者可进一步对代码进行模块化整理或修改,尝试获取其它类别的图片数据并对其进行可视化分析。
项目总结报告项目名称姓名学号小组名称(适合小组项目)实施过程记录测试结果总结后期改进思考成员分工(适合小组项目)姓名职责完成情况组长评分考核评价评价标准:1.执行力:按时完成项目任务。2.学习力:知识技能的掌握情况。3.表达力:实施报告详实、条理清晰。4.创新力:在完成基本任务之外,有创新、有突破者加分。5.协作力:团队分工合理、协作良好,组员得分在项目组得分基础上根据组长评价上下浮动。云计算与边缘计算实验手册【项目目标】(1)掌握从云端进行数据处理与模型训练,到将模型部署至边缘设备执行的全流程AI应用开发方法。(2)体验并学习使用零代码AI云平台,了解如何使用其提供的“云端算力”来简化和加速模型开发。(3)学习使用ONNXRuntime、OpenCV等行业标准工具,在个人计算机(模拟边缘设备)上调用摄像头进行实时数据处理与AI模型推理。(4)通过实践直观对比和理解云计算与边缘计算在AI应用中的不同角色、优势及其“云边协同”的工作模式。(5)培养解决实际问题的AI工程思维,体验从一个想法到一个可交互AI应用的创造过程,激发创新精神。任务一使用云平台实现图像分类应用在理论知识的讲解中,我们了解了云计算平台如何提供强大的“算力”来支持AI开发。本任务我们将体验一个免费的AI模型训练云平台。它将复杂的算力需求隐藏在简洁的网页背后,让我们可以利用自己的数据快速训练出一个有效的AI模型,使我们能更直观地聚焦于“数据->训练->模型”这一AI应用核心流程。本任务需要使用配套资源中提供的“猫狗分类数据集”,请自行下载。读者也可通过项目二的实验代码自行准备猫、狗动物图片,每种类至少100张。需要注意的是自行爬取的图片通常需要进行二次检查、筛选及清洗,以保证数据集的质量。使用Chrome浏览器访问https://train.aimaker.space/train。点击主页上的“图像项目”,如图3-6所示。图3-6在平台主页选择“图像项目”进入数据准备界面后,需要告诉平台要学习几个类别(Class),并为每个类别提供相应的学习“教材”(图片)。找到默认的“Class1”,点击旁边的铅笔图标,将其重命名为“猫”。继续点击下方的“上传”按钮上传样本图片。图3-7修改类别(Class)名称并打开上传界面在弹出的窗口中选择“在文件夹中选择图像或直接拖放到此处”,然后找到并选中提前下载好的数据集中所有猫的图片,点击“打开”进行上传。图3-8上传数据集中的样本图片按照同样的方式将“Class2”名称修改为“狗”并完成样本图片的添加。如有需要可以继续点击下方的“添加一个类别”按钮,继续添加新的Class及对应的样本图片,如图3-9所示。图3-9根据需要继续添加样本点击页面中部“训练模型”按钮下方的高级标签,可以看到模型训练的一些基本参数,如“单次训练迭代次数”、“批处理大小”、“学习速率”等。点击参数右侧的问号图标可以显示简单的参数说明。本次实验暂时不需要修改任何参数,保持默认即可。点击“训练模型”按钮,训练过程会立即开始,此时会看到一个训练进度提示。需要注意的是,训练期间页面会提示“不要切换标签页”,否则会中断训练。根据图片数量计算机性能,训练过程通常需要数分钟。图3-10使用上传的数据集训练图片分类模型训练完成后,可以点击“高级选项”按钮查看所训练模型的若干特征。图3-11模型训练的部分参数信息右侧的“预览”窗口会在训练结束后自动激活,可以测试训练好的AI模型。在“预览”窗口下方,选择输入方式为“文件夹”。点击“在文件夹中选择图像或直接拖动到此处”,从测试集中选择一张从未用于训练的、新的猫或狗的图片。上传后,模型会立刻进行分析,并在下方的“输出”区域显示结果。可以看到“猫”和“狗”两个进度条,进度条越长,代表模型认为图片属于该类别的可能性(置信度)越高。图3-12测试模型效果测试数据集中也准备了老虎、狐狸与狼的若干图片。读者也可将这些图片上传至模型进行判断,观察模型的反应。本任务在云端(网页应用)利用算力完成了一个AI图像分类模型的开发。该过程虽然简单,但完整地覆盖了数据准备、模型训练和效果验证三大核心环节,为后续学习更复杂的AI项目打下坚实基础。读者可以尝试利用本书配套资源中提供的数据集,自行训练一个能够完成手势识别的模型供下一个任务中使用。任务二边缘设备实现手势识别在任务一中,我们已经在云平台上快速训练并验证了一个在云端运行的图像分类模型。本任务将把云端训练好的模型“请”到本地计算机(边缘设备)上,使其能够在断网的情况下于本地实时运行。为方便验证模型识别的效果,本任务将使用一个手势识别的场景,通过本地摄像头实时采集手势,送至模型识别,将结果显示于本地计算机。请读者使用教材配套的手势识别数据集,按照任务一的步骤训练一个手势识别模型。训练完成后,在右上角“预览”区域,点击“导出模型”按钮。在弹出的窗口中,选择Tensorflow标签页。在其下方,确保选择的是Keras格式。点击“下载我的模型”按钮。图3-13下载训练好的模型浏览器会自动下载一个名为converted_keras.zip的压缩包。将其解压后可以得到两个文件:keras_model.h5:模型的核心文件,包含了神经网络的结构和权重。labels.txt:文本文件,记录了模型的分类标签。在步骤一中得到的.h5是Keras专用的模型格式,运行.h5模型通常需要安装庞大的TensorFlow完整库。对于存储和内存资源有限的边缘设备通常需要一种轻量化部署能力更强的模型。为了应对此类边缘设备的需求,一种名为ONNX(OpenNeuralNetworkExchange,开放神经网络交换格式)的开放标准应运而生,其目标旨在解决不同AI训练框架之间模型难以互通的壁垒。在业界,ONNX被广泛应用于AI模型的“云边端”全流程部署场景中。例如,数据科学家团队可能使用功能强大的PyTorch或TensorFlow框架在云端服务器上完成模型的训练,而负责将模型集成到手机App(端)或本地PC应用(边缘)的工程团队,则无需安装这些庞大的训练框架。他们只需要接收数据科学家交付的标准化ONNX模型,就可以利用轻量级的推理引擎(如ONNXRuntime)在最终产品上高效运行。相较于与特定框架(如TensorFlow/Keras)深度绑定的.h5格式,ONNX格式的模型具有良好的框架解耦与互操作性、优秀的轻量化部署能力以及卓越的性能优化潜力。因此在本步骤中我们将编写代码将上一步得到的.h5模型转换为.onnx格式的模型,具体如下。在一个全英文路径下新建一个名为convert_model.py的Python文件,复制以下代码至文件中:importtensorflowastfimporttf2onnximportjson#定义输入和输出文件名keras_model_path="keras_model.h5"output_onnx_path="gesture-recognition.onnx"try:#加载Keras模型model=tf.keras.models.load_model(keras_model_path)#将Keras模型转换为ONNX格式#spec:指定模型的输入签名,对于本项目导出的图像模型,通常是(None,224,224,3)#opset:ONNX的版本号,13是较为通用的版本model_proto,_=tf2onnx.convert.from_keras(model,input_signature=[tf.TensorSpec(shape=(None,224,224,3),dtype=tf.float32,name="input")],opset=13)#保存ONNX模型withopen(output_onnx_path,"wb")asf:f.write(model_proto.SerializeToString())print(f"模型转换成功!已将'{keras_model_path}'转换为'{output_onnx_path}'")exceptExceptionase:print(f"模型转换失败:{e}")print("请确保'keras_model.h5'文件与此脚本在同一个文件夹下。")将步骤一中解压出的keras_model.h5文件与convert_model.py置于同一个文件夹下。在该路径下运行convert_model.py文件,终端会输出“模型转换成功!”的提示,并且在文件夹中会生成一个gesture-recognition.onnx文件。该文件即为转换后的ONNX模型文件,接下来将利用该模型编写出能在本地计算机上实时识别手势的Python应用程序。在convert_model.py同文件夹下新建一个名为run_edge_app.py的Python程序文件。将下列代码复制至文件中。importcv2importnumpyasnpimportonnxruntimeasortfromPILimportImage,ImageDraw,ImageFont#1.初始化#从labels.txt文件中读取标签withopen('labels.txt','r',encoding='utf-8')asf:#读取所有行,并去除每行末尾的数字和换行符GESTURE_LABELS=[line.strip().split('')[1]forlineinf.readlines()]#加载上一步转换的ONNX模型文件onnx_model_path="gesture-recognition.onnx"#创建一个ONNXRuntime的推理会话ort_session=ort.InferenceSession(onnx_model_path)#获取模型的输入名称input_name=ort_session.get_inputs()[0].name#加载支持中文的字体,这里的'simhei.ttf'需要根据你的系统确认路径#通常在C:\Windows\Fonts\simhei.ttftry:font=ImageFont.truetype("simhei.ttf",32)exceptIOError:font=ImageFont.load_default()print("警告:未找到中文字体'simhei.ttf',将使用默认字体,中文可能无法显示。")print("模型加载成功,准备启动摄像头...")在上述代码中定义了一个GESTURE_LABELS列表,用于存放模型能识别的所有手势名称。ort.InferenceSession()函数是ONNXRuntime的核心,通过该行代码,模型文件被加载到内存中,随时可以开始工作。每个模型都有标准的输入口,通过ort_session.get_inputs()[0].name代码可以自动获取这个输入口的名称,方便后续步骤向其中“喂”数据。接下来需要让程序打开电脑的摄像头,并像看电影一样,逐帧读取实时画面。这是一个无限循环,直到按下键盘上的q键退出。在run_edge_app.py文件中继续添加下列代码。#2.启动摄像头与主循环#参数0代表使用电脑的默认摄像头cap=cv2.VideoCapture(0)ifnotcap.isOpened():print("错误:无法打开摄像头。");exit()#进入主循环whileTrue:#逐帧读取摄像头画面ret,frame=cap.read()ifnotret:print("错误:无法读取画面。")break#这里将是进行AI推理的核心区域#(我们将在下一个步骤中填充该部分代码)#显示实时画面cv2.imshow('Real-timeGestureRecognition',frame)#检测按键,如果按下'q'键则退出循环ifcv2.waitKey(1)&0xFF==ord('q'):break#释放资源cap.release()cv2.destroyAllWindows()print("程序已退出。")在上述代码中cv2.VideoCapture(0)打开本地计算机的默认摄像头(台式计算机可以外接一个USB摄像头)。whileTrue:语句创建了一个无限循环,使程序能持续不断地处理视频流。在循环中,ret,frame=cap.read()语句负责从摄像头抓取当前瞬间的图像,frame就代表该张图像。cv2.imshow():函数将抓取到的frame显示在一个名为“Real-timeGestureRecognition”的窗口中。使用cv2.waitKey(1)&0xFF==ord('q')语句等待1毫秒,检测用户是否有键盘输入。如果按下的键是q,就跳出循环。退出循环后,使用cap.release()和cv2.destroyAllWindows()函数释放摄像头资源并关闭所有窗口,养成良好的编程习惯。有关OpenCV控制摄像头的更多用法,我们将在计算机视觉章节进一步讲解。摄像头捕捉到的原始画面,并不能直接送给AI模型。需要先将其转换成模型能够“理解”的格式(例如,调整尺寸、归一化颜色值等),这个过程叫做预处理。处理好后,就可以将数据送入模型,并获取预测结果。请将以下代码替换到上一步代码中标记为“#这里将是进行AI推理的核心区域”的注释行处。#3.图像预处理#复制一份原始帧用于显示,避免在原图上修改display_frame=frame.copy()#将图像尺寸调整为模型需要的224x224img_resized=cv2.resize(frame,(224,224))#将图像从BGR色彩空间转为RGBimg_rgb=cv2.cvtColor(img_resized,cv2.COLOR_BGR2RGB)#将图像数据类型转为float32,并进行归一化处理img_normalized=(img_rgb.astype('float32')/127.5)-1#增加一个批次维度,因为模型期望的输入是(N,H,W,C)input_tensor=np.expand_dims(img_normalized,axis=0)#4.执行推理#将处理好的数据送入ONNX模型ort_inputs={input_name:input_tensor}ort_outs=ort_session.run(None,ort_inputs)#ort_outs[0]就是模型的输出结果prediction=ort_outs[0]#5.解析并展示结果#找到概率最高的那个类别的索引predicted_index=np.argmax(prediction)#从我们的标签列表中获取对应的手势名称predicted_gesture=GESTURE_LABELS[predicted_index]#获取该预测的置信度(概率值)confidence=np.max(prediction)#准备要显示的文本result_text=f"预测结果:{predicted_gesture}({confidence:.2f})"#使用Pillow在图像上绘制中文#将OpenCV图像(BGR)转换为Pillow图像(RGB)pil_img=Image.fromarray(cv2.cvtColor(display_frame,cv2.COLOR_BGR2RGB))draw=ImageDraw.Draw(pil_img)#在图像上绘制文本draw.text((10,30),result_text,font=font,fill=(0,255,0))#将Pillow图像转换回OpenCV图像(BGR)display_frame=cv2.cvtColor(np.array(pil_img),cv2.COLOR_RGB2BGR)在图像预处理的代码中,resize,cvtColor,astype,expand_dims等一系列操作都是为了将摄像头抓拍的原始图片,变成符合模型输入要求的标准“证件照”。在执行推理的过程中,ort_session.run(None,ort_inputs)是核心语句。将处理好的input_tensor“喂”给模型,模型就会返回一个包含各个手势预测概率的列表prediction。使用np.argmax找到概率最高的那个结果,并从GESTURE_LABELS列表中找到对应的手势名称,最后用Pillow库将这个结果实时显示在视频窗口上。确保run_edge_app.py文件与gesture-recognition.onnx模型文件在同一个文件夹下。运行该文件,程序会启动计算机所连接的摄像头,并在屏幕上显示一个实时视频窗口。请将你的手放在摄像头前,做出不同的手势(石头、剪刀、布),观察屏幕左上角的识别结果。图3-14在本地计算机上运行的实时手势识别应用本任务将一个在云端训练好的AI模型,通过行业标准的ONNX格式,部署到了本地计算机这个“边缘设备”上。利用OpenCV技术使模型能够处理来自摄像头的实时数据,并即时地将分析结果反馈在屏幕上,完整地体验了边缘计算低延迟、保护隐私(图像数据未上传到云端)的核心优势。本项目体现了云计算和边缘计算并非孤立的技术,而是相辅相成的强大组合。“云边协同”的开发模式,将极大的推进AI智慧应用普及到现实世界各个角落的进程。
【实践报告】项目总结报告项目名称姓名学号小组名称(适合小组项目)实施过程记录测试结果总结后期改进思考成员分工(适合小组项目)姓名职责完成情况组长评分考核评价评价标准:1.执行力:按时完成项目任务。2.学习力:知识技能的掌握情况。3.表达力:实施报告详实、条理清晰。4.创新力:在完成基本任务之外,有创新、有突破者加分。5.协作力:团队分工合理、协作良好,组员得分在项目组得分基础上根据组长评价上下浮动。
房价预测实训手册【项目目标】本项目旨在通过一个完整的房价预测分析任务,引导学生使用真实的二手房数据,体验机器学习解决实际问题的全过程。项目基Python语言,利用Pandas库进行数据预处理,借助Matplotlib工具实现数据可视化,并运用Scikit-learn库构建一元线性回归与多元线性回归模型,分别进行房价预测,实现从数据处理、模型训练到预测结果的完整流程。本项目具体目标如下:(1)了解从原始数据到预测模型的全流程开发步骤;(2)掌握使用Pandas进行数据清洗、筛选与重组的基本方法;(3)掌握使用Matplotlib绘制散点图、柱状图、饼图等,实现数据可视化的能力;(4)掌握使用Scikit-learn构建、训练并调用线性回归模型进行预测的核心技能。注:本项目重点为机器学习回归分析,深度学习相关案例将在项目6、7的项目实训中展开。任务一Pandas基础房价预测实训Pandas一个强大的分析结构化数据的工具集,可以对数据进行运算操作,比如筛选、归并、重组,还有数据清洗和数据加工。Pandas广泛应用在学术、金融、统计学等各个数据分析领域,因此本项目使用Pandas工具对数据进行数据清洗、处理、分析。房价预测实训步骤一:Pandas数据结构以及入门程序Pandas的主要数据结构是Series(一维数据)与DataFrame(二维数据)。Series是一种类似于一维数组的对象,它由一组数据(各种Numpy数据类型)以及一组与之相关的数据标签(即索引)组成。DataFrame是一个表格型的数据结构,它含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔型值)。DataFrame既有行索引也有列索引,它可以被看做由Series组成的字典(共同用一个索引)。下面通过一个入门的Pandas程序来展示数据结构。定义两列数据:班级名称、班级人数,每行数据一共存取3个班级的记录,如图4-12所示。示例代码如下:importpandasaspdmydataset={'班级名称':["人工智能1班","人工智能2班","人工智能3班"],'班级人数':[50,60,70]}myvar=pd.DataFrame(mydataset)print(myvar)图4-12pandas数据步骤二:Pandas数据结构Series使用方法PandasSeries类似表格中的一个列(column),类似于一维数组,可以保存任何数据类型。Series由索引(index)和列组成,函数如下:pandas.Series(data,index,dtype,name,copy)参数说明:data:一组数据(ndarray类型)。index:数据索引标签,如果不指定,默认从0开始。dtype:数据类型,默认会自己判断。name:设置名称。copy:拷贝数据,默认为False。通过定义一个列表a,转为对应Series数据类型,即定义一个列数据。示例代码如下:a=[1,2,3]myvar=pd.Series(a)print(myvar)运行效果如图4-13所示:图4-13Series数据类型如果没有指定索引,会自动添加索引值,索引值就从0开始,可以根据索引值读取数据。importpandasaspda=[1,2,3]myvar=pd.Series(a)print(myvar[1])输出结果值为2在定义数据时,可以自己定义索引值index,读取数据需要根据索引值获取数据。a=["人工智能1班","人工智能2班","人工智能3班"]myvar=pd.Series(a,index=["x","y","z"])print(myvar)print(myvar["y"])运行效果如图4-14所示:图4-14运行结果步骤三:Pandas数据结构dataFrame使用方法PandasdataFrame是一个表格型的数据结构,它含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔型值),如图4-15所示。图4-15Pandas数据组成DataFrame既有行索引也有列索引,它可以被看做由Series组成的字典(共同用一个索引),如图4-16所示。图4-16DataFrame与Series关系DataFrame构造方法如下:pandas.DataFrame(data,index,columns,dtype,copy),参数说明如表4-1所示。表4-1DataFrame构造方法参数说明data一组数据(ndarray、series,map,lists,dict等类型)index索引值,或者可以称为行标签columns列标签,默认为RangeIndex(0,1,2,…,n)dtype数据类型copy拷贝数据,默认为FalsePandasDataFrame是一个二维的数组结构,类似二维数组。下面的代码将一个定义好的列表数据转为DataFrame数据,Pandas可以使用loc属性返回指定行的数据,如果没有设置索引,默认第一行索引为0,第二行索引为1,以此类推。示例代码如下:importpandasaspddata={"班级":["人工智能1班","人工智能2班","人工智能3班"],"人数":[49,60,62]}#数据载入到DataFrame对象df=pd.DataFrame(data)print(df)#返回第一行print(df.loc[0])#返回第二行print(df.loc[1])运行结果如图4-17所示:图4-17DataFrame数据类型任务二数据预处理步骤一:数据读取北京的房价信息表名为bj_house_information.csv,此表通过爬虫爬取的房价数据,包括:朝向,地点,电梯,楼层,小区名称,Id,户型,房屋总价,区域,装修,建筑面积,楼龄等信息,如图4-18所示。图4-18房价信息表名CSV(Comma-SeparatedValues)是一种常用的文本文件格式,用于存储表格数据。它以逗号或制表符作为字段之间的分隔符,每行表示一条记录,记录之间通过换行符分隔。CSV文件可以使用记事本、Excel等常见软件直接打开和编辑,所有记录具有相同的字段结构,适合存储结构化数据。在Python中,一般使用Pandas库来读取和处理CSV文件。Pandas提供了与CSV结构高度兼容DataFrame数据类型,能够方便地进行数据加载、查看与初步分析。代码如下:importpandasaspd#导入二手房数据house_price_df=pd.read_csv('bj_house_information.csv')#打印前5行数据print(house_price_df.head())#打印列名print(house_price_df.columns)运行结果如图4-19所示:图4-19CSV数据可以使用下表的Pandas的数据函数得到对应数据信息,如表4-2所示。表4-2房价Pandas信息打印函数功能house_price_df.describe()给出行数和列数house_price_df.head(3)打印出数据的前3行。house_price_df.tail()打印对应数据的最后5行。house_price_df.loc[8]打印出第八行house_price_df.loc[8,column_1]打印第八行名为「column_1」的列house_price_df.loc[range(4,6)]第4到第6行(左闭右开)的数据子集步骤二:筛选重要字段原始数据集包含12个字段,其中一些字段(如id、楼龄等)对房价的影响较弱,或与预测目标关联性较低。为提高模型效率与可解释性,通常需要进行特征选择,即保留关键字段、移除非必要字段。本步骤演示通过drop()方法删除对房价预测影响较小的列。首先可通过columns属性查看所有字段名称,再根据业务理解与建模需求,选择需删除的字段['Id','朝向','电梯','装修','楼层','小区名称','地点','楼龄']。该操作有助于简化数据集,突出核心特征(如面积、区域、户型等),为后续建模做好准备。代码如下:importpandasaspd#二手房数据house_price_df=pd.read_csv('bj_house_information.csv')#删除一些不重要的列to_drop=['Id','朝向','电梯','装修','楼层','小区名称','地点','楼龄']house_price_df_clean=house_price_df.drop(to_drop,axis=1)#显示列名print(house_price_df_clean.columns)print(house_price_df_clean.head())运行结果如图4-20所示,看到只显示与房价关系大的数据列。图4-20显示与房价关系大的数据列Drop函数其他用法如下:表4-3Drop函数用法函数功能df.drop(5)删除第5行df.drop([1,4])或者df.drop(index=[1,4])删除第1和第4行df.drop(5,axis=1)删除第5列df.drop(['列1','列2'],axis=1)或者df.drop(columns=['列1','列2'])删除第1和第2列步骤三:调整列位置为便于数据查看及后续建模,将预测目标(即“房屋总价”)调整至数据表的首列。这样做既能使目标变量在浏览时更加醒目,也符合一般机器学习任务中特征与标签分开处理的惯例。调整列序后,可进一步输出数据集的总样本量,以帮助了解数据规模。进行列数据位置处理的代码:importpandasaspd#二手房数据house_price_df=pd.read_csv('bj_house_information.csv')#删除一些不重要的列to_drop=['Id','朝向','电梯','装修','楼层','小区名称','地点','楼龄']house_price_df_clean=house_price_df.drop(to_drop,axis=1)#显示列名print(house_price_df_clean.columns)print(house_price_df_clean.head())#重新摆放列位置columns=['房屋总价','建筑面积','区域','户型']house_price_df_clean=pd.DataFrame(house_price_df_clean,columns=columns)print(house_price_df_clean.head())house_total_num=house_price_df_clean['建筑面积'].count()print('房价数据集总数量为:'+str(house_total_num))运行结果如图4-21所示:如图4-21调整重要列数据步骤四:数据清洗为探究房价与面积之间的关系,我们从数据集中提取“建筑面积”与“房屋总价”两列数据,使用Matplotlib的scatter()方法绘制散点图。从散点图中可初步观察到:房价与建筑面积之间大致呈正相关趋势,即随着面积增大,房屋总价整体上升。代码如下:importmatplotlib.pyplotaspltarea=house_price_df_clean['建筑面积']price=house_price_df_clean['房屋总价']#支持中文,如果不加此句将无法显示中文plt.rc('font',family='SimHei',size=13)plt.scatter(area,price)plt.xlabel("建筑面积")plt.ylabel("房屋总价")plt.show()如图4-22房价散点图图4-22中同时可见部分明显异常样本,如“建筑面积”为0的记录。这类异常通常源于数据采集错误或信息缺失,若保留在数据集中将干扰模型训练,影响预测准确性,甚至导致后续计算错误,因此必须在建模前予以清洗。为进一步分析,我们可计算房屋单价作为新特征,即房屋单价df['房屋单价']=df['房屋总价']/df['建筑面积'],该特征可用于后续数据筛选与深入分析。#数据清洗df=house_price_df_cleandf['房屋单价']=df['房屋总价']/df['建筑面积']#去除有缺失项的df.dropna(how='any')#去重重复项df.drop_duplicates(keep='first',inplace=True)#一些别墅的房屋单价有异常,删选价格大于25万一平的df=df.loc[df['房屋单价']<25]area=df['建筑面积']price=df['房屋总价']#支持中文,如果不加此句将无法显示中文plt.rc('font',family='SimHei',size=13)plt.rcParams['font.sans-serif']=['SimHei']plt.scatter(area,price)plt.xlabel("建筑面积")plt.ylabel("房屋总价")plt.show()运行结果如图4-23所示:图4-23去掉异常房价散点图任务三数据可视化步骤一:各区域房价统计与条形图展示通过对北京区各区域的二手房的平均价格与数量进行统计,采用竖值条形图进行展示。通过使用df.groupby将所有样本点按照一个或多个属性划分为多个组,按照二手房区域分组对比二手房数量和每平米房价,示例代码如下所示:df_house_count=df.groupby('区域')['房屋总价'].count().sort_values(ascending=False)df_house_mean=df.groupby('区域')['房屋单价'].mean().sort_values(ascending=False)plt.bar主要生成条形图界面,具体参数如表4-4所示:表4-4条形图界面bar参数参数说明类型Xx坐标整形int,浮点型floatHeight条形的高度整形int,浮点型floatWidth条形的宽度0到1之间1,默认为0.8Botton条形的起始位置也是y轴的起始坐标Align条形的中心位置中心“center”,边缘"lege"Color条形的颜色红色“r",蓝色"b",绿色"g",默认为“b"Edgecolor边框的颜色同上Linewidth边框的宽度像素,默认无,整型inttick_label下标的标签可以是元组类型的字符组合Logy轴使用科学计算法表示布尔型BoolOrientation是竖直条还是水平条竖直:"vertical",水平条:"horizontal"代码如下:importnumpyasnpimportmatplotlib.pyplotaspltimportmatplotlib#将全局的字体设置为黑体matplotlib.rcParams['font.family']='SimHei'#数据N=5y=[20,10,30,25,15]x=np.arange(N)#绘图x轴,以y值作为条形图的高度。p1=plt.bar(x,height=y,width=0.5)#展示图形plt.show()运行效果如图4-24所示:图4-24简单竖值条形图通过使用subplot设置两个子图对房价进行分析,代码如下:df_house_count=df.groupby('区域')['房屋总价'].count().sort_values(ascending=False)df_house_mean=df.groupby('区域')['房屋单价'].mean().sort_values(ascending=False)plt.figure(figsize=(20,10))plt.rcParams['font.sans-serif']=['MicrosoftYaHei']plt.style.use('ggplot')#各区域二手房数量对比plt.subplot(212)plt.title(u'各区域二手房数量对比',fontsize=20)plt.ylabel(u'二手房总数量(单位:间)',fontsize=15)rect1=plt.bar(df_house_count.index,df_house_count.values,color='c')x=df_house_count.indexy=df_house_count.valuesfora,binzip(x,y):plt.text(a,b+50,b,ha='center')#各区域二手房平均价格对比plt.subplot(211)plt.title(u'各区域二手房平均价格对比',fontsize=20)plt.ylabel(u'二手房平均价格(单位:万/平米)',fontsize=15)#区域名称,每个区域的二手房平均价格rect2=plt.bar(df_house_mean.index,df_house_mean.values,color='c')x=df_house_mean.indexy=df_house_mean.values#将柱子的高度值写在柱子上——改掉实验手册里比较复杂的调用函数fora,binzip(x,y):plt.text(a,b+0.1,round(b,2),ha='center')plt.show()运行结果如图4-25所示:图4-25房价简单竖值条形图步骤二:各区域二手房数量百分比饼图展示使用plt.pie实现画饼状图,将各个区域上的二手房数量百分比进行显示。代码如下:#导入模块importmatplotlib.pyplotasplt#数据labels=["A","B","c","d"]fracs=[15,30,45,10]#画图plt.pie(x=fracs,labels=labels)#展示plt.show()运行结果如图4-26所示:图4-26简单饼图将房价按区域进行单价与数据的显示。importmatplotlib.pyplotaspltplt.rcParams['font.sans-serif']=['MicrosoftYaHei']plt.style.use('ggplot')plt.figure(figsize=(10,10))plt.title(u'各区域二手房数量百分比',fontsize=18)plt.pie(df_house_count,radius=3,autopct='%1.f%%',shadow=True,labels=df_house_count.index)plt.axis('equal')plt.show()运行结果如图4-27所示:图4-27房价饼图任务四线性回归模型训练与预测步骤一:一元线性回归预测房价一元线性回归:线性回归是用法非常简单、用处非常广泛、含义也非常容易理解的一类算法,是机器学习的入门比较容易的一种算法。一元线性回归就是要找一条直线,并且让这条直线尽可能地拟合图中的数据点。因此先根据建筑面积和房屋总价利用一元线性回归拟合一条房价预测曲线。代码如下:#先根据建筑面积和房屋总价训练模型(一元线性回归)fromsklearn.linear_modelimportLinearRegressionimportnumpyasnp#定义自变量:房屋面积;自变量:房屋价格area=df['建筑面积']price=df['房屋总价']area=np.array(area).reshape(-1,1)#这里需要注意新版的sklearn需要将数据转换为矩阵才能进行计算print(area)price=np.array(price).reshape(-1,1)#定义一个线性回归对象linearlinear=LinearRegression()#训练模型,linear需要输入二维数组model=linear.fit(area,price)#打印截距和回归系数:截距就是b,回归系数就是kprint('0:',ercept_,model.coef_)#线性回归可视化(数据拟合)linear_p=model.predict(area)plt.figure(figsize=(12,6))plt.scatter(area,price,c="blue")plt.plot(area,linear_p,'red')plt.xlabel("建筑面积")plt.ylabel("房屋总价")plt.show()运行结果如图4-28所示:图4-28一元线性回归步骤二:多元线性回归预测房价在一元性线回归过程中只考虑了建筑面积和房屋总价之间的关系,但是实际影响房价还有其他很多因素,因此引入四个自变量(['建筑面积','区域','装修','电梯'])进行多元线性回归。1、导入第三方库、读入数据、数据整理importpandasaspdfromsklearn.linear_modelimportLinearRegressionimportnumpyasnpimportmatplotlib.pyplotasplt#二手房数据house_price_df=pd.read_csv('bj_house_information.csv')#册除一些不重要的列to_drop=['Id','楼层','小区名称','地点','楼龄','户型','朝向']house_price_df_clean=house_price_df.drop(to_drop,axis=1)#显示列名print(house_price_df_clean.columns)print(house_price_df_clean.head())#重新摆放列位置columns=['房屋总价','建筑面积','区域','电梯','装修',]hous
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年江苏省苏州市昆山市中考数学第一次适应性试卷
- 草原洪涝后人畜共患病风险预警课件
- 草原人畜共患病健康促进科普课件
- 全国高血压日互动游戏课件
- 离散数学及其应用-03 集合的基本概念和运算
- 2026年高考新课标一卷理综生物真题试卷
- 2025年安徽省(专升本)英语考试题库(含答案)
- 2026每月时政考试题目及答案
- 2026第四季度医保知识培训考试题目及答案
- 怎么复习效率最高 - 期末冲刺课件
- 2025~2026学年七年级上学期第一次月考数学试卷2【附解析】
- 河南省郑州市实验中学2026-2027学年高二上学期第一次月考英语试卷
- 加入保险行业的十五大理由
- 酮症酸中毒指南2025版
- 社区公文写作格式和范文(15篇)
- 10kV配电站房建设施工方案
- 检验科试剂耗材精细化管理方案
- 物业维修管理流程及注意事项
- 2026年河南省高考物理试卷(含答案及解析)
- TAVR麻醉管理策略
- 直通线的制作
评论
0/150
提交评论