HOME/Articles/

pil example img utils (snippet)

Article Outline

Python pil example 'img utils'

Functions in program:

  • def change_xml_path(path):
  • def change_img_format(path):
  • def filename_to_txt(target_path,output_path):
  • def resize_img(resize_width=480,resize_height=736,input_path ="./input_example/*",output_path = "./output_example/"):
  • def add_margin(img,resize_width,resize_height):
  • def scale_box(img, width, height):
  • def change_file_name(path):

Modules used in program:

  • import xml.etree.ElementTree as ET
  • import os
  • import glob
  • import numpy as np
  • import cv2
  • import glob

python img utils

Python pil example: img utils

"""
必要なモジュール
"""
import glob
import cv2
import numpy as np
import glob
import os
from scipy.ndimage.interpolation import rotate
from scipy.misc import imresize
from PIL import Image
import xml.etree.ElementTree as ET


"""
画像のファイル名を変更する関数
"""
def change_file_name(path):
    """
    Parameters
    ファイルのパス 例:path="./test/*.jpg"
    """
    target_list = glob.glob(path)
    current_dir = os.getcwd()
    for i in range(len(target_list)):
        file_type = os.path.basename(target_list[i]).split(".")[1]
        if len(str(i)) == 1:
            filename = "img0"+str(i)+"."+file_type
        else:
            filename = "img"+str(i)+"."+file_type

        save_path = os.path.join(current_dir,filename)
        os.rename(target_list[i],save_path)
        print("{}>>{}".format(target_list[i],save_path))

"""
画像のサイズを変更する関数
"""
# アスペクト比固定で指定サイズ内に収まるようリサイズ
def scale_box(img, width, height):
    scale = min(width / img.shape[1], height / img.shape[0])
    return cv2.resize(img, dsize=None, fx=scale, fy=scale)

# 余白部分を黒で埋める
def add_margin(img,resize_width,resize_height):
    height = img.shape[0]
    width = img.shape[1]
    diff_height = resize_height - height
    diff_width = resize_width - width

    # 画像の縦幅を変更
    if diff_height <0:
        pass
    elif diff_height == 0:
        pass
    elif diff_height >0:
        while img.shape[0] <resize_height:
            img = np.insert(img, img.shape[0], 0, axis=0)

    # 画像の横幅を変更
    if diff_width <0:
        pass
    elif diff_width == 0:
        pass
    elif diff_width >0:
        while img.shape[1] <resize_width:
            img = np.insert(img, img.shape[1], 0, axis=1)
    return img

def resize_img(resize_width=480,resize_height=736,input_path ="./input_example/*",output_path = "./output_example/"):
    path_list = glob.glob(input_path)

    if os.path.exists(output_path):
        pass
    else:
        os.mkdir(output_path)

    for i in range(len(path_list)):
        filename = os.path.basename(path_list[i])
        print(filename)
        img = cv2.imread(path_list[i])
        scaled_img = scale_box(img,resize_width,resize_height)
        resize_img = add_margin(scaled_img,resize_width,resize_height)
        cv2.imwrite(os.path.join(output_path,filename),resize_img)
        print(f"{img.shape} -> {resize_img.shape}")

"""
画像のファイル名をテキストファイルにする関数
"""
def filename_to_txt(target_path,output_path):
    """
    Parameters
    target_path:画像ファイルのパス 例:path="./test/*.jpg"
    output_path:テキストファイル形式のパス 例 "./hoge.txt"
    """
    path_list = glob.glob(target_path)
    img_name_list = []

    for i in range(len(path_list)):
        img_name_list.append(os.path.basename(path_list[i]).split(".")[0])

    with open(output_path, mode="w") as f:
        f.write("\n".join(img_name_list))

"""
画像のフォーマットを変更する関数
"""
def change_img_format(path):
    """
    Parameters
    ファイルのパス 例:path="./test/*.jpg"
    """

    save_dir = "./format changed Images"
    path_list = glob.glob(path)

    if os.path.exists(save_dir):
        pass
    else:
        os.mkdir(save_dir)

    for i in range(len(path_list)):
        filename = os.path.basename(path_list[i]).split(".")[0]+".jpg"
        save_path = os.path.join(save_dir,filename)
        pil_img = Image.open(path_list[i],"r")
        pil_img = pil_img.convert("RGB")
        pil_img.save(save_path,"JPEG")

"""
アノテーションファイル(xml)のpathを.png→.jpgに変更する関数
"""
def change_xml_path(path):

    """
    <filename>と<path>を変更
    """
    path_list = glob.glob(path)
    for i in range(len(path_list)):
        tree = ET.parse(path_list[i])
        root = tree.getroot()
        filename = root.find("filename").text.split(".")[0] + ".jpg"
        pathname = root.find("path").text.split(".")[0] + ".jpg"
        root.find("filename").text = filename
        root.find("path").text = pathname
        tree.write(path_list[i])

"""
画像枚数を増やすクラス
"""
class augmentor():
    def __init__(self,path,flip_rate,rotate_rate,scale_rate):
        self.img_list = glob.glob(path)
        self.flip_rate = flip_rate
        self.rotate_rate = rotate_rate
        self.scale_rate = scale_rate

    """
    水平フリップ
    """
    def holizon_flip(self):
        holizon_flip_img_list = []
        for i in range(len(self.img_list)):
            if np.random.rand() <self.flip_rate:
                img = cv2.imread(self.img_list[i])
                img = img[:, ::-1, :] #水平Flip
                holizon_flip_img_list.append(img)
                self.save_img(img,os.path.basename(self.img_list[i]),"holizon_flip")
        return holizon_flip_img_list

    """
    垂直フリップ
    """
    def vertical_flip(self):
        vertical_flip_img_list = []
        for i in range(len(self.img_list)):
            if np.random.rand() <self.flip_rate:
                img = cv2.imread(self.img_list[i])
                img = img[::-1, :, :] #垂直Flip
                vertical_flip_img_list.append(img)
                self.save_img(img,os.path.basename(self.img_list[i]),"vertical_flip")
        return vertical_flip_img_list

    """
    回転
    """
    def random_rotate(self,angle_range=(-10,10)):
        rotate_img_list=[]
        for i in range(len(self.img_list)):
            if np.random.rand() <self.rotate_rate:
                img = cv2.imread(self.img_list[i])
                h, w, _ = img.shape
                angle = np.random.randint(*angle_range)
                if angle == 0:
                    pass
                else:
                    img = rotate(img, angle)
                    img = imresize(img, (h, w))
                    rotate_img_list.append(img)
                    self.save_img(img,os.path.basename(self.img_list[i]),"rotate")
        return rotate_img_list

    """
    拡大
    """
    def scale_up(self):
        scale_up_img_list = []
        for i in range(len(self.img_list)):
            if np.random.rand() < self.rotate_rate:
                img = cv2.imread(self.img_list[i])
                scale_rate = np.random.randint(70,90)*0.01
                h,w, _ = img.shape
                h_two_edge_size = h - h*scale_rate
                w_two_edge_size = w - w*scale_rate
                h_edge_size = int(h_two_edge_size/2)
                w_edge_size = int(w_two_edge_size/2)
                img_scale_up = img[h_edge_size:h-h_edge_size,w_edge_size:w-w_edge_size,:]
                img_scale_up_resize = imresize(img_scale_up, (h, w))
                self.save_img(img_scale_up_resize,os.path.basename(self.img_list[i]),"scale_up")
                scale_up_img_list.append(img_scale_up)
        return scale_up_img_list

    """
    縮小
    """
    def scale_down(self):
        scale_down_img_list = []
        for i in range(len(self.img_list)):
            if np.random.rand() < self.rotate_rate:
                img =cv2.imread(self.img_list[i])
                h,w, _ = img.shape
                scale_rate = np.random.randint(60,80)*0.01
                img_scale_down = cv2.resize(img,(int(w*scale_rate),int(h*scale_rate)))

                h_down,w_down,_ = img_scale_down.shape

                diff_height = h - h_down
                diff_width = w - w_down

                # 画像の縦幅を変更
                for j in range(diff_height):
                    if j < diff_height/2:
                        img_scale_down = np.insert(img_scale_down,0,0,axis=0)
                    else:
                        img_scale_down = np.insert(img_scale_down,img_scale_down.shape[0],0,axis=0)

                # 画像の横幅を変更
                for j in range(diff_width):
                    if j < diff_width/2:
                        img_scale_down = np.insert(img_scale_down,0,0,axis=1)
                    else:
                        img_scale_down = np.insert(img_scale_down,img_scale_down.shape[1],0,axis=1)
                self.save_img(img_scale_down,os.path.basename(self.img_list[i]),"scale_down")
                scale_down_img_list.append(img_scale_down)
        return scale_down_img_list

    """
    保存
    """
    def save_img(self,target_img,img_name,effect,save_dir="./aug"):
        """
        parameters
        target_img:numpy配列として格納された画像
        img_name:画像のファイル名
        effect:画像に加えた処理
        save_dir:保存先のフォルダ名
        """
        if os.path.exists(save_dir):
            pass
        else:
            os.mkdir("./aug")
        save_path = os.path.join(save_dir,img_name.split(".")[0]+"_"+effect+"."+img_name.split(".")[1])
        cv2.imwrite(save_path,target_img)