├── IMG_LEFT.png ├── IMG_RIGHT.png ├── camera_configs.py ├── README.md ├── disparity.py ├── depth.py └── Calibration.py /IMG_LEFT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TOTOROWE/Binocular-Stereo-Vision/HEAD/IMG_LEFT.png -------------------------------------------------------------------------------- /IMG_RIGHT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TOTOROWE/Binocular-Stereo-Vision/HEAD/IMG_RIGHT.png -------------------------------------------------------------------------------- /camera_configs.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TOTOROWE/Binocular-Stereo-Vision/HEAD/camera_configs.py -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Binocular-Stereo-Vision 2 | Target location and tracking technology based on binocular vision 3 | -------------------------------------------------------------------------------- /disparity.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import numpy as np 3 | import cv2 4 | import matplotlib.pyplot as plt 5 | #import camera_configs 6 | #cv2.namedWindow("left") 7 | #cv2.namedWindow("right") 8 | #cv2.moveWindow("left", 0, 0) 9 | #cv2.moveWindow("right", 600, 0) 10 | #camera1 = cv2.VideoCapture(0) 11 | #camera2 = cv2.VideoCapture(1) 12 | 13 | def callbackFunc(e, x, y, f, p): 14 | if e == cv2.EVENT_LBUTTONDOWN: 15 | print(disparity[y][x]) 16 | 17 | cv2.setMouseCallback("depth", callbackFunc, None) 18 | 19 | while True: 20 | frame1 = cv2.imread('IMG_LEFT.png') 21 | frame2 = cv2.imread('IMG_RIGHT.png') 22 | # frame1 = cv2.imread('65L.jpg') 23 | # frame2 = cv2.imread('65R.jpg') 24 | # if not ret1 or not ret2: 25 | # break 26 | 27 | # img1_rectified = cv2.remap(frame1, camera_configs.left_map1, camera_configs.left_map2, cv2.INTER_LINEAR) 28 | # img2_rectified = cv2.remap(frame2, camera_configs.right_map1, camera_configs.right_map2, cv2.INTER_LINEAR) 29 | 30 | imgL = cv2.cvtColor(frame1, cv2.COLOR_BGR2GRAY) 31 | imgR = cv2.cvtColor(frame2, cv2.COLOR_BGR2GRAY) 32 | 33 | stereo = cv2.StereoBM_create(numDisparities=0, blockSize=11) 34 | disparity = stereo.compute(imgL, imgR) 35 | 36 | # disp = cv2.normalize(disparity, disparity, alpha=0, beta=255, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U) 37 | # threeD = cv2.reprojectImageTo3D(disparity.astype(np.float32)/16., camera_configs.Q) 38 | 39 | # cv2.imshow("left", imgL) 40 | # cv2.imshow("right", imgR) 41 | plt.imshow(disparity,'gray') 42 | plt.show() 43 | break 44 | 45 | key = cv2.waitKey(1) 46 | if key == ord("q"): 47 | break 48 | # cv2.imwrite("./snapshot/BM_left.jpg", imgL) 49 | # cv2.imwrite("./snapshot/BM_right.jpg", imgR) 50 | # cv2.imwrite("./snapshot/BM_depth.jpg", disp) 51 | 52 | #camera1.release() 53 | #camera2.release() 54 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /depth.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import numpy as np 3 | import cv2 4 | import camera_configs 5 | cv2.namedWindow("left") 6 | cv2.namedWindow("right") 7 | cv2.namedWindow("depth") 8 | cv2.moveWindow("left", 0, 0) 9 | cv2.moveWindow("right", 600, 0) 10 | cv2.createTrackbar("num", "depth", 0, 10, lambda x: None) 11 | cv2.createTrackbar("blockSize", "depth", 5, 255, lambda x: None) 12 | #camera1 = cv2.VideoCapture(0) 13 | #camera2 = cv2.VideoCapture(1) 14 | 15 | def callbackFunc(e, x, y, f, p): 16 | if e == cv2.EVENT_LBUTTONDOWN: 17 | print(threeD[y][x]) 18 | 19 | cv2.setMouseCallback("depth", callbackFunc, None) 20 | 21 | while True: 22 | frame1 = cv2.imread('IMG_LEFT.jpg') 23 | frame2 = cv2.imread('IMG_RIGHT.jpg') 24 | # if not ret1 or not ret2: 25 | # break 26 | 27 | img1_rectified = cv2.remap(frame1, camera_configs.left_map1, camera_configs.left_map2, cv2.INTER_LINEAR) 28 | img2_rectified = cv2.remap(frame2, camera_configs.right_map1, camera_configs.right_map2, cv2.INTER_LINEAR) 29 | 30 | imgL = cv2.cvtColor(img1_rectified, cv2.COLOR_BGR2GRAY) 31 | imgR = cv2.cvtColor(img2_rectified, cv2.COLOR_BGR2GRAY) 32 | 33 | num = cv2.getTrackbarPos("num", "depth") 34 | blockSize = cv2.getTrackbarPos("blockSize", "depth") 35 | if blockSize % 2 == 0: 36 | blockSize += 1 37 | if blockSize < 5: 38 | blockSize = 5 39 | 40 | stereo = cv2.StereoBM_create(numDisparities=16*num, blockSize=blockSize) 41 | disparity = stereo.compute(imgL, imgR) 42 | 43 | disp = cv2.normalize(disparity, disparity, alpha=0, beta=255, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U) 44 | threeD = cv2.reprojectImageTo3D(disparity.astype(np.float32)/16., camera_configs.Q) 45 | 46 | cv2.imshow("left", img1_rectified) 47 | cv2.imshow("right", img2_rectified) 48 | cv2.imshow("depth", disp) 49 | 50 | key = cv2.waitKey(1) 51 | if key == ord("q"): 52 | break 53 | # cv2.imwrite("./snapshot/BM_left.jpg", imgL) 54 | # cv2.imwrite("./snapshot/BM_right.jpg", imgR) 55 | # cv2.imwrite("./snapshot/BM_depth.jpg", disp) 56 | 57 | #camera1.release() 58 | #camera2.release() 59 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /Calibration.py: -------------------------------------------------------------------------------- 1 | #coding:utf-8 2 | import cv2 3 | import numpy as np 4 | import glob 5 | 6 | 7 | # 模块说明:相机标定模块 8 | 9 | def Calibration(PATH,WIDTH,HEIGHT,PX,PY): 10 | # 设置寻找亚像素角点的参数,采用的停止准则是最大循环次数30和最大误差容限0.001 11 | CRITERIA = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER , 30 ,0.001) 12 | # 设置棋盘规格,即角点个数为 witdth x height 13 | # WIDTH = 7 14 | # HEIGHT = 7 15 | # 设置用于标定的图片像素 16 | SIZE = (PX,PY) 17 | # 世界坐标系中,角点坐标格式,去掉Z坐标,为二维矩阵 18 | obj_p = np.zeros((WIDTH * HEIGHT,3),np.float32) 19 | obj_p[:,:2] = np.mgrid[0:WIDTH,0:HEIGHT].T.reshape(-1,2) 20 | # 世界坐标系和图像坐标系点集 21 | obj_points = [] 22 | img_points = [] 23 | 24 | IMAGES = glob.glob(PATH) 25 | for pf in IMAGES: 26 | IMG = cv2.imread(pf) 27 | # 灰度图 28 | IMG_GRAY = cv2.cvtColor(IMG,cv2.COLOR_BGR2GRAY) 29 | # 获取角点 30 | RET,CORNERS = cv2.findChessboardCorners(IMG_GRAY,(WIDTH,HEIGHT),None) 31 | 32 | if RET == True: 33 | obj_points.append(obj_p) 34 | # 寻找亚像素点, 搜索窗口(winsize为11x11),无死区 35 | SUBCORNERS = cv2.cornerSubPix(IMG_GRAY,CORNERS,(5,5),(-1,-1),CRITERIA) 36 | if SUBCORNERS is not None: 37 | img_points.append(SUBCORNERS) 38 | else: 39 | img_points.append(CORNERS) 40 | # 标定: 41 | # MTX : 内参数矩阵 42 | # DIST: 畸变系数 43 | # RVS : 旋转向量(外参数) 44 | # TVS : 平移向量(外参数) 45 | RET,MTX,DIST,RVS,TVS = cv2.calibrateCamera(obj_points,img_points,SIZE,None,None) 46 | return (IMG_GRAY,obj_points,img_points,RET,MTX,DIST,RVS,TVS) 47 | 48 | # 去除畸变 49 | def RemvDist(IMG_GRAY,MTX,DIST): 50 | H,W = IMG_GRAY.shape[:2] 51 | # 自由设置比例参数 52 | ncmtx,roi = cv2.getOptimalNewCameraMatrix(MTX,DIST,(W,H),1,(W,H)) 53 | # 使用undistort函数去畸变 54 | dst = cv2.undistort(IMG_GRAY,MTX,DIST,None,ncmtx) 55 | return dst 56 | 57 | # 反投影误差 58 | def BackProjErr(obj_points,img_points,RET,MTX,DIST,RVS,TVS): 59 | Errs = 0 60 | AvgErr = 0 61 | for obj_p in xrange(len(obj_points)): 62 | img_points_pr ,_ = cv2.projectPoints(obj_points[obj_p],RVS[obj_p],TVS[obj_p],MTX,DIST) 63 | Errs += cv2.norm(img_points[obj_p],img_points_pr,cv2.NORM_L2)/len(img_points_pr) 64 | AvgErr = Errs / len(obj_points) 65 | return Errs,AvgErr 66 | 67 | # 画线 68 | def DrawAxis(img, corners, imgpoints): 69 | corner = tuple(corners[0].ravel()) 70 | cv2.line(img, corner, tuple(imgpoints[0].ravel()), 255 * np.random.random(size=3), 5) 71 | cv2.line(img, corner, tuple(imgpoints[1].ravel()), 255 * np.random.random(size=3), 5) 72 | cv2.line(img, corner, tuple(imgpoints[2].ravel()), 255 * np.random.random(size=3), 5) 73 | return img 74 | # 画立体对象 75 | def DrawCube(img, corners, imgpoints): 76 | imgpoints = np.int32(imgpoints).reshape(-1,2) 77 | cv2.drawContours(img, [imgpoints[:4]], -1, 255 * np.random.random(size=3), -3) 78 | for i,j in zip(range(4), range(4,8)): 79 | cv2.line(img, tuple(imgpoints[i]), tuple(imgpoints[j]), 255 * np.random.random(size=3), 3) 80 | cv2.drawContours(img, [imgpoints[4:]], -1, 255 * np.random.random(size=3), 3) 81 | return img 82 | # 图片尺寸 83 | def SizeofPic(PATH): 84 | pf = cv2.imread(PATH) 85 | return pf.shape[::-1] 86 | 87 | if __name__ == '__main__': 88 | (IMG_GRAY,obj_points,img_points,RET,MTX,DIST,RVS,TVS) = Calibration("./assets/calibration/*.JPG",7,7,1024,768) 89 | # print BackProjErr(obj_points,img_points,RET,MTX,DIST,RVS,TVS) 90 | # IMG = RemvDist(IMG_GRAY,MTX,DIST) 91 | 92 | 93 | 94 | 95 | 96 | --------------------------------------------------------------------------------