創新實訓第一週團隊博客

創新實訓第一週團隊博客

本週主要確定了大致的前端界面框架和後端接口,初步搭建了PSGAN的網絡結構,得到初步訓練結果。具體實現和工作參考團隊成員博客。

App功能設想:

登錄註冊界面;
主界面是美妝社區,有用戶關注的人分享的美妝,也有一些隨機的推薦美妝,需要可以分辨出是關注的人還是推薦,分享的美妝類似qq說說,有圖片、文字、點贊和評論;
還要有一個界面,美妝示例榜,10(或更多)個推薦,每個條目顯示的信息有比如某某明星,還有這個美妝圖的縮略圖;
還有一個上妝的界面,先是用戶上傳自己的照片,然後可以選擇示例美妝,或者在相冊中用自己的美妝圖,還要有滑動條表示要求濃淡的程度;選擇美妝圖時,可以先讓用戶選擇這張美妝圖時用全部妝容,還是隻是挑選其某個部分(只能選擇眼影、嘴脣、面部三個部分);
最後應該要有一個用戶的個人主頁界面吧,可以看和修改自己的一些個人信息,也可以查看關注的人之類的。

後端框架設計

數據庫:Mysql、Redis
數據庫表目前主要有以下幾個:
用戶表:存儲用戶信息
動態表:存儲用戶動態
評論表:存儲用戶評論
模型圖片表:存儲系統提供的模型圖片
收藏表:存儲用戶收藏的圖片
美妝歷史表:存儲用戶的美妝記錄

用戶之間的關注與被關注關係使用 redis 的 hashmap 存儲,每個用戶對應兩個 hashmap,分別用來記錄關注了誰和被誰關注.
動態的點贊使用 redis 的 hashmap 存儲,每條動態對應一個 hashmap,記錄點贊者與點贊時間.
瀏覽記錄使用 redis 的 zset 存儲,每個用戶使用一個 zset,以瀏覽時間作爲分數,上限爲 1000.

爲了提高用戶體驗和併發性,使用 RabbitMQ 消息隊列進行異步通信來進行數據庫操作。

PSGAN 初步搭建與訓練

閱讀了妝容遷移的相關論文,比如PSGAN、BeautyGAN、SPADE、StarGAN v2等,並使用PyTorch初步復現PSGAN網絡結構。

在這裏插入圖片描述

網絡結構部分代碼如下:

# Makeup Apply Network(MANet)
class Generator(nn.Module):
    """Generator. Encoder-Decoder Architecture."""

    def __init__(self, conv_dim=64, repeat_num=6):
        super(Generator, self).__init__()

        encoder_layers = []
        encoder_layers.append(nn.Conv2d(3, conv_dim, kernel_size=7, stride=1, padding=3, bias=False))
        # MANet設置沒有affine
        encoder_layers.append(nn.InstanceNorm2d(conv_dim, affine=False))
        encoder_layers.append(nn.ReLU(inplace=True))

        # Down-Sampling
        curr_dim = conv_dim
        for i in range(2):
            encoder_layers.append(nn.Conv2d(curr_dim, curr_dim * 2, kernel_size=4, stride=2, padding=1, bias=False))
            encoder_layers.append(nn.InstanceNorm2d(curr_dim * 2, affine=False))
            encoder_layers.append(nn.ReLU(inplace=True))
            curr_dim = curr_dim * 2

        # Bottleneck
        for i in range(3):
            encoder_layers.append(ResidualBlock(dim_in=curr_dim, dim_out=curr_dim))

        decoder_layers = []
        for i in range(3):
            decoder_layers.append(ResidualBlock(dim_in=curr_dim, dim_out=curr_dim))

        # Up-Sampling
        for i in range(2):
            decoder_layers.append(
                nn.ConvTranspose2d(curr_dim, curr_dim // 2, kernel_size=4, stride=2, padding=1, bias=False))
            decoder_layers.append(nn.InstanceNorm2d(curr_dim // 2, affine=True))
            decoder_layers.append(nn.ReLU(inplace=True))
            curr_dim = curr_dim // 2

        decoder_layers.append(nn.Conv2d(curr_dim, 3, kernel_size=7, stride=1, padding=3, bias=False))
        decoder_layers.append(nn.Tanh())

        self.encoder = nn.Sequential(*encoder_layers)
        self.decoder = nn.Sequential(*decoder_layers)
        self.MDNet = MDNet()
        self.AMM = AMM()

    def forward(self, source_image, reference_image):
        fm_source = self.encoder(source_image)
        fm_reference = self.MDNet(reference_image)
        morphed_fm = self.AMM(fm_source, fm_reference)
        result = self.decoder(morphed_fm)
        return result


class MDNet(nn.Module):
    """Generator. Encoder-Decoder Architecture."""

    # MDNet is similar to the encoder of StarGAN
    def __init__(self, conv_dim=64, repeat_num=3):
        super(MDNet, self).__init__()

        layers = []
        layers.append(nn.Conv2d(3, conv_dim, kernel_size=7, stride=1, padding=3, bias=False))
        layers.append(nn.InstanceNorm2d(conv_dim, affine=True))
        layers.append(nn.ReLU(inplace=True))

        # Down-Sampling
        curr_dim = conv_dim
        for i in range(2):
            layers.append(nn.Conv2d(curr_dim, curr_dim * 2, kernel_size=4, stride=2, padding=1, bias=False))
            layers.append(nn.InstanceNorm2d(curr_dim * 2, affine=True))
            layers.append(nn.ReLU(inplace=True))
            curr_dim = curr_dim * 2

        # Bottleneck
        for i in range(repeat_num):
            layers.append(ResidualBlock(dim_in=curr_dim, dim_out=curr_dim))
        self.main = nn.Sequential(*layers)

    def forward(self, reference_image):
        fm_reference = self.main(reference_image)
        return fm_reference


# AMM暫時先不用landmark detector,先試試一般的attention效果如何
# feature map也先不乘以visual_feature_weight
# 這裏attention部分的計算也先存疑,因爲論文中提到x和y需要是同一個區域,但結構圖中是softmax
class AMM(nn.Module):
    """Attentive Makeup Morphing module"""

    def __init__(self):
        super(AMM, self).__init__()
        self.visual_feature_weight = 0.01
        self.lambda_matrix_conv = nn.Conv2d(in_channels=256, out_channels=1, kernel_size=1)
        self.beta_matrix_conv = nn.Conv2d(in_channels=256, out_channels=1, kernel_size=1)
        self.softmax = nn.Softmax(dim=-1)

    def forward(self, fm_source, fm_reference):
        batch_size, channels, width, height = fm_reference.size()
        old_lambda_matrix = self.lambda_matrix_conv(fm_reference).view(batch_size, -1, width * height)
        old_beta_matrix = self.beta_matrix_conv(fm_reference).view(batch_size, -1, width * height)

        # reshape後fm的形狀是C*(H*W)
        temp_fm_reference = fm_reference.view(batch_size, -1, height * width)
        # print('temp_fm_reference shape: ', temp_fm_reference.shape)
        # fm_source 在reshape後需要transpose成(H*W)*C
        temp_fm_source = fm_source.view(batch_size, -1, height * width).permute(0, 2, 1)
        # print('temp_fm_source shape: ', temp_fm_source.shape)
        # energy的形狀應該是N*N,N=H*W
        energy = torch.bmm(temp_fm_source, temp_fm_reference)
        attention_map = self.softmax(energy)

        new_lambda_matrix = torch.bmm(old_lambda_matrix, attention_map.permute(0, 2, 1))
        new_beta_matrix = torch.bmm(old_beta_matrix, attention_map.permute(0, 2, 1))
        new_lambda_matrix = new_lambda_matrix.view(batch_size, 1, width, height)
        new_beta_matrix = new_beta_matrix.view(batch_size, 1, width, height)

        # 對feature_map_source進行修改
        lambda_tensor = new_lambda_matrix.expand(batch_size, 256, width, height)
        beta_tensor = new_beta_matrix.expand(batch_size, 256, width, height)
        morphed_fm_source = torch.mul(lambda_tensor, fm_source)
        morphed_fm_source = torch.add(morphed_fm_source, beta_tensor)

        return morphed_fm_source

訓練尚未完成,但有前幾輪迭代的妝容遷移效果,訓練效果如下:

在這裏插入圖片描述
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章