当前位置:   article > 正文

双目相机三维坐标计算与视差计算,python-opencv实现_cv2.ximgproc.createrightmatcher

cv2.ximgproc.createrightmatcher

原理我就不说了,就是各种公式推导和坐标转换再加上一些计算方法。

要使用这个代码首先你得有自己采集的双目图片,或者可以用cv自带的来运行代码。

其次该代码也是自己综合了许多人的代码略微调整修改了,可以说是缝合怪。其中如何匹配左右图像的点(貌似可以极线校正后利用极线匹配来做,但我好像不知道怎样做)我是自己想的,可能很粗糙,也不知道对不对。思路就是:通过给左右图片的内角点标上序号,然后左右相机的相同序号的内角点作为一组点位代入三维坐标求解函数。

直接上代码吧!我自己做的实验不理想(拍摄的图片找不到角点,图片分辨率太大不知道缩小分辨率是否会对标定有影响),但我不知道是代码问题还是啥,就发出来让大家一起学习与指导一下。

第一个版本:matlab标定,opencv处理

  1. import numpy as np
  2. import cv2
  3. import os
  4. import xml.dom.minidom
  5. # 遍历图片
  6. def getFileList(dir,Filelist, ext=None):
  7. """
  8. 获取文件夹及其子文件夹中文件列表
  9. 输入 dir:文件夹根目录
  10. 输入 ext: 扩展名
  11. 返回: 文件路径列表
  12. """
  13. newDir = dir
  14. if os.path.isfile(dir):
  15. if ext is None:
  16. Filelist.append(dir)
  17. else:
  18. if ext in dir[-3:]:
  19. Filelist.append(dir)
  20. elif os.path.isdir(dir):
  21. for s in os.listdir(dir):
  22. newDir=os.path.join(dir,s)
  23. getFileList(newDir, Filelist, ext)
  24. return Filelist
  25. # 计算内焦点世界坐标
  26. def calRealPoint(row,col,trueLength):
  27. imgpoint = []
  28. for rowIndex in range(0,col):
  29. for colIndex in range(0,row):
  30. imgpoint.append([colIndex*trueLength,rowIndex*trueLength,0])
  31. imgpoint = np.array(imgpoint,np.float32)
  32. return imgpoint
  33. # 画线
  34. def draw_line1(image1, image2):
  35. # 建立输出图像
  36. height = max(image1.shape[0], image2.shape[0])
  37. width = image1.shape[1] + image2.shape[1]
  38. output = np.zeros((height, width,3), dtype=np.uint8)
  39. output[0:image1.shape[0], 0:image1.shape[1]] = image1
  40. output[0:image2.shape[0], image1.shape[1]:] = image2
  41. for k in range(15):
  42. cv2.line(output, (0, 50 * (k + 1)), (2 * width, 50 * (k + 1)), (0, 255, 0), thickness=2, lineType=cv2.LINE_AA) # 直线间隔:100
  43. return output
  44. # 三维坐标计算
  45. def uvToXYZ(lx, ly, rx, ry):
  46. mLeft = np.hstack([leftRotation, leftTranslation])
  47. mLeftM = np.dot(MLS, mLeft)
  48. mRight = np.hstack([R, T])
  49. mRightM = np.dot(MRS, mRight)
  50. # print(mLeft)
  51. # print(mLeftM)
  52. A = np.zeros(shape=(4, 3))
  53. for i in range(0, 3):
  54. A[0][i] = lx * mLeftM[2, i] - mLeftM[0][i]
  55. for i in range(0, 3):
  56. A[1][i] = ly * mLeftM[2][i] - mLeftM[1][i]
  57. for i in range(0, 3):
  58. A[2][i] = rx * mRightM[2][i] - mRightM[0][i]
  59. for i in range(0, 3):
  60. A[3][i] = ry * mRightM[2][i] - mRightM[1][i]
  61. B = np.zeros(shape=(4, 1))
  62. B[0][0] = mLeftM[0][3] - lx * mLeftM[2][3]
  63. B[1][0] = mLeftM[1][3] - ly * mLeftM[2][3]
  64. B[2][0] = mRightM[0][3] - rx * mRightM[2][3]
  65. B[3][0] = mRightM[1][3] - ry * mRightM[2][3]
  66. XYZ = np.zeros(shape=(3, 1))
  67. # 采用最小二乘法求其空间坐标
  68. cv2.solve(A, B, XYZ, cv2.DECOMP_SVD)
  69. # print('坐标为:\n',XYZ)
  70. return XYZ
  71. # 获取像素坐标
  72. def get_pixel(img,index):
  73. gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
  74. _,corners = cv2.findChessboardCorners(gray,(row,col))
  75. criteria = (cv2.TermCriteria_EPS+cv2.TermCriteria_MAX_ITER,30,0.01)
  76. corners2 = cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)
  77. return corners2[index].ravel()
  78. # 从xml(matlab生成)读取内外参数等
  79. def getParams(file):
  80. dom = xml.dom.minidom.parse(file)
  81. root = dom.documentElement
  82. datas = root.getElementsByTagName('data')
  83. after_datas = []
  84. for data in datas:
  85. data = data.firstChild.data
  86. data = data.replace('\n', '').replace('\r', '')
  87. data = data.split(' ')[0:-1]
  88. data = [float(x) for x in data]
  89. after_datas.append(data)
  90. MLS = np.array(after_datas[0]).reshape(3,3)
  91. MRS = np.array(after_datas[1]).reshape(3,3)
  92. dLS = np.array(after_datas[2])
  93. dRS = np.array(after_datas[3])
  94. R = np.array(after_datas[4]).reshape(3,3)
  95. T = np.array(after_datas[5]).reshape(3,1)
  96. return MLS,MRS,dLS,dRS,R,T
  97. # 清空文件
  98. def del_file(path):
  99. ls = os.listdir(path)
  100. for i in ls:
  101. c_path = os.path.join(path, i)
  102. if os.path.isdir(c_path):
  103. del_file(c_path)
  104. else:
  105. os.remove(c_path)
  106. del_file('./left_')
  107. del_file('./right_')
  108. del_file('./left_re')
  109. del_file('./right_re')
  110. leftRotation = np.array([[1, 0, 0],
  111. [0, 1, 0],
  112. [0, 0, 1]])
  113. leftTranslation = np.array([[0],
  114. [0],
  115. [0]])
  116. # 棋盘格内焦点个数横纵
  117. # 参数读取
  118. MLS,MRS,dLS,dRS,R,T = getParams('2th.xml')
  119. print('L内参\n',MLS)
  120. print('L畸变\n',dLS)
  121. print('R内参\n',MRS)
  122. print('R畸变\n',dRS)
  123. print('旋转\n',R)
  124. print('平移\n',T)
  125. row = 9
  126. col = 6
  127. # 格子真实尺寸
  128. trueLength = 10
  129. # 图片后缀
  130. hz = 'jpg'
  131. # 遍历图片
  132. imglistL = getFileList('./left',[],hz)
  133. imglistR = getFileList('./right',[],hz)
  134. # 创建存储能被角点检测到的图片的文件夹
  135. folderL = './left_'
  136. folderR = './right_'
  137. if not os.path.exists(folderL):
  138. os.mkdir(folderL)
  139. if not os.path.exists(folderR):
  140. os.mkdir(folderR)
  141. # 首先检测图片角点检测是否正确
  142. for i in range(0,len(imglistL)):
  143. ChessImaR = cv2.imread(imglistR[i],0)
  144. ChessImaL = cv2.imread(imglistL[i],0)
  145. # 角点检测
  146. retR, cornersR = cv2.findChessboardCorners(ChessImaR,
  147. (row,col),None)
  148. retL, cornersL = cv2.findChessboardCorners(ChessImaL,
  149. (row,col),None)
  150. # 只要一对图片中有一张不能检测角点,这对图片便舍弃
  151. if (retR == True) & (retL == True):
  152. print('第%d对图片符合'%i)
  153. # 同时存入另一个文件夹
  154. cv2.imwrite(folderL+'/img'+str(i)+'.'+hz,ChessImaL)
  155. cv2.imwrite(folderR+'/img'+str(i)+'.'+hz,ChessImaR)
  156. # 画出检测的角点
  157. cv2.drawChessboardCorners(ChessImaL, (row, col), cornersL, retL)
  158. cv2.drawChessboardCorners(ChessImaR, (row, col), cornersR, retR)
  159. cv2.imshow('imgL',ChessImaL)
  160. cv2.imshow('imgR',ChessImaR)
  161. if cv2.waitKey(0) & 0xFF == ord(' '):
  162. continue
  163. if cv2.waitKey(0) & 0xFF == 27:
  164. break
  165. else:
  166. print('第%d对图片不符合,剔除'%i)
  167. # 遍历筛选后图片
  168. imglistL_ = getFileList(folderL,[],hz)
  169. imglistR_ = getFileList(folderR,[],hz)
  170. # 参数含义不知
  171. rectify_scale = 0
  172. # Q重投影矩阵
  173. RL, RR, PL, PR, Q, roiL, roiR = cv2.stereoRectify(MLS, dLS, MRS, dRS,
  174. ChessImaR.shape[::-1], R, T,
  175. rectify_scale,(0,0),alpha=-1)
  176. # 畸变校正
  177. Left_Stereo_Map = cv2.initUndistortRectifyMap(MLS, dLS, RL, PL,
  178. ChessImaR.shape[::-1], cv2.CV_16SC2)
  179. Right_Stereo_Map = cv2.initUndistortRectifyMap(MRS, dRS, RR, PR,
  180. ChessImaR.shape[::-1], cv2.CV_16SC2)
  181. # 参数设置参考官方例程
  182. window_size = 3
  183. min_disp = 16
  184. num_disp = 112-min_disp
  185. stereo = cv2.StereoSGBM_create(minDisparity = min_disp,
  186. numDisparities = num_disp,
  187. blockSize = 16,
  188. P1 = 8*3*window_size**2,
  189. P2 = 32*3*window_size**2,
  190. disp12MaxDiff = 1,
  191. uniquenessRatio = 10,
  192. speckleWindowSize = 100,
  193. speckleRange = 32
  194. )
  195. # 使用滤波器降低噪声
  196. stereoR=cv2.ximgproc.createRightMatcher(stereo)
  197. # 过滤器参数设置
  198. lmbda = 80000
  199. sigma = 1.8
  200. visual_multiplier = 1.0
  201. wls_filter = cv2.ximgproc.createDisparityWLSFilter(matcher_left=stereo)
  202. wls_filter.setLambda(lmbda)
  203. wls_filter.setSigmaColor(sigma)
  204. # 创建保存极线校正的图片
  205. folderL_ = './left_re'
  206. folderR_ = './right_re'
  207. if not os.path.exists(folderL_):
  208. os.mkdir(folderL_)
  209. if not os.path.exists(folderR_):
  210. os.mkdir(folderR_)
  211. # 标定参数使用
  212. for i in range(0,len(imglistL_)):
  213. frameR = cv2.imread(imglistR_[i])
  214. frameL = cv2.imread(imglistL_[i])
  215. # Rectify图片,极线校正
  216. Left_nice = cv2.remap(frameL,Left_Stereo_Map[0],Left_Stereo_Map[1], cv2.INTER_AREA)
  217. Right_nice = cv2.remap(frameR,Right_Stereo_Map[0],Right_Stereo_Map[1], cv2.INTER_AREA)
  218. # 保存极线校正后的图片
  219. cv2.imwrite(folderL_+'/img'+str(i)+'.'+hz,Left_nice)
  220. cv2.imwrite(folderR_+'/img'+str(i)+'.'+hz,Right_nice)
  221. # 显示极线校正的图片
  222. res1 = draw_line1(Left_nice,Right_nice)
  223. cv2.imshow('ln',Left_nice)
  224. cv2.imshow('rn',Right_nice)
  225. cv2.imshow('res1',res1)
  226. # 计算距离三维坐标
  227. u11,v11 = get_pixel(Left_nice,0)
  228. u21,v21 = get_pixel(Right_nice,0)
  229. u12,v12 = get_pixel(Left_nice,1)
  230. u22,v22 = get_pixel(Right_nice,1)
  231. p1 = uvToXYZ(u11,v11,u21,v21)
  232. p2 = uvToXYZ(u12,v12,u22,v22)
  233. print('p1坐标\n',p1)
  234. print('p2坐标\n',p2)
  235. print('距离\n',np.linalg.norm(p1-p2))
  236. ################################################
  237. grayR= cv2.cvtColor(Right_nice,cv2.COLOR_BGR2GRAY)
  238. grayL= cv2.cvtColor(Left_nice,cv2.COLOR_BGR2GRAY)
  239. # 计算深度,参考官方例程
  240. dispL= stereo.compute(grayL,grayR).astype(np.float32)/ 16.0
  241. dispR= stereo.compute(grayR,grayL).astype(np.float32)/ 16.0
  242. # 使用滤波器降噪,filteredimg为过滤后的深度图
  243. filteredImg= wls_filter.filter(dispL,grayL,None,dispR)
  244. filteredImg = cv2.normalize(src=filteredImg, dst=filteredImg, beta=0, alpha=255,
  245. norm_type=cv2.NORM_MINMAX)
  246. filteredImg = np.uint8(filteredImg)
  247. points = cv2.reprojectImageTo3D(dispL,Q)
  248. cv2.imshow('filteredImg',filteredImg)
  249. cv2.imshow('disparity', (dispL-min_disp)/num_disp)
  250. if cv2.waitKey(0) & 0xFF == ord(' '):
  251. continue
  252. if cv2.waitKey(0) & 0xFF == 27:
  253. break
  254. cv2.waitKey(0)
  255. cv2.destroyAllWindows()

matlab标定参数变xml

  1. function writeXML(stereoParams,file)
  2. docNode = com.mathworks.xml.XMLUtils.createDocument('opencv_storage'); %创建xml文件对象
  3. docRootNode = docNode.getDocumentElement; %获取根节点
  4. IntrinsicMatrixl = (stereoParams.CameraParameters1.IntrinsicMatrix)'; %相机内参矩阵
  5. RadialDistortionl = stereoParams.CameraParameters1.RadialDistortion; %相机径向畸变参数向量1*3
  6. TangentialDistortionl =stereoParams.CameraParameters1.TangentialDistortion; %相机切向畸变向量1*2
  7. Distortionl = [RadialDistortionl(1:2),TangentialDistortionl,RadialDistortionl(3)]; %构成opencv中的畸变系数向量[k1,k2,p1,p2,k3]
  8. IntrinsicMatrixr = (stereoParams.CameraParameters2.IntrinsicMatrix)'; %相机内参矩阵
  9. RadialDistortionr = stereoParams.CameraParameters2.RadialDistortion; %相机径向畸变参数向量1*3
  10. TangentialDistortionr =stereoParams.CameraParameters2.TangentialDistortion; %相机切向畸变向量1*2
  11. Distortionr = [RadialDistortionr(1:2),TangentialDistortionr,RadialDistortionr(3)]; %构成opencv中的畸变系数向量[k1,k2,p1,p2,k3]
  12. R = stereoParams.RotationOfCamera2';
  13. T = stereoParams.TranslationOfCamera2;
  14. camera_matrix = docNode.createElement('lcamera-matrix'); %创建mat节点
  15. data = docNode.createElement('data');
  16. for i=1:3
  17. for j=1:3
  18. data.appendChild(docNode.createTextNode(sprintf('%.16f ',IntrinsicMatrixl(i,j))));
  19. end
  20. data.appendChild(docNode.createTextNode(sprintf('\n')));
  21. end
  22. camera_matrix.appendChild(data);
  23. docRootNode.appendChild(camera_matrix);
  24. camera_matrix = docNode.createElement('rcamera-matrix'); %创建mat节点
  25. data = docNode.createElement('data');
  26. for i=1:3
  27. for j=1:3
  28. data.appendChild(docNode.createTextNode(sprintf('%.16f ',IntrinsicMatrixr(i,j))));
  29. end
  30. data.appendChild(docNode.createTextNode(sprintf('\n')));
  31. end
  32. camera_matrix.appendChild(data);
  33. docRootNode.appendChild(camera_matrix);
  34. distortion = docNode.createElement('ldistortion');
  35. data = docNode.createElement('data');
  36. for i=1:5
  37. data.appendChild(docNode.createTextNode(sprintf('%.16f ',Distortionl(i))));
  38. end
  39. distortion.appendChild(data);
  40. docRootNode.appendChild(distortion);
  41. distortion = docNode.createElement('rdistortion');
  42. data = docNode.createElement('data');
  43. for i=1:5
  44. data.appendChild(docNode.createTextNode(sprintf('%.16f ',Distortionr(i))));
  45. end
  46. distortion.appendChild(data);
  47. docRootNode.appendChild(distortion);
  48. rM = docNode.createElement('R');
  49. data = docNode.createElement('data');
  50. for i=1:3
  51. for j=1:3
  52. data.appendChild(docNode.createTextNode(sprintf('%.16f ',R(i,j))));
  53. end
  54. data.appendChild(docNode.createTextNode(sprintf('\n')));
  55. end
  56. rM.appendChild(data);
  57. docRootNode.appendChild(rM);
  58. tM = docNode.createElement('T');
  59. data = docNode.createElement('data');
  60. for i = 1:3
  61. data.appendChild(docNode.createTextNode(sprintf('%.16f ',T(i))));
  62. end
  63. tM.appendChild(data);
  64. docRootNode.appendChild(tM);
  65. xmlFileName = file;
  66. xmlwrite(xmlFileName,docNode);
  67. end

第二个版本,标定与立体校正匹配等全用cv

 

  1. import numpy as np
  2. import cv2
  3. import os
  4. # 遍历图片
  5. def getFileList(dir,Filelist, ext=None):
  6. """
  7. 获取文件夹及其子文件夹中文件列表
  8. 输入 dir:文件夹根目录
  9. 输入 ext: 扩展名
  10. 返回: 文件路径列表
  11. """
  12. newDir = dir
  13. if os.path.isfile(dir):
  14. if ext is None:
  15. Filelist.append(dir)
  16. else:
  17. if ext in dir[-3:]:
  18. Filelist.append(dir)
  19. elif os.path.isdir(dir):
  20. for s in os.listdir(dir):
  21. newDir=os.path.join(dir,s)
  22. getFileList(newDir, Filelist, ext)
  23. return Filelist
  24. # 计算内焦点世界坐标
  25. def calRealPoint(row,col,trueLength):
  26. imgpoint = []
  27. for rowIndex in range(0,col):
  28. for colIndex in range(0,row):
  29. imgpoint.append([colIndex*trueLength,rowIndex*trueLength,0])
  30. imgpoint = np.array(imgpoint,np.float32)
  31. return imgpoint
  32. # 画线
  33. def draw_line1(image1, image2):
  34. # 建立输出图像
  35. height = max(image1.shape[0], image2.shape[0])
  36. width = image1.shape[1] + image2.shape[1]
  37. output = np.zeros((height, width,3), dtype=np.uint8)
  38. output[0:image1.shape[0], 0:image1.shape[1]] = image1
  39. output[0:image2.shape[0], image1.shape[1]:] = image2
  40. for k in range(15):
  41. cv2.line(output, (0, 50 * (k + 1)), (2 * width, 50 * (k + 1)), (0, 255, 0), thickness=2, lineType=cv2.LINE_AA) # 直线间隔:100
  42. return output
  43. # 三维坐标计算
  44. def uvToXYZ(lx, ly, rx, ry):
  45. mLeft = np.hstack([leftRotation, leftTranslation])
  46. mLeftM = np.dot(MLS, mLeft)
  47. mRight = np.hstack([R, T])
  48. mRightM = np.dot(MRS, mRight)
  49. # print(mLeft)
  50. # print(mLeftM)
  51. A = np.zeros(shape=(4, 3))
  52. for i in range(0, 3):
  53. A[0][i] = lx * mLeftM[2, i] - mLeftM[0][i]
  54. for i in range(0, 3):
  55. A[1][i] = ly * mLeftM[2][i] - mLeftM[1][i]
  56. for i in range(0, 3):
  57. A[2][i] = rx * mRightM[2][i] - mRightM[0][i]
  58. for i in range(0, 3):
  59. A[3][i] = ry * mRightM[2][i] - mRightM[1][i]
  60. B = np.zeros(shape=(4, 1))
  61. B[0][0] = mLeftM[0][3] - lx * mLeftM[2][3]
  62. B[1][0] = mLeftM[1][3] - ly * mLeftM[2][3]
  63. B[2][0] = mRightM[0][3] - rx * mRightM[2][3]
  64. B[3][0] = mRightM[1][3] - ry * mRightM[2][3]
  65. XYZ = np.zeros(shape=(3, 1))
  66. # 采用最小二乘法求其空间坐标
  67. cv2.solve(A, B, XYZ, cv2.DECOMP_SVD)
  68. # print('坐标为:\n',XYZ)
  69. return XYZ
  70. # 获取像素坐标
  71. def get_pixel(img,index):
  72. gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
  73. _,corners = cv2.findChessboardCorners(gray,(row,col))
  74. criteria = (cv2.TermCriteria_EPS+cv2.TermCriteria_MAX_ITER,30,0.01)
  75. corners2 = cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)
  76. return corners2[index].ravel()
  77. # 清空文件夹文件
  78. def del_file(path):
  79. ls = os.listdir(path)
  80. for i in ls:
  81. c_path = os.path.join(path, i)
  82. if os.path.isdir(c_path):
  83. del_file(c_path)
  84. else:
  85. os.remove(c_path)
  86. # 初始化
  87. del_file('./left_')
  88. del_file('./right_')
  89. del_file('./left_re')
  90. del_file('./right_re')
  91. leftRotation = np.array([[1, 0, 0],
  92. [0, 1, 0],
  93. [0, 0, 1]])
  94. leftTranslation = np.array([[0],
  95. [0],
  96. [0]])
  97. # 棋盘格内焦点个数横纵
  98. row = 9
  99. col = 6
  100. # 格子真实尺寸
  101. trueLength = 10
  102. # 图片后缀
  103. hz = 'jpg'
  104. # 遍历图片
  105. imglistL = getFileList('./left',[],hz)
  106. imglistR = getFileList('./right',[],hz)
  107. # 创建存储能被角点检测到的图片的文件夹
  108. folderL = './left_'
  109. folderR = './right_'
  110. if not os.path.exists(folderL):
  111. os.mkdir(folderL)
  112. if not os.path.exists(folderR):
  113. os.mkdir(folderR)
  114. # 首先检测图片角点检测是否正确
  115. for i in range(0,len(imglistL)):
  116. ChessImaR = cv2.imread(imglistR[i],0)
  117. ChessImaL = cv2.imread(imglistL[i],0)
  118. # 角点检测
  119. retR, cornersR = cv2.findChessboardCorners(ChessImaR,
  120. (row,col),None)
  121. retL, cornersL = cv2.findChessboardCorners(ChessImaL,
  122. (row,col),None)
  123. # 只要一对图片中有一张不能检测角点,这对图片便舍弃
  124. if (retR == True) & (retL == True):
  125. print('第%d对图片符合'%i)
  126. # 同时存入另一个文件夹
  127. cv2.imwrite(folderL+'/img'+str(i)+'.'+hz,ChessImaL)
  128. cv2.imwrite(folderR+'/img'+str(i)+'.'+hz,ChessImaR)
  129. # 画出检测的角点
  130. cv2.drawChessboardCorners(ChessImaL, (row, col), cornersL, retL)
  131. cv2.drawChessboardCorners(ChessImaR, (row, col), cornersR, retR)
  132. cv2.imshow('imgL',ChessImaL)
  133. cv2.imshow('imgR',ChessImaR)
  134. if cv2.waitKey(0) & 0xFF == ord(' '):
  135. continue
  136. if cv2.waitKey(0) & 0xFF == 27:
  137. break
  138. else:
  139. print('第%d对图片不符合,剔除'%i)
  140. #############################################################
  141. #############################################################
  142. # 对筛选后的图像进行标定,校正,匹配,求视差,最小二乘求解空间坐标
  143. # 亚像素的参数和立体标定的参数
  144. criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
  145. criteria_stereo = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
  146. # 遍历筛选后图片
  147. imglistL_ = getFileList(folderL,[],hz)
  148. imglistR_ = getFileList(folderR,[],hz)
  149. # 存储每对图片的世界坐标,z为0,其它根据格子实际长度计算
  150. objpoints = []
  151. # 分别存储左右图片的角点亚像素坐标
  152. imgpointsR = []
  153. imgpointsL = []
  154. # 计算世界坐标下内角的坐标
  155. objp = calRealPoint(row,col,trueLength)
  156. print('Starting calibration for the 2 cameras... ')
  157. for i in range(0,len(imglistL_)):
  158. ChessImaL_ = cv2.imread(imglistL_[i],0)
  159. ChessImaR_ = cv2.imread(imglistR_[i],0)
  160. retR_, cornersR_ = cv2.findChessboardCorners(ChessImaR_,
  161. (row,col),None)
  162. retL_, cornersL_ = cv2.findChessboardCorners(ChessImaL_,
  163. (row,col),None)
  164. if (True == retR_) & (True == retL_):
  165. # 亚像素
  166. cornersR2_ = cv2.cornerSubPix(ChessImaR_,cornersR_,(11,11),(-1,-1),criteria)
  167. cornersL2_ = cv2.cornerSubPix(ChessImaL_,cornersL_,(11,11),(-1,-1),criteria)
  168. imgpointsR.append(cornersR2_)
  169. imgpointsL.append(cornersL2_)
  170. objpoints.append(objp)
  171. # 画角点
  172. cv2.drawChessboardCorners(ChessImaL_, (row, col), cornersL2_, retL_)
  173. cv2.drawChessboardCorners(ChessImaR_, (row, col), cornersR2_, retR_)
  174. print('第%d对图片'%i)
  175. cv2.imshow('imgL',ChessImaL_)
  176. cv2.imshow('imgR',ChessImaR_)
  177. if cv2.waitKey(0) & 0xFF == ord(' '):
  178. continue
  179. if cv2.waitKey(0) & 0xFF == 27:
  180. break
  181. # 类似先进行单目标定
  182. retR, mtxR, distR, rvecsR, tvecsR = cv2.calibrateCamera(objpoints,
  183. imgpointsR,
  184. ChessImaR_.shape[::-1],None,None)
  185. # 重投影误差计算
  186. for i in range(0,len(objpoints)):
  187. err = 0
  188. ChessImaR_1 = cv2.imread(imglistR_[i])
  189. # 反向计算像素坐标,与亚像素角点坐标比较 ,计算的temp有两部分
  190. temp = cv2.projectPoints(objpoints[i],rvecsR[i],tvecsR[i],mtxR,distR)
  191. for j in range(0,temp[0].shape[0]):
  192. err = err+np.linalg.norm(temp[0][j]-imgpointsR[i][j])
  193. err = err/temp[0].shape[0]
  194. print('右边第%d张重新投影与原角点亚像素平均误差为:%f\n'%(i,err))
  195. cv2.drawChessboardCorners(ChessImaR_1, (row, col), temp[0],patternWasFound=True)
  196. cv2.imshow('the_right',ChessImaR_1)
  197. if cv2.waitKey(0) & 0xFF == ord(' '):
  198. continue
  199. if cv2.waitKey(0) & 0xFF == 27:
  200. break
  201. ###############################################################################
  202. retL, mtxL, distL, rvecsL, tvecsL = cv2.calibrateCamera(objpoints,
  203. imgpointsL,
  204. ChessImaL_.shape[::-1],None,None)
  205. # 重投影误差计算
  206. for i in range(0,len(objpoints)):
  207. err = 0
  208. ChessImaL_1 = cv2.imread(imglistL_[i])
  209. # 反向计算像素坐标,与亚像素角点坐标比较 ,计算的temp有两部分
  210. temp = cv2.projectPoints(objpoints[i],rvecsL[i],tvecsL[i],mtxL,distL)
  211. for j in range(0,temp[0].shape[0]):
  212. err = err+np.linalg.norm(temp[0][j]-imgpointsL[i][j])
  213. err = err/temp[0].shape[0]
  214. print('左边第%d张重新投影与原角点亚像素平均误差为:%f\n'%(i,err))
  215. cv2.drawChessboardCorners(ChessImaL_1, (row, col), temp[0],patternWasFound=True)
  216. cv2.imshow('the_left',ChessImaL_1)
  217. if cv2.waitKey(0) & 0xFF == ord(' '):
  218. continue
  219. if cv2.waitKey(0) & 0xFF == 27:
  220. break
  221. print('Cameras Ready to use')
  222. #############################################################################
  223. # 立体标定及可选参数,具体查阅
  224. flags = 0
  225. flags |= cv2.CALIB_FIX_INTRINSIC
  226. #flags |= cv2.CALIB_FIX_PRINCIPAL_POINT
  227. # flags |= cv2.CALIB_USE_INTRINSIC_GUESS
  228. #flags |= cv2.CALIB_FIX_FOCAL_LENGTH
  229. #flags |= cv2.CALIB_FIX_ASPECT_RATIO
  230. #flags |= cv2.CALIB_ZERO_TANGENT_DIST
  231. #flags |= cv2.CALIB_RATIONAL_MODEL
  232. #flags |= cv2.CALIB_SAME_FOCAL_LENGTH
  233. #flags |= cv2.CALIB_FIX_K3
  234. #flags |= cv2.CALIB_FIX_K4
  235. #flags |= cv2.CALIB_FIX_K5
  236. retS, MLS, dLS, MRS, dRS, R, T, E, F = cv2.stereoCalibrate(objpoints,
  237. imgpointsL,
  238. imgpointsR,
  239. mtxL,
  240. distL,
  241. mtxR,
  242. distR,
  243. ChessImaR.shape[::-1],
  244. criteria_stereo,
  245. flags)
  246. print('L内参\n',MLS)
  247. print('L畸变\n',dLS)
  248. print('R内参\n',MRS)
  249. print('R畸变\n',dRS)
  250. print('旋转\n',R)
  251. print('平移\n',T)
  252. # 参数含义不知
  253. rectify_scale = 0
  254. # Q重投影矩阵
  255. RL, RR, PL, PR, Q, roiL, roiR = cv2.stereoRectify(MLS, dLS, MRS, dRS,
  256. ChessImaR.shape[::-1], R, T,
  257. rectify_scale,(0,0),alpha=-1)
  258. # 畸变校正
  259. Left_Stereo_Map = cv2.initUndistortRectifyMap(MLS, dLS, RL, PL,
  260. ChessImaR.shape[::-1], cv2.CV_16SC2)
  261. Right_Stereo_Map = cv2.initUndistortRectifyMap(MRS, dRS, RR, PR,
  262. ChessImaR.shape[::-1], cv2.CV_16SC2)
  263. # 参数设置参考官方例程
  264. window_size = 3
  265. min_disp = 16
  266. num_disp = 112-min_disp
  267. stereo = cv2.StereoSGBM_create(minDisparity = min_disp,
  268. numDisparities = num_disp,
  269. blockSize = 16,
  270. P1 = 8*3*window_size**2,
  271. P2 = 32*3*window_size**2,
  272. disp12MaxDiff = 1,
  273. uniquenessRatio = 10,
  274. speckleWindowSize = 100,
  275. speckleRange = 32
  276. )
  277. # 使用滤波器降低噪声
  278. stereoR=cv2.ximgproc.createRightMatcher(stereo)
  279. # 过滤器参数设置
  280. lmbda = 80000
  281. sigma = 1.8
  282. visual_multiplier = 1.0
  283. wls_filter = cv2.ximgproc.createDisparityWLSFilter(matcher_left=stereo)
  284. wls_filter.setLambda(lmbda)
  285. wls_filter.setSigmaColor(sigma)
  286. # 创建保存极线校正的图片
  287. folderL_ = './left_re'
  288. folderR_ = './right_re'
  289. if not os.path.exists(folderL_):
  290. os.mkdir(folderL_)
  291. if not os.path.exists(folderR_):
  292. os.mkdir(folderR_)
  293. # 标定参数使用
  294. for i in range(0,len(imglistL_)):
  295. frameR = cv2.imread(imglistR_[i])
  296. frameL = cv2.imread(imglistL_[i])
  297. # Rectify图片,极线校正
  298. Left_nice = cv2.remap(frameL,Left_Stereo_Map[0],Left_Stereo_Map[1], cv2.INTER_AREA)
  299. Right_nice = cv2.remap(frameR,Right_Stereo_Map[0],Right_Stereo_Map[1], cv2.INTER_AREA)
  300. # 保存极线校正后的图片
  301. cv2.imwrite(folderL_+'/img'+str(i)+'.'+hz,Left_nice)
  302. cv2.imwrite(folderR_+'/img'+str(i)+'.'+hz,Right_nice)
  303. # 显示极线校正的图片
  304. res1 = draw_line1(Left_nice,Right_nice)
  305. cv2.imshow('ln',Left_nice)
  306. cv2.imshow('rn',Right_nice)
  307. cv2.imshow('res1',res1)
  308. # 计算距离三维坐标
  309. u11,v11 = get_pixel(Left_nice,0)
  310. u21,v21 = get_pixel(Right_nice,0)
  311. u12,v12 = get_pixel(Left_nice,1)
  312. u22,v22 = get_pixel(Right_nice,1)
  313. p1 = uvToXYZ(u11,v11,u21,v21)
  314. p2 = uvToXYZ(u12,v12,u22,v22)
  315. print('p1坐标\n',p1)
  316. print('p2坐标\n',p2)
  317. print('距离\n',np.linalg.norm(p1-p2))
  318. ################################################
  319. grayR= cv2.cvtColor(Right_nice,cv2.COLOR_BGR2GRAY)
  320. grayL= cv2.cvtColor(Left_nice,cv2.COLOR_BGR2GRAY)
  321. # 计算深度,参考官方例程
  322. dispL= stereo.compute(grayL,grayR).astype(np.float32)/ 16.0
  323. dispR= stereo.compute(grayR,grayL).astype(np.float32)/ 16.0
  324. # 使用滤波器降噪,filteredimg为过滤后的深度图
  325. filteredImg= wls_filter.filter(dispL,grayL,None,dispR)
  326. filteredImg = cv2.normalize(src=filteredImg, dst=filteredImg, beta=0, alpha=255,
  327. norm_type=cv2.NORM_MINMAX)
  328. filteredImg = np.uint8(filteredImg)
  329. points = cv2.reprojectImageTo3D(dispL,Q)
  330. cv2.imshow('filteredImg',filteredImg)
  331. cv2.imshow('disparity', (dispL-min_disp)/num_disp)
  332. if cv2.waitKey(0) & 0xFF == ord(' '):
  333. continue
  334. if cv2.waitKey(0) & 0xFF == 27:
  335. break
  336. cv2.waitKey(0)
  337. cv2.destroyAllWindows()

希望能帮到大家,最好有大佬能帮我解决一个问题,以上代码都是网上搜集自己整理,我也不知道是谁的了,就感谢大家所有人!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/152814
推荐阅读
相关标签
  

闽ICP备14008679号