基于yolov8框架,使用C++实现的跨平台目标识别系统,支持windows、linux(Ubuntu或centos)跨平台编译及部署
c++跨平台版本的服务端(cmake),支持windows和linux系统
技术架构开发技术(1)C++版本 C++11 里面使用了一些C++11以上的新语法,对于老程序员来说,语言只是一种工具,花时间熟悉一下新语法即可,问题不大。 Boost C++跨平台库,C++11中的大部分新特性都是来自Boost准标准库,但是还有很多新特性暂时并未引入到c++中,它可以跨平台编码,开发人员并不需要写一些预编译语法来适应不同平台,只需要一套代码即可实现所有平台,这就是它的优势,也是为什么C++新语法基本都出自它的原因。 mysql 系统涉及到的一些模型数据、设备、场景、报警、配置等数据的存储既可以使用mysql存储,也可以使用sqlite存储,根据自己需要,可以通过配置文件配置存储方式,唯一的区别是mysql需要安装数据库而已。 sqlite 同上,AI盒子数据存储支持使用sqlite存储,所以需要用到sqlite库。 oatpp 一个开源的支持多语言的成熟http库,跨平台,支持DTO数据封装、SSL等,一个非常不错的HTTP协议库。 spdlog 一个开源的系统日志库,支持控制台打印、文件日志打印、支持自动清理、按日存储等功能。 opencv 一个很关键的一个库了,python使用pt模型,c++使用onnx模型,这里就是基于跨平台opencv来加载onnx模型实现推理的。 vue2.0 AI盒子提供了一个web管理端,通过其实现模型管理、设备管理、场景管理、报警管理、录像管理、系统配置、预警监控等功能。 注:此开源版本提供基于vue2.0开发的web管理端,提供与AI盒子内部通信的交互操作控制台,如果需要定制自己的模型、设备、场景、配置等,可能需要修改web后台管理端源码,需要此部分的源码,需联系作者付费采购,感谢理解。
yolov8 c++版本使用的yolov8的模型,通过yolov8模型或yolov5模型转换的onnx模型实现模型推理和目标识别。
基于yolov8框架,使用C++实现的跨平台目标识别系统,支持windows、linux(Ubuntu或centos)跨平台编译及部 ...
这里从下至上进行一一说明 设备层 AI盒子接入的设备为网络摄像机,当然也支持本地摄像头的采集和分析(一般用于做demon),AI盒子作为边缘计算盒,一般部署在与网络摄像机相同的局域网内,通过标准的RTSP协议采样抽帧的方式分析摄像机的视频流,然后对采样的图像帧使用yolov8模型库进行一一分析,这里的摄像头采用标准的rtsp协议,可以是任意厂家的摄像头,包括常见的海康、大华、安士讯等。 接入层 接入层其实就只我们本文介绍的主角,也就是AI智能盒子,它作为边缘计算盒子,与摄像机同属一个局域网(当然排除服务云端化后提供云识别接口之外),它通过局域网与摄像机相连,通过USB或Lane接口连接,通过USB连接IO控制器(如果AI盒子需要控制IO开关如信号灯、语音喊话、硬件信号输入到其他系统等),AI盒子通过分析网络摄像机视频流,当分析到检测预警时,记录报警信息(时间、设备、类型、报警图片、报警前后n秒录像片段),实时存储到AI盒子本地,并异步将报警信息推送到第三方平台。 服务层 sass云服务时一个多租户平台,主要功能就是提供基于AI盒子的高级应用,包括预警推送(手机、短信、公众号等)、预警处理、视频播放、预警统计、设备管理、云模型管理、策略管理、第三方数据对接、数据推送等功能应用。 应用层 基于sass云的移动端应用和管理,用户可以通过手机端接收系统预警信息、处理预警、处理各自的任务、实时查看预警和视频等功能。
功能介绍智能AI盒子提供了如下功能(部分c++版本功能可能没有,python版本有,后面会指出来,感兴趣的各位网友,也希望可以私下联系共同开发新增) web管理端web管理端指AI盒子的启动后台的交互网页终端,它基于AI盒子提供的HTTP接口实现AI盒子的数据管理、配置等功能。
资源国际化 为适应不同用户的需求,AI盒子web管理端提供了中文简体、中文繁体、英文3种语言的切换。 模型管理 管理端提供模型管理功能,包括模型上传、模型添加、模型修改、模型删除、模型更新等功能,具体见演示效果。 设备管理 管理端提供了设备管理功能,包括设备添加、更新、移除、查询、设备区域范围配置、图片预览等功能。 场景管理 管理端提供指定设备的多场景管理,包括一个设备添加多个场景、查询设备场景、更新设备场景、移除设备场景功能。 系统配置 可以通过web端动态配置AI盒子的常用配置,包括盒子编码(对接第三方唯一id)、盒子保存数据天数、是否展示识别标签、第三方平台推送地址等。 重启盒子 如果有必要,可以通过web端重启AI盒子(linux下部署时候需要root权限部署才能正常重启,启动后自动启动AI盒子服务程序)
AI盒子端HTTP、websocket协议 AI盒子支持通过Http协议管理AI盒子配置、模型、设备、场景等(如AI的WEB端),也可以通过websocket协议下发和操作AI盒子,实现与AI和的多协议交互。 模型热加载 模型可以在系统启动后随时进行更新,盒子自动检测变化重新加载模型信息。 设备热加载 被检测的设备更新后,AI盒子自动侦测信息变化,自动重新加载分析设备(如分析时间段、分析帧率等) 场景热加载 一个分析视频设备,可以叠加多种分析场景算法,当某一算法发生变化后,AI盒子自动更新加载对应场景。 配置热加载 系统配置会实时更新到内存中,实时更改对应系统配置(如保存时长、是否显示label、是否自动重启等) 抽帧采样分析 AI盒子可以根据用户配置动态分析设备抽帧采样帧率,如25帧分析一张(1秒一张) 多算法分析 一个分析设备,可以叠加多种分析场景算法,也就是分析的某张图可以叠加n种分析算法(串行叠加分析) 分析时段控制 可以根据用户需要配置不同时间段进行分析,如晚上18:00-23:00时间段内进行分析,不在改时间段则停止分析。 分析区域配置 python版本支持划定的多边形内的目标进行分析,也支持多个线段进行越界侦测分析。 模型推理分析 支持yolov5、yolov8的模型进行推理分析,其中python版本使用yolov5的pt模型,yolov8使用的是onnx模型 报警存储 当AI盒子检测到对应预警类型的目标后,将指定时间、设备、预警类型、预警图片、预警前后5秒(预录前5秒)的录像临时保存下来,然后异步推送到第三方平台。 报警录像 当AI盒子检测到预警类型的目标后,AI盒子根据用户配置进行是否录像,录制事件发生前5秒和后5秒的录像(mp4格式或flv) GPIO录像 AI盒子支持抓取GPIO信号,进行联动,开启或停止录像。 GPIO抓拍 AI盒子支持抓取GPIO信号,进行联动,开启关联摄像机的图片抓拍。 报警推送 AI盒子可以配置报警推送http地址(https),然后将报警信息(设备、报警类型、时间、图片、录像)推送至第三方平台。 报警广播 AI盒子自带的web端具有报警预览功能,当进入AI盒子报警预览页面后,发现报警会自动推送到web端,并使用tts语音播报方式将对应的报警内容以语音的形式播放出来。 报警清理 AI盒子sd卡存储能力有限,为了保证AI盒子能够持续工作,AI盒子会自动覆盖最老的报警信息(主要包括数据和录像清理) 视频播放 AI盒子与IPC摄像机一般处于同一个局域网,所以AI盒子具有能直接访问摄像机的条件,而云端要看摄像机的视频必须通过盒子(或其他第三方视频云平台)转发,AI盒子正好集成了改功能,它通过websocket下发指令启动视频的开始、停止播放(rtmp推送到服务端),启动远程抓拍功能。 远程抓拍 如上说,AI盒子既具备视频转发能力,也具备远程控制抓拍功能。 远程录像 AI盒子及支持关联摄像机(或非关联但是与其摄像机在同一张局域网内)的实时视频转发,也具有开启远程录像、停止远程录像的手动录像功能,录像完成后AI盒子会立即将录像信息推送到第三方云平台中(mp4格式-可以在web端播放)。 自动重启 如果有必要,可以配置AI盒子自动重启(每晚12点),但是一般情况下不会这么做,除非网络有问题。 自动校时 AI盒子会定时与第三方云平台进行心跳,为了保证AI盒子时间与云平台保持一致,在心跳的时候云平台如果返回服务器时间则AI盒子会自动将服务器时间设置为本地时间,以便与服务器进行时间对齐。 分析接口 AI盒子具有自己抓取摄像头图片进行分析的能力,此外,AI盒子也提供的对外的http接口,用户可以通过接口将推送推送给AI盒子,然后进行识别,最后将结果以接口结果形式返回的第三方平台(不推荐使用)
示例下载windows如果windows是win7或者xp系统,可能运行demon报缺少ucrtbase.dll,该文件可以在源码路径中找到,找到后放exe所在目录即可 AiBoxrdpartylibwin32
(1)默认80分类检测模型demon windows7或win10以上,编译打包的下载链接如下 链接:https://pan.baidu.com/s/1tCrcjAK-1lERMut013kPXw?pwd=abcd 提取码:abcd
使用:下载后直接解压到当前文件夹,然后运行AiBox.exe即可 注意,如果电脑没有摄像头,请插入usb摄像头后尝试!
(2)安全帽反光衣检测模型demon 链接:https://pan.baidu.com/s/1UkfkLnTFGgn_w87xQ6u0bA?pwd=62h3 提取码:62h3
ubuntu(1)默认80分类检测模型demon x64_86架构的,系统为ubuntu20.04版本编译的demon连接如下 链接:https://pan.baidu.com/s/1dGd4SYjWtIKEmcEbYlYrGA?pwd=abcd 提取码:abcd
使用 tar -zxvf ai_box_ubuntu20.04.tar.gzcd ai_box/./AiBox
注意: 如果是WMWare Workshop启动的虚拟机,请将主机的摄像头共享给Ubuntu虚拟机,操作步骤如下: windows打开服务:ctrl+r输入services.msc,然后找到VM的USB服务,名字为VMware USB Arbitration Service,设置为开机启动,并手动启动该服务。 重启WMWare Workshop及Ubuntu虚拟机(如果usb重启的情况下必须重启) 启动Ubuntu20.04机器 在VM上选择该机器,鼠标右键菜单,选择对应设备,然后连接即可
基于yolov8框架,使用C++实现的跨平台目标识别系统,支持windows、linux(Ubuntu或centos)跨平台编译及部 ...
使用ubuntu再带的茄子工具cheese打开测试摄像头是否可用
orangePI(1)默认80分类检测模型demon 国产华为升腾芯片(主要跑NPU,还没空适配NPU,目前也是跑CPU)demon下载链接如下 链接:https://pan.baidu.com/s/1j3FzFwx1uNKNnwVGRg95hQ?pwd=abcd 提取码:abcd
上传到orangePI中,解压运行即可 tar -zxvf ai_box_ubuntu20.04.tar.gzcd ai_box/./AiBox
jetson Nanojetson nano是跑python、GPU版本的,不是跑C++的,追求实时性、识别速度和高性能的请私下联系我采购商业python版本,功能比cpp版本更强,所以这里就没有CPU版本的适配demon,见谅! VOC2YOLOVOC格式数据是一种标准格式数据,而在yolo中有自己的格式数据,它是txt格式的,每一行表示一个对象的基本信息,所以我们需要将VOC格式的数据转换为YOLO格式数据之后,才能拿到yolo中进行训练,当然,我们可以一开始的时候就标注yolo格式数据,这里我不太推荐,原因如下 VOC是通用格式数据,记录信息非常详细,yolo格式不是通用格式数据,信息损失大 VOC格式数据兼容性和移植性较好,可以较好的与其他平台对接,如paddle飞桨、阿里天池等 开源工具基本都支持VOC格式标注 这里我们使用的是labeling标注工具标注,它支持voc和yolo格式数据。
所以,我们在数据标注的时候,首先选择VOC格式,标注完成后自己协议个python脚本实现VOC格式数据到YOLO格式数据转换即可,这里我已经写好了python脚本,各种问题已经考虑好了,你拿过去用就好了- """
- 注意:
- 1、首先更改VOC格式根目录路径,然后将生成的images和labels目录
- 拷贝到训练数据集目录下(名字自定义)即可
- 2、修改classes类别名称列表
- 3、配置是否进行文件重命名:batch_rename_voc_samples
- """
- import xml.etree.ElementTree as ET
- import os
- import uuid
- import shutil
- import random
- from PIL import Image
- # voc中的类别名对应yolo的类别下标
- # 改成自己的类别名称,注意类别顺序
- classes = ["person", "hat", "reflective_clothes", "other_clothes"]
- # 转成yolov5-txt格式图片大小
- # yolov5长宽必须是32像素整倍
- # yolov5默认大小为640x640
- # 为了提高精度建议放大1280x1280
- # 摄像机分辨率1280x720
- glob_resize_img = False
- global_img_size = (1280, 1280)
- # 是否对原来的样本文件进行重命名
- # 如果文件名为非uuid的文件,建议重命名
- # 以免与其他数据文件名相同覆盖(不同分类训练样本粘贴的时候)
- batch_rename_voc_samples = False
- # VOC图片格式目录根路径
- # VOC满足其约定的目录结构
- # ROOT(dir)
- # --Annotations(存放标注的标签文件(目标真值标注数据,xml格式))
- # --ImageSets(类别标签其中包含4个文件夹Action|Layout|Main|Segmentation,识别任务必须有Main)
- # --JPEGImages(存放需要打标签的图片文件(图像jpg格式))
- voc_root_path = 'D:/datasets/per_hat'
- # 添加后斜杠
- if not voc_root_path.endswith('\\') and not voc_root_path.endswith('/'):
- voc_root_path += '/'
- # voc格式标签文件路径
- xml_file_path = voc_root_path + 'Annotations/'
- # voc格式标注图片目录
- # 最好不要用"images"作文件夹名字,
- # 后续会对图片进行划分,命名的新文件夹叫"images"
- images_file_path = voc_root_path + 'JPEGImages/'
- # 数据集划分比例建议:训练集80%,验证集10%,测试集10%(标准的8:1:1)
- train_percent = 0.9
- val_percent = 0.1
- test_percent = 0.0
- # 批量重命名图片(uuid名称)
- def rename_images(xml_dir, images_dir):
- # 获取xml文件列表
- xml_file_list = os.listdir(xml_dir)
- # 处理所有xml文件
- for index, fn in enumerate(xml_file_list):
- print(f'正在重命名第{index}个文件:{fn}')
- # 新文件的文件名
- new_name = str(uuid.uuid1()).replace('-', '')
- # 老文件的文件名
- old_name = fn[:-4]
- # xml原文件路径
- xml_oldname = xml_dir + fn
- # xml新文件路径
- xml_newname = xml_dir + new_name + '.xml'
- # 重命名新文件名
- os.rename(xml_oldname, xml_newname)
- # 对应jpeg图片
- jpg_oldname = images_dir + old_name + '.jpg'
- # 对应的jpg图片存在
- if os.path.exists(jpg_oldname):
- # jpg新文件路径
- jpg_newname = images_dir + new_name + '.jpg'
- # 删除老的图片
- os.rename(jpg_oldname, jpg_newname)
- # voc盒子型=>中点+宽高
- def convert(size, box):
- dw = 1. / size[0]
- dh = 1. / size[1]
- x = (box[0] + box[1]) / 2.0
- y = (box[2] + box[3]) / 2.0
- w = box[1] - box[0]
- h = box[3] - box[2]
- x = x * dw
- w = w * dw
- y = y * dh
- h = h * dh
- return x, y, w, h
- # 转换标签文件
- def convert_annotations(source_file, dest_file):
- print(f'正在转换文件:{source_file}')
- in_file = open(source_file, encoding='UTF-8')
- out_file = open(dest_file, 'w', encoding='UTF-8')
- tree = ET.parse(in_file)
- root = tree.getroot()
- size = root.find('size')
- w = 0
- h = 0
- if size is not None:
- w = int(size.find('width').text)
- h = int(size.find('height').text)
- # 图片尺寸为0处理
- if 0 == w or 0 == h:
- # xxx.jpg
- name = os.path.basename(source_file)
- name = name[:-4]
- # 获取jpg文件
- image_file = images_file_path + name + '.jpg'
- if not os.path.exists(image_file):
- image_file = images_file_path + name + '.png'
- # 只有xml没有图片
- if not os.path.exists(image_file):
- in_file.close()
- out_file.close()
- os.remove(source_file)
- os.remove(dest_file)
- return
- # 获取图片宽高
- img = Image.open(image_file)
- w, h = img.size
- img.close()
- for obj in root.iter('object'):
- # difficult = obj.find('difficult').text
- cls = obj.find('name').text
- # if cls not in classes or int(difficult) == 1:
- # continue
- if cls not in classes:
- print(f'class {cls} not in config list')
- continue
- # 类别名转为yolov5的类别索引下标
- cls_id = classes.index(cls)
- # 读取物体识别位置
- xmlbox = obj.find('bndbox')
- b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text),
- float(xmlbox.find('ymin').text), float(xmlbox.find('ymax').text))
- bb = convert((w, h), b)
- out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')
- # *********************************************** #
- # parent folder
- # --data
- # ----images
- # ----train
- # ----val
- # ----test
- # ----labels
- # ----train
- # ----val
- # ----test
- # *********************************************** #
- # 创建yolov5格式目录
- def create_dir():
- if not os.path.exists(voc_root_path + 'images/'):
- os.makedirs(voc_root_path + 'images/')
- if not os.path.exists(voc_root_path + 'labels/'):
- os.makedirs(voc_root_path + 'labels/')
- if not os.path.exists(voc_root_path + 'images/train/'):
- os.makedirs(voc_root_path + 'images/train')
- if not os.path.exists(voc_root_path + 'images/val/'):
- os.makedirs(voc_root_path + 'images/val/')
- if not os.path.exists(voc_root_path + 'images/test/'):
- os.makedirs(voc_root_path + 'images/test/')
- if not os.path.exists(voc_root_path + 'labels/train/'):
- os.makedirs(voc_root_path + 'labels/train/')
- if not os.path.exists(voc_root_path + 'labels/val/'):
- os.makedirs(voc_root_path + 'labels/val/')
- if not os.path.exists(voc_root_path + 'labels/test/'):
- os.makedirs(voc_root_path + 'labels/test/')
- return
- # png转jpg
- def png_to_jpg_if_png_exists(jpg_image):
- # 文件不存在
- if not os.path.exists(jpg_image):
- # xxx.jpg
- name = os.path.basename(jpg_image)
- name = name[:-4]
- # png文件
- png_image = images_file_path + name + '.png'
- # png文件也不存在
- if not os.path.exists(png_image):
- print(f'file {jpg_image} not exists')
- return
- # 转行png文件为jpg
- img = Image.open(png_image)
- # 转换为JPG格式图片
- img = img.convert("RGB")
- # 保存为新的jpg格式图片
- img.save(jpg_image)
- # 关闭图片
- img.close()
- # 删除原来的png格式图片
- os.remove(png_image)
- # 重置图片大小
- def resize_source_image(source_path, dest_path):
- img = None
- try:
- # 打开图片
- img = Image.open(source_path)
- # 放大图片
- image = img.resize(global_img_size)
- # 将新图像保存至桌面
- image.save(dest_path)
- except IOError as e:
- print("缩放图像失败:" + e)
- finally:
- # 关闭图像
- if img is not None:
- img.close()
- pass
- # 转行所有数据集
- def convert_all_data():
- # 创建yolov5格式目录
- create_dir()
- # 原数据集XML文件列表及总数
- total_xml = os.listdir(xml_file_path)
- num_xml = len(total_xml)
- # 计算训练集、验证集、测试集数量
- num_train = int(num_xml * train_percent)
- num_val = int(num_xml * val_percent)
- num_test = num_xml - num_train - num_val
- print(f"训练集数目:{num_train}, 验证集数目:{num_val},测试集数目:{num_test}")
- # 随机训练集
- train = random.sample(total_xml, num_train)
- # 验证测试集[排除训练集数据]
- val_test = [i for i in total_xml if not i in train]
- # 从训练测试集取出验证集
- val = random.sample(val_test, num_val)
- # 测试集[排除训练集及验证集数据]
- test = [i for i in total_xml if not i in train and not i in val]
- # 开始转换训练集标签
- for index, fn in enumerate(train):
- print(f'正在转换第{index}个训练数据集文件:{fn}')
- # 原来文件名
- old_name = fn[:-4]
- new_name = old_name
- # 重命名文件
- if batch_rename_voc_samples:
- new_name = str(uuid.uuid1()).replace('-', '')
- # 转换xml文件
- xml_old_file = xml_file_path + old_name + '.xml'
- xml_new_file = voc_root_path + 'labels/train/' + new_name + '.txt'
- convert_annotations(xml_old_file, xml_new_file)
- # 拷贝jpg文件
- src_image = images_file_path + old_name + '.jpg'
- dst_image = voc_root_path + 'images/train/' + new_name + '.jpg'
- png_to_jpg_if_png_exists(src_image)
- if os.path.exists(src_image):
- if glob_resize_img:
- resize_source_image(src_image, dst_image)
- else:
- shutil.copyfile(src_image, dst_image)
- # 开始转换验证集标签
- for index, fn in enumerate(val):
- print(f'正在转换第{index}个验证数据集文件:{fn}')
- # 原来文件名
- old_name = fn[:-4]
- new_name = old_name
- # 重命名文件
- if batch_rename_voc_samples:
- new_name = str(uuid.uuid1()).replace('-', '')
- # 转换xml文件
- xml_old_file = xml_file_path + old_name + '.xml'
- xml_new_file = voc_root_path + 'labels/val/' + new_name + '.txt'
- convert_annotations(xml_old_file, xml_new_file)
- # 拷贝jpg文件
- src_image = images_file_path + old_name + '.jpg'
- dst_image = voc_root_path + 'images/val/' + new_name + '.jpg'
- png_to_jpg_if_png_exists(src_image)
- if os.path.exists(src_image):
- if glob_resize_img:
- resize_source_image(src_image, dst_image)
- else:
- shutil.copyfile(src_image, dst_image)
- # 开始转换测试集标签
- for index, fn in enumerate(test):
- print(f'正在转换第{index}个测试数据集文件:{fn}')
- # 原来文件名
- old_name = fn[:-4]
- new_name = old_name
- # 重命名文件
- if batch_rename_voc_samples:
- new_name = str(uuid.uuid1()).replace('-', '')
- # 转换xml文件
- xml_old_file = xml_file_path + old_name + '.xml'
- xml_new_file = voc_root_path + 'labels/test/' + new_name + '.txt'
- convert_annotations(xml_old_file, xml_new_file)
- # 拷贝jpg文件
- src_image = images_file_path + old_name + '.jpg'
- dst_image = voc_root_path + 'images/test/' + new_name + '.jpg'
- png_to_jpg_if_png_exists(src_image)
- if os.path.exists(src_image):
- if glob_resize_img:
- resize_source_image(src_image, dst_image)
- else:
- shutil.copyfile(src_image, dst_image)
- pass
- # 开始执行转行
- convert_all_data()
复制代码 百度爬虫模型的训练关键在于数据集的准备,如何弄到我们需要的数据集?其实有很多方面,我这里大概找了几个方法,大部分可以通过网上获取,也可以自己写爬虫从百度爬取(后面我也找了很多数据集获取地址,参见《数据集采集》一页。 百度爬虫我也准备好了,只需执行python脚本然后输入你要搜索的关键词、要下载的图片数量即可下载到对应关键词的图片。 千图爬虫和百度图库图片爬虫一样,我也写了一个关于千图网的一个爬虫,脚本如下 - """
- 千图网图库图片抓取
- 汉字转拼音:pip install pohan -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com
- """
- import uuid
- import requests
- import re
- from urllib import parse
- import os
- import pohan
- from pohan.pinyin.pinyin import Style
- # 判断词语是否为中文
- def is_chinese(strings):
- for _char in strings:
- if '\u4e00' <= _char <= '\u9fa5':
- return True
- class ImageSpider(object):
- def __init__(self, save_dir):
- # 分页从1开始
- self.url = 'https://www.58pic.com/tupian/{}-852-0-{}.html'
- self.headers = {'User-Agent': 'Mozilla/4.0'}
- self.word_parse = ''
- self.save_dir = save_dir
- self.image_count = 1000
- self.i = 1
- # 获取图片递归函数
- def getimage(self, url, word):
- # 使用 requests模块得到响应对象
- res = requests.get(url, headers=self.headers)
- # 更改编码格式
- res.encoding = "utf-8"
- # 得到html网页
- html = res.text
- # print(html)
- # 正则解析
- pattern = re.compile('data-original="(.*?)"', re.S)
- img_link_list = pattern.findall(html)
- # 存储图片的url链接
- print(img_link_list)
- # 创建目录,用于保存图片
- directory = str(self.save_dir + '/{}').format(word)
- # 如果目录不存在则创建新目录
- if not os.path.exists(directory):
- os.makedirs(directory, mode=0o777, exist_ok=True)
- previous_image = ''
- for img_link in img_link_list:
- # 添加请求前缀https
- img_link = "https:" + img_link
- # 忽略图片是图标图等且与上一张图不相同
- if img_link.find("icon.qiantucdn.com/static") == -1 and previous_image != img_link:
- # 本地文件路径
- filename = '{}/{}_{}.jpg'.format(directory, word, str(uuid.uuid1()))
- self.save_image(img_link, filename)
- # 上一张图地址
- previous_image = img_link
- self.i += 1
- # 每页只能下载60张图片,这里可以直接跳出,或者按需要的数量更改
- if self.i == self.image_count:
- print(f'下载完成{self.image_count}张图,退出下载')
- return
- # 也可以改成翻页下载的形式
- if self.i % 77 == 0:
- pn = (int)(self.i / 77) + 1
- urlnew = self.url.format(self.word_parse, pn)
- print(f'请求下一页{urlnew}')
- self.getimage(urlnew, word)
- # 保存图片
- def save_image(self, img_link, filename):
- try:
- # https:\\/\\/ns-strategy.cdn.bcebos.com\\/ns-strategy\\/upload\\/fc_big_pic\\/part-00384-1388.jpg
- img_link = img_link.replace("\\/", '/')
- html = requests.get(url=img_link, headers=self.headers).content
- with open(filename, 'wb') as f:
- f.write(html)
- print(f'下载{img_link}到{filename}成功')
- except Exception as e:
- print(f'下载图片{img_link}异常:{e}')
- # 执行函数
- def run(self):
- word = input("您想要搜索下载的图片关键词?")
- # 千图网汉字自动转拼音搜索
- pinyin_list = pohan.pinyin.han2pinyin(word, style=Style.NORMAL)
- key_word = ''
- for item in pinyin_list:
- key_word += item[0]
- self.word_parse = parse.quote(key_word)
- count = input("抓取图片最大数量?")
- self.image_count = int(count)
- url = self.url.format(self.word_parse, '1')
- print(url)
- self.getimage(url, word)
- if __name__ == '__main__':
- spider = ImageSpider('D:/capture')
- spider.run()
复制代码千图网图片可能精准一些,当然可能是数据量没有百度图库的大,但是也是一个不错选择,执行过程和百度一样,这里不在赘述。 注意: 千图网之前的爬虫可以爬,现在发现这个脚本不能用了,应该是静态图片访问千图网做了token访问,还需要登录,人没百度大,心机耍的一溜一溜的,真要命,各位大神请贡献你们自己的其他图库的爬虫,在此为大家感谢你! 测试模型在源码里我提供了如下几个onnx测试模型,各位可以修改自己的代码,然后使用对应模型进行测试,模型路径见源码 AiBox\3rdparty\model 演示效果AI盒子管理端(web)
基于yolov8框架,使用C++实现的跨平台目标识别系统,支持windows、linux(Ubuntu或centos)跨平台编译及部 ...
基于yolov8框架,使用C++实现的跨平台目标识别系统,支持windows、linux(Ubuntu或centos)跨平台编译及部 ...
基于yolov8框架,使用C++实现的跨平台目标识别系统,支持windows、linux(Ubuntu或centos)跨平台编译及部 ...
基于yolov8框架,使用C++实现的跨平台目标识别系统,支持windows、linux(Ubuntu或centos)跨平台编译及部 ...
基于yolov8框架,使用C++实现的跨平台目标识别系统,支持windows、linux(Ubuntu或centos)跨平台编译及部 ...
基于yolov8框架,使用C++实现的跨平台目标识别系统,支持windows、linux(Ubuntu或centos)跨平台编译及部 ...
基于yolov8框架,使用C++实现的跨平台目标识别系统,支持windows、linux(Ubuntu或centos)跨平台编译及部 ...
基于yolov8框架,使用C++实现的跨平台目标识别系统,支持windows、linux(Ubuntu或centos)跨平台编译及部 ...
基于yolov8框架,使用C++实现的跨平台目标识别系统,支持windows、linux(Ubuntu或centos)跨平台编译及部 ...
AI盒子服务端(C++)
(1)ubuntu系统启动
基于yolov8框架,使用C++实现的跨平台目标识别系统,支持windows、linux(Ubuntu或centos)跨平台编译及部 ...
(2)windows系统启动
基于yolov8框架,使用C++实现的跨平台目标识别系统,支持windows、linux(Ubuntu或centos)跨平台编译及部 ...
AI预警云平台(Sass)
基于yolov8框架,使用C++实现的跨平台目标识别系统,支持windows、linux(Ubuntu或centos)跨平台编译及部 ...
基于yolov8框架,使用C++实现的跨平台目标识别系统,支持windows、linux(Ubuntu或centos)跨平台编译及部 ...
基于yolov8框架,使用C++实现的跨平台目标识别系统,支持windows、linux(Ubuntu或centos)跨平台编译及部 ...
基于yolov8框架,使用C++实现的跨平台目标识别系统,支持windows、linux(Ubuntu或centos)跨平台编译及部 ...
基于yolov8框架,使用C++实现的跨平台目标识别系统,支持windows、linux(Ubuntu或centos)跨平台编译及部 ...
基于yolov8框架,使用C++实现的跨平台目标识别系统,支持windows、linux(Ubuntu或centos)跨平台编译及部 ...
基于yolov8框架,使用C++实现的跨平台目标识别系统,支持windows、linux(Ubuntu或centos)跨平台编译及部 ...
基于yolov8框架,使用C++实现的跨平台目标识别系统,支持windows、linux(Ubuntu或centos)跨平台编译及部 ...
基于yolov8框架,使用C++实现的跨平台目标识别系统,支持windows、linux(Ubuntu或centos)跨平台编译及部 ...
基于yolov8框架,使用C++实现的跨平台目标识别系统,支持windows、linux(Ubuntu或centos)跨平台编译及部 ...
基于yolov8框架,使用C++实现的跨平台目标识别系统,支持windows、linux(Ubuntu或centos)跨平台编译及部 ...
基于yolov8框架,使用C++实现的跨平台目标识别系统,支持windows、linux(Ubuntu或centos)跨平台编译及部 ...
基于yolov8框架,使用C++实现的跨平台目标识别系统,支持windows、linux(Ubuntu或centos)跨平台编译及部 ...
基于yolov8框架,使用C++实现的跨平台目标识别系统,支持windows、linux(Ubuntu或centos)跨平台编译及部 ...
基于yolov8框架,使用C++实现的跨平台目标识别系统,支持windows、linux(Ubuntu或centos)跨平台编译及部 ...
开发环境机器准备ubuntu、centos、windows、VMware Workstation Pro
本次开源部分为c++版跨平台服务端,开发技术使用cmake、boost、sqlite、opencv、oatpp(http)、oatpp-websocket、spdlog(项目中已有),所以必须先安装对应的软件和必要的库,软件和库请移步此处下载: 链接:https://pan.baidu.com/s/1bPi_l4fKvhZOSducrd4eZw?pwd=ghwm 提取码:ghwm
除了必要的软件之外,我们需要准备一台windows开发机和一台linux开发机器(ubuntu或者centos都可以) 环境准备vs2019、boost、oatpp、oatpp-websocket、opencv、spdlog
本次实际开发环境为vs2019,各位可以使用vs2019或以上都可以,支持跨平台开发调试工具,各个环境和软件安装详细细节如下所示。 提取码下载:
|