image_processing.py 7.3 KB
Newer Older
H
hypox64 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
import cv2
import numpy as np
import random

import platform
system_type = 'Linux'
if 'Windows' in platform.platform():
    system_type = 'Windows'

def imread(file_path,mod = 'normal'):
    '''
    mod = 'normal' | 'gray' | 'all'
    '''
    if system_type == 'Linux':
        if mod == 'normal':
            img = cv2.imread(file_path)
        elif mod == 'gray':
            img = cv2.imread(file_path,0)
        elif mod == 'all':
            img = cv2.imread(file_path,-1)
    
    #For chinese path, use cv2.imdecode in windows.
    #It will loss EXIF, I can't fix it
    else: 
        if mod == 'gray':
            img = cv2.imdecode(np.fromfile(file_path,dtype=np.uint8),0)
        else:
            img = cv2.imdecode(np.fromfile(file_path,dtype=np.uint8),-1)

    return img

def imwrite(file_path,img):
    '''
    in other to save chinese path images in windows,
    this fun just for save final output images
    '''
    if system_type == 'Linux':
        cv2.imwrite(file_path, img)
    else:
        cv2.imencode('.jpg', img)[1].tofile(file_path)

def resize(img,size,interpolation=cv2.INTER_LINEAR):
    '''
    INTER_NEAREST-  最近邻插值
    INTER_LINEAR-  双线性插值(默认使用)
    INTER_AREA-  使用像素面积关系进行重采样。这可能是首选的图像抽取方法,因为它可以提供无波纹的结果。但是,当图像放大时,它类似于INTER_NEAREST方法。
    INTER_CUBIC-  在4x4像素邻域上的双三次插值
    INTER_LANCZOS4-  在8x8像素邻域上的Lanczos插值
    当压缩一幅图像时,选择INTER_AREA算法实现效果较好;当放大一幅图像时,常常选择INTER_CUBIC,但是速度较慢,INTER_LINEAR响应较快,效果也相对较好。
        
    '''
    h, w = img.shape[:2]
    if np.min((w,h)) ==size:
        return img
    if w >= h:
        res = cv2.resize(img,(int(size*w/h), size),interpolation=interpolation)
    else:
        res = cv2.resize(img,(size, int(size*h/w)),interpolation=interpolation)
    return res

def resize_like(img,img_like):
    h, w = img_like.shape[:2]
    img = cv2.resize(img, (w,h))
    return img

def ch_one2three(img):
    #zeros = np.zeros(img.shape[:2], dtype = "uint8")
    # ret,thresh = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
    res = cv2.merge([img, img, img])
    return res

def color_adjust(img,alpha=1,beta=0,b=0,g=0,r=0,ran = False):
    '''
    g(x) = (1+α)g(x)+255*β, 
    g(x) = g(x[:+b*255,:+g*255,:+r*255])
    
    Args:
        img   : input image
        alpha : contrast
        beta  : brightness
        b     : blue hue
        g     : green hue
        r     : red hue
        ran   : if True, randomly generated color correction parameters
    Retuens:
        img   : output image
    '''
    img = img.astype('float')
    if ran:
        alpha = random.uniform(-0.2,0.2)
        beta  = random.uniform(-0.2,0.2)
        b     = random.uniform(-0.1,0.1)
        g     = random.uniform(-0.1,0.1)
        r     = random.uniform(-0.1,0.1)
    img = (1+alpha)*img+255.0*beta
    bgr = [b*255.0,g*255.0,r*255.0]
    for i in range(3): img[:,:,i]=img[:,:,i]+bgr[i]
    
    return (np.clip(img,0,255)).astype('uint8')

def makedataset(target_image,orgin_image):
    target_image = resize(target_image,256)
    orgin_image = resize(orgin_image,256)
    img = np.zeros((256,512,3), dtype = "uint8")
    w = orgin_image.shape[1]
    img[0:256,0:256] = target_image[0:256,int(w/2-256/2):int(w/2+256/2)]
    img[0:256,256:512] = orgin_image[0:256,int(w/2-256/2):int(w/2+256/2)]
    return img

def image2folat(img,ch):
    size=img.shape[0]
    if ch == 1:
        img = (img[:,:,0].reshape(1,size,size)/255.0).astype(np.float32)
    else:
        img = (img.transpose((2, 0, 1))/255.0).astype(np.float32)
    return img

def spiltimage(img,size = 128):
    h, w = img.shape[:2]
    # size = min(h,w)
    if w >= h:
        img1 = img[:,0:size]
        img2 = img[:,w-size:w]
    else:
        img1 = img[0:size,:]
        img2 = img[h-size:h,:]

    return img1,img2

def mergeimage(img1,img2,orgin_image,size = 128):
    h, w = orgin_image.shape[:2]
    new_img1 = np.zeros((h,w), dtype = "uint8")
    new_img2 = np.zeros((h,w), dtype = "uint8")

    # size = min(h,w)
    if w >= h:
        new_img1[:,0:size]=img1
        new_img2[:,w-size:w]=img2
    else:
        new_img1[0:size,:]=img1
        new_img2[h-size:h,:]=img2
    result_img = cv2.add(new_img1,new_img2)
    return result_img

def find_best_ROI(mask):
    contours,hierarchy=cv2.findContours(mask, cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
    if len(contours)>0:
        areas = []
        for contour in contours:
            areas.append(cv2.contourArea(contour))
        index = areas.index(max(areas))
        mask = np.zeros_like(mask)
        mask = cv2.fillPoly(mask,[contours[index]],(255))
    return mask

def boundingSquare(mask,Ex_mul):
    # thresh = mask_threshold(mask,10,threshold)
    area = mask_area(mask)
    if area == 0 :
        return 0,0,0,0

    x,y,w,h = cv2.boundingRect(mask)
    
    center = np.array([int(x+w/2),int(y+h/2)])
    size = max(w,h)
    point0=np.array([x,y])
    point1=np.array([x+size,y+size])

    h, w = mask.shape[:2]
    if size*Ex_mul > min(h, w):
        size = min(h, w)
        halfsize = int(min(h, w)/2)
    else:
        size = Ex_mul*size
        halfsize = int(size/2)
        size = halfsize*2
    point0 = center - halfsize
    point1 = center + halfsize
    if point0[0]<0:
        point0[0]=0
        point1[0]=size
    if point0[1]<0:
        point0[1]=0
        point1[1]=size
    if point1[0]>w:
        point1[0]=w
        point0[0]=w-size
    if point1[1]>h:
        point1[1]=h
        point0[1]=h-size
    center = ((point0+point1)/2).astype('int')
    return center[0],center[1],halfsize,area

def mask_threshold(mask,blur,threshold):
    mask = cv2.threshold(mask,threshold,255,cv2.THRESH_BINARY)[1]
    mask = cv2.blur(mask, (blur, blur))
    mask = cv2.threshold(mask,threshold/5,255,cv2.THRESH_BINARY)[1]
    return mask

def mask_area(mask):
    mask = cv2.threshold(mask,127,255,0)[1]
    # contours= cv2.findContours(mask,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)[1] #for opencv 3.4
    contours= cv2.findContours(mask,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)[0]#updata to opencv 4.0
    try:
        area = cv2.contourArea(contours[0])
    except:
        area = 0
    return area


def replace_mosaic(img_origin,img_fake,x,y,size,no_father):
    img_fake = resize(img_fake,size*2)
    if no_father:
        img_origin[y-size:y+size,x-size:x+size]=img_fake
        img_result = img_origin
    else:
        #color correction
        RGB_origin = img_origin[y-size:y+size,x-size:x+size].mean(0).mean(0)
        RGB_fake = img_fake.mean(0).mean(0)
        for i in range(3):img_fake[:,:,i] = np.clip(img_fake[:,:,i]+RGB_origin[i]-RGB_fake[i],0,255)      
        #eclosion
        eclosion_num = int(size/5)
        entad = int(eclosion_num/2+2)
        mask = np.zeros(img_origin.shape, dtype='uint8')
        mask = cv2.rectangle(mask,(x-size+entad,y-size+entad),(x+size-entad,y+size-entad),(255,255,255),-1)
        mask = (cv2.blur(mask, (eclosion_num, eclosion_num)))
        mask = mask/255.0

        img_tmp = np.zeros(img_origin.shape)
        img_tmp[y-size:y+size,x-size:x+size]=img_fake
        img_result = img_origin.copy()
        img_result = (img_origin*(1-mask)+img_tmp*mask).astype('uint8')
    return img_result