Ask Your Question

Revision history [back]

Output coordinates of cv2.triangulatePoints()

Hi there I am trying to convert two 2D points center1 = (x1, y1), center2 = (x2,y2) from a stereo camera into 3D world coordinates. First I calculate the center of a detected object in both pictures (left and right), afterwards this points are triangulated with the LeftProjection and RightProjection from cv2.StereoRectify()

It looks like this:

P1 = calibration["leftProjection"]      #read camera matrix
P2 = calibration["rightProjection"]

center1 = cX1, cY1          #x,y coordinates of an object in the pictures 
center2 = cX2, cY2

arr = np.array([])
arr = cv2.triangulatePoints(P1, P2, center1, center2, arr)
arrCar = arr/arr[3]           # from homogeneous to cartesian coordinates.
arrCar = np.delete(arrCar, (3), axis=0)
print(center1)
print(center2)
print(arrCar)

center1 and center2 are calculated with the remaped pictures from calibration like below..

fixedLeft = cv2.remap(leftFrame, leftMapX, leftMapY, REMAP_INTERPOLATION)
fixedRight = cv2.remap(rightFrame, rightMapX, rightMapY, REMAP_INTERPOLATION)

My purpose is to find distance and angle of an the object from the camera. (the goal is to follow an object autonomous..)

My output looks like this:

(818, 556) #center1 (left image) #camera resolution = (1920,1080)

(351, 555) #center2

[[ 0.34404608] #x

[ 1.01526877] #y

[38.3707673 ]] #z

In my opinion the origin (0,0,z) should be in the center of the left image (1920/2 = 960 and 1080/2 = 560) but x and y are approcimately 0 at a (800,500) pixel value..

In addition the z=38.37 is computed with an object distance of 1m from the camera... which I donĀ“t know if I just can multiply this value with a weight to get 1m. Because of the fact that z is changing linear...

I would appreciate any help..

The whole code you can find here:

CAMERA_WIDTH = 1920
CAMERA_HEIGHT = 1080

 left = cv2.VideoCapture(0)
 right = cv2.VideoCapture(1)

 #User set camera
 left.set(3, CAMERA_WIDTH) # Set resolution width
 left.set(4, CAMERA_HEIGHT) # Set resolution height
 right.set(3, CAMERA_WIDTH) # Set resolution width
 right.set(4, CAMERA_HEIGHT) # Set resolution hight
REMAP_INTERPOLATION = cv2.INTER_LINEAR
#read parameters

rootDir = './'
outputFile = rootDir + 'output/calibration.npz'

calibration = np.load(outputFile, allow_pickle=False)
imageSize = tuple(calibration["imageSize"])
leftMapX = calibration["leftMapX"]
leftMapY = calibration["leftMapY"]
leftROI = tuple(calibration["leftROI"])
rightMapX = calibration["rightMapX"]
rightMapY = calibration["rightMapY"]
rightROI = tuple(calibration["rightROI"])

R = calibration["rotationMatrix"]
T = calibration["translationVector"]
P1 = calibration["leftProjection"]
P2 = calibration["rightProjection"]

global cX2
global cX1,D
cX1=0
cX2=0;D=0
count=0

print("Ready!")
while(1):
    if not left.grab() or not right.grab():
        print("No more frames")
        break

ret, leftFrame = left.retrieve()
leftHeight, leftWidth = leftFrame.shape[:2]
ret, rightFrame = right.retrieve()
rightHeight, rightWidth = rightFrame.shape[:2]

if (leftWidth, leftHeight) != imageSize:
    print("Left camera has different size than the calibration data")
    #break

if (rightWidth, rightHeight) != imageSize:
    print("Right camera has different size than the calibration data")
    #break

#cv2.imshow('left', leftFrame)
fixedLeft = cv2.remap(leftFrame, leftMapX, leftMapY, REMAP_INTERPOLATION)
fixedRight = cv2.remap(rightFrame, rightMapX, rightMapY, REMAP_INTERPOLATION)

image_blur1 = cv2.GaussianBlur(fixedLeft, (7, 7), 0)
image_blur2 = cv2.GaussianBlur(fixedRight, (7, 7), 0)
#HSV format of image
image_blur_hsv1 = cv2.cvtColor(image_blur1, cv2.COLOR_BGR2RGB)
image_blur_hsv2 = cv2.cvtColor(image_blur2, cv2.COLOR_BGR2RGB)

#colour grading for cone
max_orange = np.array([245,136,99])
min_orange = np.array([150,45,10])

max_white= np.array([225,224,228])
min_white=np.array([119,115,136])

#colour masks, using only orange
mask11 = cv2.inRange(image_blur_hsv1,min_orange,max_orange)
mask12 = cv2.inRange(image_blur_hsv1,min_white,max_white)
mask21 = cv2.inRange(image_blur_hsv2,min_orange,max_orange)
mask22 = cv2.inRange(image_blur_hsv2,min_white,max_white)

mask1=mask11+mask12
mask2=mask21+mask22

#canny edges
edged1 = cv2.Canny(mask11, 50, 100)
edged1 = cv2.dilate(edged1, None, iterations=1)
edged1 = cv2.erode(edged1, None, iterations=1)
edged2 = cv2.Canny(mask21, 50, 100)
edged2 = cv2.dilate(edged2, None, iterations=1)
edged2 = cv2.erode(edged2, None, iterations=1)

#contour plays
_,contours1,_ = cv2.findContours(edged1, cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
_,contours2,_ = cv2.findContours(edged2, cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
if (len(contours1) and len(contours2))!=0:
    c1 = max(contours1, key = cv2.contourArea)
    M1=cv2.moments(c1)
    if M1["m00"] != 0:
        cX1=int(M1['m10']/M1["m00"])
        cY1=int(M1["m01"]/M1["m00"])
        cv2.drawContours(fixedLeft,c1, -1, (0, 255, 0), 2)
        cv2.circle(fixedLeft, (cX1, cY1), 7, (255, 255, 255), -1)
        cv2.putText(fixedLeft, "center", (cX1 - 20, cY1 - 20),cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2)
    else:
        cX1,cY1=0,0
    c2 = max(contours2, key = cv2.contourArea)
    M2=cv2.moments(c2)
    if M2["m00"] != 0:
        cX2=int(M2['m10']/M2["m00"])
        cY2=int(M2["m01"]/M2["m00"])
        cv2.drawContours(fixedRight,c2, -1, (0, 255, 0), 2)
        cv2.circle(fixedRight, (cX2, cY2), 7, (255, 255, 255), -1)
        cv2.putText(fixedRight, "center", (cX2 - 20, cY2 - 20),cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2)
    else:
        cX2,cY2=0,0


else:
    print("0")

center1 = cX1, cY1
center2 = cX2, cY2

arr = np.array([])
arr = cv2.triangulatePoints(P1, P2, center1, center2, arr)
arrCar = arr/arr[3]
arrCar = np.delete(arrCar, (3), axis=0)
print(center1)
print(center2)
print(arrCar)

cv2.imshow('left', cv2.resize(fixedLeft, (960, 540)))
cv2.imshow('right', cv2.resize(fixedRight, (960, 540)))
if cv2.waitKey(10)==27:
    break
count=count+1