利用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()
这是一个能够标定和校正的函数,合在一起就是如下所示:
# 作者:LOSER # 开发日期: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文件名。