确定欲研究方向,搜集相关的图片,每种类别大概需要2百张左右。
代码来源:爬取百度图片——详细思路
import requests
import os
import urllib
class Spider_baidu_image():
def __init__(self):
self.url = 'http://image.baidu.com/search/acjson?'
self.headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.\
3497.81 Safari/537.36'}
self.headers_image = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.\
3497.81 Safari/537.36','Referer':'http://image.baidu.com/search/index?tn=baiduimage&ipn=r&ct=201326592&cl=2&lm=-1&st=-1&fm=result&fr=&sf=1&fmq=1557124645631_R&pv=&ic=&nc=1&z=&hd=1&latest=0©right=0&se=1&showtab=0&fb=0&width=&height=&face=0&istype=2&ie=utf-8&sid=&word=%E8%83%A1%E6%AD%8C'}
# self.keyword = '黄瓜幼苗'
self.keyword = input("请输入搜索图片关键字:")
self.paginator = int(input("请输入搜索页数,每页30张图片:"))
# self.paginator = 50
# print(type(self.keyword),self.paginator)
# exit()
def get_param(self):
"""
获取url请求的参数,存入列表并返回
:return:
"""
keyword = urllib.parse.quote(self.keyword)
params = []
for i in range(1,self.paginator+1):
params.append('tn=resultjson_com&ipn=rj&ct=201326592&is=&fp=result&queryWord={}&cl=2&lm=-1&ie=utf-8&oe=utf-8&adpicid=&st=-1&z=&ic=&hd=1&latest=0©right=0&word={}&s=&se=&tab=&width=&height=&face=0&istype=2&qc=&nc=1&fr=&expermode=&force=&cg=star&pn={}&rn=30&gsm=78&1557125391211='.format(keyword,keyword,30*i))
return params
def get_urls(self,params):
"""
由url参数返回各个url拼接后的响应,存入列表并返回
:return:
"""
urls = []
for i in params:
urls.append(self.url+i)
return urls
def get_image_url(self,urls):
image_url = []
for url in urls:
json_data = requests.get(url,headers = self.headers).json()
json_data = json_data.get('data')
for i in json_data:
if i:
image_url.append(i.get('thumbURL'))
return image_url
def get_image(self,image_url):
"""
根据图片url,在本地目录下新建一个以搜索关键字命名的文件夹,然后将每一个图片存入。
:param image_url:
:return:
"""
cwd = os.getcwd()
file_name = os.path.join(cwd,self.keyword)
if not os.path.exists(self.keyword):
os.mkdir(file_name)
for index,url in enumerate(image_url,start=1):
with open(file_name+'\\{}.jpg'.format(index),'wb') as f:
f.write(requests.get(url,headers = self.headers_image).content)
if index != 0 and index % 30 == 0:
print('{}第{}页下载完成'.format(self.keyword,index/30))
def __call__(self, *args, **kwargs):
params = self.get_param()
urls = self.get_urls(params)
image_url = self.get_image_url(urls)
self.get_image(image_url)
if __name__ == '__main__':
spider = Spider_baidu_image()
spider()
YOLOv5模型要求.txt格式的标注文件,而一般标注出来的文件是.xml格式的标注文件,故需要转换。
代码参考:如何将xml格式转换为yolov5所需的txt格式
#导入的python模块
import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join
import glob
#分类名
classes = ["cucumber","Hydrocotyle L","Chlorophytum","eggplant","pakchoi","tomato","radish","sundew","majoram","petunia"]
#类名标识name: 黄瓜叶 轮生香菇草 吊兰 茄子 青菜 番茄 萝卜 茅膏菜 牛至 矮牵牛
"""
方法作用:转换标注信息
方法参数:size,box
"""
#size数组含有图片的规格信息
#box数组含有标注框的具体信息
#.xml格式存储的是标注框的左上角坐标(xmin,ymin)和右下角坐标(xmax,ymax)
#.txt格式存储的是标注框在整张图片中的中心点相对坐标(x,y)和相对宽高(w,h)
def convert(size, box):
dw = 1.0 / size[0]
dh = 1.0 / 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)
"""
方法作用:转换文件格式
方法参数:image_name(图片名)
"""
def convert_annotation(image_name):
in_file = open('E:/大创项目/格式转换/formatConversion/labels/train_xml/' + image_name[:-3] + 'xml',encoding='utf-8') # xml文件路径
out_file = open('E:/大创项目/格式转换/formatConversion/labels/train_txt/' + image_name[:-3] + 'txt', 'w',encoding='utf-8') # 转换后的txt文件存放路径
f = in_file
xml_text = f.read()
root = ET.fromstring(xml_text)
f.close()
size = root.find('size')
w = int(size.find('width').text)
h = int(size.find('height').text)
for obj in root.iter('object'):
cls = obj.find('name').text
if cls not in classes:
print(cls)
continue
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')
wd = getcwd()
if __name__ == '__main__':
for image_path in glob.glob("E:/大创项目/格式转换/formatConversion/images/train/*.jpg"): # 每一张图片都对应一个xml文件这里写xml对应的图片的路径
image_name = image_path.split('\\')[-1]
convert_annotation(image_name)
注意:linux路径需改动倒数第二句,改动如下:
image_name = image_path.split('/')[-1]
这部分工作交由其他小伙伴完成了。
1、官网下载(慢):https://github.com/ultralytics/yolov5
2、网盘链接,提取码:tno6
images文件夹存放样本图片
labels文件夹存储标注信息
train文件夹需要80%-90%左右的图片或样本,用于模型训练
val文件夹需要10%-20%左右的图片或样本,用于模型验证
1、按照文件结构进行布置
#随机取一定比例的图片存入另一个文件夹的代码
import os, random, shutil
def moveFile(fileDir, tarDir):
pathDir = os.listdir(fileDir) # 取图片的原始路径
filenumber = len(pathDir)
rate = 0.2 # 自定义抽取图片的比例,比方说100张抽10张,那就是0.1
picknumber = int(filenumber * rate) # 按照rate比例从文件夹中取一定数量图片
sample = random.sample(pathDir, picknumber) # 随机选取picknumber数量的样本图片
print(sample)
print(len(sample))
for name in sample:
shutil.move(fileDir + name, tarDir + name)
if __name__ == '__main__':
fileDir = "C:/KuoZeng/200-至少1种方式组合xml/" # 源图片文件夹路径
tarDir = 'C:/KuoZeng/' # 移动到新的文件夹路径
moveFile(fileDir, tarDir)
#根据前边所取图片名取出同名标注的代码
import os, random, shutil
import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join
import glob
def moveFile(fileDir, tarDir, image_name):
pathDir = os.listdir(fileDir) # 取图片的原始路径
filenumber = len(pathDir)
# rate = 0.5 # 自定义抽取图片的比例,比方说100张抽10张,那就是0.1
# picknumber = int(filenumber * rate) # 按照rate比例从文件夹中取一定数量图片
# sample = random.sample(pathDir, picknumber) # 随机选取picknumber数量的样本图片
#print(sample)
#print(len(sample))
#for name in sample:
shutil.move(fileDir + image_name[:-3] + 'txt', tarDir + image_name[:-3] + 'txt')
if __name__ == '__main__':
fileDir = '/hy-tmp/datasets/demo2/lables/train/' # 源图片文件夹路径
tarDir = '/hy-tmp/datasets/demo2/lables/train-2/' # 移动到新的文件夹路径
for image_path in glob.glob("/hy-tmp/datasets/demo2/images/train-2/*.jpg"): # 每一张图片都对应一个xml文件这里写xml对应的图片的路径
image_name = image_path.split('/')[-1]
moveFile(fileDir, tarDir, image_name)
注意:Windows路径需改动倒数第二句,改动如下:
image_name = image_path.split('\\')[-1]
2、创建数据集文件demo1.yaml
yaml的书写规范如下:
:
后跟一个空格/
而不用 \../
path: ../datasets/demo1 # dataset root dir
#训练图片集路径
train: ../datasets/demo1/images/train # train images (relative to 'path') 128 images
#验证图片集路径
val: ../datasets/demo1/images/val # val images (relative to 'path') 128 images
#测试图片集路径
test:
# test images (optional)
#分类数量:10
nc: 10
#分类名
names: ['cucumber','Hydrocotyle L','Chlorophytum','eggplant','pakchoi','tomato','radish','sundew','majoram','petunia']
3、修改配置模型的yaml文件
进入./yolov5-master/models/
选择欲训练的模型文件,修改nc个数,改成需要识别的分类数量
我记录在了另一篇博客中,链接
#(单张图)
python detect.py --source ./data/images/1.jpg --weights ./runs/train/exp3/weights/best.pt --device 0 --save-txt
#(整个文件夹中的所有图)
python detect1.py --source ./data/images/ --weights ./runs/train/exp3/weights/best.pt --device 0 --save-txt
说明:
python detect1.py --source 被推理图片所在路径 --weights 权重文件路径 --device 0 --save-txt
–save-txt可选,命令带有则会生成.txt文件记录推理出的标注框坐标信息等】
推理结果默认被存在:./runs/detect/exp*
参考链接:
1、yolov5 文件函数detect分析
2、yolov5修改detect.py生成新的txt文本
3、python:批量读取图片和批量添加文本
#图片添加文字代码解读
#导入相关模块
import cv2
import os
from PIL import Image,ImageDraw,ImageFont
src_path = /hy-tmp/src/1.jpg #读入的图片路径
des_path = /hy-tmp/des/1.jpg #保存的图片路径
pict=cv2.imread(src_path) #读取图片
font = cv2.FONT_HERSHEY_DUPLEX # 字体样式
##在图片中添加文字
cv2.putText(pict, addText, (50,50), font,2, (255, 0, 0), 2 )
##putText()参数说明
#1.输入图像
#2.需要添加的文字
#3.左上角坐标
#4.字体类型
#5.字体大小
#6.文字颜色
#7.字体粗细
cv2.waitKey(0)
cv2.imwrite(des_path,pict) #写入