已标注数据的可视化有两种方式:
1.将图片和标注文件(json\xml)放在同一文件夹中,然后用labelme\labelimg打开此文件夹即可查看;
2.解析标注文件,用opencv进行可视化。
显然,本文要讲的是第二种!!!
一、labelimg标注的xml文件可视化
# 导入工具包
import cv2
import matplotlib.pyplot as plt
import xml.etree.ElementTree as ET
# 载入图像
img_path = '3.jpg'
img_bgr = cv2.imread(img_path)
# 可视化
# plt.imshow(img_bgr[:,:,::-1]) # 将bgr通道转换成rgb通道
# plt.show()
# 载入labelimg格式的xml标注文件
xml_path = '3.xml'
xml_inf = open(xml_path)
tree = ET.parse(xml_inf)
# print(tree)
root = tree.getroot()
# print(root)
# 框可视化配置
bbox_color = (255, 129, 0) # 框的颜色
bbox_thickness = 2 # 框的线宽
# 框类别文字
bbox_labelstr = {
'font_size':1, # 字体大小
'font_thickness':2, # 字体粗细
'offset_x':0, # X 方向,文字偏移距离,向右为正
'offset_y':-10, # Y 方向,文字偏移距离,向下为正
}
# 画框
for obj in root.iter('object'): # 一个object代表一个标注物体
# 框的类别
bbox_label = obj.find('name').text
# 框的两点坐标
# 左上角坐标
bbox_top_left_x = int(obj.find('bndbox').find('xmin').text)
bbox_top_left_y = int(obj.find('bndbox').find('ymin').text)
# 右下角坐标
bbox_bottom_right_x = int(obj.find('bndbox').find('xmax').text)
bbox_bottom_right_y = int(obj.find('bndbox').find('ymax').text)
# 画矩形:画框
img_bgr = cv2.rectangle(img_bgr, (bbox_top_left_x, bbox_top_left_y), (bbox_bottom_right_x, bbox_bottom_right_y),
bbox_color, bbox_thickness)
# 写框类别文字:图片,文字字符串,文字左上角坐标,字体,字体大小,颜色,字体粗细
img_bgr = cv2.putText(img_bgr, bbox_label, (
bbox_top_left_x + bbox_labelstr['offset_x'],
bbox_top_left_y + bbox_labelstr['offset_y']),
cv2.FONT_HERSHEY_SIMPLEX, bbox_labelstr['font_size'], bbox_color,
bbox_labelstr['font_thickness'])
# 可视化
plt.imshow(img_bgr[:,:,::-1]) # 将bgr通道转换成rgb通道
plt.show()
# 当前目录下保存可视化结果
cv2.imwrite('visualize3.jpg', img_bgr)
二、labelme标注的json文件可视化
# 导入工具包
import cv2
import numpy as np
import json
import matplotlib.pyplot as plt
# matplotlib inline
# 载入图像
img_path = '1.jpg'
img_bgr = cv2.imread(img_path)
# 可视化
# plt.imshow(img_bgr[:,:,::-1]) # 将bgr通道转换成rgb通道
# plt.show()
# 载入labelme格式的json标注文件
labelme_path = '1_labelme.json'
with open(labelme_path, 'r', encoding='utf-8') as f:
labelme = json.load(f)
# 查看标注信息 rectangle:矩形 point:点 polygon:多边形
# print(labelme.keys())
# dict_keys(['version', 'flags', 'shapes', 'imagePath', 'imageData', 'imageHeight', 'imageWidth'])
# print(labelme['shapes'])
# <<<<<<<<<<<<<<<<<<可视化框(rectangle)标注>>>>>>>>>>>>>>>>>>>>>
# 框可视化配置
bbox_color = (255, 129, 0) # 框的颜色
bbox_thickness = 5 # 框的线宽
# 框类别文字
bbox_labelstr = {
'font_size':6, # 字体大小
'font_thickness':14, # 字体粗细
'offset_x':0, # X 方向,文字偏移距离,向右为正
'offset_y':-80, # Y 方向,文字偏移距离,向下为正
}
# 画框
for each_ann in labelme['shapes']: # 遍历每一个标注
if each_ann['shape_type'] == 'rectangle': # 筛选出框标注
# 框的类别
bbox_label = each_ann['label']
# 框的两点坐标
bbox_keypoints = each_ann['points']
bbox_keypoint_A_xy = bbox_keypoints[0]
bbox_keypoint_B_xy = bbox_keypoints[1]
# 左上角坐标
bbox_top_left_x = int(min(bbox_keypoint_A_xy[0], bbox_keypoint_B_xy[0]))
bbox_top_left_y = int(min(bbox_keypoint_A_xy[1], bbox_keypoint_B_xy[1]))
# 右下角坐标
bbox_bottom_right_x = int(max(bbox_keypoint_A_xy[0], bbox_keypoint_B_xy[0]))
bbox_bottom_right_y = int(max(bbox_keypoint_A_xy[1], bbox_keypoint_B_xy[1]))
# 画矩形:画框
img_bgr = cv2.rectangle(img_bgr, (bbox_top_left_x, bbox_top_left_y), (bbox_bottom_right_x, bbox_bottom_right_y),
bbox_color, bbox_thickness)
# 写框类别文字:图片,文字字符串,文字左上角坐标,字体,字体大小,颜色,字体粗细
img_bgr = cv2.putText(img_bgr, bbox_label, (
bbox_top_left_x + bbox_labelstr['offset_x'],
bbox_top_left_y + bbox_labelstr['offset_y']),
cv2.FONT_HERSHEY_SIMPLEX, bbox_labelstr['font_size'], bbox_color,
bbox_labelstr['font_thickness'])
# # 可视化
# plt.imshow(img_bgr[:,:,::-1]) # 将bgr通道转换成rgb通道
# plt.show()
# <<<<<<<<<<<<<<<<<<可视化关键点(keypoint)标注>>>>>>>>>>>>>>>>>>>>>
# 关键点的可视化配置
# 关键点配色
kpt_color_map = {
'angle_30':{'id':0, 'color':[255,0,0], 'radius':30, 'thickness':-1},
'angle_60':{'id':1, 'color':[0,255,0], 'radius':30, 'thickness':-1},
'angle_90':{'id':2, 'color':[0,0,255], 'radius':30, 'thickness':-1}
}
# 点类别文字
kpt_labelstr = {
'font_size':4, # 字体大小
'font_thickness':12, # 字体粗细
'offset_x':30, # X 方向,文字偏移距离,向右为正
'offset_y':100, # Y 方向,文字偏移距离,向下为正
}
# 画点
for each_ann in labelme['shapes']: # 遍历每一个标注
if each_ann['shape_type'] == 'point': # 筛选出关键点标注
kpt_label = each_ann['label'] # 该点的类别
# 该点的 XY 坐标
kpt_xy = each_ann['points'][0]
kpt_x, kpt_y = int(kpt_xy[0]), int(kpt_xy[1])
# 该点的可视化配置
kpt_color = kpt_color_map[kpt_label]['color'] # 颜色
kpt_radius = kpt_color_map[kpt_label]['radius'] # 半径
kpt_thickness = kpt_color_map[kpt_label]['thickness'] # 线宽(-1代表填充)
# 画圆:画该关键点
img_bgr = cv2.circle(img_bgr, (kpt_x, kpt_y), kpt_radius, kpt_color, kpt_thickness)
# 写该点类别文字:图片,文字字符串,文字左上角坐标,字体,字体大小,颜色,字体粗细
img_bgr = cv2.putText(img_bgr, kpt_label, (kpt_x + kpt_labelstr['offset_x'], kpt_y + kpt_labelstr['offset_y']),
cv2.FONT_HERSHEY_SIMPLEX, kpt_labelstr['font_size'], kpt_color,
kpt_labelstr['font_thickness'])
# 可视化
# plt.imshow(img_bgr[:,:,::-1]) # 将bgr通道转换成rgb通道
# plt.show()
# <<<<<<<<<<<<<<<<<<可视化多段线(polygon)标注>>>>>>>>>>>>>>>>>>>>>
# 多段线的可视化配置
poly_color = (151, 57, 224)
poly_thickness = 3
poly_labelstr = {
'font_size':4, # 字体大小
'font_thickness':12, # 字体粗细
'offset_x':-200, # X 方向,文字偏移距离,向右为正
'offset_y':0, # Y 方向,文字偏移距离,向下为正
}
# 画多段线
img_mask = np.ones(img_bgr.shape, np.uint8) #创建一个和img_bgr一样大小的黑色mask
for each_ann in labelme['shapes']: # 遍历每一个标注
if each_ann['shape_type'] == 'polygon': # 筛选出多段线(polygon)标注
poly_label = each_ann['label'] # 该多段线的类别
poly_points = [np.array(each_ann['points'], np.int32).reshape((-1, 1, 2))] #reshape后增加一个维度
# 该多段线平均 XY 坐标,用于放置多段线类别文字
x_mean = int(np.mean(poly_points[0][:, 0, :][:, 0])) #取出所有点的x坐标并求平均值
y_mean = int(np.mean(poly_points[0][:, 0, :][:, 1])) #取出所有点的y坐标并求平均值
# 画该多段线轮廓
img_bgr = cv2.polylines(img_bgr, poly_points, isClosed=True, color=poly_color, thickness=poly_thickness)
# 画该多段线内部填充
img_mask = cv2.fillPoly(img_mask, poly_points, color=poly_color) #填充的颜色为color=poly_color
# 写该多段线类别文字:图片,文字字符串,文字左上角坐标,字体,字体大小,颜色,字体粗细
img_bgr = cv2.putText(img_bgr, poly_label,
(x_mean + poly_labelstr['offset_x'], y_mean + poly_labelstr['offset_y']),
cv2.FONT_HERSHEY_SIMPLEX, poly_labelstr['font_size'], poly_color,
poly_labelstr['font_thickness'])
opacity = 0.8 # 透明度,越大越接近原图
img_bgr = cv2.addWeighted(img_bgr, opacity, img_mask, 1-opacity, 0)
# 可视化
plt.imshow(img_bgr[:,:,::-1]) # 将bgr通道转换成rgb通道
plt.show()
# 可视化多段线填充效果
# plt.imshow(img_mask[:, :, ::-1]) # 将bgr通道转换成rgb通道
# plt.show()
# 当前目录下保存可视化结果
cv2.imwrite('visualize1.jpg', img_bgr)
reference
【标注关键点检测数据集】 https://www.bilibili.com/video/BV19g4y1777q/?share_source=copy_web&vd_source=95705b32f23f70b32dfa1721628d5874