资讯详情

基于自动编码器的赛车视角转换与分割

如下所示,输入图像为

输出:

综上所述,我们的任务是获取输入图像,即前轨道的前摄像头视图,并构建鸟瞰轨道视图,它将分割不同的颜色来表示轨道和边界。

仅仅从输入图像中提取方向信息是相当困难的,因为未来的许多轨道信息将被压缩到图像的前20个像素线中。鸟瞰图摄像头可以以更清晰的格式表达前方轨道的信息,我们可以更容易地使用它来规划汽车的行为。

在正常驾驶过程中很难拍摄鸟瞰图,所以如果我们可以使用前置摄像头的图像来重建这些鸟眼图像,我们可以使用更清晰的信息来规划路径。另一个优点是,它可以降低维度,有效地将整个图像表示为一组32个数字,比整个图像占用的空间要少得多。如果你也可以使用这个低维数据作为观察空间来加强学习算法。

本文使用了一种称为变分自动编码器(VAEs)的工具来帮助我们完成这项任务。简单地说,我们把图像压缩到32维的潜在空间,然后重建我们分割的鸟瞰图。本文末尾的PyTorch代码显示完整的模型代码。

为了训练这一点,我们从前置摄像头和鸟类摄像头中收集了一系列图像。然后用编码器编码,然后用全连接层将维度降低到目标尺寸,最后用解码器用一系列反卷积层重建图像。

结果如下:

在重建过程中,虽然能看到一些噪音,但能很好地捕捉到整体曲线。代码如下:

import cv2 import tqdm import numpy as np import torch import torch.nn as nn import torch.nn.functional as F  class BEVVAE(nn.Module):     """Input should be (bsz, C, H, W) where C=3, H=42, W=144"""      def __init__(self, im_c=3, im_h=95, im_w=512, z_dim=32):         super().__init__()          self.im_c = im_c         self.im_h = im_h         self.im_w = im_w          encoder_list = [             nn.Conv2d(im_c, 32, kernel_size=4, stride=2, padding=1),             nn.ReLU(),             nn.Conv2d(32, 64, kernel_size=4, stride=2, padding=1),             nn.ReLU(),             nn.Conv2d(64, 128, kernel_size=4, stride=2, padding=1),             nn.ReLU(),             nn.Conv2d(128, 256, kernel_size=4, stride=2, padding=1),             nn.ReLU(),             nn.Conv2d(256, 512, kernel_size=4, stride=2, padding=1),             nn.ReLU(),             nn.Flatten(),         ]         self.encoder = nn.Sequential(*encoder_list)         self.encoder_list = encoder_list         sample_img = torch.zeros([1, im_c, im_h, im_w])         em_shape = nn.Sequential(*encoder_list[:-1])(sample_img).shape[1:]         h_dim = np.prod(em_shape)          self.fc1 = nn.Linear(h_dim, z_dim)         self.fc2 = nn.Linear(h_dim, z_dim)         self.fc3 = nn.Linear(z_dim, h_dim)          self.decoder = nn.Sequential(             nn.Unflatten(1, em_shape),             nn.ConvTranspose2d(                 em_shape[0],                 256,                 kernel_size=4,                 stride=2,                 padding=1,                 output_padding=(1, 0),             ),             nn.ReLU(),             nn.ConvTranspose2d(256, 128, kernel_size=4, stride=2, padding=1, output_padding=(1, 0)),             nn.ReLU(),             nn.ConvTranspose2d(128, 64, kernel_size=4, stride=2, padding=1, output_padding=(1, 0)),             nn.ReLU(),             nn.ConvTranspose2d(                 64, 32, kernel_size=4, stride=2, padding=1, output_padding=(1, 0)             ),             nn.ReLU(),             nn.ConvTranspose2d(32, im_c, kernel_size=4, stride=2, padding=1, output_padding=(1, 0)),             nn.Sigmoid(),         )      def reparameterize(self, mu, logvar):         std = logvar.mul(0.5).exp_()         esp = torch.randn(*mu.size(), device=mu.device)         z = mu   std * esp         return z      def bottleneck(self, h):         mu, logvar = self.fc1(h), self.fc2(h)         z = self.reparameterize(mu, logvar)         return z, mu, logvar      def representation(self, x):         return self.bottleneck(self.encoder(x))[0]      def encode_raw(self, x: np.ndarray, device):         # assume x is RGB image with shape (bsz, H, W, 3)         p = np.zeros([x.shape[0], 95, 512, 3], np.float)         for i in range(x.shape[0]):             p[i] = x[i][190:285] / 255         x = p.transpose(0, 3, 1, 2)         x = torch.as_tensor(x, device=device, dtype=torch.float)         v = self.representation(x)         return v, v.detach().cpu().numpy()      def squish_targets(self, x: np.ndarray) -> np.ndarray:         # Take in target images and resize them         p = np.zeros([x.shape[0], 95, 512, 3], np.float)         for i in range(x.shape[0]):             p[i] = cv2.resize(x[i], (512, 95)) / 255         x = p.transpose(0, 3, 1, 2)         return x      def encode(self, x):         h = self.encoder(x)         z, mu, logvar = self.bottleneck(h)         return z, mu, logvar      def decode(self, z):         z = self.fc3(z)         return self.decoder(z)      def forward(self, x):         # expects (N, C, H, W)         z, mu, logvar = self.encode(x)         z = self.decode(z)         return z, mu, logvar      def loss(self, bev, recon, mu, logvar, kld_weight=1.0):         bce = F.binary_cross_entropy(recon, bev, reduction="sum")         kld = -0.5 * torch.sum(1   logvar - mu ** 2 - logvar.exp())         return bc + kld * kld_weight

https://avoid.overfit.cn/post/48f129f8e05242128cc55be13433ad0a

作者:Nandan Tumu

标签: 300前置连接器392

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台