学习记录 -官网文档学习-相机标定和三维重建

1、 相机标定

https://docs.opencv.org/3.0-beta/doc/py_tutorials/py_calib3d/py_calibration/py_calibration.html#calibration

图片:https://files.cnblogs.com/files/blogs/760881/%E7%9B%B8%E6%9C%BA%E6%A0%A1%E5%87%86%E5%92%8C3%E7%BB%B4%E9%87%8D%E5%BB%BA.zip?t=1736736254&download=true

import numpy as np
import cv2
import glob# termination criteria
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)# 获得棋盘格数据 用来相机标定
# prepare object points, like (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)# Arrays to store object points and image points from all the images.
objpoints = [] # 3d point in real world space
imgpoints = [] # 2d points in image plane.

images = glob.glob('pics_calibration/*.jpg')for fname in images:img = cv2.imread(fname)gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)# Find the chess board cornersret, corners = cv2.findChessboardCorners(gray, (7,6),None)# If found, add object points, image points (after refining them)if ret == True:objpoints.append(objp)cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)imgpoints.append(corners)# Draw and display the cornerscv2.drawChessboardCorners(img, (7,6), corners,ret)cv2.imshow('img',img)cv2.waitKey(500)# 标定相机
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1],None,None)
# retval:标定的重投影误差,该误差越小,标定结果越好。
# cameraMatrix:估计的相机内参矩阵(如果作为输入参数提供,则此参数将被更新)。
# distCoeffs:估计的畸变系数(如果作为输入参数提供,则此参数将被更新)。
# rvecs:每幅图像的旋转向量。
# tvecs:每幅图像的平移向量。# 消除图片的畸变 方法1
img = cv2.imread('pics_calibration/left12.jpg')
h,  w = img.shape[:2]
newcameramtx, roi=cv2.getOptimalNewCameraMatrix(mtx,dist,(w,h),0,(w,h))
# undistort
dst = cv2.undistort(img, mtx, dist, None, newcameramtx)
# crop the image
x,y,w,h = roi
dst = dst[y:y+h, x:x+w]
cv2.imwrite('calibresult1.png',dst)# 消除图片的畸变 方法2
# undistort  
mapx,mapy = cv2.initUndistortRectifyMap(mtx,dist,None,newcameramtx,(w,h),5)
dst = cv2.remap(img,mapx,mapy,cv2.INTER_LINEAR)#消除img的畸变得到新图片 dst# crop the image
x,y,w,h = roi
dst = dst[y:y+h, x:x+w]
cv2.imwrite('calibresult2.png',dst)cv2.imshow('undistort', dst)# 计算误差
mean_error = 0
for i in range(len(objpoints)):imgpoints2, _ = cv2.projectPoints(objpoints[i], rvecs[i], tvecs[i], mtx, dist)error = cv2.norm(imgpoints[i],imgpoints2, cv2.NORM_L2)/len(imgpoints2)mean_error += errorprint("total error: ", mean_error/len(objpoints))cv2.waitKey(0)
cv2.destroyAllWindows()

 2、位姿估计

 在图片上绘制坐标系

import cv2
import numpy as np
import glob# Load previously saved data
import numpy as np# 直接加载.npy文件,假设它保存了一个字典
data = np.load('B.npy',allow_pickle=True).item()  # 使用allow_pickle=True来加载可能包含pickle对象的.npy文件,并使用.item()将字典从NumPy数组中提取出来(如果.npy文件直接保存的是字典,则可能不需要.item())# 解包数据
mtx, dist, rvecs, tvecs = data['mtx'], data['dist'], data['rvecs'], data['tvecs']def draw(img, corners, imgpts):corner = tuple(corners[0].ravel())img = cv2.line(img, corner, tuple(imgpts[0].ravel()), (255,0,0), 5)img = cv2.line(img, corner, tuple(imgpts[1].ravel()), (0,255,0), 5)img = cv2.line(img, corner, tuple(imgpts[2].ravel()), (0,0,255), 5)return img# 类型:cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER
# cv2.TERM_CRITERIA_EPS 表示算法会在达到某个指定的精度(或误差)时停止。
# cv2.TERM_CRITERIA_MAX_ITER 表示算法会在达到最大迭代次数时停止。
# 通过使用按位或运算符 +(在Python中实际上是按位或 |,但在这里由于历史原因使用了 +,尽管在OpenCV的C++接口中它是按位或 |),您可以同时指定这两个条件。算法会在满足任一条件时停止。
# 最大迭代次数:30
# 这是算法在停止之前可以执行的最大迭代次数。
# 所需精度:0.001
# 这是算法在停止之前需要达到的精度(或误差)阈值。
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)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)for fname in glob.glob('pics_calibration/left*.jpg'):img = cv2.imread(fname)gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)ret, corners = cv2.findChessboardCorners(gray, (7,6),None)if ret == True:corners2 = cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)# Find the rotation and translation vectors.# rvecs:旋转向量(旋转矩阵的紧凑表示)。# tvecs:平移向量。# inliers:内点索引数组(表示哪些点被认为是内点)。# mask:与# inliers# 对应的掩码数组(通常用于标记哪些点是内点) 内点,即被认为是有效匹配的数据点retval, rvecs, tvecs, inliers= cv2.solvePnPRansac(objp, corners2, mtx, dist)#print(objp.shape)# print(mtx)# print(dist)# print(rvecs.shape)# print(rvecs.dtype)print(rvecs)# project 3D points to image planeimgpts, jac = cv2.projectPoints(axis, rvecs, tvecs, mtx, dist)img = draw(img,corners2,imgpts)cv2.imshow('img',img)k = cv2.waitKey(0) & 0xffif k == 's':cv2.imwrite(fname[:6]+'.png', img)cv2.waitKey(0)
cv2.destroyAllWindows()

在图片上绘制一个cube

import cv2
import numpy as np
import glob# Load previously saved data
import numpy as np# 直接加载.npy文件,假设它保存了一个字典
data = np.load('B.npy',allow_pickle=True).item()  # 使用allow_pickle=True来加载可能包含pickle对象的.npy文件,并使用.item()将字典从NumPy数组中提取出来(如果.npy文件直接保存的是字典,则可能不需要.item())# 解包数据
mtx, dist, rvecs, tvecs = data['mtx'], data['dist'], data['rvecs'], data['tvecs']# def draw(img, corners, imgpts):
#     corner = tuple(corners[0].ravel())
#     img = cv2.line(img, corner, tuple(imgpts[0].ravel()), (255,0,0), 5)
#     img = cv2.line(img, corner, tuple(imgpts[1].ravel()), (0,255,0), 5)
#     img = cv2.line(img, corner, tuple(imgpts[2].ravel()), (0,0,255), 5)
#     return img
def draw(img, corners, imgpts):imgpts = np.int32(imgpts).reshape(-1,2)# draw ground floor in greenimg = cv2.drawContours(img, [imgpts[:4]],-1,(0,255,0),-3)# draw pillars in blue colorfor i,j in zip(range(4),range(4,8)):img = cv2.line(img, tuple(imgpts[i]), tuple(imgpts[j]),(255),3)# draw top layer in red colorimg = cv2.drawContours(img, [imgpts[4:]],-1,(0,0,255),3)return img
# 类型:cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER
# cv2.TERM_CRITERIA_EPS 表示算法会在达到某个指定的精度(或误差)时停止。
# cv2.TERM_CRITERIA_MAX_ITER 表示算法会在达到最大迭代次数时停止。
# 通过使用按位或运算符 +(在Python中实际上是按位或 |,但在这里由于历史原因使用了 +,尽管在OpenCV的C++接口中它是按位或 |),您可以同时指定这两个条件。算法会在满足任一条件时停止。
# 最大迭代次数:30
# 这是算法在停止之前可以执行的最大迭代次数。
# 所需精度:0.001
# 这是算法在停止之前需要达到的精度(或误差)阈值。
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)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 = np.float32([[0,0,0], [0,3,0], [3,3,0], [3,0,0],[0,0,-3],[0,3,-3],[3,3,-3],[3,0,-3] ])
for fname in glob.glob('pics_calibration/left*.jpg'):img = cv2.imread(fname)gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)ret, corners = cv2.findChessboardCorners(gray, (7,6),None)if ret == True:corners2 = cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)# Find the rotation and translation vectors.# rvecs:旋转向量(旋转矩阵的紧凑表示)。# tvecs:平移向量。# inliers:内点索引数组(表示哪些点被认为是内点)。# mask:与# inliers# 对应的掩码数组(通常用于标记哪些点是内点) 内点,即被认为是有效匹配的数据点retval, rvecs, tvecs, inliers= cv2.solvePnPRansac(objp, corners2, mtx, dist)#print(objp.shape)# print(mtx)# print(dist)# print(rvecs.shape)# print(rvecs.dtype)print(rvecs)# project 3D points to image planeimgpts, jac = cv2.projectPoints(axis, rvecs, tvecs, mtx, dist)img = draw(img,corners2,imgpts)cv2.imshow('img',img)k = cv2.waitKey(0) & 0xffif k == 's':cv2.imwrite(fname[:6]+'.png', img)cv2.waitKey(0)
cv2.destroyAllWindows()

 

3、Epipolar Geometry

3.1 ORB 特征检测和描述器

import cv2
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.pyplot import imshowimg1 = cv2.imread('pics_Epipolar_Geometry/left.jpg',0)  #queryimage # left image
img2 = cv2.imread('pics_Epipolar_Geometry/right.jpg',0) #trainimage # right image
print(img1 is not None, img2 is not None)# cv2.imshow('img2',img2)
# cv2.waitKey(0)
# cv2.destroyAllWindows()
# sift = cv2.SIFT()
#
# # find the keypoints and descriptors with SIFT
# kp1, des1 = sift.detectAndCompute(img1,None)
# kp2, des2 = sift.detectAndCompute(img2,None)# 创建 ORB 特征检测和描述器实例
#orb = cv2.ORB()
orb = cv2.ORB_create()
# 使用 ORB 算法找到关键点和描述符
# 注意:这里的注释已经更改为反映实际使用的算法
kp1, des1 = orb.detectAndCompute(img1, None)
kp2, des2 = orb.detectAndCompute(img2, None)# FLANN parameters
FLANN_INDEX_KDTREE = 0
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)# 使用 KDTree 算法和 5 棵树
search_params = dict(checks=50) # 每个查询检查 50 个节点

flann = cv2.FlannBasedMatcher(index_params,search_params)des1 = des1.astype(np.float32)
des2 = des2.astype(np.float32)#matches = flann.knnMatch(des1,des2,k=2)
# 假设 des1 和 des2 已经是有效的 np.float32 类型的描述符矩阵
matches = flann.knnMatch(des1, des2, k=2)good = []
pts1 = []
pts2 = []# ratio test as per Lowe's paper
for i,(m,n) in enumerate(matches):if m.distance < 0.8*n.distance:good.append(m)pts2.append(kp2[m.trainIdx].pt)pts1.append(kp1[m.queryIdx].pt)pts1 = np.int32(pts1)
pts2 = np.int32(pts2)
F, mask = cv2.findFundamentalMat(pts1,pts2,cv2.FM_LMEDS)# We select only inlier points
pts1 = pts1[mask.ravel()==1]
pts2 = pts2[mask.ravel()==1]def drawlines(img1,img2,lines,pts1,pts2):''' img1 - image on which we draw the epilines for the points in img2lines - corresponding epilines '''r,c = img1.shapeimg1 = cv2.cvtColor(img1,cv2.COLOR_GRAY2BGR)img2 = cv2.cvtColor(img2,cv2.COLOR_GRAY2BGR)for r,pt1,pt2 in zip(lines,pts1,pts2):color = tuple(np.random.randint(0,255,3).tolist())x0,y0 = map(int, [0, -r[2]/r[1] ])x1,y1 = map(int, [c, -(r[2]+r[0]*c)/r[1] ])img1 = cv2.line(img1, (x0,y0), (x1,y1), color,1)img1 = cv2.circle(img1,tuple(pt1),5,color,-1)img2 = cv2.circle(img2,tuple(pt2),5,color,-1)return img1,img2# Find epilines corresponding to points in right image (second image) and
# drawing its lines on left image
lines1 = cv2.computeCorrespondEpilines(pts2.reshape(-1,1,2), 2,F)
lines1 = lines1.reshape(-1,3)
img5,img6 = drawlines(img1,img2,lines1,pts1,pts2)# Find epilines corresponding to points in left image (first image) and
# drawing its lines on right image
lines2 = cv2.computeCorrespondEpilines(pts1.reshape(-1,1,2), 1,F)
lines2 = lines2.reshape(-1,3)
img3,img4 = drawlines(img2,img1,lines2,pts2,pts1)plt.subplot(121),plt.imshow(img5)
plt.subplot(122),plt.imshow(img3)
plt.show()

3.2  使用 SIFT算法,必须安装 opencv-contrib-python  4.4.0.46或以上

pip install opencv-contrib-python==4.4.0.46

sift 查找关键点

import cv2
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.pyplot import imshowimg1 = cv2.imread('pics_Epipolar_Geometry/left.jpg',0)  #queryimage # left image
img2 = cv2.imread('pics_Epipolar_Geometry/right.jpg',0) #trainimage # right image
print(img1 is not None, img2 is not None)# cv2.imshow('img2',img2)
# cv2.waitKey(0)
# cv2.destroyAllWindows()
# sift = cv2.SIFT()
#
# # find the keypoints and descriptors with SIFT
# kp1, des1 = sift.detectAndCompute(img1,None)
# kp2, des2 = sift.detectAndCompute(img2,None)# 创建 ORB 特征检测和描述器实例
#orb = cv2.ORB()# orb = cv2.ORB_create()
# # 使用 ORB 算法找到关键点和描述符
# # 注意:这里的注释已经更改为反映实际使用的算法
# kp1, des1 = orb.detectAndCompute(img1, None)
# kp2, des2 = orb.detectAndCompute(img2, None)
# 使用SIFT 算法找到关键点和描述符
sift = cv2.SIFT_create()
kp1, des1 = sift.detectAndCompute(img1, None)
kp2, des2 = sift.detectAndCompute(img2, None)
# FLANN parameters
FLANN_INDEX_KDTREE = 0
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)# 使用 KDTree 算法和 5 棵树
search_params = dict(checks=50) # 每个查询检查 50 个节点

flann = cv2.FlannBasedMatcher(index_params,search_params)des1 = des1.astype(np.float32)
des2 = des2.astype(np.float32)#matches = flann.knnMatch(des1,des2,k=2)
# 假设 des1 和 des2 已经是有效的 np.float32 类型的描述符矩阵
matches = flann.knnMatch(des1, des2, k=2)good = []
pts1 = []
pts2 = []# ratio test as per Lowe's paper
for i,(m,n) in enumerate(matches):if m.distance < 0.8*n.distance:good.append(m)pts2.append(kp2[m.trainIdx].pt)pts1.append(kp1[m.queryIdx].pt)pts1 = np.int32(pts1)
pts2 = np.int32(pts2)
F, mask = cv2.findFundamentalMat(pts1,pts2,cv2.FM_LMEDS)# We select only inlier points
pts1 = pts1[mask.ravel()==1]
pts2 = pts2[mask.ravel()==1]def drawlines(img1,img2,lines,pts1,pts2):''' img1 - image on which we draw the epilines for the points in img2lines - corresponding epilines '''r,c = img1.shapeimg1 = cv2.cvtColor(img1,cv2.COLOR_GRAY2BGR)img2 = cv2.cvtColor(img2,cv2.COLOR_GRAY2BGR)for r,pt1,pt2 in zip(lines,pts1,pts2):color = tuple(np.random.randint(0,255,3).tolist())x0,y0 = map(int, [0, -r[2]/r[1] ])x1,y1 = map(int, [c, -(r[2]+r[0]*c)/r[1] ])img1 = cv2.line(img1, (x0,y0), (x1,y1), color,1)img1 = cv2.circle(img1,tuple(pt1),5,color,-1)img2 = cv2.circle(img2,tuple(pt2),5,color,-1)return img1,img2# Find epilines corresponding to points in right image (second image) and
# drawing its lines on left image
lines1 = cv2.computeCorrespondEpilines(pts2.reshape(-1,1,2), 2,F)
lines1 = lines1.reshape(-1,3)
img5,img6 = drawlines(img1,img2,lines1,pts1,pts2)# Find epilines corresponding to points in left image (first image) and
# drawing its lines on right image
lines2 = cv2.computeCorrespondEpilines(pts1.reshape(-1,1,2), 1,F)
lines2 = lines2.reshape(-1,3)
img3,img4 = drawlines(img2,img1,lines2,pts2,pts1)plt.subplot(121),plt.imshow(img5)
plt.subplot(122),plt.imshow(img3)
plt.show()

 4、

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

协作管理工具在多部门协作中的优势与应用

一、跨职能团队协作的挑战 跨职能团队的协作面临多个方面的挑战,这些挑战往往会影响团队的工作效率、项目的推进速度以及最终的项目质量。 1.1 信息传递不畅在跨职能团队中,成员来自不同的部门,各自拥有不同的背景、职责和目标。因此,团队成员之间的沟通可能不够顺畅,信息…

side channel

‌Side Channel‌,中文称为“边信道”,是指通过加密软件或硬件运行时产生的各种泄漏信息来获取密文信息的攻击方式。在狭义上,边信道攻击特指针对密码算法的非侵入式攻击,通过分析加密电子设备在运行过程中的边信道信息泄露来破解密码算法。常见的边信道攻击包括计时攻击、…

RocketMQ工具的使用方法

RocketMQ简介 启动rocketmq-Dashboard项目 输入 http://localhost:8888/#/ 即可到rocketmq界面 整体横向菜单分为八个部分:OPS(运维):主要是设置nameserver和配置vipchannel Dashboard(驾驶舱):控制台的dashboard,可以分别按broker和主题来查看消息的数量和趋势。 Cluster(…

【docker】docker desktop换国内源时 apply按钮为灰色or换源失败 解决方法

配docker环境时复制进去国内镜像源后,发现apply按钮为灰色,点不了,如下图解决方法:往下滑,找到下图圈住的选项打勾再回到Docker Engine界面,发现可以点apply按钮了在文本框中添加"registry-mirrors": ["http://mirrors.ustc.edu.cn","http://mi…

ElasticSearch在Windows环境搭建测试

引子 也持续关注大数据相关内容一段时间,大数据内容很多。想了下还是从目前项目需求侧出发,进行相关学习。Elasticsearch(ES)是位于 Elastic Stack(ELK stack) 核心的分布式搜索和分析引擎。Logstash 和 Beats 有助于收集、聚合和丰富您的数据并将其存储在 Elasticsearch…

科研绘图系列:python语言绘制SCI图合集

介绍 科研绘图系列:python语言绘制SCI图合集 加载python import numpy as np import pandas as pd import matplotlib.pyplot as plt import matplotlib.patches as mpatches import seaborn as snsfrom statsmodels.stats.multitest import multipletests# Setup for local r…

Postman相关

postman打开控制台的快捷键alt+ctrl+c1、工具栏 New: 新建,可以新建Request请求,Collection请求集,环境等等 Import: 导入,可以导入别人导出的请求集 Runner: 运行一个请求集(批量执行) Invite: 邀请(需要注册,邀请进行协作) 同步图标: (需要注册,同步你的项目到云…

TorchOptimizer:基于贝叶斯优化的PyTorch Lightning超参数调优框架

超参数优化是深度学习模型开发过程中的一个核心技术难点。合适的超参数组合能够显著提升模型性能,但优化过程往往需要消耗大量计算资源和时间。本文介绍TorchOptimizer,这是一个基于贝叶斯优化方法的超参数优化框架,专门用于优化PyTorch Lightning模型的超参数配置。TorchOp…

深入理解ASP.NET Core 管道的工作原理

在 .NET Core 中,管道(Pipeline)是处理 HTTP 请求和响应的中间件组件的有序集合。每个中间件组件都可以对请求进行处理,并将其传递给下一个中间件组件,直到请求到达最终的处理程序。管道的概念类似于流水线,每个中间件组件都是流水线中的一个步骤。1. 管道的基本概念 在 …

svn检出has encountered a problem cannot checkout

报错信息:"svn检出has encountered a problem Cannot checkout" 表示 Subversion(SVN)在尝试检出(即下载)版本控制仓库的时候遇到了问题。 解释: 这个错误通常意味着 SVN 客户端无法完成检出操作,可能的原因有多种,包括网络问题、权限问题、URL错误、服务器不…

ABC388

好像已经很久没有写过题解了 C link对于每一个糕点,二分查找大于等于它大小的二倍的糕点的位置(可以用\(lower_{}bound\)函数),从这个位置到\(n\)就是可以和这个糕点配对的糕点。猜猜我是啥 #include<bits/stdc++.h>#define int long longusing namespace std;int n;…

零知识证明二(椭圆曲线配对)

本文章将V神关于椭圆曲线配对的文章进行了翻译。原文在此: https://medium.com/@VitalikButerin/exploring-elliptic-curve-pairings-c73c1864e627 1 简介 椭圆曲线配对是各种构造背后的关键密码原型之一,包括确定性阈值签名、zk-SNARKs和其他更简单形式的零知识证明。椭圆曲…