Opencv-python 用solvepnp实现棋盘测距和欧拉角测定

Opencv-python 用solvepnp实现棋盘测距和欧拉角测定,第1张

概述Opencv-python用solvepnp实现棋盘测距和欧拉角测定相机标定,获取相机内参(内参数矩阵,畸变系数)用以标定的图像相机标定代码:importcv2importnumpyasnpimportglob#相机标定criteria=(cv2.TERM_CRITERIA_MAX_ITER|cv2.TERM_CRITERIA_EPS,30,0.001)#获取 Opencv-python 用solvepnp实现棋盘测距和欧拉角测定相机标定,获取相机内参 (内参数矩阵,畸变系数)
用以标定的图像

相机标定代码:

import cv2import numpy as npimport glob# 相机标定criteria = (cv2.TERM_CRITERIA_MAX_ITER | cv2.TERM_CRITERIA_EPS, 30, 0.001)# 获取标定板角点的位置objp = np.zeros((6 * 9, 3), np.float32)objp[:, :2] = np.mgrID[0:9, 0:6].T.reshape(-1, 2)  # 将世界坐标系建在标定板上,所有点的Z坐标全部为0,所以只需要赋值x和yobj_points = []  # 存储3D点img_points = []  # 存储2D点images=glob.glob(r"C:\*.jpg")  #黑白棋盘的图片路径i=0;for fname in images:    img = cv2.imread(fname)    gray = cv2.cvtcolor(img, cv2.color_BGR2GRAY)    size = gray.shape[::-1]    ret, corners = cv2.findChessboardCorners(gray, (9, 6), None)    if ret:        obj_points.append(objp)        corners2 = cv2.cornerSubPix(gray, corners, (5, 5), (-1, -1), criteria)  # 在原角点的基础上寻找亚像素角点        #print(corners2)        if [corners2]:            img_points.append(corners2)        else:            img_points.append(corners)        cv2.drawChessboardCorners(img, (9, 6), corners, ret)  # 记住,OpenCV的绘制函数一般无返回值        i+=1;        cv2.imwrite(r'Calibration_img\conimg'+str(i)+'.jpg', img)        cv2.waitKey(150)print(len(img_points))cv2.destroyAllwindows()# 标定ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(obj_points, img_points, size, None, None)print("ret:", ret)print("mtx:\n", mtx) # 内参数矩阵--内参print("dist:\n", dist)  # 畸变系数--内参 print("rvecs:\n", rvecs)  # 旋转向量--外参print("tvecs:\n", tvecs ) # 平移向量--外参

测量棋盘的长宽 手动测量棋盘长宽

将测量完棋盘的长宽和相机内参放进config配置文件中 (下为我的config文件)在Camera_intrinsic 中替换成自己的相机内参,在Object 替换自己的棋盘大小。icol 内置了几种用以检测颜色的HSV数值,可根据实际情况进行更改。

# -*- Coding: utf-8 -*-import numpy as np# 内参数矩阵Camera_intrinsic = {    "mtx": np.array([[652.90522946, 0., 321.31072448], [0., 653.00569689, 255.77694781], [0., 0., 1.]],                    dtype=np.double),    "dist": np.array([[-0.23397356, 0.39554466, 0.01463653, -0.00176085, -0.48223752]], dtype=np.double),}Object = {"height": 190, "wIDth": 279}# 初始的HSV GUI滑块值在程序启动时加载icol = {    # lowHue,highHue,lowSat,highSat,lowVal,highVal    "icol_black": (0, 180, 0, 255, 0, 46),  # 找黑色 适合白天    "icol_gray": (0, 180, 0, 43, 46, 220),    "icol_white": (0, 180, 0, 30, 221, 255),  # 找白色 适合晚上没灯    "icol_red": (156, 180, 43, 255, 46, 255),}
配置完成后先确定相机是电脑自带相机还是外接相机。电脑自带相机在VIDeoCapture中参数默认为0。import cv2.cv2 as cv2 这句报错的话改成import cv2 即可。
from __future__ import divisionimport numpy as npimport mathimport cv2.cv2 as cv2from config import *def nothing(*arg):    passhalf_Weight = int(Object["wIDth"] / 2)half_Height = int(Object["height"] / 2)# 滑动条用以调节HSV的参数cv2.nameDWindow('colorTest')  # 为滑动条创建窗口Icol = icol["icol_black"] # 初始化滑动条内的起始数据cv2.createTrackbar('lowHue', 'colorTest', Icol[0], 255, nothing)cv2.createTrackbar('highHue', 'colorTest', Icol[1], 255, nothing)cv2.createTrackbar('lowSat', 'colorTest', Icol[2], 255, nothing)cv2.createTrackbar('highSat', 'colorTest', Icol[3], 255, nothing)cv2.createTrackbar('lowVal', 'colorTest', Icol[4], 255, nothing)cv2.createTrackbar('highVal', 'colorTest', Icol[5], 255, nothing)camera = cv2.VIDeoCapture(0)while True:    (grabbed, frame) = camera.read()    # Get HSV values from the GUI slIDers.    lowHue = cv2.getTrackbarPos('lowHue', 'colorTest')    lowSat = cv2.getTrackbarPos('lowSat', 'colorTest')    lowVal = cv2.getTrackbarPos('lowVal', 'colorTest')    highHue = cv2.getTrackbarPos('highHue', 'colorTest')    highSat = cv2.getTrackbarPos('highSat', 'colorTest')    highVal = cv2.getTrackbarPos('highVal', 'colorTest')    frameBGR = cv2.GaussianBlur(frame.copy(), (7, 7), 0)  # 高斯模糊    hsv = cv2.cvtcolor(frameBGR, cv2.color_BGR2HSV)  # 颜色转换    colorLow = np.array([lowHue, lowSat, lowVal]) # 获取low HSV 的值    colorHigh = np.array([highHue, highSat, highVal]) # 获取high HSV 的值    mask = cv2.inRange(hsv, colorLow, colorHigh)    edged = cv2.Canny(mask, 35, 100) # canny算子找轮廓    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (7, 7))    dst = cv2.dilate(edged.copy(), kernel)  # 扩张,使轮廓闭合。    (cnts, _) = cv2.findContours(dst.copy(), cv2.RETR_List, cv2.CHAIN_APPROX_NONE)  # 找轮廓    area = []    # 求最大面积    try:        for k in range(len(cnts)):            area.append(cv2.contourArea(cnts[k]))        max_IDx = np.argmax(np.array(area))        cv2.drawContours(mask, cnts, max_IDx, (255, 255, 255), cv2.FILLED)        (cnts, _) = cv2.findContours(mask.copy(), cv2.RETR_List, cv2.CHAIN_APPROX_NONE)        c = max(cnts, key=cv2.contourArea)        marker = cv2.minAreaRect(c)        Box = np.int0(cv2.BoxPoints(marker))        cv2.drawContours(frame, [Box], -1, (255, 255, 255), 2)        obj = np.array([[-half_Weight, -half_Height, 0], [half_Weight, -half_Height, 0], [half_Weight, half_Height, 0],                        [-half_Weight, half_Height, 0]], dtype=np.float64)  # 世界坐标        pnts = np.array(Box, dtype=np.float64) # 像素坐标        # rotation_vector 旋转向量 translation_vector 平移向量        (success, rvec, tvec) = cv.solvePnP(obj, pnts, Camera_intrinsic["mtx"], Camera_intrinsic["dist"])        distance=math.sqrt(tvec[0]**2+tvec[1]**2+tvec[2]**2)/10  # 测算距离        rvec_matrix = cv2.Rodrigues(rvec)[0]        proj_matrix = np.hstack((rvec_matrix, rvec))        eulerAngles = -cv2.decomposeProjectionMatrix(proj_matrix)[6]  # 欧拉角        pitch, yaw, roll = eulerAngles[0], eulerAngles[1], eulerAngles[2]        rot_params = np.array([yaw, pitch, roll])  # 欧拉角 数组        # 这里pitch要变为其相反数(不知道为啥)        cv2.putText(frame, "%.2fcm,%.2f,%.2f,%.2f" % (distance, yaw, -pitch, roll),                    (frame.shape[1] - 500, frame.shape[0] - 20), cv2.Font_HERShey_SIMPLEX, 1.0, (0, 255, 0), 3)    except Exception:        pass    cv2.imshow('frame', frame)    cv2.imshow('mask-plain', mask)    if cv2.waitKey(1) & 0xFF == ord('q'):        breakcv2.destroyAllwindows()

mask-plain内为经过图像处理后的图像,也是用来找轮廓的图像。调试时可参照此图进行调节。
效果图:


有问题可以在评论区留言。如果喜欢这篇文章记得点赞哦!!!

总结

以上是内存溢出为你收集整理的Opencv-python 用solvepnp实现棋盘测距和欧拉角测定全部内容,希望文章能够帮你解决Opencv-python 用solvepnp实现棋盘测距和欧拉角测定所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/1188385.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-03
下一篇 2022-06-03

发表评论

登录后才能评论

评论列表(0条)

保存