美文网首页
一个备忘录:非方形图片裁剪填充成方形

一个备忘录:非方形图片裁剪填充成方形

作者: Valar_Morghulis | 来源:发表于2022-10-11 15:41 被阅读0次

    这是一个私人备忘录,目的是流程规范。给定一批不一定为方形的图片及其标签(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)
    

    相关文章

      网友评论

          本文标题:一个备忘录:非方形图片裁剪填充成方形

          本文链接:https://www.haomeiwen.com/subject/bsgtzrtx.html