专栏首页深度学习和计算机视觉基于GAN的自动驾驶汽车语义分割

基于GAN的自动驾驶汽车语义分割

语义分割是计算机视觉中的关键概念之一,语义分割允许计算机通过按类型对图像中的对象进行颜色编码。GAN建立在基于真实内容的基础上复制和生成原始内容的概念上,这使它们适合于在街景图像上进行语义分割的任务,不同部分的分割使在环境中导航的代理能够适当地发挥作用。

数据预处理

我们从一个kaggle数据集获取数据,街景和分割的图像被配对在一起。这意味着为了构建数据集,必须将每个图像分成两部分,以分割每个实例的语义图像和街景图像。

from PIL import Image
from IPython.display import clear_output
import numpy as np
semantic = []
real = []
semantic_imgs = []
real_imgs = []
counter = 0
for img in img_paths:
    if 'jpg' in img:
        im = Image.open(img)
        left = 0
        top = 0
        right = 256
        bottom = 256
        real_img = im.crop((left, top, right, bottom)) 
        real_imgs.append(real_img)
        real.append(np.array(real_img.getdata()).reshape(256,256,3))
        left = 256
        top = 0
        right = 512
        bottom = 256
        semantic_img = im.crop((left, top, right, bottom)) 
        semantic_imgs.append(semantic_img)
        semantic.append(np.array(semantic_img.getdata()).reshape(256,256,3))
        counter += 1
        print(counter)
        if counter % 10 == 0:
          clear_output()
    else:
        print(img)

该脚本将每个图像裁剪为两个,并记录像素值和原始图像。原始图像也被记录下来,因此以后无需再进行显示。

import numpy as np
semantic = np.array(semantic)
real = np.array(real)
X = real
y = semantic

将两个列表都转换为numpy数组后,可以直接定义x和y值。实际上,根据目标,你们可以切换x和y值以控制模型的输出。在这种情况下,我们想将真实图像转换为语义图像。但是,稍后我们将尝试训练GAN将语义数据转换为真实数据。

构建GAN

from numpy import expand_dims
from numpy import zeros
from numpy import ones
from numpy import vstack
from numpy.random import randn
from numpy.random import randint
from keras.utils import plot_model
from keras.models import Model
from keras.layers import Input
from keras.layers import Dense
from keras.layers import Flatten
from keras.layers.convolutional import Conv2D,Conv2DTranspose
from keras.layers.pooling import MaxPooling2D
from keras.layers.merge import concatenate
from keras.initializers import RandomNormal
from keras.layers import LeakyReLU
from keras.layers import BatchNormalization
from keras.layers import Activation,Reshape
from keras.optimizers import Adam
from keras.models import Sequential
from keras.layers import Dropout
from IPython.display import clear_output
from keras.layers import Concatenate

当我们使用keras框架构造生成器和鉴别器时,我们需要导入所有必需的图层类型以构造模型。这包括主要的卷积和卷积转置层,以及批处理归一化层和泄漏的relu层。串联层用于构建U-net体系结构,因为它可以将某些层链接在一起。

def define_discriminator(image_shape=(256,256,3)):
    init = RandomNormal(stddev=0.02)
    in_src_image = Input(shape=image_shape)
    in_target_image = Input(shape=image_shape)
    merged = Concatenate()([in_src_image, in_target_image])
    d = Conv2D(64, (4,4), strides=(2,2), padding='same', kernel_initializer=init)(merged)
    d = LeakyReLU(alpha=0.2)(d)
    d = Conv2D(128, (4,4), strides=(2,2), padding='same', kernel_initializer=init)(d)
    d = BatchNormalization()(d)
    d = LeakyReLU(alpha=0.2)(d)
    d = Conv2D(256, (4,4), strides=(2,2), padding='same', kernel_initializer=init)(d)
    d = BatchNormalization()(d)
    d = LeakyReLU(alpha=0.2)(d)
    d = Conv2D(512, (4,4), strides=(2,2), padding='same', kernel_initializer=init)(d)
    d = BatchNormalization()(d)
    d = LeakyReLU(alpha=0.2)(d)
    d = Conv2D(512, (4,4), padding='same', kernel_initializer=init)(d)
    d = BatchNormalization()(d)
    d = LeakyReLU(alpha=0.2)(d)
    d = Conv2D(1, (4,4), padding='same', kernel_initializer=init)(d)
    patch_out = Activation('sigmoid')(d)
    model = Model([in_src_image, in_target_image], patch_out)
    opt = Adam(lr=0.0002, beta_1=0.5)
    model.compile(loss='binary_crossentropy', optimizer=opt, loss_weights=[0.5])
    return model

该判别器是pix2pix GAN论文使用的模型的keras实现。使用泄漏的Relu而不是正常的Relu是为了使负值仍然被考虑在内。这增加了收敛速度。鉴别器执行二进制分类,因此在最后一层使用S形,并使用二进制交叉熵作为损失函数。

def define_encoder_block(layer_in, n_filters, batchnorm=True):
    init = RandomNormal(stddev=0.02)
    g = Conv2D(n_filters, (4,4), strides=(2,2), padding='same', kernel_initializer=init)(layer_in)
    if batchnorm:
        g = BatchNormalization()(g, training=True)
    g = LeakyReLU(alpha=0.2)(g)
    return g
 
def decoder_block(layer_in, skip_in, n_filters, dropout=True):
    init = RandomNormal(stddev=0.02)
    g = Conv2DTranspose(n_filters, (4,4), strides=(2,2), padding='same', kernel_initializer=init)(layer_in)
    g = BatchNormalization()(g, training=True)
    if dropout:
        g = Dropout(0.5)(g, training=True)
    g = Concatenate()([g, skip_in])
    g = Activation('relu')(g)
    return g

生成器包括多次对初始数据进行编码,直到获得原始图像的特征图为止。然后将此特征图像解码,直到获得完整分辨率的图像为止。这意味着生成器中的大多数层只是编码器和解码器块。在对编码器解码器块进行了精心设计之后,为了构建生成器,没有更多的工作要做。

def define_generator(image_shape=(256,256,3)):
    init = RandomNormal(stddev=0.02)
    in_image = Input(shape=image_shape)
    e1 = define_encoder_block(in_image, 64, batchnorm=False)
    e2 = define_encoder_block(e1, 128)
    e3 = define_encoder_block(e2, 256)
    e4 = define_encoder_block(e3, 512)
    e5 = define_encoder_block(e4, 512)
    e6 = define_encoder_block(e5, 512)
    e7 = define_encoder_block(e6, 512)
    b = Conv2D(512, (4,4), strides=(2,2), padding='same', kernel_initializer=init)(e7)
    b = Activation('relu')(b)
    d1 = decoder_block(b, e7, 512)
    d2 = decoder_block(d1, e6, 512)
    d3 = decoder_block(d2, e5, 512)
    d4 = decoder_block(d3, e4, 512, dropout=False)
    d5 = decoder_block(d4, e3, 256, dropout=False)
    d6 = decoder_block(d5, e2, 128, dropout=False)
    d7 = decoder_block(d6, e1, 64, dropout=False)
    g = Conv2DTranspose(3, (4,4), strides=(2,2), padding='same', kernel_initializer=init)(d7)
    out_image = Activation('tanh')(g)
    model = Model(in_image, out_image)
    return model

使用多个编码器和解码器,我们得到了这个生成器。使用双曲正切可对数据进行归一化,范围从(0,255)到(-1,1)。我们必须记住将数据编码为范围(-1,1),这样才能正确评估生成器的输出和y值。

def define_gan(g_model, d_model, image_shape):
    d_model.trainable = False
    in_src = Input(shape=image_shape)
    gen_out = g_model(in_src)
    dis_out = d_model([in_src, gen_out])
    model = Model(in_src, [dis_out, gen_out])
    opt = Adam(lr=0.0002, beta_1=0.5)
    model.compile(loss=['binary_crossentropy', 'mse'], optimizer=opt)
    return model

将两个模型连接在一起即可得到完整的GAN。发生器的输出直接馈入鉴别器。

生成样本

def generate_real_samples(dataset, n_samples, patch_shape):
    trainA, trainB = dataset
    ix = randint(0, trainA.shape[0], n_samples)
    X1, X2 = trainA[ix], trainB[ix]
    y = ones((n_samples, patch_shape, patch_shape, 1))
    X1 = (X1 - 127.5) / 127.5
    X2 = (X2 - 127.5) / 127.5
    return [X1, X2], y
 
def generate_fake_samples(g_model, samples, patch_shape):
    X = g_model.predict(samples)
    y = zeros((len(X), patch_shape, patch_shape, 1))
    return X, y

为了使鉴别器起作用,必须同时提供真实样本和计算机生成的样本。但是,该过程并不是那么简单,需要对这些值进行标准化。由于像素值的范围介于0到255之间,因此通过使用等式X1 =(X1–127.5)/ 127.5,所有值都将在(-1,1)范围内进行归一化。

执行程序

def train(d_model, g_model, gan_model, dataset, n_epochs=100, n_batch=10):
    n_patch = d_model.output_shape[1]
    trainA, trainB = dataset
    bat_per_epo = int(len(trainA) / n_batch)
    n_steps = bat_per_epo * n_epochs
    for i in range(n_steps):
        [X_realA, X_realB], y_real = generate_real_samples(dataset, n_batch, n_patch)
        X_fakeB, y_fake = generate_fake_samples(g_model, X_realA, n_patch)
        d_loss1 = d_model.train_on_batch([X_realA, X_realB], y_real)
        d_loss2 = d_model.train_on_batch([X_realA, X_fakeB], y_fake)
        g_loss, _, _ = gan_model.train_on_batch(X_realA, [y_real, X_realB])
        print('>%d, d1[%.3f] d2[%.3f] g[%.3f]' % (i+1, d_loss1, d_loss2, g_loss))
        if (i+1) % 100 == 0:
            clear_output()

此功能训练GAN。这里要注意的关键是批次大小。该论文建议使用迷你们批处理(n_batch = 1),但经过一些测试,我们发现批处理大小为10会产生更好的结果。

image_shape = (256,256,3)
d_model = define_discriminator()
g_model = define_generator()
gan_model = define_gan(g_model, d_model, image_shape)
train(d_model, g_model, gan_model, [X,y])

该脚本定义图像形状,并调用函数来构造GAN的不同部分。然后,它调用训练功能来训练模型。

结果

真实到语义:

尽管计算机生成的图像模糊,但可以正确对图像中的所有内容进行颜色编码。请记住,计算机无法看到真实图像的实际语义表示!我们认为图像是模糊的,因为真正的256 x 256图像不是很复杂,而且有许多可能使机器掉色的颜色。右边的图像(计算机生成)可以分割成正方形。如果计算这些平方,它将与卷积层的过滤器数量匹配!

语义到真实:

将语义数据转换为真实的街景图像时,我们担心这是不可能的,因为当转换为语义数据时,会丢失大量数据。例如,红色汽车和绿色汽车都变成蓝色,因为汽车是按蓝色像素分类的。这是一个明显的问题。可能具有不同颜色的对象根本没有出现,从而导致图像看起来只有一点点相似。看一下下面的图片:

结论

考虑到该网络仅训练了10个纪元,我们认为该项目是成功的,并且结果似乎很有希望。我们希望人们可以玩弄模型架构和超参数,以提高GAN创建的图像的质量。

下载1:OpenCV-Contrib扩展模块中文版教程

在「小白学视觉」公众号后台回复:扩展模块中文教程,即可下载全网第一份OpenCV扩展模块教程中文版,涵盖扩展模块安装、SFM算法、立体视觉、目标跟踪、生物视觉、超分辨率处理等二十多章内容。

下载2:Python视觉实战项目52讲

在「小白学视觉」公众号后台回复:Python视觉实战项目,即可下载包括图像分割、口罩检测、车道线检测、车辆计数、添加眼线、车牌识别、字符识别、情绪检测、文本内容提取、面部识别等31个视觉实战项目,助力快速学校计算机视觉。

下载3:OpenCV实战项目20讲

在「小白学视觉」公众号后台回复:OpenCV实战项目20讲,即可下载含有20个基于OpenCV实现20个实战项目,实现OpenCV学习进阶。

本文分享自微信公众号 - 小白学视觉(NoobCV),作者:小白

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2021-03-22

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 业界 | 反GAN传统,Petuum自动驾驶新研究提出从复杂真实图像生成简单虚拟表征以预测驾驶指令

    机器之心
  • 腾讯光影研究室凭GYSeg算法斩获MIT场景解析评测第一

    ? 近日,腾讯光影研究室(Tencent GY-Lab)凭借自研语义分割算法GYSeg,在MIT Scene Parsing Benchmark 场景解析任务...

    天天P图攻城狮
  • 百度Apollo发布海量自动驾驶数据集,还有两项重磅挑战赛

    作者 | 费棋 近日, ApolloScape 宣布开放了大规模自动驾驶数据集。 它是 Apollo 自动驾驶项目的一个研究型项目,旨在促进自动驾驶的各方面创新...

    AI科技大本营
  • 250,000辆汽车–用于机器学习的十大免费车辆图像和视频数据集

    随着特斯拉自动驾驶汽车的兴起以及谷歌Waymo等项目的兴起,自动驾驶汽车行业似乎每年都在增长。无人驾驶汽车是计算机视觉的一个重要领域,具有众多应用程序,并且具有...

    代码医生工作室
  • 地平线“小目标”:2025年,三千万汽车搭载地平线自动驾驶BPU

    【新智元导读】从AI处理器的发展变革可以看出,越是面向专门计算的芯片架构越能达到更好的功耗性能比,因此地平线基于高斯架构同时推出了“旭日”和“征程”两款芯片,每...

    新智元
  • AI新闻报

    1.【TV++】这位博士深掘电视用户流量 以内容识别技术跨屏互动 与江苏卫视促成 合作

    用户3578099
  • 重磅 | 自动驾驶计算机视觉研究综述:难题、数据集与前沿成果(附67页论文下载)

    选自arXiv 机器之心编译 参与:李亚洲、微胖、黄小天、蒋思源 近日,德国马克斯普朗克智能系统研究所(Max Planck Institute for Int...

    机器之心
  • 【论文读书笔记】自动驾驶新思路:现实域到虚拟域统一的无监督方法

    【导读】近日,针对无人驾驶中端到端模型缺乏训练数据以及训练数据噪声大、模型难解释等问题,来自卡内基梅隆大学、Petuum公司的Eric P. Xing等学者发表...

    WZEARW
  • 【中国芯奋起】地平线征程2.0芯片即将问世,自动驾驶计算平台Matrix1.0现场体验

    新智元
  • 百度Apollo加入DeepDrive联盟,并发布了技术品牌Apollo Scape | 热点

    镁客网
  • 数据标注,自动驾驶汽车的新“引擎”

    伴随着计算机视觉技术的日臻成熟,出行生态不断智能化,这其中典型的应用场景就是汽车自动驾驶。

    曼孚科技
  • NeurIPS2019无人驾驶研究成果大总结(含大量论文及项目数据)

    神经信息处理系统大会(NeurIPS),是一个机器学习和计算神经科学相关的顶级学术会议。每年的12月举办。2019的第33届NeurIPS在加拿大温哥华于12月...

    CV君
  • 资源 | 伯克利发布BDD100K:目前最大规模开放驾驶视频数据集

    机器之心
  • 吴甘沙:驭势位列无人驾驶1.5梯队,GAN可改善深度学习不足

    【新智元导读】12月27日的媒体沟通会上,驭势科技CEO吴甘沙带来无人驾驶行业解读和技术分享。他坦言作为创业公司的驭势面临3大难题,第一个就是数据不足的问题。他...

    新智元
  • 【数据集】自动驾驶都有什么测试基准?

    自动驾驶是现在非常活跃的领域,几乎所有的车厂,大型互联网公司都参与其中,其中计算机视觉技术的应用也非常广泛,这篇文章将对自动驾驶中的重要数据集做简单介绍。

    用户1508658
  • uNetXST:将多个车载摄像头转换为鸟瞰图语义分割图像

    项目地址:https://github.com/ika-rwth-aachen/Cam2BEV

    3D视觉工坊
  • 【智驾深谈】特斯拉4大车祸复盘,图像语义分割或成自动驾驶突破口

    【新智元导读】今年对于特斯拉公司来说,无疑是个多事之秋。接二连三事故的发生,让人们对辅助驾驶乃至无人驾驶技术产生了质疑。实际上,自动驾驶向智能化发展的一个重要标...

    新智元
  • 2020年| 最新自动驾驶数据集汇总,持续更新(1)

    网址:http://www.cvlibs.net/datasets/kitti/raw_data.php

    CNNer
  • 深度学习中的图像分割:方法和应用

    基于人工智能和深度学习方法的现代计算机视觉技术在过去10年里取得了显著进展。如今,它被用于图像分类、人脸识别、图像中物体的识别、视频分析和分类以及机器人和自动驾...

    OpenCV学堂

扫码关注云+社区

领取腾讯云代金券