Opencv实验合集——实验九:姿势估计

news2025/1/17 13:54:27

在上一章节(相机校准),你已经找到了相机矩阵,畸变系数等等参数。给出一个图案图像,我们便可以利用上面的信息用于计算其姿势,或者物体在空间中位于何处,比如如何旋转,如何移动等等问题。对于一个平面物体,我们可以假定 Z = 0,这样,问题现在便转化为了如何放置摄像机才能查看到我们的图案图像。所以如果我们知道物体在空间中的位置,我们便可以绘制一些 2D 图像用以模拟 3D 效果。

我们的问题是,我们想在我们棋盘的第一个角上绘制 3D 坐标系(x, y, z 坐标系),其中 X 轴是蓝色,Y 轴是绿色,Z 轴是红色。所以从效果上讲,Z 轴应该感觉像是与棋盘垂直的。

1.定义

姿势估计是指通过分析图像或传感器数据来推断物体、人体或相机在三维空间中的姿势,即位置和方向。姿势通常由平移和旋转两个主要组成部分构成。

2.有关的函数方法

本节与上一个实验密切相关,重复的方法就不再一一赘述了

cv2.projectPoints 函数是 OpenCV 中用于将 3D 点投影到图像平面的函数。它是摄像机标定和相机投影中常用的一个函数。该函数的签名如下:

cv2.projectPoints(objectPoints, rvec, tvec, cameraMatrix, distCoeffs[, imagePoints[, jacobian[, aspectRatio]]]) → imagePoints, jacobian

  • objectPoints: 三维物体点的坐标,是一个 numpy 数组,形状为 (N, 3),N 是点的数量。
  • rvec: 旋转向量,描述了物体坐标系相对于相机坐标系的旋转。是一个长度为 3 的 numpy 数组。
  • tvec: 平移向量,描述了物体坐标系相对于相机坐标系的平移。是一个长度为 3 的 numpy 数组。
  • cameraMatrix: 相机内参矩阵,是一个 3x3 的矩阵。
  • distCoeffs: 相机的畸变系数,是一个包含畸变参数的 numpy 数组。
  • imagePoints (可选): 输出参数,是一个 numpy 数组,包含了三维点在图像平面上的投影坐标。
  • jacobian (可选): 输出参数,是一个 numpy 数组,包含了投影函数的导数信息。
  • aspectRatio (可选): 相机的纵横比,即图像的宽高比。

3.代码演示

首先我们先在棋盘上的三个点上建立三角坐标系XYZ,通过绘图进行展示,上个实验已经讲述了如何从世界坐标系转化相机坐标系,获得一系列参数(旋转,平移参数等),如何通过转化成相机坐标系再通过方法将3D点投影到图像平面上。

import numpy as np
import cv2 as cv
import glob

# 终止标准
criteria = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 30, 0.001)

# 准备对象点, 如 (0,0,0), (1,0,0), (2,0,0) ....,(6,5,0)
objp = np.zeros((6*7,3), np.float32)
objp[:,:2] = np.mgrid[0:7,0:6].T.reshape(-1,2)
axis = np.float32([[3,0,0], [0,3,0], [0,0,-3]]).reshape(-1,3)
#axis是世界坐标系中的三个点,用来绘制图像上的相机坐标系

# 用于存储所有图像对象点与图像点的矩阵
objpoints = [] # 在真实世界中的 3d 点
imgpoints = [] # 在图像平面中的 2d 点

# images = glob.glob('*.jpg')
images = [r'C:\Users\xiaoou\Desktop\picture\chess.jpg']
def draw(img, corners, imgpts):#在一个角点上建立相机平面坐标系
    corner = tuple(corners[0].ravel())#在检测的众多角点中随机抽取一个
    img = cv.line(img, np.int32(corner), np.int32(tuple(imgpts[0].ravel())), (255,0,0), 5)
    img = cv.line(img, np.int32(corner), np.int32(tuple(imgpts[1].ravel())), (0,255,0), 5)
    img = cv.line(img, np.int32(corner), np.int32(tuple(imgpts[2].ravel())), (0,0,255), 5)
    return img

for fname in images:
    img = cv.imread(fname)
    gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

    # 找到棋盘上所有的角点
    ret, corners = cv.findChessboardCorners(gray, (7,6), None)

    # 如果找到了,便添加对象点和图像点(在细化后)
    if ret == True:
        objpoints.append(objp)

        corners2 = cv.cornerSubPix(gray,corners, (11,11), (-1,-1), criteria)
        imgpoints.append(corners)
        # 绘制角点
        # cv.drawChessboardCorners(img, (7,6), corners2, ret)

        ret, mtx, dist, rvecs, tvecs = cv.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)
        imgpts, jac = cv.projectPoints(axis,rvecs[0],tvecs[0],mtx,dist)
        img = draw(img, corners2, imgpts)

        cv.imshow('img', img)

        cv.waitKey(0)

现在把投影的点扩大为8个,构成一个长方体,绘制底部为绿色,顶部为红色,来让姿势估计更加具体。

import numpy as np
import cv2 as cv
import glob

# 终止标准
criteria = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 30, 0.001)

# 准备对象点, 如 (0,0,0), (1,0,0), (2,0,0) ....,(6,5,0)
objp = np.zeros((6*7,3), np.float32)
objp[:,:2] = np.mgrid[0:7,0:6].T.reshape(-1,2)
axis = np.float32([ [0,0,0], [0,1,0], [1,1,0], [1,0,0],
                   [0,0,-1],[0,1,-1],[1,1,-1],[1,0,-1] ])

# 用于存储所有图像对象点与图像点的矩阵
objpoints = [] # 在真实世界中的 3d 点
imgpoints = [] # 在图像平面中的 2d 点

images = [r'C:\Users\xiaoou\Desktop\picture\chess.jpg']

def cube_draw(img, imgpts):#对8个平面的点建立相连建立一个长方体
    imgpts = np.int32(imgpts).reshape(-1,2)
    # 将底面绘制为绿色
    img = cv.drawContours(img, [imgpts[:4]], -1, (0,255,0), -3)
    # 将支柱绘制为蓝色
    for i,j in zip(range(4), range(4,8)):
        img = cv.line(img,tuple(imgpts[i]), tuple(imgpts[j]), (255,0,0), 3)
    # 将顶面绘制为红色
    img = cv.drawContours(img, [imgpts[4:]], -1, (0,0,255), 3)
    return img
for fname in images:
    img = cv.imread(fname)
    gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

    # 找到棋盘上所有的角点
    ret, corners = cv.findChessboardCorners(gray, (7,6), None)

    # 如果找到了,便添加对象点和图像点(在细化后)
    if ret == True:
        objpoints.append(objp)

        corners2 = cv.cornerSubPix(gray,corners, (11,11), (-1,-1), criteria)
        imgpoints.append(corners)

        ret, mtx, dist, rvecs, tvecs = cv.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)
        imgpts, jac = cv.projectPoints(axis,rvecs[0],tvecs[0],mtx,dist)
        img = cube_draw(img, imgpts)

        cv.imshow('img', img)

        cv.waitKey(0)

 本次实验主要演示了三维重建中的姿势估计,主要通过将世界坐标系中的目标点转化为平面中的投影点,以此用来估计目标点在平面上的形状。

如有错误或遗漏,希望小伙伴批评指正!!!! 

希望这篇博客对你有帮助!!!!

实验八:Opencv实验合集——实验八:相机校准-CSDN博客

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

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

相关文章

Google Breakpad使用方法

源码下载地址:https://chromium.googlesource.com/breakpad/breakpad 依赖头文件下载地址: https://chromium.googlesource.com/linux-syscall-support Breakpad由三个主要组件: client 是一个库, 以library的形式内置在应用中&#xff0c…

Mongodb使用指定索引删除数据

回顾Mongodb删除语法 db.collection.deleteMany(<filter>,{writeConcern: <document>,collation: <document>,hint: <document|string>} ) 删除语法中&#xff0c;除了指定过滤器外&#xff0c;还可以指定写入策略&#xff0c;字符序和使用的索引。 …

分布式系统架构设计之分布式消息队列中间件的技术选型报告

1、主流消息队列中间件 01 Kafka 基本原理 Kafka 基于发布-订阅模式&#xff0c;它维护了一个或多个 Topic&#xff0c;生产者将消息发送到 Topic&#xff0c;消费者从 Topic 中读取消息。Kafka 强调高吞吐量&#xff0c;通过批量处理、顺序 I/O 和零拷贝等技术实现高性能 …

【算法Hot100系列】搜索插入位置

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学习,不断总结,共同进步,活到老学到老导航 檀越剑指大厂系列:全面总结 jav…

从起高楼到楼塌了的中台战略 —— 业务中台、数据中台、技术中台

目录 一. 前言 二. 中台能力总体框架 三. 业务中台 四. 数据中台 五. 技术中台 5.1. API 网关 5.2. 开发框架 5.3. 微服务治理 5.4. 分布式数据库 5.5. 数据处理组件 六. 阿里拆中台的原因和意义 七. 总结 一. 前言 中台是近年来互联网行业的一个热门话题。它最早是…

【STM32】| 01——常用外设 | USART

系列文章目录 【STM32】| 01——常用外设 | USART 失败了也挺可爱&#xff0c;成功了就超帅。 文章目录 前言1. 基础理论1.1 并行通信和串行通信1.2 同步通信和异步通信1.3 单工/半双工/全双工1.4 电平信号(RS232/TTL)和差分信号(RS485)1.5 端口(COM) 2. 串口理论2.1 串口物理…

基于apache的http文件服务配置

背景&#xff1a; 公司的产品使用的第三方模组可以OTA&#xff0c;厂家提供的是window开启软件&#xff0c;这样就可以在本机做http下载服务器&#xff0c;然后使用端口映射的方式&#xff0c;公开到外网&#xff0c;这样就可以进行4G网络访问内网服务器了。但这个有个弊端&am…

【C++】—— 工厂模式详解

目录 &#xff08;一&#xff09;工厂模式的特点 &#xff08;二&#xff09;工厂模式分类 1、简单工厂模式 2、工厂方法模式 3、抽象工厂模式 &#xff08;三&#xff09;总结与回顾 &#xff08;一&#xff09;工厂模式的特点 1、优势 ⼯⼚模式是⼀种创建型设计模式&a…

【大数据进阶第三阶段之Hue学习笔记】Hue的安装和使用

1、 Hue的安装 1.1 上传解压安装包 Hue的安装支持多种方式&#xff0c;包括rpm包的方式进行安装、tar.gz包的方式进行安装以及cloudera manager的方式来进行安装等&#xff0c;我们这里使用tar.gz包的方式来进行安装 Hue的压缩包的下载地址&#xff1a; http://archive.cloude…

C++|19.C++类与结构体对比

类和结构体 类和结构体本质上并没有太大区别。 但两者在默认上有所区别。 类默认成员变量是私有的&#xff0c;而结构体默认成员变量是公有的。 也就是说&#xff0c;对于一个类来说&#xff0c;会默认使用private去保护其内部成员变量使得无法直接访问到其内部的变量。 同时从…

CANoe中的AutoSequence

简单介绍&#xff1a; AutoSequence是一种简单的&#xff0c;快速的类似脚本的一个可视化自动脚本插件。使用起来非常方便&#xff0c;甚至在很多时候能够代替一些简单的脚本。 1&#xff1a;Automation工程的创建 &#xff08;1.1&#xff09;打开Automation插件,双击这个插…

TypeScript进阶(一)深入理解类和接口

✨ 专栏介绍 TypeScript是一种由微软开发的开源编程语言&#xff0c;它是JavaScript的超集&#xff0c;意味着任何有效的JavaScript代码都是有效的TypeScript代码。TypeScript通过添加静态类型和其他特性来增强JavaScript&#xff0c;使其更适合大型项目和团队开发。 在TypeS…

【2024最新-python3小白零基础入门】No2.python基础语法

文章目录 1 编码2 标识符规则3 python保留字4 注释5 行与缩进6 多行语句7 数字(Number)类型8 字符串(String)9 空行10 等待用户输入11 同一行显示多条语句12 import 与 from...import 环境准备&#xff0c;打开pycharm,新建一个python文件 文件名称随便&#xff0c;可中文可英文…

golang 记录一次协程和协程池的使用,利用ants协程池来处理定时器导致服务全部阻塞

前言 在实习的项目中有一个地方遇到了需要协程池的地方&#xff0c;在mt推荐下使用了ants库。因此在此篇记录一下自己学习使用此库的情况。 场景描述 此服务大致是一个kafka消息接收、发送相关。接收消息&#xff0c;根据参数设置定时器进行重发。 通过这里新建kafka服务&a…

ffmpeg[学习(四)](代码实现) 实现音频数据解码并且用SDL播放

0、作者杂谈 CSDN大多数都是落后的&#xff0c;要么是到处复制粘贴的&#xff0c;对于初学者我来说困惑了很久&#xff0c;大多数CSDN文章都是使用旧的API &#xff0c;已经被否决了&#xff0c;于是我读一些官方文档&#xff0c;和一些开源项目音视频的输出过程&#xff0c;写…

CCSC,一种CPU架构

core-circuit-separate-computer 核与执行电路的分离&#xff0c;最初是为了省电。 用寄存器实现这种分离。 V寄存器控制着执行电路的供电&#xff0c;V0则不供电&#xff0c;进入省电模式&#xff1b;V1则供电&#xff0c;进入工作模式。 P寄存器是parameter-register&#xf…

Qt应用-实现图像截取功能类似QQ上传头像截取功能

本文演示利用Qt实现图像截取功能类似QQ上传头像截取功能。 效果如下,通过移动中间的裁剪区域可以获得一张裁剪后的图片。 目录

Open3D 搜索某个点的圆柱形邻域点云(11)

Open3D 搜索某个点的圆柱形邻域点云(11) 一、算法介绍二、算法实现1、代码2、结果一、算法介绍 具体而言,search_hybrid_vector_3d方法会以指定的查询点为中心,在给定的半径范围内搜索邻域点。还可以指定近邻点的数量阈值,这对于需要特定数量邻域点的应用非常有用,比如提…

安全技能讲座 - 便携式灭火器 (Portable Fire Extinguishers )

【Transcript 】 火灾随时随地都可能发生&#xff0c;而且毫无征兆。如果您在家中或工作中遇到火灾&#xff0c;便携式灭火器可以帮助您保护自己&#xff0c;并有可能将火灾扼杀在摇篮中。本课程将向您介绍便携式灭火器、其工作原理和使用方法。成功完成本课程后&#xff0c;您…

kubectl常用命令(主题篇)

上一篇是按照操作把全局性的命令给整理出来&#xff0c;但是在实际的使用中&#xff0c;经常需要对某一个主题进行操作&#xff0c;因此这一篇按照对应的主题进行一系列操作。 集群 查看集群基本信息 kubectl cluster-info namespace 命名空间 查看 kubectl get namespace k…