(深度学习)yolo坐标形式数据的扩充、与普通图片坐标系的转换、在原图上绘制目标框

一、问题背景

        要使用yolo框架进行目标检测步骤如下:1、数据标注 ,生成对应的txt文档 2、对现有数据进行扩充,生成相应的txt文档 3、根据txt文档 在图片上绘制目标框 4、训练 。此文档主要解决前三个问题。

1、数据标注后生成的txt文档的格式如下:


 注:第一个数字代表目标类别 第2-5个数字代表 x_center(目标框中心位置的x坐标)/原本图片的宽度, y_center(目标框中心位置的y坐标)/原本图片的高度 width(目标框的宽度)/原本图片的宽度, height(目标框的高度)/原本图片的高度

 yolo以及其他图片的坐标形式参考此文档

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)

效果图:

猜你喜欢

转载自blog.csdn.net/MissLemonh/article/details/120641798