Neural Style Transfer (NST) đề cập đến như một lớp thuật toán phần mềm thao tác hình ảnh hoặc video kỹ thuật số hoặc áp dụng hình thức hoặc phong cách trực quan của hình ảnh khác. Khi chúng tôi thực hiện thuật toán, chúng tôi xác định hai khoảng cách; một cho nội dung (Dc) và một cho hình thức (Ds).
Trong chủ đề, chúng tôi sẽ thực hiện một hệ thống nhân tạo dựa trên Deep Neural Network, hệ thống này sẽ tạo ra những hình ảnh có chất lượng cảm nhận cao. Hệ thống sẽ sử dụng biểu diễn thần kinh để tách, kết hợp lại nội dung-hình ảnh (một hình ảnh kiểu) làm đầu vào và trả về hình ảnh nội dung khi nó được in bằng cách sử dụng kiểu nghệ thuật của hình ảnh kiểu.
Các bài viết liên quan:
Neural Style Transfer là một kỹ thuật tối ưu hóa chủ yếu được sử dụng để chụp hai hình ảnh – một hình ảnh nội dung và một hình ảnh tham chiếu kiểu và pha trộn chúng. Vì vậy, hình ảnh đầu ra trông giống như hình ảnh nội dung kết hợp với hình ảnh tham chiếu. Các số liệu thống kê này được lấy từ các hình ảnh sử dụng một mạng phức hợp.
Hoạt động của thuật toán neural style transfer
Khi chúng tôi triển khai thuật toán đã cho, chúng tôi xác định hai khoảng cách; một cho phong cách (Ds) và một cho nội dung (Dc). Dc đo lường sự khác nhau giữa nội dung giữa hai hình ảnh và Ds đo lường sự khác nhau giữa phong cách giữa hai hình ảnh. Chúng tôi lấy hình ảnh thứ ba làm đầu vào và biến đổi nó thành cả hai cách giảm thiểu khoảng cách giữa nội dung với hình ảnh nội dung và khoảng cách kiểu của nó với hình ảnh kiểu.
Thư viện bắt buộc
import tensorflow as tf #we transform and models because we will modify our images and we will use pre-trained model VGG-19 from torchvision import transforms, models from PIL import Image import matplotlib.pyplot as plt import numpy as np
VGG-19 model
VGG-19 model tương tự như mô hình VGG-16. Simonyan và Zisserman giới thiệu mô hình VGG. VGG-19 được đào tạo trên hơn một triệu hình ảnh từ cơ sở dữ liệu ImageNet. Mô hình này có 19 lớp của mạng nơ-ron sâu, có thể phân loại hình ảnh thành 1000 loại đối tượng.
High-level architecture
Neural style transfer sử dụng mạng nơ-ron tích chập liên tục. Sau đó, xác định một hàm mất mát kết hợp hoàn toàn hai hình ảnh để tạo ra tác phẩm nghệ thuật hấp dẫn trực quan, NST xác định các đầu vào sau:
- Một hình ảnh nội dung (c) – Hình ảnh chúng tôi muốn chuyển kiểu sang
- (Các) hình ảnh tạo kiểu – Hình ảnh mà chúng tôi muốn di chuyển phương thức từ
- Hình ảnh đầu vào (g) – Hình ảnh chứa kết quả cuối cùng.
Kiến trúc của mô hình giống nhau, cũng như sự mất mát, được tính toán, được hiển thị bên dưới. Chúng ta không cần phải hiểu sâu về những gì đang diễn ra trong hình ảnh dưới đây, vì chúng ta sẽ xem chi tiết từng thành phần trong một số phần tiếp theo. Ý tưởng là cung cấp sự hiểu biết ở mức độ cao về quy trình làm việc đang diễn ra trong quá trình chuyển giao phong cách.
Tải xuống và tải VGG-16 liên tục
Chúng tôi sẽ mượn VGG-16 từ trang web này. Chúng tôi sẽ cần tải xuống tệp vgg16_weights.npz và thay thế tệp đó trong một thư mục có tên là vgg trong thư mục chính dự án của chúng tôi. Chúng ta sẽ chỉ cần các lớp chập và các lớp gộp. Rõ ràng, chúng tôi sẽ tải bảy lớp phức hợp đầu tiên được sử dụng làm mạng NST. Chúng ta có thể thực hiện việc này bằng cách sử dụng hàm load_weights (…) được cung cấp trong sổ ghi chép.
Lưu ý: Chúng ta phải thử nhiều lớp hơn. Nhưng hãy cẩn thận với các giới hạn bộ nhớ của CPU và GPU của chúng tôi.
# This function takes in a file path to the file containing weights # and an integer that denotes how many layers to be loaded. vgg_layers=load_weights(os.path.join('vgg','vgg16_weights.npz'),7)
Xác định các chức năng để xây dựng style transfer network
Chúng tôi xác định một số hàm sẽ giúp chúng tôi sau này xác định đầy đủ đồ thị tính toán của CNN cho một đầu vào.
Tạo biến TensorFlow
Chúng tôi đã tải các mảng numpy vào các biến TensorFlow. Chúng tôi đang tạo các biến sau:
- hình ảnh nội dung (tf.placeholder)
- hình ảnh kiểu (tf.placeholder)
- hình ảnh được tạo (tf.Variable và trainable = True)
- Trọng lượng và sai lệch trước khi xử lý (tf. Biến đổi và có thể đào tạo = Sai)
Đảm bảo rằng chúng tôi để hình ảnh được tạo có thể đào tạo được trong khi giữ các trọng số và trọng số và độ lệch được đào tạo trước. Chúng tôi hiển thị hai chức năng để xác định trọng số đầu vào và mạng nơ-ron.
def define_inputs (input_shape): """ This function defines the inputs (placeholders) and image to be generated (variable) """ content = tf.placeholder(name='content' , shape=input_shape, dtype=tf.float32) style= tf.placeholder(name='style', shape=input_shape, dtype=tf.float32) generated= tf.get_variable(name='generated', initializer=tf.random_normal_initalizer=tf.random_normal_initiallizer(), shape=input_shape, dtype=tf.float32, trainable=true) return {'content':content,'style,'generated': generated} def define_tf_weights(): """ This function defines the tensorflow variables for VGG weights and biases """ for k, w_dict in vgg_layers.items(): w, b=w_dict['weights'], w_dict['bias'] with tf.variable_scope(k): tf.get_variable(name='weights', initializer=tf.constant(w, dtype=tf.float32), trainable=false) tf.get_variable(name='bias', initializer=tf.constant(b, dtype=tf.float32), trainable=False)
Tính toán VGG net output
Computing the VGG net output Def build_vggnet(inp, layer_ids, pool_inds, on_cpu=False): "This function computes the output of full VGG net """ outputs = OrderedDict() out = inp for lid in layer_ids: with tf.variable_scope(lid, reuse=tf.AUTO_REUSE): print('Computing outputs for the layer {}'.format(lid)) w, b = tf.get_variable('weights'), tf.get_variable('bias') out = tf.nn.conv2d(filter=w, input=out, strides=[1,1,1,1], padding='SAME') out = tf.nn.relu(tf.nn.bias_add(value=out, bias=b)) outputs[lid] = out if lid in pool_inds: with tf.name_scope(lid.replace('conv','pool')): out = tf.nn.avg_pool(input=out, ksize=[1,2,2,1], strides=[1, 2, 2, 1], padding='SAME') outputs[lid.replace('conv','pool')] = out return outputs
Loss functions
Trong phần này, chúng tôi xác định hai hàm mất mát; chức năng mất kiểu dáng và chức năng nội dung. Chức năng mất nội dung đảm bảo rằng sự kích hoạt của lớp cao hơn là tương tự giữa hình ảnh được tạo ra và hình ảnh nội dung.
Content cost function
Hàm chi phí nội dung chắc chắn rằng nội dung hiện diện trong hình ảnh nội dung được thu vào hình ảnh được tạo. Người ta thấy rằng CNN nắm bắt thông tin về nội dung ở các cấp cao hơn, trong đó các cấp thấp hơn tập trung nhiều hơn vào các giá trị pixel đơn.
Gọi A ^ l_ {ij} (I) là kích hoạt của lớp thứ l, bản đồ đối tượng thứ i và vị trí thứ j đạt được bằng cách sử dụng hình ảnh I. Khi đó, mất mát nội dung được định nghĩa là
Trực giác đằng sau việc mất nội dung
Nếu chúng ta hình dung những gì học được bởi mạng nơ-ron, có bằng chứng cho thấy rằng các bản đồ đối tượng địa lý khác nhau ở các lớp cao hơn được kích hoạt khi có sự hiện diện của các đối tượng khác nhau. Vì vậy, nếu hai hình ảnh có cùng nội dung, chúng có các kích hoạt tương tự nhau ở các cấp trên cùng.
Trực giác đằng sau việc mất nội dung
Chúng tôi xác định chi phí nội dung như sau.
def define_content_loss(inputs, layer_ids, pool_inds, c_weight): c_outputs= build_vggnet (inputs ["content"], layer_ids, pool_inds) g_outputs= build_vggnet (inputs ["generated"], layer_ids, pool_inds) content_loss= c_weight * tf.reduce_mean(0.5*(list(c_outputs.values())[-1]-list(g_outputs.values())[-1])**2)
Style Loss function
Nó xác định hàm mất kiểu mong muốn làm việc nhiều hơn. Để lấy thông tin kiểu từ mạng VGG, chúng tôi sẽ sử dụng các lớp CNN đầy đủ. Thông tin kiểu được đo lường mức độ tương quan giữa các bản đồ đối tượng trong một lớp. Về mặt toán học, mất kiểu được định nghĩa là,
Trực giác đằng sau sự style loss
Bằng hệ thống phương trình trên, ý tưởng là đơn giản. Mục tiêu chính là tính toán ma trận kiểu cho hình ảnh gốc và hình ảnh kiểu.
Sau đó, mất kiểu được định nghĩa là hiệu số bình phương căn bậc hai giữa hai ma trận kiểu.
def define_style_matrix(layer_out): """ This function computes the style matrix, which essentially computes how correlated the activations of a given filter to all the other filers. Therefore, if there are C channels, the matrix will be of size C x C """ n_channels = layer_out.get_shape().as_list()[-1] unwrapped_out = tf.reshape(layer_out, [-1, n_channels]) style_matrix = tf.matmul(unwrapped_out, unwrapped_out, transpose_a=True) return style_matrix def define_style_loss(inputs, layer_ids, pool_inds, s_weight, layer_weights=None): """ This function computes the style loss using the style matrix computed for the style image and the generated image """ c_outputs = build_vggnet(inputs["style"], layer_ids, pool_inds) g_outputs = build_vggnet(inputs["generated"], layer_ids, pool_inds) c_grams = [define_style_matrix(v) for v in list(c_outputs.values())] g_grams = [define_style_matrix(v) for v in list(g_outputs.values())] if layer_weights is None: style_loss = s_weight * \ tf.reduce_sum([(1.0/len(layer_ids)) * tf.reduce_mean((c - g)**2) for c,g in zip(c_grams, g_grams)]) else: style_loss = s_weight * \