这是一个私人备忘录,目的是流程规范。给定一批不一定为方形的图片及其标签(alpha),裁剪填充成方形。
将图像缩放至标签尺寸,并根据图像宽高将样本分成三类:方形图片,高瘦图片(高>宽),矮胖图片(高<宽)。
裁剪过程要完整裁剪出主体,对于不能完整裁剪出主体的图片就不裁剪,而是选择填充(pad)。填充函数中[-h:, :w, :]
是根据具体图像内容设置的
import cv2
import numpy as np
import os
import random
import shutil
from pathlib import Path
def batch_opencv_resize_as(raw_folder, refence_folder, save_folder):
os.makedirs(save_folder, exist_ok = True)
for file in os.listdir(refence_folder):
afa = cv2.imread(refence_folder + file , 1)
if Path(raw_folder + file).is_file():
img = cv2.imread(raw_folder + file)
else:
img = cv2.imread(raw_folder + file.strip("jpg")+ "png")
if img.shape == afa.shape:
shutil.copy(raw_folder + file, save_folder)
else:
h, w, c = afa.shape
img = cv2.resize(img, (w, h), interpolation=cv2.INTER_AREA)
cv2.imwrite(save_folder + file, img)
def pad(raw_img, raw_afa):
h, w = raw_afa.shape
maxside = max(h,w)
padimg = np.ones((maxside, maxside, 3)) * 127
padafa = np.zeros((maxside, maxside))
padimg[-h:, :w, :] = raw_img
padafa[-h:, :w] = raw_afa
return padimg, padafa
def crop_or_pad_by_alpha(img, alpha):
h, w = img.shape[0], img.shape[1]
alpah_temp = np.copy(alpha).astype(np.uint8)
a = np.where(alpah_temp > 30)
if np.max(alpha) <= 30: # nobody img, center crop
crop_x0 = 0
crop_x1 = w
crop_y0 = (h-w)//2
crop_y1 = crop_y0 + w
out_img = img[crop_y0:crop_y1, crop_x0:crop_x1, :]
out_afa = alpha[crop_y0:crop_y1, crop_x0:crop_x1]
return out_img, out_afa
if w > h:
x0 = min(a[1])
x1 = max(a[1])
portrait_w = x1 - x0
if not portrait_w > h:
crop_size = h
crop_y0 = 0
crop_y1 = h
crop_x0 = x0 - random.randint(0, (crop_size - portrait_w))
crop_x1 = crop_x0 + crop_size
if crop_x0 < 0 :
crop_x0 = 0
crop_x1 = crop_size
if crop_x1 > w:
crop_x1 = w
crop_x0 = w - crop_size
out_img = img[crop_y0:crop_y1, crop_x0:crop_x1, :]
out_afa = alpha[crop_y0:crop_y1, crop_x0:crop_x1]
else:
out_img, out_afa = pad(img, alpha)
else: # w < h
y0 = min(a[0])
y1 = max(a[0])
portrait_h = y1 - y0
if portrait_h < w:
crop_size = w
crop_x0 = 0
crop_x1 = w
crop_y0 = y0 - random.randint(0, (crop_size - portrait_h))
crop_y1 = crop_y0 + crop_size
if crop_y0 < 0:
crop_y0 = 0
crop_y1 = crop_size
if crop_y1 > h:
crop_y1 = h
crop_y0 = h - crop_size
out_img = img[crop_y0:crop_y1, crop_x0:crop_x1, :]
out_afa = alpha[crop_y0:crop_y1, crop_x0:crop_x1]
else:
out_img, out_afa = pad(img, alpha)
return out_img, out_afa
def batch_crop_or_pad(raw_img_folder, raw_afa_folder, save_root):
save_img_folder = save_root + "./imgs/"
save_afa_folder = save_root + "./afas/"
os.makedirs(save_img_folder, exist_ok = True)
os.makedirs(save_afa_folder, exist_ok = True)
for file in os.listdir(raw_afa_folder):
afa = cv2.imread(raw_afa_folder+file, 0)
h, w = afa.shape
if h == w:
shutil.copy(raw_img_folder + file, save_img_folder + "./imgs/")
shutil.copy(raw_afa_folder + file, save_afa_folder + "./afas/")
else:
img = cv2.imread(raw_img_folder + file, 1)
cropad_img, cropad_afa = crop_or_pad_by_alpha(img,afa)
cv2.imwrite(save_img_folder + file, cropad_img)
cv2.imwrite(save_afa_folder + file, cropad_afa)
batch_crop_or_pad("./imgs/", "./afas/", "./cropad/")
对于不能完整裁剪出主体的,如果不想要padding,而是使用中心裁剪或靠上裁剪(优先中心裁剪,把头也裁掉的就用靠上裁剪),则更改为:
import cv2
import numpy as np
import os
import random
import shutil
def center_crop(img, afa):
h, w, c = img.shape
if h > w:
crop_x0 = 0
crop_x1 = w
crop_y0 = (h-w)//2
crop_y1 = crop_y0 + w
else:
crop_y0 = 0
crop_y1 = h
crop_x0 = (w-h)//2
crop_x1 = crop_x0 + h
out_img = img[crop_y0:crop_y1, crop_x0:crop_x1, :]
out_afa = afa[crop_y0:crop_y1, crop_x0:crop_x1]
return out_img, out_afa
def top_crop(img, afa):
h, w, c = img.shape
assert h > w
crop_x0 = 0
crop_x1 = w
crop_y0 = 0
crop_y1 = w
out_img = img[crop_y0:crop_y1, crop_x0:crop_x1, :]
out_afa = afa[crop_y0:crop_y1, crop_x0:crop_x1]
return out_img, out_afa
def crop_or_topcrop_by_alpha(img, alpha):
h, w = img.shape[0], img.shape[1]
alpah_temp = np.copy(alpha).astype(np.uint8)
a = np.where(alpah_temp > 30)
if np.max(alpha) <= 30: # nobody img, center crop
out_img, out_afa = center_crop(img, alpha)
return out_img, out_afa
if w > h:
x0 = min(a[1])
x1 = max(a[1])
portrait_w = x1 - x0
if not portrait_w > h:
crop_size = h
crop_y0 = 0
crop_y1 = h
crop_x0 = x0 - random.randint(0, (crop_size - portrait_w))
crop_x1 = crop_x0 + crop_size
if crop_x0 < 0 :
crop_x0 = 0
crop_x1 = crop_size
if crop_x1 > w:
crop_x1 = w
crop_x0 = w - crop_size
out_img = img[crop_y0:crop_y1, crop_x0:crop_x1, :]
out_afa = alpha[crop_y0:crop_y1, crop_x0:crop_x1]
else:
out_img, out_afa = center_crop(img, alpha)
else: # w < h
y0 = min(a[0])
y1 = max(a[0])
portrait_h = y1 - y0
if portrait_h < w:
crop_size = w
crop_x0 = 0
crop_x1 = w
crop_y0 = y0 - random.randint(0, (crop_size - portrait_h))
crop_y1 = crop_y0 + crop_size
if crop_y0 < 0:
crop_y0 = 0
crop_y1 = crop_size
if crop_y1 > h:
crop_y1 = h
crop_y0 = h - crop_size
out_img = img[crop_y0:crop_y1, crop_x0:crop_x1, :]
out_afa = alpha[crop_y0:crop_y1, crop_x0:crop_x1]
else:
out_img, out_afa = center_crop(img, alpha)
if np.max(out_afa[0,:]) >= 30:
out_img, out_afa = top_crop(img, alpha)
return out_img, out_afa
def batch_crop_or_pad(raw_img_folder, raw_afa_folder, save_root):
save_img_folder = save_root + "imgs/"
save_afa_folder = save_root + "afas/"
os.makedirs(save_img_folder, exist_ok = True)
os.makedirs(save_afa_folder, exist_ok = True)
for file in os.listdir(raw_afa_folder):
afa = cv2.imread(raw_afa_folder+file, 0)
h, w = afa.shape
if h == w:
shutil.copy(raw_img_folder + file, save_img_folder )
shutil.copy(raw_afa_folder + file, save_afa_folder )
else:
img = cv2.imread(raw_img_folder + file, 1)
cropad_img, cropad_afa = crop_or_topcrop_by_alpha(img,afa)
cv2.imwrite(save_img_folder + file.replace("png", "jpg"), cropad_img)
cv2.imwrite(save_afa_folder + file.replace("png", "jpg"), cropad_afa)
网友评论