2017-10-11 18 views
0

필자의 상황에서는 OpenCV StereoBM Depth Map에 의해 반환 된 데이터가 매개 변수 튜닝에 관계없이 의미가 없습니다.StereoBM과 함께 사용하려면 카메라를 보정해야합니까?

저는 OpenCV를 사용하고 입체감을 사용하여 깊이 맵을 생성하는 디자인 프로젝트에 대한 연구를하고 있습니다. 나는 현재 내 웹 카메라를 모두로드하고 StereoBM을 사용하여 깊이 맵을 생성 할 수있었습니다. 그러나 결과 화면은 내 스크린 샷이 아래에 나와있는 것처럼 유용하지 않습니다. 그래서 도움이되지 않은 StereoBM 매개 변수를 조정하는 데 도움이되는 작은 파이썬 응용 프로그램을 만들었습니다.

내 질문 StereoBM 기능과 함께 사용하려면 카메라를 보정해야합니까? 그렇지 않으면

는에 명시된 바와 같이

enter image description here

코드

import cv2 
import time 
import numpy as np 
from Tkinter import * 

oldVal = 15 
def oddVals(n): 
     global oldVal 
     n = int(n) 
     if not n % 2: 
       window_size.set(n+1 if n > oldVal else n-1) 
       oldVal = window_size.get() 

minDispValues = [16,32,48,64] 
def minDispCallback(n): 
     n = int(n) 
     newvalue = min(minDispValues, key=lambda x:abs(x-float(n))) 
     min_disp.set(newvalue) 

# Display the sliders to control the stereo vision 
master = Tk() 

master.title("StereoBM Settings"); 

min_disp = Scale(master, from_=16, to=64, command=minDispCallback, length=600, orient=HORIZONTAL, label="Minimum Disparities") 
min_disp.pack() 
min_disp.set(16) 

window_size = Scale(master, from_=5, to=255, command=oddVals, length=600, orient=HORIZONTAL, label="Window Size") 
window_size.pack() 
window_size.set(15) 

Disp12MaxDiff = Scale(master, from_=5, to=30, length=600, orient=HORIZONTAL, label="Max Difference") 
Disp12MaxDiff.pack() 
Disp12MaxDiff.set(0) 

UniquenessRatio = Scale(master, from_=0, to=30, length=600, orient=HORIZONTAL, label="Uniqueness Ratio") 
UniquenessRatio.pack() 
UniquenessRatio.set(15) 

SpeckleRange = Scale(master, from_=0, to=60, length=600, orient=HORIZONTAL, label="Speckle Range") 
SpeckleRange.pack() 
SpeckleRange.set(34) 

SpeckleWindowSize = Scale(master, from_=60, to=150, length=600, orient=HORIZONTAL, label="Speckle Window Size") 
SpeckleWindowSize.pack() 
SpeckleWindowSize.set(100) 

master.update() 

vcLeft = cv2.VideoCapture(0) # Load video campture for the left camera 
#vcLeft.set(cv2.cv.CV_CAP_PROP_FRAME_WIDTH,420); 
#vcLeft.set(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT,340); 
vcLeft.set(3,640) # Set camera width 
vcLeft.set(4,480) # Set camera height 

vcRight = cv2.VideoCapture(1) # Load video capture for the right camera 
#vcRight.set(cv2.cv.CV_CAP_PROP_FRAME_WIDTH,420); 
#vcRight.set(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT,340); 

firstTime = time.time() # First time log 

totalFramesPassed = 0 # Number of frames passed 

if vcLeft.isOpened() and vcRight.isOpened(): 
     rvalLeft, frameLeft = vcLeft.read() 
     rvalRight, frameRight = vcRight.read() 

else: 
     rvalLeft = False 
     rvalRight = False 

while rvalLeft and rvalRight: # If the cameras are opened 

     rvalLeft, frameLeft = vcLeft.read() 

     rvalRight, frameRight = vcRight.read() 

     cv2.putText(frameLeft, "FPS : " + str(totalFramesPassed/(time.time() - firstTime)),(40, 40), cv2.FONT_HERSHEY_SIMPLEX, 0.8, 150, 2, 10) 

     cv2.imshow("Left Camera", frameLeft) 

     cv2.putText(frameRight, "FPS : " + str(totalFramesPassed/(time.time() - firstTime)),(40, 40), cv2.FONT_HERSHEY_SIMPLEX, 0.8, 150, 2, 10) 

     cv2.imshow("Right Camera", frameRight) 

     frameLeftNew = cv2.cvtColor(frameLeft, cv2.COLOR_BGR2GRAY) 

     frameRightNew = cv2.cvtColor(frameRight, cv2.COLOR_BGR2GRAY) 

     num_disp = 112 - min_disp.get() 

     stereo = cv2.StereoBM_create(numDisparities = num_disp, blockSize = window_size.get()) 

     stereo.setMinDisparity(min_disp.get()) 

     stereo.setNumDisparities(num_disp) 

     stereo.setBlockSize(window_size.get()) 

     stereo.setDisp12MaxDiff(Disp12MaxDiff.get()) 

     stereo.setUniquenessRatio(UniquenessRatio.get()) 

     stereo.setSpeckleRange(SpeckleRange.get()) 

     stereo.setSpeckleWindowSize(SpeckleWindowSize.get()) 

     disparity = stereo.compute(frameLeftNew, frameRightNew).astype(np.float32)/16.0 

     disp_map = (disparity - min_disp.get())/num_disp 

     cv2.imshow("Disparity", disp_map) 

     master.update() # Update the slider options 

     key = cv2.waitKey(20) 

     totalFramesPassed = totalFramesPassed + 1 # One frame passed, increment 

     if key == 27: 

       break 


vcLeft.release() 

vcRight.release() 
+0

갖는 카메라 보정 : 사람이 미래에 자신의 카메라를 보정해야하는 경우

, 당신은 당신이 그렇게 할 수 있도록이 코드를 사용할 수 있습니다. 랜덤 한 장면 (텍스트, 랜덤 점 등)을 사용하여 StereoBM을 사용하려고 했습니까? 아마도 대응에 문제가있을 수 있습니다. 나는 간단한 상관 알고리즘을 구현하고 얼마나 좋은 코 릴레이션인지를 보게 될 것이다. –

+0

@KamilSzelag 조언을 주셔서 감사합니다. 나는 두 이미지의 왼쪽과 오른쪽 이미지를 보정하려고 시도합니다. 그러면 알고리즘이 잘 작동 할 수 있습니다. StereoBM을 다른 장면과 함께 사용하려고 시도했지만 상관 관계가 좋은지 확인합니다. 현장에서 많은 물체가있는 상황에서도 현재 결과가 신뢰할 수 없기 때문에 교정이 주요 문제가되기를 바랍니다. 다시 한번 감사드립니다. –

답변

0

(등, StereoSBGM를 사용, 즉 증가 해상도) 내 결과를 개선하는 데 도움이되는 몇 가지 대안이 무엇인가 StereoBM opencv stereoBM doc의 opencv 문서 두 이미지는 "정류 된 스테레오 쌍"이어야합니다.

이렇게하면 불일치를 계산하기 전에 두 카메라를 수정해야합니다.

불균형을 계산하기 전에 두 카메라를 수정하는 방법을 볼 수있는 stereo_match을 살펴보십시오.

stereoBM을 사용하여 불일치를 계산할 때 두 이미지의 평행 에피 폴라 선의 일치를 볼 수 있습니다. 이것은 두 이미지의 같은 행이 공간의 같은 줄에 해당하는 거리에 이미지가 정렬되어야합니다. 정류 프로세스가이를 처리합니다. 자세한 내용은

나는 우리가 StereoBM 기능을 사용하기 위해 쌍을 시정 할 필요가 있음을 발견 Rectification with opencv

0

봐. 또한 리소스 집약적이지만 StereoSGBM 기능이 더 나은 결과를 제공한다는 것을 알게되었습니다. - 도움이 될 것입니다, 특히 왜곡

# Imports 
import cv2 
import numpy as np 

# Constants 
leftCameraNumber = 2 # Number for left camera 
rightCameraNumber = 1 # Number for right camera 

numberOfChessRows = 6 
numberOfChessColumns = 8 
chessSquareSize = 30 # Length of square in millimeters 

numberOfChessColumns = numberOfChessColumns - 1 # Update to reflect how many corners are inside the chess board 
numberOfChessRows = numberOfChessRows - 1 

objp = np.zeros((numberOfChessColumns*numberOfChessRows,3), np.float32) 
objp[:,:2] = np.mgrid[0:numberOfChessRows,0:numberOfChessColumns].T.reshape(-1,2)*chessSquareSize 

objectPoints = [] 
leftImagePoints = [] 
rightImagePoints = [] 

parameterCriteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001) 

# Code 
print("Press \"n\" when you're done caputing checkerboards.") 

vcLeft = cv2.VideoCapture(leftCameraNumber) # Load video campture for the left camera 
vcLeft.set(cv2.CAP_PROP_FRAME_WIDTH,640*3/2); 
vcLeft.set(cv2.CAP_PROP_FRAME_HEIGHT,480*3/2); 

vcRight = cv2.VideoCapture(rightCameraNumber) # Load video capture for the right camera 
vcRight.set(cv2.CAP_PROP_FRAME_WIDTH,640*3/2); 
vcRight.set(cv2.CAP_PROP_FRAME_HEIGHT,480*3/2); 

if vcLeft.isOpened() and vcRight.isOpened(): 
    rvalLeft, frameLeft = vcLeft.read() 
    rvalRight, frameRight = vcRight.read() 

else: 
    rvalLeft = False 
    rvalRight = False 

# Number of succesful recognitions 
checkerboardRecognitions = 0 

while rvalLeft and rvalRight: # If the cameras are opened 

    vcLeft.grab(); 

    vcRight.grab(); 

    rvalLeft, frameLeft = vcLeft.retrieve() 

    rvalRight, frameRight = vcRight.retrieve() 

    frameLeftNew = cv2.cvtColor(frameLeft, cv2.COLOR_BGR2GRAY) 

    frameRightNew = cv2.cvtColor(frameRight, cv2.COLOR_BGR2GRAY) 

    foundPatternLeft, cornersLeft = cv2.findChessboardCorners(frameLeftNew, (numberOfChessRows, numberOfChessColumns), None, cv2.CALIB_CB_ADAPTIVE_THRESH + cv2.CALIB_CB_NORMALIZE_IMAGE + cv2.CALIB_CB_FAST_CHECK) 

    foundPatternRight, cornersRight = cv2.findChessboardCorners(frameRightNew, (numberOfChessRows, numberOfChessColumns), None, cv2.CALIB_CB_ADAPTIVE_THRESH + cv2.CALIB_CB_NORMALIZE_IMAGE + cv2.CALIB_CB_FAST_CHECK) 


    if foundPatternLeft and foundPatternRight: # If found corners in this frame 

     # Process the images and display the count of checkboards in our array 
     checkerboardRecognitions = checkerboardRecognitions + 1 
     print("Checker board recognitions: " + str(checkerboardRecognitions)) 

     objectPoints.append(objp) 

     exactCornersLeft = cv2.cornerSubPix(frameLeftNew, cornersLeft, (11, 11), (-1, -1), parameterCriteria); 
     leftImagePoints.append(exactCornersLeft) 

     exactCornersRight = cv2.cornerSubPix(frameRightNew, cornersRight, (11, 11), (-1, -1), parameterCriteria); 
     rightImagePoints.append(exactCornersRight) 

     frameLeft = cv2.drawChessboardCorners(frameLeft, (numberOfChessRows, numberOfChessColumns), (exactCornersLeft), True); 

     frameRight = cv2.drawChessboardCorners(frameRight, (numberOfChessRows, numberOfChessColumns), (exactCornersRight), True); 


    # Display current webcams regardless if board was found or not 
    cv2.imshow("Left Camera", frameLeft) 

    cv2.imshow("Right Camera", frameRight) 


    key = cv2.waitKey(250) # Give the frame some time 

    if key == ord('n'): 

     break 

cameraMatrixLeft = np.zeros((3,3)) 
cameraMatrixRight = np.zeros((3,3)) 
distortionLeft = np.zeros((8,1)) 
distortionRight = np.zeros((8,1)) 
height, width = frameLeft.shape[:2] 

rms, leftMatrix, leftDistortion, rightMatrix, rightDistortion, R, T, E, F = cv2.stereoCalibrate(objectPoints, leftImagePoints, rightImagePoints, cameraMatrixLeft, distortionLeft, cameraMatrixRight, distortionRight, (width, height),parameterCriteria, flags=0) 

arr1 = np.arange(8).reshape(2, 4) 
arr2 = np.arange(10).reshape(2, 5) 
np.savez('camera_calibration.npz', leftMatrix=leftMatrix, leftDistortion=leftDistortion, rightMatrix=rightMatrix, rightDistortion=rightDistortion, R=R, T=T, E=E, F=F) 
print("Calibration Settings Saved to File!") 

print("RMS:") 
print(rms) 
print("Left Matrix:") 
print(leftMatrix) 
print("Left Distortion:") 
print(leftDistortion) 
print("Right Matrix:") 
print(rightMatrix) 
print("Right Distortion:") 
print(rightDistortion) 
print("R:") 
print(R) 
print("T:") 
print(T) 
print("E:") 
print(E) 
print("F:") 
print(F) 


leftRectTransform, rightRectTransform, leftProjMatrix, rightProjMatrix, _, _, _ = cv2.stereoRectify(leftMatrix, leftDistortion, rightMatrix, rightDistortion, (width, height), R, T, alpha=-1); 
leftMapX, leftMapY = cv2.initUndistortRectifyMap(leftMatrix, leftDistortion, leftRectTransform, leftProjMatrix, (width, height), cv2.CV_32FC1); 
rightMapX, rightMapY = cv2.initUndistortRectifyMap(rightMatrix, rightDistortion, rightRectTransform, rightProjMatrix, (width, height), cv2.CV_32FC1); 

minimumDisparities = 0 
maximumDisparities = 128 

stereo = cv2.StereoSGBM_create(minimumDisparities, maximumDisparities, 18) 

while True: # If the cameras are opened 
    vcLeft.grab(); 

    vcRight.grab(); 

    rvalLeft, frameLeft = vcLeft.retrieve() 

    rvalRight, frameRight = vcRight.retrieve() 

    frameLeftNew = cv2.cvtColor(frameLeft, cv2.COLOR_BGR2GRAY) 

    frameRightNew = cv2.cvtColor(frameRight, cv2.COLOR_BGR2GRAY) 

    leftRectified = cv2.remap(frameLeftNew, leftMapX, leftMapY, cv2.INTER_LINEAR); 

    rightRectified = cv2.remap(frameRightNew, rightMapX, rightMapY, cv2.INTER_LINEAR); 

    disparity = stereo.compute(leftRectified, rightRectified) 

    cv2.filterSpeckles(disparity, 0, 6000, maximumDisparities); 

    cv2.imshow("Normalized Disparity", (disparity/16.0 - minimumDisparities)/maximumDisparities); 

    cv2.imshow("Left Camera", leftRectified) 

    cv2.imshow("Right Camera", rightRectified) 


    key = cv2.waitKey(10) # Give the frame some time 

    if key == 27: 

     break 

print("Finished!")