|
import cv2 |
|
from matplotlib import pyplot as plt |
|
import numpy as np |
|
import torch |
|
from PIL import Image, ImageDraw, ImageFont |
|
from datetime import datetime |
|
import os |
|
from typing import List, Dict |
|
|
|
def convert_and_resize_mask(mask): |
|
|
|
print("mask ",mask) |
|
|
|
if mask.ndim == 3: |
|
mask = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY) |
|
resized_mask = cv2.resize(mask, (1024, 1024)) |
|
return resized_mask |
|
|
|
def add_masks_resized(masks): |
|
final_mask = np.zeros((1024, 1024), dtype=np.uint8) |
|
for mask in masks: |
|
if mask is not None: |
|
resized_mask = convert_and_resize_mask(mask) |
|
resized_mask = resized_mask.astype(np.uint8) |
|
final_mask = cv2.add(final_mask, resized_mask) |
|
return final_mask |
|
|
|
def attend_mask(mask_file, attend_scale=10, save=False): |
|
if isinstance(mask_file, str): |
|
if mask_file == '': |
|
return torch.zeros([1, 1, 128, 128], dtype=torch.float32).cuda() |
|
else: |
|
image_with_mask = cv2.imread(mask_file, cv2.IMREAD_GRAYSCALE) |
|
elif len(mask_file.shape) == 3: |
|
image_with_mask = cv2.cvtColor(mask_file, cv2.COLOR_BGR2GRAY) |
|
|
|
else: |
|
image_with_mask = mask_file |
|
|
|
if attend_scale != 0: |
|
kernel = np.ones((abs(attend_scale), abs(attend_scale)), np.uint8) |
|
if attend_scale > 0: |
|
image_with_mask = cv2.dilate(image_with_mask, kernel, iterations=1) |
|
else: |
|
image_with_mask = cv2.erode(image_with_mask, kernel, iterations=1) |
|
|
|
if save and isinstance(mask_file, str): |
|
new_mask_file_name = mask_file[:-4]+'_'+str(attend_scale)+'.jpg' |
|
cv2.imwrite(new_mask_file_name, image_with_mask) |
|
print("new_mask is saved in ", new_mask_file_name) |
|
|
|
dilated_image= cv2.resize(image_with_mask, (128, 128), interpolation=cv2.INTER_NEAREST) |
|
dilated_image = torch.from_numpy(dilated_image).to(torch.float32).unsqueeze(0).unsqueeze(0).cuda() / 255 |
|
return dilated_image |
|
|
|
|
|
def panning(img_path=None, op_list=[['left', 0.2]], save=False, save_dir=None): |
|
if isinstance(img_path, str): |
|
img = cv2.imread(img_path) |
|
else: |
|
img = img_path |
|
img_new = img.copy() |
|
img_height, img_width, _ = img.shape |
|
w_mask = 255 * np.ones((img_height, img_width), dtype=np.uint8) |
|
h_mask = 255 * np.ones((img_height, img_width), dtype=np.uint8) |
|
|
|
for op in op_list: |
|
scale = op[1] |
|
if op[0] in ['right', 'left']: |
|
K = int(scale*img_width) |
|
elif op[0] in ['up', 'down']: |
|
K = int(scale*img_height) |
|
|
|
if op[0] == 'right': |
|
img_new[:, K:, :] = img[:, 0:img_width-K, :] |
|
w_mask[:, K:] = 0 |
|
elif op[0] == 'left': |
|
img_new[:, 0:img_width-K, :] = img[:, K:, :] |
|
w_mask[:, 0:img_width-K] = 0 |
|
elif op[0] == 'down': |
|
img_new[K:, :, :] = img[0:img_height-K, :, :] |
|
h_mask[K:, :] = 0 |
|
elif op[0] == 'up': |
|
img_new[0:img_height-K, :, :] = img[K:, :, :] |
|
h_mask[0:img_height-K, :] = 0 |
|
img = img_new |
|
|
|
mask = w_mask + h_mask |
|
mask[mask>0] = 255 |
|
|
|
if save: |
|
if save_dir is None: |
|
base_dir = os.path.dirname(img_path) |
|
save_dir = os.path.join(base_dir, 'preprocess') |
|
elif not os.path.exists(save_dir): |
|
os.makedirs(save_dir) |
|
resized_img_name = f"{save_dir}/resized_image.png" |
|
resized_mask_name = f"{save_dir}/resized_mask.png" |
|
cv2.imwrite(resized_img_name, img_new) |
|
cv2.imwrite(resized_mask_name, mask) |
|
return resized_img_name, resized_mask_name |
|
else: |
|
return img_new, mask |
|
|
|
def zooming(img_path=None, scale=[0.8, 0.8], save=False, save_dir=None): |
|
if isinstance(img_path, str): |
|
img = cv2.imread(img_path) |
|
else: |
|
img = img_path |
|
img_new = img.copy() |
|
img_height, img_width, _ = img.shape |
|
mask = 255 * np.ones((img_height, img_width), dtype=np.uint8) |
|
|
|
new_height = int(img_height*scale[0]) |
|
new_width = int(img_width*scale[1]) |
|
resized_img = cv2.resize(img, (new_width, new_height), interpolation=cv2.INTER_AREA) |
|
x_offset = (img_width - new_width) // 2 |
|
y_offset = (img_height - new_height) // 2 |
|
|
|
img_new[y_offset:y_offset + new_height, x_offset:x_offset + new_width] = resized_img |
|
mask[y_offset:y_offset + new_height, x_offset:x_offset + new_width] = 0 |
|
|
|
if save: |
|
if save_dir is None: |
|
base_dir = os.path.dirname(img_path) |
|
save_dir = os.path.join(base_dir, 'preprocess') |
|
elif not os.path.exists(save_dir): |
|
os.makedirs(save_dir) |
|
|
|
resized_img_name = f"{save_dir}/resized_image.png" |
|
resized_mask_name = f"{save_dir}/resized_mask.png" |
|
cv2.imwrite(resized_img_name, img_new) |
|
cv2.imwrite(resized_mask_name, mask) |
|
return resized_img_name, resized_mask_name |
|
else: |
|
return img_new, mask |
|
|
|
def get_box(mask, bias = 2): |
|
nonzero_indices = torch.nonzero(mask) |
|
H, W = mask.shape[-2:] |
|
min_x = max(min(nonzero_indices[:, 1]) - bias, 0) |
|
min_y = max(min(nonzero_indices[:, 0]) - bias, 0) |
|
max_x = min(max(nonzero_indices[:, 1]) + bias, W) |
|
max_y = min(max(nonzero_indices[:, 0]) + bias, H) |
|
return (min_x, min_y, max_x, max_y) |
|
|
|
|
|
def draw_axis(img,grid_dict,x_len,y_len): |
|
if grid_dict is not None and grid_dict is not False: |
|
assert isinstance(grid_dict,Dict) |
|
assert "x_title" in grid_dict |
|
assert "y_title" in grid_dict |
|
assert "x_text_list" in grid_dict |
|
assert "y_text_list" in grid_dict |
|
x_title=grid_dict["x_title"] |
|
y_title=grid_dict["y_title"] |
|
x_text_list=grid_dict['x_text_list'] |
|
y_text_list=grid_dict['y_text_list'] |
|
assert len(y_text_list)==y_len |
|
assert len(x_text_list)==x_len |
|
assert "font_size" in grid_dict |
|
font_size=grid_dict["font_size"] |
|
if "x_color" in grid_dict: |
|
color_x=grid_dict['x_color'] |
|
else: |
|
color_x="black" |
|
if "y_color" in grid_dict: |
|
color_y=grid_dict['y_color'] |
|
else: |
|
color_y="black" |
|
if "num_decimals" in grid_dict: |
|
num_decimals=grid_dict['num_decimals'] |
|
else: |
|
num_decimals=2 |
|
if "shift_x" in grid_dict: |
|
shift_x_x,shift_x_y=grid_dict['shift_x'] |
|
else: |
|
shift_x_x=shift_x_y=0 |
|
if "shift_y" in grid_dict: |
|
shift_y_x,shift_y_y=grid_dict['shift_y'] |
|
else: |
|
shift_y_x=shift_y_y=0 |
|
if "title" in grid_dict: |
|
title=grid_dict['title'] |
|
if isinstance(title,List): |
|
all_title="" |
|
for s in title: |
|
all_title=all_title+s+"\n" |
|
title=all_title |
|
else: |
|
title='' |
|
width, height = img.size |
|
num_x=x_len |
|
num_y=y_len |
|
|
|
new_img = Image.new("RGB", (width + width // num_x+width // (num_x*2), height + height // num_y+height // (num_y*2)), color=(255, 255, 255)) |
|
width,height=(width + width // num_x, height + height // num_y) |
|
num_x=num_x+1 |
|
num_y=num_y+1 |
|
new_img.paste(img, (width // num_x, height // num_y)) |
|
|
|
draw = ImageDraw.Draw(new_img) |
|
|
|
font = ImageFont.truetype("DejaVuSansMono.ttf", font_size) |
|
for i in range(2, num_x+1): |
|
x = (i - 1) * width // num_x + width // (num_x * 2)-width *0.2// num_x+shift_x_x |
|
y = height // (num_y * 2)+shift_x_y |
|
k=i-1 |
|
if isinstance(x_text_list[i-2],str): |
|
draw.text((x, y), x_text_list[i-2], font=font,fill=color_x,align="center") |
|
else: |
|
draw.text((x, y), "{:.{}f}".format(x_text_list[i-2],num_decimals), font=font,fill=color_x,align="center") |
|
|
|
for i in range(2, num_y+1): |
|
x = width // (num_x * 2)-width *0.1// num_x+shift_y_x |
|
y = (i - 1) * height // num_y + height // (num_y * 2)-height*0.1//num_y+shift_y_y |
|
k = i - 1 |
|
if isinstance(y_text_list[i-2],str): |
|
draw.text((x, y), y_text_list[i-2], font=font,fill=color_y,align="center") |
|
else: |
|
draw.text((x, y), "{:.{}f}".format(y_text_list[i-2],num_decimals), font=font,fill=color_y,align="center") |
|
i=1 |
|
x = (i - 1) * width // num_x + width // (num_x * 2)-height*0.1//num_y+shift_y_x |
|
y = height // (num_y * 2)+width *0.2// num_x+shift_y_y |
|
draw.text((x, y), y_title, font=font, fill=color_y,align="center") |
|
x = width // (num_x * 2)+width *0.2// num_x+shift_x_x |
|
y = (i - 1) * height // num_y + height // (num_y * 2)+shift_x_y |
|
draw.text((x, y), x_title, font=font, fill=color_x,align="left") |
|
x = width // 4 |
|
y = (i - 1) * height // num_y + height // (num_y * 10) |
|
draw.text((x, y), title, font=font, fill='blue',align="left") |
|
else: |
|
|
|
new_img=img |
|
return new_img |
|
|
|
def view_images(images, num_rows=1, offset_ratio=0.02,text="",folder=None,Notimestamp=False, |
|
grid_dict=None,subfolder=None,verbose=True,output_dir=None,timestamp=None,**kwargs): |
|
if type(images) is list: |
|
num_empty = len(images) % num_rows |
|
elif images.ndim == 4: |
|
num_empty = images.shape[0] % num_rows |
|
else: |
|
images = [images] |
|
num_empty = 0 |
|
origin_size=kwargs.get("origin_size",None) |
|
images_copy=images.copy() |
|
for i, per_image in enumerate(images_copy): |
|
if isinstance(per_image, Image.Image) and origin_size is not None: |
|
images[i] = np.array(per_image.resize((origin_size[1],origin_size[0]))) |
|
else: |
|
images[i] = np.array(per_image) |
|
|
|
empty_images = np.ones(images[0].shape, dtype=np.uint8) * 255 |
|
images = [image.astype(np.uint8) for image in images] + [empty_images] * num_empty |
|
num_items = len(images) |
|
|
|
h, w, c = images[0].shape |
|
offset = int(h * offset_ratio) |
|
num_cols = num_items // num_rows |
|
image_ = np.ones((h * num_rows + offset * (num_rows - 1), |
|
w * num_cols + offset * (num_cols - 1), 3), dtype=np.uint8) * 255 |
|
for i in range(num_rows): |
|
for j in range(num_cols): |
|
image_[i * (h + offset): i * (h + offset) + h:, j * (w + offset): j * (w + offset) + w] = images[ |
|
i * num_cols + j] |
|
|
|
pil_img = Image.fromarray(image_) |
|
|
|
pil_img_=draw_axis(pil_img,grid_dict,num_cols,num_rows) |
|
if pil_img_.size[0]==pil_img_.size[1]: |
|
pil_img_.resize((2048,2048)) |
|
else: |
|
longer_side = max(pil_img.size) |
|
ratio = 2048/longer_side |
|
new_size = tuple([int(x*ratio) for x in pil_img.size]) |
|
pil_img = pil_img.resize(new_size) |
|
|
|
if verbose is False: |
|
return pil_img |
|
now = datetime.now() |
|
if timestamp is None: |
|
if Notimestamp is False: |
|
timestamp = now.strftime("%Y-%m-%d_%H-%M-%S") |
|
else: |
|
timestamp="" |
|
if output_dir is None: |
|
if timestamp != "": |
|
date, time = timestamp.split('_') |
|
else: |
|
date, time = "","" |
|
if folder is not None: |
|
dirname="./"+folder |
|
filename = text+f"img_{timestamp}.jpg" |
|
else: |
|
if subfolder is not None: |
|
dirname=os.path.join("./img", subfolder,date) |
|
dirname=os.path.join(dirname,time) |
|
filename =text+f"img_{timestamp}.jpg" |
|
else: |
|
dirname=os.path.join("./img",date) |
|
dirname=os.path.join(dirname,time) |
|
filename =text+f"img_{timestamp}.jpg" |
|
else: |
|
dirname=output_dir |
|
filename =text+f"img_{timestamp}.jpg" |
|
if not os.path.exists(dirname): |
|
os.makedirs(dirname) |
|
if verbose is True: |
|
for i, img in enumerate(images): |
|
im = Image.fromarray(img) |
|
im.save(os.path.join(dirname,f"{i}.jpg")) |
|
print(f"Output dir: {dirname}") |
|
pil_img.save(os.path.join(dirname, filename)) |
|
if grid_dict is not None and grid_dict is not False: |
|
if not os.path.exists(dirname): |
|
os.makedirs(dirname) |
|
pil_img_.save(os.path.join(dirname, filename[:-4]+"_2048x.jpg")) |
|
|
|
def resize_image_with_mask(img, mask, scale): |
|
if scale == 1: |
|
return img, mask, None |
|
img_blackboard = img.copy() |
|
mask_blackboard = np.zeros_like(mask) |
|
|
|
M = cv2.moments(mask) |
|
cx = int(M["m10"] / M["m00"]) |
|
cy = int(M["m01"] / M["m00"]) |
|
|
|
scale_factor = [scale, scale] |
|
resized_img = cv2.resize(img, None, fx=scale_factor[0], fy=scale_factor[1], interpolation=cv2.INTER_AREA) |
|
resized_mask = cv2.resize(mask, None, fx=scale_factor[0], fy=scale_factor[1], interpolation=cv2.INTER_AREA) |
|
new_cx, new_cy = cx * scale_factor[0], cy * scale_factor[1] |
|
|
|
for y in range(resized_mask.shape[0]): |
|
for x in range(resized_mask.shape[1]): |
|
if 0 <= cy - (new_cy - y) < img.shape[0] and 0 <= cx - (new_cx - x) < img.shape[1]: |
|
mask_blackboard[int(cy - (new_cy - y)), int(cx - (new_cx - x))] = resized_mask[y, x] |
|
img_blackboard[int(cy - (new_cy - y)), int(cx - (new_cx - x))] = resized_img[y, x] |
|
return img_blackboard, mask_blackboard, (cx, cy) |
|
|
|
def flip_image_with_mask(img, mask, flip_code=None): |
|
if flip_code is None: |
|
return img, mask, None |
|
M = cv2.moments(mask) |
|
if M["m00"] == 0: |
|
return img, mask |
|
cx = int(M["m10"] / M["m00"]) |
|
cy = int(M["m01"] / M["m00"]) |
|
|
|
h, w = img.shape[:2] |
|
img_center = (w // 2, h // 2) |
|
|
|
tx = img_center[0] - cx |
|
ty = img_center[1] - cy |
|
|
|
M_translate = np.float32([[1, 0, tx], [0, 1, ty]]) |
|
img_translated = cv2.warpAffine(img, M_translate, (w, h)) |
|
mask_translated = cv2.warpAffine(mask, M_translate, (w, h)) |
|
flipped_img = cv2.flip(img_translated, flip_code) |
|
flipped_mask = cv2.flip(mask_translated, flip_code) |
|
M_translate_back = np.float32([[1, 0, -tx], [0, 1, -ty]]) |
|
flipped_img_back = cv2.warpAffine(flipped_img, M_translate_back, (w, h)) |
|
flipped_mask_back = cv2.warpAffine(flipped_mask, M_translate_back, (w, h)) |
|
|
|
return flipped_img_back, flipped_mask_back, (cx, cy) |
|
|