Major changes: - New frontend (platform/web/): Vite + React 18 + TypeScript + Tailwind - 4-module navigation: 数据送标 / 模型管理 / 车队管理 / 系统管理 - Data catalog with charts (DMS/ADAS/Lane 3-tab view) - Quality review workflow (标注质检): Good/Fine/Bad scoring with auto-advance - Audit enhancements: batch operations, rejection categories, Feishu notifications - Operation audit log (操作日志) - World model simulation studio (仿真工坊) - Dataset version management with snapshots and diff - ADAS 7-class dataset integration (138K images organized + compressed) - User management with Feishu integration and pagination - CRUD/search/filter on all pages, card layout redesign - PIL-optimized image overlay rendering - Auto-snapshot on build, in_review workflow stage - Removed embedded algorithm code (now in workspace)
188 lines
6.1 KiB
Python
Executable File
188 lines
6.1 KiB
Python
Executable File
import numbers
|
|
import random
|
|
import numpy as np
|
|
from PIL import Image, ImageOps, ImageFilter
|
|
#from config import cfg
|
|
import torch
|
|
import pdb
|
|
import cv2
|
|
|
|
# ===============================img tranforms============================
|
|
|
|
class Compose2(object):
|
|
def __init__(self, transforms):
|
|
self.transforms = transforms
|
|
|
|
def __call__(self, img, mask, bbx=None):
|
|
if bbx is None:
|
|
for t in self.transforms:
|
|
# print(t)
|
|
# print('\\: ', img.size, mask.size)
|
|
img, mask = t(img, mask)
|
|
# print('//: ', img.size, mask.size)
|
|
return img, mask
|
|
for t in self.transforms:
|
|
img, mask, bbx = t(img, mask, bbx)
|
|
return img, mask, bbx
|
|
|
|
class FreeScale(object):
|
|
def __init__(self, size):
|
|
self.size = size # (h, w)
|
|
|
|
def __call__(self, img, mask):
|
|
return img.resize((self.size[1], self.size[0]), Image.BILINEAR), mask.resize((self.size[1], self.size[0]), Image.NEAREST)
|
|
|
|
class FreeScaleMask(object):
|
|
def __init__(self,size):
|
|
self.size = size
|
|
def __call__(self,mask):
|
|
return mask.resize((self.size[1], self.size[0]), Image.NEAREST)
|
|
|
|
class Scale(object):
|
|
def __init__(self, size):
|
|
self.size = size
|
|
|
|
def __call__(self, img, mask):
|
|
# if img.size != mask.size:
|
|
# print(img.size)
|
|
# print(mask.size)
|
|
assert img.size == mask.size
|
|
w, h = img.size
|
|
if (w <= h and w == self.size) or (h <= w and h == self.size):
|
|
return img, mask
|
|
if w < h:
|
|
ow = self.size
|
|
oh = int(self.size * h / w)
|
|
return img.resize((ow, oh), Image.BILINEAR), mask.resize((ow, oh), Image.NEAREST)
|
|
else:
|
|
oh = self.size
|
|
ow = int(self.size * w / h)
|
|
return img.resize((ow, oh), Image.BILINEAR), mask.resize((ow, oh), Image.NEAREST)
|
|
|
|
|
|
class RandomRotate(object):
|
|
"""Crops the given PIL.Image at a random location to have a region of
|
|
the given size. size can be a tuple (target_height, target_width)
|
|
or an integer, in which case the target will be of a square shape (size, size)
|
|
"""
|
|
|
|
def __init__(self, angle):
|
|
self.angle = angle
|
|
|
|
def __call__(self, image, label):
|
|
# w, h = image.size
|
|
# if w != 1280 or h != 720:
|
|
# image = image.resize(image, (1280, 720))
|
|
# print(w, h)
|
|
assert label is None or image.size == label.size
|
|
|
|
angle = random.randint(0, self.angle * 2) - self.angle
|
|
|
|
label = label.rotate(angle, resample=Image.NEAREST)
|
|
image = image.rotate(angle, resample=Image.BILINEAR)
|
|
|
|
return image, label
|
|
|
|
|
|
|
|
# ===============================label tranforms============================
|
|
|
|
class DeNormalize(object):
|
|
def __init__(self, mean, std):
|
|
self.mean = mean
|
|
self.std = std
|
|
|
|
def __call__(self, tensor):
|
|
for t, m, s in zip(tensor, self.mean, self.std):
|
|
t.mul_(s).add_(m)
|
|
return tensor
|
|
|
|
|
|
class MaskToTensor(object):
|
|
def __call__(self, img):
|
|
return torch.from_numpy(np.array(img, dtype=np.int32)).long()
|
|
|
|
|
|
def find_start_pos(row_sample,start_line):
|
|
# row_sample = row_sample.sort()
|
|
# for i,r in enumerate(row_sample):
|
|
# if r >= start_line:
|
|
# return i
|
|
l,r = 0,len(row_sample)-1
|
|
while True:
|
|
mid = int((l+r)/2)
|
|
if r - l == 1:
|
|
return r
|
|
if row_sample[mid] < start_line:
|
|
l = mid
|
|
if row_sample[mid] > start_line:
|
|
r = mid
|
|
if row_sample[mid] == start_line:
|
|
return mid
|
|
|
|
class RandomLROffsetLABEL(object):
|
|
def __init__(self,max_offset):
|
|
self.max_offset = max_offset
|
|
def __call__(self,img,label):
|
|
offset = np.random.randint(-self.max_offset,self.max_offset)
|
|
w, h = img.size
|
|
# print('max_offset:', self.max_offset, 'ro_offset: ', offset)
|
|
img = np.array(img)
|
|
if offset > 0:
|
|
img[:,offset:,:] = img[:,0:w-offset,:]
|
|
img[:,:offset,:] = 0
|
|
if offset < 0:
|
|
real_offset = -offset
|
|
img[:,0:w-real_offset,:] = img[:,real_offset:,:]
|
|
img[:,w-real_offset:,:] = 0
|
|
|
|
label = np.array(label)
|
|
if offset > 0:
|
|
label[:,offset:] = label[:,0:w-offset]
|
|
label[:,:offset] = 0
|
|
if offset < 0:
|
|
offset = -offset
|
|
label[:,0:w-offset] = label[:,offset:]
|
|
label[:,w-offset:] = 0
|
|
return Image.fromarray(img),Image.fromarray(label)
|
|
|
|
class RandomUDoffsetLABEL(object):
|
|
def __init__(self,max_offset):
|
|
self.max_offset = max_offset
|
|
def __call__(self,img,label):
|
|
offset = np.random.randint(-self.max_offset,self.max_offset)
|
|
# offset = np.random.randint(0, self.max_offset)
|
|
# offset = 17
|
|
# print('max_offset:', self.max_offset, 'do_offset: ', offset)
|
|
w, h = img.size
|
|
# if w != 1280 or h != 720:
|
|
# img = img.resize(img, (1280, 720))
|
|
# print(w, h)
|
|
img = np.array(img)
|
|
if offset > 0:
|
|
# print('dim > 0:', h - offset, offset)
|
|
# print(img[offset:,:,:].shape, img[0:h-offset,:,:].shape)
|
|
img[offset:,:,:] = img[0:h-offset,:,:]
|
|
img[:offset,:,:] = 0
|
|
if offset < 0:
|
|
real_offset = -offset
|
|
# print('dim < 0:', h - real_offset, real_offset)
|
|
img[0:h-real_offset,:,:] = img[real_offset:,:,:]
|
|
img[h-real_offset:,:,:] = 0
|
|
|
|
label = np.array(label)
|
|
if offset > 0:
|
|
# print('dla > 0:', h - offset, offset)
|
|
# # print(label[0:h-offset,:].shape, label[offset:,:].shape)
|
|
# if label[0:h-offset,:].shape == label[offset:,:].shape:
|
|
label[offset:,:] = label[0:h-offset,:]
|
|
label[:offset,:] = 0
|
|
# else:
|
|
# print(label[0:h - offset, :].shape, label[offset:, :].shape, '/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/')
|
|
if offset < 0:
|
|
offset = -offset
|
|
# print('dla < 0:', h - offset, offset)
|
|
label[0:h-offset,:] = label[offset:,:]
|
|
label[h-offset:,:] = 0
|
|
return Image.fromarray(img),Image.fromarray(label)
|