使用OpenCV合成训练图片,同时生成labelme兼容格式的标注文件

Posted henreash

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用OpenCV合成训练图片,同时生成labelme兼容格式的标注文件相关的知识,希望对你有一定的参考价值。

 思路很简单,加载背景图片,加载目标图片,随机抽取N个目标图像,将目标图像的像素copy到背景图片上,拷贝的位置可根据要求指定;同时合成标注json文件。代码如下:

# coding=utf-8

from cv2 import cv2
import os
import numpy as np
import random

from gen_ann_json import AnnotationsJson

XXX_WIDTH = 48
XXX_HEIGHT = 72

#加载源图像,多个,随机抽取后复制到背景图像上
def load_src_images():
    path = './src_img'
    files = os.listdir(path)
    xxxs = []
    for f in files:
        if '000' in f:
            continue
        if os.path.isdir(f):
            continue
        img_file = os.path.join(path, f)
        xxx = cv2.imread(img_file)
        xxx = cv2.resize(xxx,(XXX_WIDTH, XXX_HEIGHT))
        xxxs.append(xxx)
    return xxxs

#图像混合(将src拷贝到dst上,位置:x、y)
def img_mix(dst, src, x, y):
    output = dst.copy()
    output[y:y + src.shape[0], x:x + src.shape[1]] = src
    return output

#功能同上,多了一次90°旋转操作
def img_mix_horv(dst, src, x, y):
    #transposedImage = cv2.transpose(src)
    transposedImage=np.rot90(src)
    output = img_mix(dst, transposedImage, x, y)
    return output

#合成一个大的子区域,上面copy多个src图像,最后在将子区域拷贝到背景上
def mix_xxx_region(offset_x, offset_y, show_region_img, xxxs):
    fixed_xxx_regions = [[85, 12], [138, 12], [208, 12], [261, 12]]
    random.shuffle(xxxs)#将样本打乱,抽取前4--6个
    outputImg = show_region_img.copy()
    pointsArr = []
    for i in range(4):
        xxx = xxxs[i]
        x, y = fixed_xxx_regions[i][0], fixed_xxx_regions[i][1]
        outputImg = img_mix(outputImg, xxx, x, y)
        pointsArr.append([[offset_x + x, offset_y + y], [offset_x + x + XXX_WIDTH, offset_y + y + XXX_HEIGHT]])
    if random.random() > 0.5:
        outputImg = img_mix_horv(outputImg, xxxs[4], 9, 35)
        pointsArr.append([[offset_x+9, offset_y+35], [offset_x+9 + XXX_HEIGHT, offset_y+35 + XXX_WIDTH]])
    if random.random() > 0.5:
        outputImg= img_mix_horv(outputImg, xxxs[5], 314, 35)
        pointsArr.append([[offset_x+314, offset_y+35], [offset_x+314 + XXX_HEIGHT, offset_y+35 + XXX_WIDTH]])   
    return outputImg, pointsArr

#保存json格式的标注文件
def saveJsonFile(jpgFileName, jsonFileName, pointsArr):
    annObj = AnnotationsJson(jpgFileName, 811, 833)
    for points in pointsArr:
        annObj.AppendLabel("xxx", points)
    annObj.SaveToJsonFile(jsonFileName)

#合成图片
def mix_image(dst, show_region_img, xxxs):
    #6个子区域所在位置
    show_region_pos_list = [[2, 157],[2, 435],[2, 713],[410, 157],[410, 435],[410, 713]]
    output = dst.copy()
    pointsArr = []
    subRegion = [0,1,2,3,4,5]
    random.shuffle(subRegion)#将位置打散,选取前4个
    for i in range(4):
        index = subRegion[i]
        x = show_region_pos_list[index][0]
        y = show_region_pos_list[index][1]
        #先将随机的牌复制到显示区域
        xxx_region, pointsArr2 = mix_xxx_region(x, y, show_region_img, xxxs)
        pointsArr.extend(pointsArr2)
        #再将显示区域复制到桌位面板上
        output = img_mix(output, xxx_region, x, y)
    return output, pointsArr

xxxs = load_xxx_images()
dst = cv2.imread('./back1.jpg')
show_region_img = cv2.imread('./show_region.jpg')
for i in range(1, 1001):
    output, pointsArr = mix_image(dst, show_region_img, xxxs)
    cv2.imwrite('./images_ann/.jpg'.format(i), output)
    saveJsonFile('.jpg'.format(i), './images_ann/.json'.format(i), pointsArr)

生成json标注文件代码:

import json

class AnnotationsJson(object):
    def __init__(self, imagePath, imgWidht, imgHeight):
        self.version = "3.16.7"
        self.flags = ,
        self.shapes = []
        self.fillColor = [255,0,0,128]
        self.lineColor = [0, 255, 0, 128]
        self.imagePath = imagePath
        self.imageData = None
        self.imageHeight = imgHeight
        self.imageWidth = imgWidht
    
    def AppendLabel(self, label, points):
        self.shapes.append("label":label, "line_color":None, "fill_color":None, "points":points, "shape_type":"rectangle", "flag":)

    def ToJson(self):
        outObj = "version": self.version, "flags": , "shapes":[],   "fillColor": self.fillColor,"lineColor":self.lineColor, 
                  "imagePath":self.imagePath, "imageData":None, "imageHeight":self.imageHeight, "imageWidth":self.imageWidth
        for shape in self.shapes:
            outObj["shapes"].append("label":shape["label"], "line_color":None, "fill_color":None, 
                                     "points":shape["points"], "shape_type":"rectangle", "flags":)
        res = json.dumps(outObj)
        return res

    def SaveToJsonFile(self, filename):
        jsonString = self.ToJson()
        with open(filename, "w") as f:
            f.write(jsonString)

if __name__ == "__main__":
    annObj = AnnotationsJson("1.jpg", 811, 833)
    annObj.AppendLabel("xxx", [[11,22], [33,44]])
    print(annObj.ToJson())
    annObj.SaveToJsonFile("1.json")

合成几千张图片后,即可使用unet等网络进行训练、验证。

以上是关于使用OpenCV合成训练图片,同时生成labelme兼容格式的标注文件的主要内容,如果未能解决你的问题,请参考以下文章

MMsegmentation训练自己的voc数据集

labelme生成的.json文件批量转化为label图片

Detectron2 maskRCNN训练自己的数据集

MOT20数据集转VOC和Labelme标注的数据集,以及YoloV5的数据集。

labelme使用labelme2voc.py忽略部分标签生成VOC/coco类型数据集(Ignore a label in json file)

paddledet 训练旋转目标检测 ppyoloe-r 训练自己的数据集