본문 바로가기

Language

[Python] 사진 자동 정리 프로그램 개발 (EXIF)

핸드폰/디카로 사진 촬영하는 일은 이제 일상이 되었습니다. 

Google Photo 를 사용하면 간편하지만, 비용도 문제고 과거 파일도 업로드해야하고, 용량이 크면 비용도 문제가 됩니다.

저도 NAS에 아이 과거부터 있던 사진만 수만장이 되는데, 한 폴더에 넣고 찾기 편하게 관리했더니 폴더가 느려져서 문제가 생기고 역시 사진 찾기도 어려웠습니다.

 

수만장 사진 파일을 어떻게 정리할지 고민하다..
촬영 년/월로 자동으로 정리해 주는 프로그램을 만들어 보았습니다.

이미지 정리 규칙

촬영한 년>월 형태로 디렉토리(폴더)를 만들고 자동으로 파일을 옮겨줍니다.
동일한 파일명이 있으면, "dup_" 파일명을 수정해서 이동합니다. (혹시나 동일 파일명으로 이전파일을 삭제 하지 않도록)

촬영 년,월 로 정리

 

알고리즘

소스 프로그램

 

GitHub - jasonbaek97/photo_arrange

Contribute to jasonbaek97/photo_arrange development by creating an account on GitHub.

github.com

#-*- coding: utf-8 -*-
import os
import shutil

from PIL import Image
from PIL.ExifTags import TAGS
from datetime import datetime


img_ext = ['.jpg','.jpeg','.JPG','.png','.bmp']     # 이미지 확장지
video_ext = ['.mp4','.avi','.mts','.m2ts','.MTS']   # 비디오 확장자
DEBUG = False
img_list = []
video_list = []
etc_list =[]

cur_dir =  os.getcwd()
if DEBUG :
    print('img_list length : ',len(img_list))
    print(f'current_dir : {cur_dir}')

def getImageDate(image,DEBUG=False):
    '''
    이미지 EXIF 정보를 읽어, 이미지 생성 년,월 return
    :param image(str)
    :return img_date(list)
    '''
    img = Image.open(image)
    img_date = []

    if DEBUG : print(img.filename)

    # exif 정보로 이미지 촬영일 체크
    img_info = img._getexif()
    if img_info is not None:
        for tag_id in img_info:                                 # exif TAG 정보에서 촬영일 체크
            tag = TAGS.get(tag_id, tag_id)
            data = img_info.get(tag_id)
            if tag == 'DateTime' or tag == 'DateTimeOriginal':      # 촬영일 존재하면 년,월 세팅
                data = data.replace('-',':')                        # '-' 일자 구분자를 :로 변환

                # meta정보 고려해서 10자리 끊고 -> 빈칸 0 trim후 0 채워넣기
                data = data[:11]                                    # yyyy:mm:dd 10자리만 읽기
                data = data.replace(' ','0')                        # 공백 '0' 채움
                date = data.split(':')                              # date = [년, 월, 일]
                if DEBUG: print(f'Data : {data}, Date : {date}')
                try:
                    img_date.append(date[0])
                    img_date.append(date[1])
                except:
                    print('!!!!!! ERRROR !!!!!!!!!')
                    print(f'img name : ', image)
                    print(f'data : {data}')
                    print(f'date : {date}')
                    img_date[0] = 'error'           # 강제 error 세팅
                    img_date.append('00')           # 두번째 값 '00' 추가
                    print(f'img_date : {img_date}')
            if DEBUG:
                print(f'{tag:25}: {data}')

    # EXIF 값이 없으면, 파일 생성일 세팅
    if len(img_date) == 0 :
        date = datetime.fromtimestamp(os.path.getctime(image)).strftime('%Y:%m:%d').split(':')
        img_date.append(date[0])
        img_date.append(date[1])

    if(DEBUG):
        print(f'date : {date}')
        print(f'img_date : {img_date}')
    return img_date

def moveImageFiles(img_list, DEBUG=False):
    count =0
    img_cnt = len(img_list)
    print(f'Target file count : {img_cnt}')
    for img in img_list:
        img_date = getImageDate(img)
        if DEBUG : print(img_date[0], img_date[1], img)

        dir_path = os.path.join(cur_dir, img_date[0], img_date[1])
        s_path = os.path.join(cur_dir, img)
        t_path = os.path.join(dir_path, img)
        if DEBUG:
            print(f'dir_path : {dir_path}')
            print(f'Source_path : {s_path}')
            print(f'Target_path : {t_path}')

        # 이미지 년\월 디렉토리 존재하면, 파일을 이동하고 없으면 생성 후 이동
        if not os.path.exists(dir_path):
            os.makedirs(dir_path)

        # 해당 폴더에 동일파일 존재 시 이름 변경 (prefix : dup_ 추가)
        if os.path.isfile(t_path) :
            dup_name = 'dup_'+ img
            t_path = os.path.join(dir_path, dup_name)

        shutil.move(s_path, t_path)
        print(f'{img} ====> {t_path}')
        count = count+1

    print(f'{count} files moved!')

'''
현제 디렉토리의 이미지,비디오,기타 파일 목록 확인
'''
for file in os.listdir(cur_dir):
    if os.path.isfile(file):
        name,ext = os.path.splitext(file)
        if ext in img_ext:
            img_list.append(file)
        elif ext in video_ext:
            video_list.append(file)
        else:
            etc_list.append(file)
    else:
        print(f'[{file}] is not File')
print('========== report ===========')
print(f'Working Directory : {cur_dir}')
print(f'{len(img_list)} file(s) detected.')

if DEBUG:
    print(f'img_list : {img_list}')
    print(f'video_list : {video_list}')
    print(f'etc_list : {etc_list}')

moveImageFiles(img_list)

 

실행결과

480개 정도의 파일을 테스트 해봤는데, 잘 작동합니다. 

 

위 프로그램으로 실제 NAS 서버에 python 설치하고, contab 형태로 10분 단위로 작업을 실행해 주었습니다. 

저는 이제 휴대폰 사진을 찍으면 NAS로 자동 upload 되고 10분이네, 자동 년/월로 정리가 됩니다. 

 

이후 AI 객체 검출 (Object Detection)을 추가하여 특정 이미지(내가 있는 사진, 음식, 자동차 등)를 자동으로 찾는것도 만들어 볼 생각입니다.