mosaic.py 5.9 KB
Newer Older
HypoX64's avatar
preview  
HypoX64 已提交
1 2 3 4
import cv2
import numpy as np
import os
import random
HypoX64's avatar
HypoX64 已提交
5
from .image_processing import resize,ch_one2three,mask_area
HypoX64's avatar
preview  
HypoX64 已提交
6

H
hypox64 已提交
7 8 9 10 11 12
def addmosaic(img,mask,opt):
    if opt.mosaic_mod == 'random':
        img = addmosaic_random(img,mask)
    elif opt.mosaic_size == 0:
        img = addmosaic_autosize(img, mask, opt.mosaic_mod)
    else:
H
hypox64 已提交
13
        img = addmosaic_base(img,mask,opt.mosaic_size,opt.output_size,model = opt.mosaic_mod)
H
hypox64 已提交
14
    return img
HypoX64's avatar
preview  
HypoX64 已提交
15

H
hypox64 已提交
16
def addmosaic_base(img,mask,n,out_size = 0,model = 'squa_avg',rect_rat = 1.6,feather=0,start_point=[0,0]):
H
hypox64 已提交
17 18 19 20 21 22 23
    '''
    img: input image
    mask: input mask
    n: mosaic size
    out_size: output size  0->original
    model : squa_avg squa_mid squa_random squa_avg_circle_edge rect_avg
    rect_rat: if model==rect_avg , mosaic w/h=rect_rat
H
hypox64 已提交
24 25
    feather : feather size, -1->no 0->auto
    start_point : [0,0], please not input this parameter
H
hypox64 已提交
26
    '''
H
hypox64 已提交
27
    n = int(n)
H
hypox64 已提交
28 29 30 31 32 33 34 35
    
    h_start = np.clip(start_point[0], 0, n)
    w_start = np.clip(start_point[1], 0, n)
    pix_mid_h = n//2+h_start
    pix_mid_w = n//2+w_start
    h, w = img.shape[:2]
    h_step = (h-h_start)//n
    w_step = (w-w_start)//n
HypoX64's avatar
preview  
HypoX64 已提交
36 37
    if out_size:
        img = resize(img,out_size)      
H
hypox64 已提交
38 39 40
    if mask.shape[0] != h:
        mask = cv2.resize(mask,(w,h))
    img_mosaic = img.copy()
HypoX64's avatar
preview  
HypoX64 已提交
41 42

    if model=='squa_avg':
H
hypox64 已提交
43 44 45 46 47
        for i in range(h_step):
            for j in range(w_step):
                if mask[i*n+pix_mid_h,j*n+pix_mid_w]:
                    img_mosaic[i*n+h_start:(i+1)*n+h_start,j*n+w_start:(j+1)*n+w_start,:]=\
                           img[i*n+h_start:(i+1)*n+h_start,j*n+w_start:(j+1)*n+w_start,:].mean(axis=(0,1))
HypoX64's avatar
preview  
HypoX64 已提交
48

H
hypox64 已提交
49
    elif model=='squa_mid':
H
hypox64 已提交
50 51 52 53 54
        for i in range(h_step):
            for j in range(w_step):
                if mask[i*n+pix_mid_h,j*n+pix_mid_w]:
                    img_mosaic[i*n+h_start:(i+1)*n+h_start,j*n+w_start:(j+1)*n+w_start,:]=\
                           img[i*n+n//2+h_start,j*n+n//2+w_start,:]
H
hypox64 已提交
55

HypoX64's avatar
preview  
HypoX64 已提交
56
    elif model == 'squa_random':
H
hypox64 已提交
57 58 59 60 61
        for i in range(h_step):
            for j in range(w_step):
                if mask[i*n+pix_mid_h,j*n+pix_mid_w]:
                    img_mosaic[i*n+h_start:(i+1)*n+h_start,j*n+w_start:(j+1)*n+w_start,:]=\
                    img[h_start+int(i*n-n/2+n*random.random()),w_start+int(j*n-n/2+n*random.random()),:]
HypoX64's avatar
preview  
HypoX64 已提交
62 63

    elif model == 'squa_avg_circle_edge':
H
hypox64 已提交
64 65 66 67
        for i in range(h_step):
            for j in range(w_step):
                img_mosaic[i*n+h_start:(i+1)*n+h_start,j*n+w_start:(j+1)*n+w_start,:]=\
                       img[i*n+h_start:(i+1)*n+h_start,j*n+w_start:(j+1)*n+w_start,:].mean(axis=(0,1))
HypoX64's avatar
HypoX64 已提交
68
        mask = cv2.threshold(mask,127,255,cv2.THRESH_BINARY)[1]
H
hypox64 已提交
69 70 71
        _mask = ch_one2three(mask)
        mask_inv = cv2.bitwise_not(_mask)
        imgroi1 = cv2.bitwise_and(_mask,img_mosaic)
HypoX64's avatar
preview  
HypoX64 已提交
72 73 74 75
        imgroi2 = cv2.bitwise_and(mask_inv,img)
        img_mosaic = cv2.add(imgroi1,imgroi2)

    elif model =='rect_avg':
H
hypox64 已提交
76 77 78 79 80 81 82 83 84
        n_h = n
        n_w = int(n*rect_rat)
        n_h_half = n_h//2+h_start
        n_w_half = n_w//2+w_start
        for i in range((h-h_start)//n_h):
            for j in range((w-w_start)//n_w):
                if mask[i*n_h+n_h_half,j*n_w+n_w_half]:
                    img_mosaic[i*n_h+h_start:(i+1)*n_h+h_start,j*n_w+w_start:(j+1)*n_w+w_start,:]=\
                           img[i*n_h+h_start:(i+1)*n_h+h_start,j*n_w+w_start:(j+1)*n_w+w_start,:].mean(axis=(0,1))
HypoX64's avatar
preview  
HypoX64 已提交
85
    
H
hypox64 已提交
86 87
    if feather != -1:
        if feather==0:
H
hypox64 已提交
88 89
            mask = (cv2.blur(mask, (n, n)))
        else:
H
hypox64 已提交
90 91 92 93
            mask = (cv2.blur(mask, (feather, feather)))
        mask = mask/255.0
        for i in range(3):img_mosaic[:,:,i] = (img[:,:,i]*(1-mask)+img_mosaic[:,:,i]*mask)
        img_mosaic = img_mosaic.astype(np.uint8)
H
hypox64 已提交
94
    
HypoX64's avatar
preview  
HypoX64 已提交
95 96
    return img_mosaic

H
hypox64 已提交
97 98
def get_autosize(img,mask,area_type = 'normal'):
    h,w = img.shape[:2]
H
hypox64 已提交
99 100 101
    size = np.min([h,w])
    mask = resize(mask,size)
    alpha = size/512
H
hypox64 已提交
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
    try:
        if area_type == 'normal':
            area = mask_area(mask)
        elif area_type == 'bounding':
            w,h = cv2.boundingRect(mask)[2:]
            area = w*h
    except:
        area = 0
    area = area/(alpha*alpha)
    if area>50000:
        size = alpha*((area-50000)/50000+12)
    elif 20000<area<=50000:
        size = alpha*((area-20000)/30000+8)
    elif 5000<area<=20000:
        size = alpha*((area-5000)/20000+7)
    elif 0<=area<=5000:
        size = alpha*((area-0)/5000+6)
    else:
        pass
    return size

H
hypox64 已提交
123 124 125 126 127
def get_random_parameter(img,mask):
    # mosaic size
    p = np.array([0.5,0.5])
    mod = np.random.choice(['normal','bounding'], p = p.ravel())
    mosaic_size = get_autosize(img,mask,area_type = mod)
H
hypox64 已提交
128
    mosaic_size = int(mosaic_size*random.uniform(0.9,2.5))
HypoX64's avatar
preview  
HypoX64 已提交
129

H
hypox64 已提交
130
    # mosaic mod
H
hypox64 已提交
131 132
    p = np.array([0.25, 0.3, 0.45])
    mod = np.random.choice(['squa_mid','squa_avg','rect_avg'], p = p.ravel())
H
hypox64 已提交
133 134 135 136

    # rect_rat for rect_avg
    rect_rat = random.uniform(1.1,1.6)
    
H
hypox64 已提交
137 138 139 140
    # feather size
    feather = -1
    if random.random()<0.7:
        feather = int(mosaic_size*random.uniform(0,1.5))
H
hypox64 已提交
141

H
hypox64 已提交
142
    return mosaic_size,mod,rect_rat,feather
H
hypox64 已提交
143 144 145 146 147


def addmosaic_autosize(img,mask,model,area_type = 'normal'):
    mosaic_size = get_autosize(img,mask,area_type = 'normal')
    img_mosaic = addmosaic_base(img,mask,mosaic_size,model = model)
HypoX64's avatar
preview  
HypoX64 已提交
148
    return img_mosaic
H
hypox64 已提交
149

H
hypox64 已提交
150
def addmosaic_random(img,mask):
H
hypox64 已提交
151 152 153 154 155 156 157 158 159 160 161 162 163 164
    mosaic_size,mod,rect_rat,feather = get_random_parameter(img,mask)
    img_mosaic = addmosaic_base(img,mask,mosaic_size,model = mod,rect_rat=rect_rat,feather=feather)
    return img_mosaic

def get_random_startpos(num,bisa_p,bisa_max,bisa_max_part):
    pos = np.zeros((num,2), dtype=np.int64)
    if random.random()<bisa_p:
        indexs = random.sample((np.linspace(1,num-1,num-1,dtype=np.int64)).tolist(), random.randint(1, bisa_max_part))
        indexs.append(0)
        indexs.append(num)
        indexs.sort()
        for i in range(len(indexs)-1):
            pos[indexs[i]:indexs[i+1]] = [random.randint(0,bisa_max),random.randint(0,bisa_max)]
    return pos