Aim:使用calib3D模块在图像中创建3D效果
基础
- 通过摄像机矩阵、畸变系数等,估计图像中图案的姿势。比如:目标对象如何摆放、如何旋转。对平面对象增加z=0从而成为摄像机在空间内摆放的问题。
- 首先,加载摄像机矩阵和畸变系数。
- 然后,创建函数draw,参数:棋盘上的角点(cv2.findChessboardCorners() 得到)、要绘制的3D坐标轴上的点。
- 其次,设置终止条件,对象点(棋盘上的3D角点)和坐标轴点(为了绘制坐标轴)。
- 先加载图像搜寻7×6的格子,如果找到就优化到亚像素级,再使用函数cv2.solvePnPRansac() 计算旋转和变换。也可以利用变换矩阵将坐标轴点映射到图像平面。
- 第五点的目的就是在图像平面找到与3D空间中点相对应的点,再用函数draw() 从图像上第一个角点绘制连接这些点的直线。
代码演示
#coding=utf-8
import cv2
import glob
import numpy as np
with np.load('B.npz') as X:
mtx,dist,_,_=[X[i] for i in ('mtx','dist','rvecs','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
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('./image2/qipan.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)
rvecs,tvecs,inliers=cv2.solvePnPRansac(objp,corners2,mtx,dist)
imgpts,jac=cv2.projectPoints(axis,rvecs,tvecs,mtx,dist)
img=draw(img,corners2,imgpts)
cv2.imshow('img',img)
k=cv2.waitKey(0)&0xFF
if k=='s':
cv2.imshow('img2',img)
cv2.destroyAllWindows()
渲染一个立方体
对draw()函数进行修改,修改后的坐标轴点是3D空间中一个立方体的8个角点。
代码演示
#coding=utf-8
import numpy as np
import cv2
def draw(img,corners,imgpts):
imgpts=np.int32(imgpts).reshape(-1,2)
img=cv2.drawContours(img,[imgpts[:4]],-1,(0,255,0),-3)
for i,j in zip(range(4),range(4,8)):
img=cv2.line(img,tuple(imgpts[i]),tuple(imgpts[j]),(255),3)
img=cv2.drawContours(img,[imgpts[4:]],-1,(0,0,255),3)
return img