당우 일기장

wil- 텐서플로우를 활용한 유화처리 해보기 본문

카테고리 없음

wil- 텐서플로우를 활용한 유화처리 해보기

당우 2022. 2. 26. 19:45

팀 프로젝트에서 머신러닝을ㅑ 담당하게되어 사진을 넣으면 유화로 바꿔주는 프로그램을 만들게 되었다

ide 는 파이참을 사용하였고 언어는 파이썬 프레임워크는 장고, 장고닌자 ,텐서플로우를 활용하였다 그리고 사진이 저장될곳은 s3 를 활용하여 사진서버를 따로 분리해주었다 키 값으로 파일을 받아주게된다.

유화처리될 그림은 칸딘스키의 유화를 사용하게되었다

모델은   구글의 api 를 사용하였다

 

from django.apps import AppConfig
import boto3
import tensorflow_hub as hub

class NstappConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'nstapp'
    hub_module = hub.load('https://tfhub.dev/google/magenta/arbitrary-image-stylization-v1-256/2')

    s3 = boto3.client('s3', aws_access_key_id='AKIAW35GBHX2HOFBVFKW',
                      aws_secret_access_key='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', region_name='ap-northeast-2')

 

 

 

예시로 아기상어를 유화처리 해보았다.

 

from ninja.files import UploadedFile
from ninja import File
import tensorflow as tf
import numpy as np
from nstapp.apps import NstappConfig
from io import BytesIO
from PIL import Image
import requests
from crawling.service.crawling import search_img


def upload_tensor_img(bucket, tensor, key):
    # normalize 해제
    tensor = np.array(tensor * 255, dtype=np.uint8)
    # image 화
    image = Image.fromarray(tensor[0])
    # 메모리에다가 이미지를 파일 형태로 저장
    buffer = BytesIO()
    image.save(buffer, 'PNG')
    buffer.seek(0)  # 0번째 포인터위치부터 파일을 읽으라는 뜻
    # s3 에다가 업로드
    NstappConfig.s3.put_object(Bucket=bucket, Key=f"{key}.png", Body=buffer, ACL='public-read')
    # s3 에 올라간 파일의 링크를 리턴함
    location = NstappConfig.s3.get_bucket_location(Bucket=bucket)['LocationConstraint']
    url = "https://s3-%s.amazonaws.com/%s/%s.png" % (location, bucket, key)
    return url


def load_style(path_to_style, max_dim):
    # 이미지의 최대 크기 제한
    img = tf.io.read_file(path_to_style)
    img = tf.image.decode_image(img, channels=3)
    img = tf.image.convert_image_dtype(img, tf.float32)

    # 이미지의 채널 부분 제외하고, 이미지의 가로/세로 shape 를 추출함
    shape = tf.cast(tf.shape(img)[:-1], tf.float32)
    # 이미지의 가로/세로 중에서 긴 부분의 길이를 추출함
    long_dim = max(shape)
    # 이미지의 최대 크기를 제한하기 위해서, 제한하고자 하는 길이 / 긴 부분의 길이를 구함
    scale = max_dim / long_dim

    # 이미지의 가로/세로 길이 * (제한하고자 하는 길이 / 긴 부분의 길이) 해서 축소될 길이(shape)를 구함
    new_shape = tf.cast(shape * scale, tf.int32)
    # 축소될 길이를 구했으니 해당 길이대로 resize 함
    img = tf.image.resize(img, new_shape)
    # batch dimension 추가
    img = img[tf.newaxis, :]
    return img


def nst_apply(key: str) -> str:
    style_path = tf.keras.utils.get_file('kandinsky5.jpg',
                                         'htps://storage.googleapis.com/download.tensorflow.org/example_images/Vassily_Kandinsky%2C_1913_-_Composition_7.jpg'
                                         )

    
    keyword_img = search_img(key)
    response = requests.get(keyword_img)
    print(keyword_img)

    # 이미지 읽기
    # img = Image.open(response.file).convert('RGB')
    img = Image.open(BytesIO(response.content)).convert('RGB')
    content_image = tf.keras.preprocessing.image.img_to_array(img)
    # 스타일도 위처럼 읽어와도 되지만, 스타일은 비율이 유지되어야만 올바르게 적용됨
    # 스타일 비율도 일괄적으로 resizing 할 경우 결과가 이상할 수 있음에 유의
    # load_style 함수는 비율을 유지하면서 스타일 이미지 크기를 줄이는 함수
    style_image = load_style(style_path, 1024)

    # float32 타입으로 바꾸고, newaxis 를 통해 배치 차원을 추가한 후에 255 로 나눠서 normalize 함
    # 이후 256, 256 으로 리사이즈
    content_image = content_image.astype(np.float32)[np.newaxis, ...] / 255.
    content_image = tf.image.resize(content_image, (256, 256))

    stylized_image = NstappConfig.hub_module(tf.constant(content_image), tf.constant(style_image))[0]
    image_url = upload_tensor_img('noonch-catch-ai', stylized_image, key)
    return image_url