본문 바로가기

VISION

Image style transfer

이미지를 원하는 스타일로 바꿔주는 image style transfer에서는 정해진(또는 이미 학습된) DNN 모델을 사용한다. 모델의 파라미터를 업데이트하는 대신 generated image를 랜덤하게 초기화시켜놓고 이미지의 픽셀값을 업데이트하면서 content image, style image의 특징을 담은 이미지로 변화시킨다.

Content image , style image , random-initialized image

import scipy

content = scipy.misc.imread("content_image.jpg")
style = scipy.misc.imread("style_image.jpg")

content = np.reshape(content, ((1,) + content.shape))
style = np.reshape(style, ((1,) + style.shape))

generated = np.random.uniform(-20, 20, (1, height, width, channel)).astype('float32')	#랜덤 이미지 생성
input_image = ratio * generated + (1-ratio) * content	# 생성된 이미지와 content 이미지를 결합하여 input으로 넣어줌

imshow(generated_image[0])

 

 

Define cost function

비용함수는 content image와의 거리와 style image와의 거리를 더한 값을 사용하여 두 이미지가 적절히 결합되도록 한다. α, β는 content image와 style image에 대한 가중치를 설정하는 하이퍼파라미터이다. style cost를 계산할 때는 gram matrix(style matrix)를 이용하는데, 여러 필터 간의 상관성을 계산해 스타일의 특징을 matrix로 표현하는 것이다. 이 gram matrix 간의 차이를 계산함으로써 style cost를 정의할 수 있다.

 

model = vgg_model
session = tf.InteractiveSession()

### computing content cost ###
  session.run(model['input'].assign(content_image))	# input으로 content 이미지를 넣어줌
  content_output = session.run(model['conv4_2'])	# content cost를 계산할 레이어 지정. 중간 레이어를 지정하는 것이 좋다.
  generated_output = model['conv4_2']

  m, height, width, channel = generated_output.get_shape().as_list()

  content_unrolled = tf.reshape(content_output, (m,n_H*n_W,n_C))
  generated_unrolled = tf.reshape(generated_output, (m,n_H*n_W,n_C))

  content_cost = tf.reduce_sum((content_unrolled - generated_unrolled)**2)/(4*n_H*n_W*n_C)


### computing style cost ###
  session.run(model['input'].assign(style_image))
  style_output = session.run(model['conv4_2'])

  m, height, width, channel = generated_output.get_shape().as_list()

  style_unrolled = tf.transpose(tf.reshape(style_output, (-1,n_C)))
  generated_unrolled = tf.transpose(tf.reshape(generated_output, (-1,n_C)))

  style_gram = tf.matmul(style_unrolled, tf.transpose(style_unrolled))
  generated_gram = tf.matmul(generated_unrolled, tf.transpose(generated_unrolled))

  style_cost = tf.reduce_sum((style_gram-generated_gram)**2)/(2*n_C*n_H*n_W)**2


### total cost ###
total_cost = alph*content_cost + beta*style_cost

 

 

모델 설계 및 실행

total cost를 줄이는 방향으로 학습하면서 이미지를 업데이트한다. 학습 과정에서 content cost는 지속적으로 올라가고, style cost는 지속적으로 내려가면서 style이 이미지에 적용되는 것을 확인할 수 있다.

def model_nn(session, input_image, num_iterations = 200):
    optimizer = tf.train.AdamOptimizer(2.0).minimize(total_cost)
    session.run(tf.global_variables_initializer())
    session.run(model["input"].assign(input_image))
    
    for i in range(num_iterations):
        session.run(optimizer)
        generated_image = session.run(model['input'])
        scipy.misc.imsave("output/" + str(i) + ".png", generated_image)
    
    scipy.misc.imsave('output/generated_image.jpg', generated_image)