利用pycharm工具+python语言,设计一个单目摄像头的调用函数,可以进行实时的抓拍的功能。具体封装的函数,实现的代码如下:
def read_show():
cap = cv2.VideoCapture(0, cv2.CAP_DSHOW) # 捕获摄像头
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('output.mp4', fourcc, 30, (640, 480)) # 自己更改视频的格式
index = 1
while cap.isOpened():
ret, frame = cap.read()
out.write(frame)
cv2.imshow("截图", frame)
k = cv2.waitKey(0) & 0xFF
if k == ord("q"): # 按q进行退出模式
break
elif k == ord('s'): # 按s进行截图
cv2.imwrite('C:/Users/28719/Desktop/video_test/' + str(index) + ".jpg", frame) # 保存相机拍照文件夹
index += 1
cap.release()
cv2.destroyAllWindows()
当我们完成封装调用拍摄的任务之后,就可以通过调用网络上常用的opencv的矫正代码,进行校正,我的矫正代码是通过垃圾入门封装自己弄的。自己弄的时候,没有把标定的过程去掉,所以代码中含有标定的部分,具体代码如下:
import cv2
import numpy as np
import glob
def jiao_zheng(char):
"""
相机校正函数,需要先点击此函数,更改相机的标定图片,然后进行相机的内参矩阵获取。
:param char: 为待校正图片路径
"""
# 设置寻找亚像素角点的参数,采用的停止准则是最大循环次数30和最大误差容限0.001
criteria = (cv2.TERM_CRITERIA_MAX_ITER | cv2.TERM_CRITERIA_EPS, 30, 0.001)
# 获取标定板角点的位置
objp = np.zeros((11 * 8, 3), np.float32)
objp[:, :2] = np.mgrid[0:11, 0:8].T.reshape(-1, 2) # 将世界坐标系建在标定板上,所有点的Z坐标全部为0,所以只需要赋值x和y
obj_points = [] # 存储3D点
img_points = [] # 存储2D点
images = glob.glob("C:/Users/28719/Desktop/image/*.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, (11, 8), None)
if ret:
obj_points.append(objp)
# 在原角点的基础上寻找亚像素角点
corners2 = cv2.cornerSubPix(gray, corners, (6, 7), (-1, -1), criteria)
if [corners2]:
img_points.append(corners2)
else:
img_points.append(corners)
# 记住,OpenCV的绘制函数一般无返回值
cv2.drawChessboardCorners(img, (11, 8), corners, ret)
i += 1
cv2.imwrite("C:/Users/28719/Desktop/image_test/" + str(i) + '.png', img)
cv2.waitKey(1500)
else:
print(str(fname))
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) # 畸变系数 distortion cofficients = (k_1,k_2,p_1,p_2,k_3)
print("旋转向量rvecs:\n", rvecs) # 旋转向量 # 外参数
print("平移向量tvecs:\n", tvecs) # 平移向量 # 外参数
print("-----------------------------------------------------")
# 使用读取到的第三张图片进行校正
img = cv2.imread(char)
h, w = img.shape[:2]
# 使用cv.getOptimalNewCameraMatrix()优化内参数和畸变系数,
# 当alpha设为1的时候,将会返回一个包含额外黑色像素点的内参数和畸变系数,并返回一个ROI用于将其剪裁掉
newcameramtx, roi = cv2.getOptimalNewCameraMatrix(mtx, dist, (w, h), 1, (w, h))
print("调节视场大小后的相机内参矩阵为:\n")
print(newcameramtx)
print("------------------使用undistort函数-------------------")
# 有两种方法,第二种是重映射的方法:通过cv2.initUndistortRectifyMap和cv2.remap一起校正
dst = cv2.undistort(img, mtx, dist, None, newcameramtx)
x, y, w, h = roi
dst1 = dst[y:y + h, x:x + w]
# 将矫正后的图片写入到指定文件夹
cv2.imwrite("C:/Users/28719/Desktop/video_test_photo/1.jpg", dst1)
# 展示校正前的图片与校正后的图片
cv2.imshow("original", img)
cv2.imshow("undistorted", dst)
print("dst的大小为:", dst.shape)
cv2.waitKey(0)
cv2.destroyAllWindows()
这是一个能够标定和校正的函数,合在一起就是如下所示:
# 开发日期:2022/7/28
import cv2
import xp_相机标定1
def read_show():
cap = cv2.VideoCapture(0, cv2.CAP_DSHOW) # 捕获摄像头
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('output.mp4', fourcc, 30, (640, 480)) # 自己更改视频的格式
index = 1
while cap.isOpened():
ret, frame = cap.read()
out.write(frame)
cv2.imshow("截图", frame)
k = cv2.waitKey(0) & 0xFF
if k == ord("q"): # 按q进行退出模式
break
elif k == ord('s'): # 按s进行截图
cv2.imwrite('C:/Users/28719/Desktop/video_test/' + str(index) + ".jpg", frame) # 保存相机拍照文件夹
index += 1
cap.release()
cv2.destroyAllWindows()
if __name__ == '__main__':
read_show()
char = "C:/Users/28719/Desktop/video_test/1.jpg" # 指定待校正的文件夹
xp_相机标定1.jiao_zheng(char)
通过 mian来调用事先写好的函数,xp_相机标定1.jiao_zheng(char)中xp_相机标定1为函数所在的python文件名。