赞
踩
一、问题背景
要使用yolo框架进行目标检测步骤如下:1、数据标注 ,生成对应的txt文档 2、对现有数据进行扩充,生成相应的txt文档 3、根据txt文档 在图片上绘制目标框 4、训练 。此文档主要解决前三个问题。
1、数据标注后生成的txt文档的格式如下:
注:第一个数字代表目标类别 第2-5个数字代表 x_center(目标框中心位置的x坐标)/原本图片的宽度, y_center(目标框中心位置的y坐标)/原本图片的高度 , width(目标框的宽度)/原本图片的宽度, height(目标框的高度)/原本图片的高度 。
2、对现有数据扩充(对图片水平、垂直、水平垂直翻转 扩充三倍,具体见另一篇文档图片扩充
图片扩充完成之后需要生成对应的txt文档。也就是原txt文档中的第二个数字 和第三个数字需要发生变化,即目标框的中心位置。可由数学推理得出
水平翻转之后 现目标框的x=1-原目标框的x坐标 现目标框的y=原目标框y。
垂直翻转之后 现目标框的y=1-原目标框的y坐标 现目标框的x=原目标框x。
水平垂直翻转之后 现目标框的x=1-原目标框的x坐标,现目标框的y=1-原目标框的y坐标。
python代码为:(以水平垂直翻转举例,前两中稍加更改即可。
- import glob
- import os
- import copy
- from array import array
-
- def main():
- txt_path = 'E:/home/home/test/' #原txt文档
- txt_out_path = 'E:/ver_mir/' #水平垂直翻转后的txt
- if not os.path.exists(txt_out_path):
- os.mkdir(txt_out_path)
- filelist = os.listdir(txt_path)
- for file in filelist:
- f = open(txt_path + file, 'r') #以只读形式打开txt文档
- lines = f.readlines() #按行读取
- t = []
- out_txt_name = os.path.splitext(file)[0] #取.txt之前
- for i in lines:
- line_object = i.split(' ')
- #print(line_object)
- line_object[1] = float(1- float(line_object[1])) #新目标框 x的值
- line_object[2] = float(1-float(line_object[2]) ) #新目标框 y的值
- t.append(line_object)
- out_path = txt_out_path + out_txt_name + '_ver_mir.txt' #新保存入的txt文档
- with open(out_path, 'w') as f:
- for i in t:
- str_array = " ".join(map(str, i)) #将i转为str类型,并用空格连接
- print(str_array)
- f.write(str_array)
-
- if __name__ == '__main__':
- main()
运行之后生成的txt文档如下:
3、根据txt文档在原图片上绘制目标框。
绘制矩形框需要用到opencv 的是rectabgle函数。
- cv2.rectangle(image,(xmin,ymin),(xmax,ymax),(0,0,255),2) #image要画框的图片
- #(xmin,ymin)框的左上角坐标
- #(xmax,ymax)框的右下角坐标
- #(0,255,255)框的颜色
- #2 边框厚度
为了得到检测框的坐上以及右下的坐标,首先需要进行坐标的转换,详情见yolo坐标与普通坐标的转换具体参见这篇文章yolo坐标转换问题。为了方便我直接贴出图片。
目标转化以及绘制目标框的代码如下:
- #原始图片宽为 w,高为h,bounding box(xmin,ymin,xmax,ymax)
- #归一化后的图片:宽为w1,高为h1,中心点坐标为(x,y)
- #由归一化到原始图片:xmin=w*(x-w1/2) xmax=w*(x+w1/2) ymin=h*(y-h1/2) ymax=h*(y+h1/2)
-
- import os
- import cv2
- image_path='E:/new4' #图片路径
- txt_path ='E:/home/home/test' #txt文档路径
- image_out_path=r'E:\new4kuang' #绘制框之后的图片保存路径
- if not os.path.exists(image_out_path):
- os.mkdir(image_out_path)
-
- list = os.listdir(image_path) #返回指定路径下文件列表
- list2=os.listdir(txt_path)
-
- #print(list)
- for i in range(0,len(list)):
- out_image_name = os.path.splitext(list[i])[0]
- #读出原始图片的高 宽
- pathimage = os.path.join(image_path, list[i])
- #print(list[i])
- image=cv2.imread(pathimage)
- imginfo=image.shape
- h=imginfo[0]
- w=imginfo[1]
- print(h,w)
- imageNamelist='.jpg'
- #print(h)
- #txt文档操作
- pathtxt = os.path.join(txt_path, list2[i])
- #print(pathtxt)
- f = open(pathtxt, 'r')
- lines = f.readlines() #按行读取
-
- for i in lines:
- line_object = i.split(' ') #用空格分开
- x=float(line_object[1])
- y=float(line_object[2])
- w1=float(line_object[3])
- h1=float(line_object[4])
-
- print(x,y,w1,h1)
-
- #坐标系的转换
- xmin=int(w*(x-(w1/2.0)))
- ymin=int(h*(y-(h1/2.0)))
- xmax = int(w* (x + (w1 / 2.0)))
- ymax = int(h * (y + (h1 / 2.0)))
-
- ptLeftTop =(xmin,ymin)
- ptRightBottom = (xmax, ymax)
- point_color=(0,255,0)
- thickness = 1
- lineType = 4
- #cv2.rectangle(image,ptLeftTop,ptRightBottom,point_color,thickness,lineType)
- #ptLeftTop =(xmin,ymin)左上角
- #ptRightBottom=(xmax,ymax)右下角
- #point_color=(0,255,0)绿色 (0,0,255)红色
- #thickness=1
- #lineType=4
- if (float(line_object[0])==0):
- point_color = (0, 0, 255) #蓝色
- elif (float(line_object[0])==1):
- point_color = (0, 255, 0) #绿色
- elif (float(line_object[0])==2):
- point_color = (0, 255, 255) #青色
- elif (float(line_object[0])==3):
- point_color = (255, 255, 0) #红色
- else:
- point_color = (200, 10, 10) #白色
-
- cv2.rectangle(image, ptLeftTop,ptRightBottom, point_color,1,4)
-
- #cv2.imshow('AlanWang', image)
- #cv2.waitKey(1000) # 显示 10000 ms 即 10s 后消失
- #cv2.destroyAllWindows()
- path_out = os.path.join(image_out_path, out_image_name+'.jpg')
- print(path_out)
- cv2.imwrite(path_out,image)
-
效果图:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。