数据集增广 之 多个图片贴到一张图上,以及生成相应的json文件
                                                            生活随笔
收集整理的這篇文章主要介紹了
                                数据集增广 之 多个图片贴到一张图上,以及生成相应的json文件
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.                        
                                多圖合成一圖:
import os import tqdm import glob import json import math import random import numpy as np from pathlib import Path from PIL import Image, ImageDrawforesuffix = '_foreground.jpg' pseudosuffix = '_pseudo.jpg' jsonsuffix = '.jpg.json'# 旋轉(zhuǎn)圖片,沒有黑邊 def rotateImage(img):image = np.asarray(img)rotated = np.rot90(image) # 逆時針旋轉(zhuǎn)!'''# 通道特殊處理# Image 通道是 “RGB”# numpy 通道是 “BGR”r, g, b = rotated[:, :, 0], rotated[:, :, 1], rotated[:, :, 2]h, w = r.shapenew = np.zeros((h, w, 3))new[:, :, 0] = rnew[:, :, 1] = gnew[:, :, 2] = b'''newimage = Image.fromarray(np.uint8(rotated))return newimage# 規(guī)劃拼接區(qū)域 def splitArea(count, width, height):if count == 2:# 左右拼接if width >= height:########## A ########### B ##########w, h = width // 2, heightx1, y = w // 2, h // 2x2 = x1 * 3boxlist = [(x1, y, w, h), (x2, y, w, h)]# 上下拼接else:############## A # B ##############w, h = width, height//2x, y1 = w // 2, h // 2y2 = y1 * 3boxlist = [(x, y1, w, h), (x, y2, w, h)]elif count == 3:if width >= height:############## # B ## A ######## # C ##############w, h1, h2 = width // 2, height, height // 2x1, y1, y2 = w // 2, h1 // 2, h2 // 2x2 = x1 * 3y3 = y2 * 3boxlist = [(x1, y1, w, h1), (x2, y2, w, h2), (x2, y3, w, h2)]# 上下拼接else:############## A ############### B # C ##############w1, w2, h = width, width // 2, height // 2x1, x2, y1 = w1 // 2, w2 // 2, h // 2y2 = y1 * 3x3 = x2 * 3boxlist = [(x1, y1, w1, h), (x2, y2, w2, h), (x3, y2, w2, h)]elif count == 4:############## A # C ############### B # D ##############w, h = width//2, height//2x1, y1 = w // 2, h // 2x2, y2 = x1 * 3, y1 * 3boxlist = [(x1, y1, w, h), (x1, y2, w, h), (x2, y1, w, h), (x2, y2, w, h)]else:passreturn boxlist# 旋轉(zhuǎn)坐標點 def processPoints(pointList, boundingbox, lx, ly, fw, fh, w, h):pointlist = []offsetx, offsety = boundingbox[0], boundingbox[1]for point in pointList:# 把衣服框從原圖中摳出來x, y = point[0]-offsetx, point[1]-offsety# 旋轉(zhuǎn)"""點point1繞點point2旋轉(zhuǎn)angle后的點======================================在平面坐標上,任意點P(x1,y1),繞一個坐標點Q(x2,y2)旋轉(zhuǎn)θ角度后,新的坐標設(shè)為(x, y)的計算公式:x= (x1 - x2)*cos(θ) - (y1 - y2)*sin(θ) + y2 ;y= (x1 - x2)*sin(θ) + (y1 - y2)*cos(θ) + x2 ;======================================將圖像坐標(x,y)轉(zhuǎn)換到平面坐標(x`,y`):x`=xy`=height-y:param point1::param point2: base point (基點):param angle: 旋轉(zhuǎn)角度,正:表示逆時針,負:表示順時"""tfw, tfh = fw, fhif (w >= h and fw < fh) or (w < h and fw >= fh):x1, y1 = x, yrotx, roty = tfw // 2, tfh // 2# # 將圖像坐標轉(zhuǎn)換到平面坐標y1 = tfh - y1roty = tfh - roty# 逆時針x = (x1 - rotx) * math.cos(math.pi/2) - (y1 - roty) * math.sin(math.pi/2) + rotyy = (x1 - rotx) * math.sin(math.pi/2) + (y1 - roty) * math.cos(math.pi/2) + rotx# 旋轉(zhuǎn)之后,長寬對調(diào),將平面坐標轉(zhuǎn)換到圖像坐標tfw, tfh = tfh, tfwy = tfh - y# 縮放ratiox, ratioy = w / tfw, h / tfhx *= ratioxy *= ratioy# # 拼接到新圖的新區(qū)域x += lxy += lypointlist.append([int(x), int(y)])return pointlist# 拼接 def joint(baseimage, forelist, imagesavepath, savejsonpath=None, threshold=50, debug=False):# 獲取基底圖片尺寸base = Image.open(baseimage)if debug:print(f"baseimage mode is :{base.mode}")base.show()# 設(shè)置拼接坐標count = len(forelist)assert count >= 2, "ERROR: the count of foregrounds is not enough !"assert count <= 4, "ERROR: the count of foregrounds is too many !"width, height = base.sizeboxlist = splitArea(count, width, height)if savejsonpath is not None:# 拼接原圖,從基底圖片中截取一小部分進行放大,作為新的圖片的背景box=(0, 0, threshold, threshold)background = base.crop(box)background = background.resize((width, height))else:# 拼接pseudo 和 foreground,直接生成純黑背景background = Image.new("RGB", (width, height), "#000000")if debug:background.show()# 拼接前景圖片jsonlist = []for idx, (fore, box) in enumerate(zip(forelist, boxlist)):fimg = Image.open(fore)boundingbox = fimg.getbbox()fimg = fimg.crop(boundingbox)if debug:print(fore)fimg.show()# 獲取拼接區(qū)域cx, cy, w, h = boxfw, fh = fimg.sizeif (w >= h and fw < fh) or (w < h and fw >= fh):fimg = rotateImage(fimg)if debug:print(fore, "旋轉(zhuǎn)了")fimg.show()fimg = fimg.resize((w, h))if debug:fimg.show()# 獲取maskmask, _, _ = fimg.split()mask = np.array(mask)mask[mask > 10] = 255mask[mask <= 10] = 0mask = Image.fromarray(mask)# 拼接lx, ly = cx-w//2, cy-h//2rx, ry = cx+w//2, cy+h//2background.paste(fimg, (lx, ly, rx, ry), mask)# 修改該json文件if savejsonpath is not None:readpath = fore.replace(foresuffix, jsonsuffix)with open(readpath, 'r') as reader:jsonfile = json.load(reader)# 如果只有一件衣服的圖片中存在多個標注連通域,則警告if len(jsonfile) > 1 or len(jsonfile) == 0:with open('./runningLog.json', 'a') as writer:info = f"WARNING: {fore}\n"writer.write(info)# 遍歷每個標注區(qū)域for object in jsonfile:savejson = dict()savejson['name'] = object['name']savejson['color'] = object['color']savejson['labelIdx'] = idx + 1savejson['points'] = processPoints(object['points'], boundingbox, lx, ly, fw, fh, w, h)jsonlist.append(savejson)# 保存圖片及json文件background.save(imagesavepath)if len(jsonlist) > 0:with open(savejsonpath, 'w') as writer:json.dump(jsonlist, writer)if debug:background.show()if __name__ == '__main__':imageroot = './hx_clothes_1122/hx_clothes_imgs'maskroot = './hx_clothes_1122/hx_clothes_masks'idx = 0for _ in tqdm.tqdm(range(4)):imagelist = os.listdir(imageroot)while len(imagelist) > 1:idx += 1if len(imagelist) < 4:count = len(imagelist) # 如果剩余圖片不足4張,則都拼一塊else:count = random.randint(2, 4) # 隨機產(chǎn)生【2,4】閉區(qū)間上的一個整數(shù)forelist = []psedolist = []jsonlist = []imglist = []for i in range(count):img = random.choice(imagelist)imgpath = os.path.join(imageroot, img)imglist.append(imgpath)forename = img.replace('.jpg', foresuffix)forepath = os.path.join(maskroot, forename)forelist.append(forepath)pseudoname = img.replace('.jpg', pseudosuffix)pseudopath = os.path.join(maskroot, pseudoname)psedolist.append(pseudopath)jsonname = img.replace('.jpg', jsonsuffix)jsonpath = os.path.join(maskroot, jsonname)jsonlist.append(jsonpath)imagelist.remove(img)saveimagename = f"hx_clothes_1122/joint_images/aug_{idx}.jpg"savejsonname = f"hx_clothes_1122/joint_masks/aug_{idx}.jpg.json"saveforename = f"hx_clothes_1122/joint_masks/aug_{idx}_foreground.jpg"savepseudoname = f"hx_clothes_1122/joint_masks/aug_{idx}_pseudo.jpg"joint(imglist[0], forelist, saveimagename, savejsonname) # , debug=Truejoint(forelist[0], forelist, saveforename)joint(psedolist[0], psedolist, savepseudoname)with open('./runningLog.json', 'a') as writer:info = f"{json.dumps(imglist)}\n===> {str(idx)}\n\n"writer.write(info)# breakprint(f"\r剩余:{len(imagelist)}", end='', flush=True)# break總結(jié)
以上是生活随笔為你收集整理的数据集增广 之 多个图片贴到一张图上,以及生成相应的json文件的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 可视化COCO分割标注文件,以及单个js
- 下一篇: 二值mask图像 + RGB原图 生成可
