BE/Python

[Python] 번호판 인식 데이터셋 생산하기 (가상 차량 번호판 생성)

콩다영 2024. 1. 29.
728x90

 

번호판 인식이 필요한 프로젝트를 진행 중 모델을 훈련하기 위해서는 대량의 번호판 데이터가 필요했다.

그러나 자동차 번호판은 개인정보에 해당하고, 현실적으로 실제 데이터를 구하는 것이 어려웠다.

 

그래서 가상의 차량 번호판 이미지를 활용해야 했다.

가상의 데이터를 사용함으로써 개인정보 보호 문제를 회피하고 효과적으로 모델을 훈련해 보자!!

 

 

 

1. 사용 라이브러리 설치 및 글꼴, 이미지 다운로드

▽ 사용 라이브러리

# tqdm
pip install tqdm      # 진행상황 시각화 용도
# PIL
pip install pillow    # 번호판 이미지 처리 용도
#argparse
pip install argparse  # 이미지 경로,갯수,설정 용도

 

▽ 사용 글꼴, 이미지(자동차 번호판 테두리 이미지)

  • 한길체 폰트
  • Noto Sans KR-Medium 폰트
  • 번호판 템플릿 이미지

 

 

2.  코드 작성 및 실행 (run.py) 

import os
import random
import time
import argparse

from tqdm import tqdm
from PIL import Image, ImageDraw, ImageFont


# Hangul Classification Used for Vehicle License Plates
korean = '가나다라마' \
         '거너더러머버서어저' \
         '고노도로모보소오조' \
         '구누두루무부수우주'
korean_taxi = '바사아자'
korean_rent = '하허호'
korean_parcel = '배'

#
new_img_path = 'images/number_plate_new.png'
old_img_path = 'images/number_plate_old.png'

# User default path through environment variables
user_profile = os.environ['USERPROFILE']

# Hangul font download path
# https://www.juso.go.kr/notice/NoticeBoardDetail.do?mgtSn=44&currentPage=11&searchType=&keyword=
ko_font = ImageFont.truetype(f'{user_profile}/AppData/Local/Microsoft/Windows/Fonts/한길체_0.ttf',
                             100, encoding='unic')
# Numeric font information
# https://fonts.google.com/noto/specimen/Noto+Sans+KR
font = ImageFont.truetype(f'{user_profile}/AppData/Local/Microsoft/Windows/Fonts/NotoSansKR-Medium.ttf',
                          120, encoding='unic')


def run():
    count, save_path = opt.count, opt.save_path

    start = time.time()

    # Make folder to saving outputs
    os.makedirs(f'{save_path}/new8', exist_ok=True)
    os.makedirs(f'{save_path}/old8', exist_ok=True)
    os.makedirs(f'{save_path}/old7', exist_ok=True)

    # 8-digit license plate with holographic
    for i in tqdm(range(count), desc='8-digit license plate(holographic)'):
        front = f'{random.randint(100, 999)}'
        middle = random.choice(korean)
        back = f' {random.randint(1000, 9999)}'
        full_name = front + middle + back

        image_pil = Image.open(new_img_path)
        draw = ImageDraw.Draw(image_pil)
        # draw.text( (x,y), License plate string, Font color, Font )
        draw.text((85, -20), front, 'black', font)
        draw.text((290, 35), middle, 'black', ko_font)
        draw.text((375, -20), back, 'black', font)

        image_pil.save(f'{save_path}/new8/' + full_name + '.png', 'PNG')

    # 8-digit license plate
    for i in tqdm(range(count), desc='8-digit license plate'):
        front = f'{random.randint(100, 999)}'
        middle = random.choice(korean)
        back = f' {random.randint(1000, 9999)}'
        full_name = front + middle + back

        image_pil = Image.open(old_img_path)
        draw = ImageDraw.Draw(image_pil)
        draw.text((40, -20), front, 'black', font)
        draw.text((245, 35), middle, 'black', ko_font)
        draw.text((340, -20), back, 'black', font)

        image_pil.save(f'{save_path}/old8/' + full_name + '.png', 'PNG')

    # 7-digit license plate
    for i in tqdm(range(count), desc='7-digit license plate'):
        front = f'{random.randint(10, 99)}'
        middle = random.choice(korean)
        back = f' {random.randint(1000, 9999)}'
        full_name = front + middle + back

        image_pil = Image.open(old_img_path)
        draw = ImageDraw.Draw(image_pil)
        draw.text((65, -20), front, 'black', font)
        draw.text((205, 30), middle, 'black', ko_font)
        draw.text((315, -20), back, 'black', font)

        image_pil.save(f'{save_path}/old7/' + full_name + '.png', 'PNG')

    print(f'Done. ({round(time.time() - start, 3)}s)')  # Spending time


if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--count', type=int, default=100, help='Number of image to save')
    parser.add_argument('--save-path', type=str, default='result', help='Output path')
    opt = parser.parse_args()

    run()

 

 

▼ 기본 실행.

python run.py

 

▼ Argparse를 사용하여 실행.

python run.py --count 50 --save-path output_images

 

 

 

 

 OSError: cannot open resource 오류 발생

이 오류는 OSError: cannot open resource라는 메시지로 나타납니다. 

주로 이 오류는 PIL (Python Imaging Library) 또는 Pillow와 관련된 문제로 발생할 수 있습니다.

 

찾아보니 이 오류의 원인을 파악하기 위해 몇 가지 점을 확인할 수 있었습니다.

폰트 파일 경로 확인, 폰트 파일 읽기 권한, 폰트 라이브러리 설치 확인, Pillow 버전 확인...

 

 

필자는 Pillow 최신 업그레이드가 유력한 것 같아 최신 버전으로 업그레이드를 해줬습니다.

아래 명령을 실행하면 최신 버전의 Pillow가 설치됩니다.

pip install --upgrade Pillow

 

 

하지만 업그레이드 이후에도 동일 오류가 발생하였고,

폰트 관련 이것저것을 확인해 보다가 '한길체' 파일명(파일경로)이 기존과 조금 달라 코드 수정이 필요했습니다.

수정해 주니 위 오류가 해결되었습니다. 

 

 

 

'Hangil.ttf'  →  '한길체_0.ttf'

 

 

 

 

3. 결과 이미지

result 폴더에 new8 폴더 내

신형 번호판 템플릿 이미지에 랜덤 8자리 자동차 번호를 조합하여 가상의 번호판을 생성했다.

 

 

 

이제 이 생성된 가상의 번호판을 활용하여 모델을 학습시킬 수 있게 되었습니다.

대량의 데이터가 필요할 때 매우 유용하게 사용될 것 같습니다 ! good~!! :D

728x90
반응형

댓글