Ultra-Fast-Lane-Detection-v2 {后处理优化}//参考

news2024/11/23 21:29:18

采用三次多项式拟合生成的anchor特征点,在给定的polyfit_draw函数中,degree参数代表了拟合多项式的度数。

具体来说,当我们使用np.polyfit函数进行数据点的多项式拟合时,我们需要指定一个度数。这个度数决定了多项式的复杂度。例如:

  • degree = 1:线性拟合,也就是最简单的直线拟合。拟合的多项式形式为 f(y)=ax+b。

  • degree = 2:二次多项式拟合。拟合的多项式形式为 f(y)=ax2+bx+c。

  • degree = 3:三次多项式拟合。拟合的多项式形式为 f(y)=ax3+bx2+cx+d。

...以此类推。

度数越高,多项式越复杂,可以更准确地拟合数据点,但也更容易过拟合(即模型过于复杂,过于依赖训练数据,对新数据的适应性差)。

import torch, os, cv2
from utils.dist_utils import dist_print
import torch, os
from utils.common import merge_config, get_model
import tqdm
import torchvision.transforms as transforms
from data.dataset import LaneTestDataset

def pred2coords(pred, row_anchor, col_anchor, local_width = 1, original_image_width = 1640, original_image_height = 590):
    batch_size, num_grid_row, num_cls_row, num_lane_row = pred['loc_row'].shape
    batch_size, num_grid_col, num_cls_col, num_lane_col = pred['loc_col'].shape

    max_indices_row = pred['loc_row'].argmax(1).cpu()
    # n , num_cls, num_lanes
    valid_row = pred['exist_row'].argmax(1).cpu()
    # n, num_cls, num_lanes

    max_indices_col = pred['loc_col'].argmax(1).cpu()
    # n , num_cls, num_lanes
    valid_col = pred['exist_col'].argmax(1).cpu()
    # n, num_cls, num_lanes

    pred['loc_row'] = pred['loc_row'].cpu()
    pred['loc_col'] = pred['loc_col'].cpu()

    coords = []

    row_lane_idx = [1,2]
    col_lane_idx = [0,3]

    for i in row_lane_idx:
        tmp = []
        if valid_row[0,:,i].sum() > num_cls_row / 2:
            for k in range(valid_row.shape[1]):
                if valid_row[0,k,i]:
                    all_ind = torch.tensor(list(range(max(0,max_indices_row[0,k,i] - local_width), min(num_grid_row-1, max_indices_row[0,k,i] + local_width) + 1)))
                    
                    out_tmp = (pred['loc_row'][0,all_ind,k,i].softmax(0) * all_ind.float()).sum() + 0.5
                    out_tmp = out_tmp / (num_grid_row-1) * original_image_width
                    tmp.append((int(out_tmp), int(row_anchor[k] * original_image_height)))
            coords.append(tmp)

    for i in col_lane_idx:
        tmp = []
        if valid_col[0,:,i].sum() > num_cls_col / 4:
            for k in range(valid_col.shape[1]):
                if valid_col[0,k,i]:
                    all_ind = torch.tensor(list(range(max(0,max_indices_col[0,k,i] - local_width), min(num_grid_col-1, max_indices_col[0,k,i] + local_width) + 1)))
                    
                    out_tmp = (pred['loc_col'][0,all_ind,k,i].softmax(0) * all_ind.float()).sum() + 0.5

                    out_tmp = out_tmp / (num_grid_col-1) * original_image_height
                    tmp.append((int(col_anchor[k] * original_image_width), int(out_tmp)))
            coords.append(tmp)

    return coords

def polyfit_draw(img, coords, degree=3, color=(144, 238, 144), thickness=2):
    """
    对车道线坐标进行多项式拟合并在图像上绘制曲线。
    :param img: 输入图像
    :param coords: 车道线坐标列表
    :param degree: 拟合的多项式的度数
    :param color: 曲线的颜色
    :param thickness: 曲线的宽度
    :return: 绘制了曲线的图像
    """
    if len(coords) == 0:
        return img

    x = [point[0] for point in coords]
    y = [point[1] for point in coords]

    # 对点进行多项式拟合
    coefficients = np.polyfit(y, x, degree)

    poly = np.poly1d(coefficients)

    ys = np.linspace(min(y), max(y), 100)
    xs = poly(ys)

    for i in range(len(ys) - 1):
        start_point = (int(xs[i]), int(ys[i]))
        end_point = (int(xs[i+1]), int(ys[i+1]))
        cv2.line(img, start_point, end_point, color, thickness)

    return img

if __name__ == "__main__":
    torch.backends.cudnn.benchmark = True

    args, cfg = merge_config()
    cfg.batch_size = 1
    print('setting batch_size to 1 for demo generation')

    dist_print('start testing...')
    assert cfg.backbone in ['18','34','50','101','152','50next','101next','50wide','101wide']

    if cfg.dataset == 'CULane':
        cls_num_per_lane = 18
    elif cfg.dataset == 'Tusimple':
        cls_num_per_lane = 56
    else:
        raise NotImplementedError

    net = get_model(cfg)

    state_dict = torch.load(cfg.test_model, map_location='cpu')['model']
    compatible_state_dict = {}
    for k, v in state_dict.items():
        if 'module.' in k:
            compatible_state_dict[k[7:]] = v
        else:
            compatible_state_dict[k] = v

    net.load_state_dict(compatible_state_dict, strict=False)
    net.eval()

    img_transforms = transforms.Compose([
        transforms.Resize((int(cfg.train_height / cfg.crop_ratio), cfg.train_width)),
        transforms.ToTensor(),
        transforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225)),
    ])
    if cfg.dataset == 'CULane':
        splits = ['test0_normal.txt']
        datasets = [LaneTestDataset(cfg.data_root,os.path.join(cfg.data_root, 'list/test_split/'+split),img_transform = img_transforms, crop_size = cfg.train_height) for split in splits]
        img_w, img_h = 1570, 660
    elif cfg.dataset == 'Tusimple':
        splits = ['test.txt']
        datasets = [LaneTestDataset(cfg.data_root,os.path.join(cfg.data_root, split),img_transform = img_transforms, crop_size = cfg.train_height) for split in splits]
        img_w, img_h = 1280, 720
    else:
        raise NotImplementedError
    for split, dataset in zip(splits, datasets):
        loader = torch.utils.data.DataLoader(dataset, batch_size=1, shuffle = False, num_workers=1)
        fourcc = cv2.VideoWriter_fourcc(*'MJPG')
        print(split[:-3]+'avi')
        vout = cv2.VideoWriter('4.'+'avi', fourcc , 30.0, (img_w, img_h))
        for i, data in enumerate(tqdm.tqdm(loader)):
            imgs, names = data
            imgs = imgs.cuda()
            with torch.no_grad():
                pred = net(imgs)

            vis = cv2.imread(os.path.join(cfg.data_root,names[0]))
            coords = pred2coords(pred, cfg.row_anchor, cfg.col_anchor, original_image_width = img_w, original_image_height = img_h)
            for lane in coords:
#                 for coord in lane:
#                     cv2.circle(vis,coord,1,(0,255,0),-1)
#             vis = draw_lanes(vis, coords)
#             polyfit_draw(vis, lane)
                vis = polyfit_draw(vis, lane)  # 对每一条车道线都使用polyfit_draw函数
            vout.write(vis)
        vout.release()

    

 ps:

优化前

优化后

显存利用情况

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1069399.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

buuctf-[GYCTF2020]Blacklist sql堆叠注入

这题我一开始还以为是rce,但是看到注入框内写了1,那就肯定是sql 提交1 1 报错,更加确定是sql 1 order by 2 -- 说明是两列 1 union select 1,# 发现select被过滤了 这里我想起了之前做的强网杯的随便住,也是被过滤了&#x…

unocss+vite+vue3初使unocss

一、什么是UnoCss? UnoCSS 是一个即时的原子CSS引擎,而非一款框架,因为它并未提供核心工具类,所有功能可以通过预设和内联配置提供。它可以让你用简短的类名来控制元素的样式 原子样式也有很多选择,最著名的就是 Tail…

Sonar代码审查

概念 Sonar 下载地址 是一款功能强大的代码审核工具,可以帮助开发团队更好的维护项目代码。同时,Sonar只是一个统称,这款工具不是单纯一个应用,一般来说我们会使用Sonar Qube和Sonar scanner这两个组件来搭配使用。Sonar Scanner…

面试算法21:删除倒数第k个节点

题目 如果给定一个链表,请问如何删除链表中的倒数第k个节点?假设链表中节点的总数为n,那么1≤k≤n。要求只能遍历链表一次。 例如,输入图4.1(a)中的链表,删除倒数第2个节点之后的链表如图4.1&a…

LabVIEW应用开发——控件的使用(一)

LabVIEW与其他开发语言相比,最大的优点就是可用控件非常多,涵盖了各种数值、数组、波形、图表、图形等控件,在前面板右键调出控件面板选择。 1、数值型控件 按左上角的图钉,可以使相同控件类别的固定显示,始终处于打开…

模板中的依赖类型使用 --- typename

依赖类型,顾名思义就是依赖于模板参数的类型,在使用这种类型时,必须使用 typename,否则编译器是无法知道是在使用类型,还是类的成员(因为类的静态成员的使用方法也是T::xxx,这跟某个类中的类型的…

【EI会议信息】第二届航空航天与控制工程国际学术会议(ICoACE 2023)

2023 2nd International Conference on Aerospace and Control Engineering 第二届航空航天与控制工程国际学术会议(ICoACE 2023) 2023年第二届航空航天与控制工程国际学术会议(ICoACE 2023)将于2023年12月15-17日在江苏南京召开。ICoACE 2023会议主要…

【虚拟机】NAT 模式下访问外网

目录 一、NAT 模式的作用原理 二、配置 NAT 模式实现外网访问 1、配置NAT模式的网段 2、虚拟机选择 VMnet8 网卡 3、IP地址设为自动分配 一、NAT 模式的作用原理 NAT模式下,虚拟机的系统会把宿主机当作一个大路由器,发送的网络请求和数据都是先发给…

LongLoRA:超长上下文,大语言模型高效微调方法

麻省理工学院和香港中文大学联合发布了LongLoRA,这是一种全新的微调方法,可以增强大语言模型的上下文能力,而无需消耗大量算力资源。 通常,想增加大语言模型的上下文处理能力,需要更多的算力支持。例如,将…

借助PLC-Recorder,汇川中型PLC(AM、AC系列,CODESYS平台)2ms高速采集的方法

高速数据采集要保证速度,也要保证时刻的准确性。在windows系统里,时间稳定性是个很难的问题。如果PLC发送的数据里带有时间信息,则可以由PLC来保证采样周期的稳定性。 从V2.12版本开始,PLC-Recorder软件可以处理发送电文里的时间…

国庆出游远程实测:ToDesk 、TeamViewer、AnyDesk远程控制软件稳定性

ToDesk 、TeamViewer、AnyDesk远程控制软件稳定性 【前言】【实测软件】【测试环境】【实操体验】1. 软件安装2. 登录速度3. 文件传输4. 操作延迟5. 画面清晰度6. 安全防护 【本文小结】 【前言】 随着科技的不断发展,远程控制软件已成为我们生活中不可或缺的一部分…

数据结构-图-最短路径问题

最短路径问题 单源最短路径Dijkstra算法原理代码实现 Bellman-Ford算法原理代码实现SPFA优化SPFA代码实现 多元最短路径Floyd-Warshall算法原理代码实现 单源最短路径 🚀最短路径:从图G的某个顶点出发到达另一个顶点的最短路径,其中最短是指…

鼠标灵敏度怎么调?4个方法提高使用体验感!

“不知道怎么回事,我的鼠标反应很慢慢,有时候好像会有延迟。使用起来感觉特别不舒服。这个问题应该怎么解决呢?希望大家帮帮我!” 在使用电脑的过程中,鼠标是很常用的一个工具。调整鼠标的灵敏度对电脑的使用体验会有显…

DBeaver 导出数据的问题 SQL 错误: jdbc 驱动内部错误 Java heap space

DBeaver 导出结果集 报错 具体操作如下: 网友给出的解决方案是 :调整java参数 dbeaver.ini -startup plugins/org.eclipse.equinox.launcher_1.6.400.v20210924-0641.jar --launcher.library plugins/org.eclipse.equinox.launcher.win32.win32.x86_6…

第八章 排序 九、归并排序

一、定义 把两个或多个有序的序列合并成一个有序序列 二、2路归并 三、归并排序 四、例子 1、首先将数组A复制一份到另一个B数组。 2、在定义三个指针分别指向A数组头部、中间、尾部。定义两个指针指向B数组的头部和中间。 3、然后比较B数组中头指针和中间指针的数字大小&a…

Dockerfile自定义容器

1、Dockerfile Dockerfile 是用于构建 Docker 镜像的文本文件,其中包含一系列的指令和配置,用于定义镜像的构建过程。通过 Dockerfile,你可以定义镜像的基础操作系统、依赖、环境设置、应用程序等信息,从而实现可复制、自动化的镜…

mmcv视频处理,如何遇到异常帧不中断

背景 mmcv读取视频帧如果遇到error,则会直接停止执行。但是,视频后面的内容有时候也十分重要,所以这个时候就需要一种方式可以继续处理后续帧。 处理方法 修改mmcv的VideoReader中的__next__函数,修改为如下: def _…

Django使用SMTP发送邮件教程

CONTENTS 1. SMTP介绍2. 申请邮箱授权码3. Django发送邮件 1. SMTP介绍 SMTP(Simple Mail Transfer Protocol)即简单邮件传输协议,它是一组用于由源地址到目的地址传送邮件的规则,由它来控制信件的中转方式。SMTP 协议属于 TCP/I…

fiddler 的用法

使用fiddler进行抓包 举例一些常见的代理工具 1.wireshark:功能非常强大,但是使用起来更复杂一些 2.fiddler:功能虽然比wireshark少,但是使用简单方便,功能也足以应付大部分场景了 安装了fiddler之后,http和https的请求和响应都会被抓包工具捕捉到,其他的不会 打开软件,左侧是…

网络安全:六种常见的网络攻击手段

1、什么是VPN服务? 虚拟专用网络(或VPN)是您的设备与另一台计算机之间通过互联网的安全连接。VPN服务可用于在离开办公室时安全地访问工作计算机系统。但它们也常用于规避政府审查制度,或者在电影流媒体网站上阻止位置封锁&#…