利用PaddleHub目标检测预训练模型 生成相应的图像数据标注-VOC
格式数据(XML
文件),之后利用Labelimg 进行图像标注数据的查看与修改。
本次我使用yolov3_darknet53_pedestrian 进行行人半自动标注演示,其它标注实现原理相同。关于yolov3_darknet53_pedestrian
预训练模型:
我上传了五张行人的图片到
work/images/
下
# 单张图片
# 测试:work/images/1.jpg
import paddlehub as hub
import cv2
pedestrian_detector = hub.Module(name="yolov3_darknet53_pedestrian")
result = pedestrian_detector.object_detection(images=[cv2.imread('work/images/1.jpg')])
print(result)
print(type(result))
[2021-08-23 15:09:13,736] [ WARNING] - The _initialize method in HubModule will soon be deprecated, you can use the __init__() to handle the initialization of the object
[{'data': [{'label': 'pedestrian', 'confidence': 0.9487035870552063, 'left': 171.19189453125, 'top': 16.71392822265625, 'right': 441.5438232421875, 'bottom': 950.821533203125}, {'label': 'pedestrian', 'confidence': 0.32225432991981506, 'left': 378.99603271484375, 'top': 233.63763427734375, 'right': 509.3026123046875, 'bottom': 525.3494873046875}], 'save_path': 'yolov3_pedestrian_detect_output/image_numpy_0.jpg'}]
import paddlehub as hub
import cv2
# 预测单张图片中单个目标或者多个目标的位置以及标签,并以列表方式返回
def object_detec(images):
coordinates_list = []
pedestrian_detector = hub.Module(name="yolov3_darknet53_pedestrian")
result = pedestrian_detector.object_detection(images=[cv2.imread(images)])
for i in range(len(result[0]['data'])):
'''
left (int): 边界框的左上角x坐标;
top (int): 边界框的左上角y坐标;
right (int): 边界框的右下角x坐标;
bottom (int): 边界框的右下角y坐标;
'''
xmin = int(result[0]['data'][i]['left'])
ymin = int(result[0]['data'][i]['top'])
xmax = int(result[0]['data'][i]['right'])
ymax = int(result[0]['data'][i]['right'])
pre_label = result[0]['data'][0]['label']
coordinates_list.append([xmin,ymin,xmax,ymax,pre_label])
return coordinates_list
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/matplotlib/__init__.py:107: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working
from collections import MutableMapping
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/matplotlib/rcsetup.py:20: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working
from collections import Iterable, Mapping
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/matplotlib/colors.py:53: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working
from collections import Sized
# 模块实现测试
r = object_detec('work/images/1.jpg')
r
[2021-08-23 16:24:36,208] [ WARNING] - The _initialize method in HubModule will soon be deprecated, you can use the __init__() to handle the initialization of the object
[[171, 16, 441, 441, 'pedestrian'], [378, 233, 509, 509, 'pedestrian']]
import os
from os import getcwd
from xml.etree import ElementTree as ET
# 定义一个创建一级分支object的函数
def create_object(root,xi,yi,xa,ya,obj_name): # 参数依次,树根,xmin,ymin,xmax,ymax
#创建一级分支object
_object=ET.SubElement(root,'object')
#创建二级分支
name=ET.SubElement(_object,'name')
print(obj_name)
name.text= str(obj_name)
pose=ET.SubElement(_object,'pose')
pose.text='Unspecified'
truncated=ET.SubElement(_object,'truncated')
truncated.text='0'
difficult=ET.SubElement(_object,'difficult')
difficult.text='0'
#创建bndbox
bndbox=ET.SubElement(_object,'bndbox')
xmin=ET.SubElement(bndbox,'xmin')
xmin.text='%s'%xi
ymin = ET.SubElement(bndbox, 'ymin')
ymin.text = '%s'%yi
xmax = ET.SubElement(bndbox, 'xmax')
xmax.text = '%s'%xa
ymax = ET.SubElement(bndbox, 'ymax')
ymax.text = '%s'%ya
# 创建xml文件的函数
def create_tree(image_name, h, w, imgdir):
global annotation
# 创建树根annotation
annotation = ET.Element('annotation')
#创建一级分支folder
folder = ET.SubElement(annotation,'folder')
#添加folder标签内容
folder.text=(imgdir)
#创建一级分支filename
filename=ET.SubElement(annotation,'filename')
filename.text=image_name
#创建一级分支path
path=ET.SubElement(annotation,'path')
path.text= getcwd() + '/{}/{}'.format(imgdir,image_name) # 用于返回当前工作目录
#创建一级分支source
source=ET.SubElement(annotation,'source')
#创建source下的二级分支database
database=ET.SubElement(source,'database')
database.text='Unknown'
#创建一级分支size
size=ET.SubElement(annotation,'size')
#创建size下的二级分支图像的宽、高及depth
width=ET.SubElement(size,'width')
width.text= str(w)
height=ET.SubElement(size,'height')
height.text= str(h)
depth = ET.SubElement(size,'depth')
depth.text = '3'
#创建一级分支segmented
segmented = ET.SubElement(annotation,'segmented')
segmented.text = '0'
def pretty_xml(element, indent, newline, level=0): # elemnt为传进来的Elment类,参数indent用于缩进,newline用于换行
if element: # 判断element是否有子元素
if (element.text is None) or element.text.isspace(): # 如果element的text没有内容
element.text = newline + indent * (level + 1)
else:
element.text = newline + indent * (level + 1) + element.text.strip() + newline + indent * (level + 1)
# else: # 此处两行如果把注释去掉,Element的text也会另起一行
# element.text = newline + indent * (level + 1) + element.text.strip() + newline + indent * level
temp = list(element) # 将element转成list
for subelement in temp:
if temp.index(subelement) < (len(temp) - 1): # 如果不是list的最后一个元素,说明下一个行是同级别元素的起始,缩进应一致
subelement.tail = newline + indent * (level + 1)
else: # 如果是list的最后一个元素, 说明下一行是母元素的结束,缩进应该少一个
subelement.tail = newline + indent * level
pretty_xml(subelement, indent, newline, level=level + 1) # 对子元素进行递归操作
imgdir = 'work/images'
outdir = './work/Annotation'
if not os.path.exists(outdir): #判断是否存在文件夹如果不存在则创建为文件夹
os.makedirs(outdir)
IMAGES_LIST = os.listdir(imgdir)
for image_name in IMAGES_LIST:
#print(image_name)
#break
# 判断后缀只处理jpg文件
if image_name.endswith('.jpg'):
image = cv2.imread(os.path.join(imgdir, image_name))
#print(image)
coordinates_list = object_detec('./work/images/'+image_name)
(h, w) = image.shape[:2]
create_tree(image_name, h, w, imgdir)
if coordinates_list:
#print(image_name)
for coordinate in coordinates_list:
label_id = coordinate[4]
create_object(annotation, coordinate[0], coordinate[1], coordinate[2], coordinate[3], label_id)
# 将树模型写入xml文件
tree = ET.ElementTree(annotation)
root = tree.getroot()
pretty_xml(root, '\t', '\n')
#tree.write('.\{}\{}.xml'.format(outdir, image_name.strip('.jpg')), encoding='utf-8')
tree.write('{}/{}.xml'.format(outdir, image_name.strip('.jpg')), encoding='utf-8')
else:
print(image_name)
[2021-08-23 15:55:05,995] [ WARNING] - The _initialize method in HubModule will soon be deprecated, you can use the __init__() to handle the initialization of the object
pedestrian
pedestrian
[2021-08-23 15:55:09,781] [ WARNING] - The _initialize method in HubModule will soon be deprecated, you can use the __init__() to handle the initialization of the object
pedestrian
pedestrian
[2021-08-23 15:55:13,763] [ WARNING] - The _initialize method in HubModule will soon be deprecated, you can use the __init__() to handle the initialization of the object
pedestrian
[2021-08-23 15:55:17,363] [ WARNING] - The _initialize method in HubModule will soon be deprecated, you can use the __init__() to handle the initialization of the object
pedestrian
pedestrian
[2021-08-23 15:55:21,189] [ WARNING] - The _initialize method in HubModule will soon be deprecated, you can use the __init__() to handle the initialization of the object
pedestrian
pedestrian
work/
下的images
和Annotation
内容到本地;home
aistudio
work
│
├─Annotation
│ 1.xml
│ 2.xml
│ 3.xml
│ ...
│
└─images
1.jpg
2.jpg
3.jpg
...
labelimg_win/windows_v1.8.1/data/predefined_classes.txt
,我这里只框选行人,所以txt内容为:pedestrian
如果你的是车、人、手机…,你可以这样写:
car
people
phone
labelImg.exe
,在左侧点击Open Dir
选择到下载的images
文件夹,点击Change Save Dir
选择到下载的Annotation
文件夹。上图就是我半自动标注的结果,嗯~还是挺感人的
trian
如果你的是车、人、手机...,你可以这样写:
```html
car
people
phone
labelImg.exe
,在左侧点击Open Dir
选择到下载的images
文件夹,点击Change Save Dir
选择到下载的Annotation
文件夹。上图就是我半自动标注的结果,嗯~还是挺感人的