从视频帧生成点云数据、使用PointNet++模型提取特征,并将特征保存下来的完整实现。

文件地址

https://github.com/yanx27/Pointnet_Pointnet2_pytorch?spm=5176.28103460.0.0.21a95d27ollfze

Pointnet_Pointnet2_pytorch\log\classification\pointnet2_ssg_wo_normals文件夹改名为Pointnet_Pointnet2_pytorch\log\classification\pointnet2_cls_ssg

"E:\Pointnet_Pointnet2_pytorch\provider.py" 在provider.py文件头添加

def pc_normalize(pc):
    l = pc.shape[0]
    centroid = np.mean(pc, axis=0)
    pc = pc - centroid
    m = np.max(np.sqrt(np.sum(pc**2, axis=1)))
    pc = pc / m
    return pc

详细介绍了如何从视频帧中生成点云数据并使用PointNet++模型提取特征,最后将特征保存下来。
从视频帧中生成点云数据并提取特征
1. 引言

在计算机视觉领域,点云数据是一种重要的三维数据形式,广泛应用于自动驾驶、机器人导航、物体识别等场景。本文将详细介绍如何从视频帧中生成点云数据,并使用PointNet++模型提取特征,最后将特征保存下来以供后续分析或使用。
2. 环境准备

在开始之前,确保你的环境中安装了以下依赖项:

    Python 3.6+
    PyTorch 1.7+
    Open3D
    OpenCV
    NumPy

你可以使用以下命令安装这些依赖项:

pip install torch torchvision
pip install open3d opencv-python numpy

3. 代码实现

import os
import sys
# 获取当前脚本所在的目录
current_dir = os.path.dirname(os.path.abspath(__file__))
# 将 models 目录添加到 sys.path
sys.path.insert(0, os.path.join(current_dir, 'models'))
import numpy as np
import torch
import cv2
import open3d as o3d
from models.pointnet2_cls_ssg import get_model
from provider import pc_normalize
import time
import hashlib


# 打印 sys.path 以确认路径是否正确
print(sys.path)

# 设置设备
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
print(f"设备设置为: {device}")

# 加载预训练模型
#"E:\Pointnet_Pointnet2_pytorch\log\classification\pointnet2_cls_ssg\checkpoints\best_model.pth"
model_path = os.path.join('log', 'classification', 'pointnet2_cls_ssg', 'checkpoints', 'best_model.pth')  # 替换为实际路径
print(f"加载预训练模型: {model_path}")
model = get_model(num_class=40, normal_channel=False).to(device)

# 只加载模型参数
checkpoint = torch.load(model_path, map_location=device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
print("模型加载完成")

# 从视频帧生成点云数据
def frame_to_point_cloud(frame, depth_frame=None):
    if depth_frame is None:
        # 如果没有深度图,使用随机生成的点云数据作为示例
        points = np.random.rand(1024, 3)  # 生成 1024 个点,每个点有 3 个坐标
    else:
        # 使用深度图生成点云
        h, w = depth_frame.shape
        y, x = np.indices((h, w))
        z = depth_frame
        points = np.stack([x, y, z], axis=-1).reshape(-1, 3)
        points = points[~np.isnan(points).any(axis=1)]  # 去除无效点
        if points.shape[0] > 1024:
            points = points[np.random.choice(points.shape[0], 1024, replace=False)]
        elif points.shape[0] < 1024:
            points = np.pad(points, ((0, 1024 - points.shape[0]), (0, 0)), mode='constant')
    print(f"生成点云数据: {points.shape}")
    return points

# 提取特征
def extract_features(model, point_cloud):
    point_cloud = pc_normalize(point_cloud)  # 归一化点云
    point_cloud = torch.from_numpy(point_cloud).float().unsqueeze(0).transpose(2, 1).to(device)
    with torch.no_grad():
        pred, trans_feat = model(point_cloud)  # 只接收两个返回值
    print(f"提取特征完成: {pred.shape}")
    return pred.cpu().numpy()

# 处理单个视频文件
def process_video(video_path, output_folder):
    cap = cv2.VideoCapture(video_path)
    frame_count = 0
    video_name = os.path.basename(video_path).split('.')[0]
    print(f"开始处理视频: {video_path}")
    all_features = []
    while cap.isOpened():
        ret, frame = cap.read()
        if not ret:
            break

        # 生成点云数据
        point_cloud = frame_to_point_cloud(frame)
        if point_cloud.shape[0] < 1024:  # 确保至少有 1024 个点
            print(f"帧 {frame_count} 点云数据不足,跳过")
            continue  # 如果点不够,跳过此帧

        # 提取特征
        features = extract_features(model, point_cloud)
        print(f"处理帧 {frame_count} 特征: {features}")

        # 保存特征到 all_features 列表中
        all_features.append(features)

        frame_count += 1

    cap.release()
    print(f"视频处理完成: {video_path}")

    # 生成唯一的文件名
    output_file = os.path.join(output_folder, f'{video_name}_features.npy')

    # 将所有特征保存到一个文件中
    np.save(output_file, np.vstack(all_features))
    print(f"特征已保存到: {output_file}")

# 检查视频文件是否已处理
def is_video_processed(video_path, processed_videos):
    video_hash = hashlib.md5(video_path.encode()).hexdigest()
    return video_hash in processed_videos

# 获取已处理的视频文件列表
def get_processed_videos(output_file):
    if not os.path.exists(output_file):
        return set()
    
    processed_videos = set()
    with open(output_file, 'r') as f:
        for line in f:
            processed_videos.add(line.strip())
    return processed_videos

# 记录已处理的视频文件
def record_processed_video(video_path, output_file):
    video_hash = hashlib.md5(video_path.encode()).hexdigest()
    with open(output_file, 'a') as f:
        f.write(video_hash + '\n')

# 处理视频文件夹
def process_video_folder(folder_path, output_folder):
    processed_videos_file = os.path.join(output_folder, 'processed_videos.txt')
    processed_videos = get_processed_videos(processed_videos_file)
    print(f"开始处理视频文件夹: {folder_path}")
    for root, dirs, files in os.walk(folder_path):
        for file in files:
            if file.endswith('.mp4') or file.endswith('.avi'):
                video_path = os.path.join(root, file)
                if is_video_processed(video_path, processed_videos):
                    print(f"视频已处理,跳过: {video_path}")
                    continue
                process_video(video_path, output_folder)
                record_processed_video(video_path, processed_videos_file)

    print("所有视频处理完成")

# 主程序
if __name__ == "__main__":
    # 视频文件夹路径
    input_folder = r'E:\Pointnet_Pointnet2_pytorch\data\voide'
    output_folder = r'E:\Pointnet_Pointnet2_pytorch\data\voide_features'  # 特征保存路径

    # 确保输出文件夹存在
    os.makedirs(output_folder, exist_ok=True)

    # 处理视频文件夹
    process_video_folder(input_folder, output_folder)


3.1 导入必要的库

首先,我们需要导入一些必要的库,包括文件操作、数值计算、深度学习框架、图像处理和点云处理相关的库。
3.2 设置设备

检查是否有可用的GPU,并设置设备。如果存在GPU,将使用GPU进行计算;否则,使用CPU。
3.3 加载预训练模型

我们使用PointNet++模型来提取点云特征。首先,加载预训练模型。这通常涉及以下几个步骤:

    指定模型路径:提供预训练模型的路径。
    加载模型:使用 get_model 函数创建模型实例,并将其移动到指定的设备(CPU或GPU)。
    加载模型参数:从预训练模型文件中加载模型参数,并设置模型为评估模式。

3.4 从视频帧生成点云数据

定义一个函数 frame_to_point_cloud,该函数从视频帧中生成点云数据。如果没有深度图,可以生成随机点云数据作为示例。具体步骤如下:

    生成随机点云:如果没有深度图,生成1024个随机点,每个点有3个坐标。
    使用深度图生成点云:如果有深度图,从深度图中提取点云数据。具体做法是将深度图的每个像素位置(x, y)和对应的深度值z组合成一个三维点(x, y, z)。然后,去除无效点,并确保点云数据的形状为 (1024, 3)。

3.5 提取特征

定义一个函数 extract_features,该函数使用预训练模型提取点云数据的特征。具体步骤如下:

    归一化点云:对点云数据进行归一化处理,使其适合输入到模型中。
    转换为张量:将点云数据转换为PyTorch张量,并移动到指定的设备。
    提取特征:使用预训练模型提取特征,并返回特征向量。

3.6 处理单个视频文件

定义一个函数 process_video,该函数处理单个视频文件,逐帧生成点云数据并提取特征。具体步骤如下:

    打开视频文件:使用OpenCV的 cv2.VideoCapture 打开视频文件。
    读取帧:逐帧读取视频。
    生成点云数据:调用 frame_to_point_cloud 函数生成点云数据。
    提取特征:调用 extract_features 函数提取特征。
    保存特征:将提取的特征保存为 .npy 文件。

3.7 处理视频文件夹

定义一个函数 process_video_folder,该函数处理指定文件夹中的所有视频文件。具体步骤如下:

    遍历文件夹:使用 os.walk 遍历指定文件夹中的所有视频文件。
    处理每个视频:调用 process_video 函数处理每个视频文件。

3.8 主程序

在主程序中,指定输入视频文件夹和输出特征文件夹的路径,并调用 process_video_folder 函数处理所有视频文件。
4. 总结

本文详细介绍了如何从视频帧中生成点云数据,并使用PointNet++模型提取特征,最后将特征保存下来。通过这些步骤,你可以将视频数据转换为点云数据,并提取有用的特征,为后续的分析和应用提供支持。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

时间序列关于可解释性值得关注的论文汇总-第2篇

前言 这是时序可解释性论文汇总的第二篇&#xff0c;第一篇见这里&#xff08;后台回复&#xff1a;“论文合集”可直接获取整理的文章&#xff09;。深度学习的可解释性研究一直是热门&#xff0c;而时间序列的可解释性同样非常重要。这是因为时序模型被大量应用到特定领域&a…

DataStream编程模型之数据源、数据转换、数据输出

Flink之DataStream数据源、数据转换、数据输出&#xff08;scala&#xff09; 0.前言–数据源 在进行数据转换之前&#xff0c;需要进行数据读取。 数据读取分为4大部分&#xff1a; &#xff08;1&#xff09;内置数据源&#xff1b; 又分为文件数据源&#xff1b; socket…

Java面试题2024-Java基础

Java基础 1、 Java语言有哪些特点 1、简单易学、有丰富的类库 2、面向对象&#xff08;Java最重要的特性&#xff0c;让程序耦合度更低&#xff0c;内聚性更高&#xff09; 3、与平台无关性&#xff08;JVM是Java跨平台使用的根本&#xff09; 4、可靠安全 5、支持多线程 2、…

数据结构(基本概念及顺序表——c语言实现)

基本概念&#xff1a; 1、引入 程序数据结构算法 数据&#xff1a; 数值数据&#xff1a;能够直接参加运算的数据&#xff08;数值&#xff0c;字符&#xff09; 非数值数据&#xff1a;不能够直接参加运算的数据&#xff08;字符串、图片等&#xff09; 数据即是信息的载…

使用爬虫获取的数据如何有效分析以优化店铺运营?

在数字化时代&#xff0c;数据已成为电商运营的核心。通过爬虫技术&#xff0c;我们可以从淘宝等电商平台获取大量数据&#xff0c;这些数据如果得到有效分析&#xff0c;将极大助力店铺运营的优化。本文将探讨如何使用爬虫技术获取数据&#xff0c;并利用数据分析来优化店铺运…

c++类对象练习

#include <iostream> #include <cstring>using namespace std;class mystring {char* buf; public:mystring(); //构造函数mystring(const char* str); //构造函数void show(); //输出函数void setmystr(const mystring str); //设置函数const char* getmystr() co…

后端:Spring AOP原理--动态代理

文章目录 1. Spring AOP底层原理2. 代理模式3. 静态代理4. 动态代理4.1 jdk 实现动态代理4.2 cglib 实现动态代理4.3 jdk、cglib动态代理两者的区别 1. Spring AOP底层原理 创建容器 new applicationContext()&#xff1b;Spring把所有的Bean进行创建&#xff0c;进行依赖注入…

微信小程序 最新获取用户头像以及用户名

一.在小程序改版为了安全起见 使用用户填写来获取头像以及用户名 二.代码实现 <view class"login_box"><!-- 头像 --><view class"avator_box"><button wx:if"{{ !userInfo.avatarUrl }}" class"avatorbtn" op…

【Linux】进程的状态详解

进程的状态详解 一、各种状态的概念二、运行状态的详细介绍三、阻塞状态详解四、挂起状态和阻塞状态的关系五、观察各种状态在linux中的表示1.运行态R2.睡眠态S3.暂停态T4.深度睡眠状态D5.僵尸状态Z6.孤儿进程 一、各种状态的概念 为了弄明白正在运行的进程是什么意思&#xf…

python高级之简单爬虫实现

一、前言 场景1&#xff1a;一个网络爬虫&#xff0c;顺序爬取一个网页花了一个小时&#xff0c;采用并发下载就减少到了20分钟。 场景2&#xff1a;一个应用软件优化前每次打开网页需要3秒&#xff0c;采用异步并发提升到了200毫秒。 假设一个工程的工作量为100&#xff0c…

web——upload-labs——第十关——.空格.绕过

审计源码 这次先删除文件名左右的空格&#xff0c;然后又删除了我们文件末尾的.&#xff0c;其次将我们上传的文件名转换为小写&#xff0c;删除文件末尾的::$DATA&#xff0c;最后又删除了文件名左右两侧的空格 根据他的逻辑&#xff0c;我们可以构造文件名phpinfo.php. .就是…

Percona XtraBackup备份docker版本mysql 5.7

my.cnf配置文件 [client] default_character_setutf8[mysqld] # 数据存储目录&#xff08;必须手动指定&#xff09; datadir/var/lib/mysql/data# 字符集 collation_server utf8_general_ci character_set_server utf8 # 二进制日志 server-id1 log_bin/var/log/mysql/binl…

JavaWeb之Vue

前言 这一节讲Vue 1. Vue概述 这些都是DOM的操作 原来模型和视图不能实现同步变化&#xff0c;但是Vue就可以了 2. 快速入门 1. 2. <script src"js/vue.js"></script><div id"app"> <!-- 准备一个input输入框,绑定一个模…

汽车资讯新篇章:Spring Boot技术启航

4系统概要设计 4.1概述 本系统采用B/S结构(Browser/Server,浏览器/服务器结构)和基于Web服务两种模式&#xff0c;是一个适用于Internet环境下的模型结构。只要用户能连上Internet,便可以在任何时间、任何地点使用。系统工作原理图如图4-1所示&#xff1a; 图4-1系统工作原理…

Windows注册表基础学习

修改注册表让cmd ascii输出有颜色 reg add HKCU\Console /v VirtualTerminalLevel /t REG_DWORD /d 1 如何打开注册表编辑器 运行regedit 按下"Winr"组合键&#xff0c;在打开的"运行"对话框中输入"regedit"&#xff0c;单击"确定"…

C++ | Leetcode C++题解之第564题寻找最近的回文数

题目&#xff1a; 题解&#xff1a; using ULL unsigned long long;class Solution { public:vector<ULL> getCandidates(const string& n) {int len n.length();vector<ULL> candidates {(ULL)pow(10, len - 1) - 1,(ULL)pow(10, len) 1,};ULL selfPrefi…

Debezium-MySqlConnectorTask

文章目录 概要整体架构流程技术名词解释技术细节小结 概要 MySqlConnectorTask&#xff0c;用于读取MySQL的二进制日志并生成对应的数据变更事件 整体架构流程 技术名词解释 数据库模式&#xff08;Database Schema&#xff09; 数据库模式是指数据库中数据的组织结构和定义&…

【WPF】Prism学习(二)

Prism Commands 1.命令&#xff08;Commanding&#xff09; 1.1. ViewModel的作用&#xff1a; ViewModel不仅提供在视图中显示或编辑的数据&#xff0c;还可能定义一个或多个用户可以执行的动作或操作。这些用户可以通过用户界面&#xff08;UI&#xff09;执行的动作或操作…

如何实现主备租户的无缝切换 | OceanBase应用实践

对于DBA而言&#xff0c;确保数据库的高可用性、容灾等能力是其日常工作中需要持续思考和关注的重要事项。一方面&#xff0c;可以利用数据库自身所具备的功能来实现这些目标&#xff1b;若数据库本身不提供相应功能&#xff0c;DBA则需寻找其他工具来增强数据库的高可用性和容…

壁仞科技上市前最后一波 校招 社招 内推

随着美国大选结束&#xff0c;国内GPU 产业得到空前的的发展空间&#xff0c;国内芯片相关股票一片飘红。 国内大型 GPU厂商壁仞科技&#xff0c;摩尔线程等正紧锣密鼓地加紧上市。 GPGPU 芯片赛道来到了史无前例的红利点&#xff0c;抓住机会&#x1f4aa; 壁仞科技正在火热…