Projecting KITTI velodyne to image produces a narrow strip
I am trying to project the KITTI velodyne onto the left camera images. I followed the README in the KITTI devkit, but the result is off -- the points are projected as a narrow band on the top of the image. The band looks like it has some distribution, so I am suspecting I am doing something wrong with the calibration matrices. Or maybe in the PIL.ImageDraw.point?
The projection equation that I am using is per the KITTI devkit documentation:
x = P2 * R0_rect * Tr_velo_to_cam * y, where
yis a4xNmatrix withNpoints inXYZLformat (Lis the luminescence),
Tr_velo_to_camis the3x4velodyne to camera transformation matrix
R0_rectis the3x3extrinsic camera rotation matrix
P2is the3x3intrinsic camera projection matrix
Below is the code, STDIO of it, and the produced image.
test.py:
import numpy as np
import os
from PIL import Image, ImageDraw
DATASET_PATH = "<DATASET PATH HERE>"
vld_path = os.path.join(DATASET_PATH, "velodyne/{:06d}.bin")
img_path = os.path.join(DATASET_PATH, "image_2/{:06d}.png")
clb_path = os.path.join(DATASET_PATH, "calib/{:06d}.txt")
frame_num = 58
# Load files
img = Image.open(img_path.format(frame_num))
clb = {}
with open(clb_path.format(frame_num), 'r') as clb_f:
for line in clb_f:
calib_line = line.split(':')
if len(calib_line) < 2:
continue
key = calib_line[0]
value = np.array(list(map(float, calib_line[1].split())))
value = value.reshape((3, -1))
clb[key] = value
vld = np.fromfile(vld_path.format(frame_num), dtype=np.float32)
vld = vld.reshape((-1, 4)).T
print("img.shape:", np.shape(img))
print("P2.shape:", clb['P2'].shape)
print("R0_rect.shape:", clb['R0_rect'].shape)
print("Tr_velo_to_cam.shape:", clb['Tr_velo_to_cam'].shape)
print("vld.shape:", vld.shape)
# Reshape calibration files
P2 = clb['P2']
R0 = np.eye(4)
R0[:-1, :-1] = clb['R0_rect']
Tr = np.eye(4)
Tr[:-1, :] = clb['Tr_velo_to_cam']
# Prepare 3d points
pts3d = vld[:, vld[-1, :] > 0].copy()
pts3d[-1, :] = 1
# Project 3d points
pts3d_cam = R0 @ Tr @ pts3d
mask = pts3d_cam[2, :] >= 0 # Z >= 0
pts2d_cam = P2 @ pts3d_cam[:, mask]
pts2d = (pts2d_cam / pts2d_cam[2, :])[:-1, :]
print("pts2d.shape:", pts2d.shape)
# Draw the points
img_draw = ImageDraw.Draw(img)
img_draw.point(pts2d, fill=(255, 0, 0))
img.show()
STDOUT:
$> python ./test.py
img.shape: (370, 1224, 3)
P2.shape: (3, 4)
R0_rect.shape: (3, 3)
Tr_velo_to_cam.shape: (3, 4)
vld.shape: (4, 115052)
pts2d.shape: (2, 53119)
Produced image:

python computer-vision python-imaging-library projection
add a comment |
I am trying to project the KITTI velodyne onto the left camera images. I followed the README in the KITTI devkit, but the result is off -- the points are projected as a narrow band on the top of the image. The band looks like it has some distribution, so I am suspecting I am doing something wrong with the calibration matrices. Or maybe in the PIL.ImageDraw.point?
The projection equation that I am using is per the KITTI devkit documentation:
x = P2 * R0_rect * Tr_velo_to_cam * y, where
yis a4xNmatrix withNpoints inXYZLformat (Lis the luminescence),
Tr_velo_to_camis the3x4velodyne to camera transformation matrix
R0_rectis the3x3extrinsic camera rotation matrix
P2is the3x3intrinsic camera projection matrix
Below is the code, STDIO of it, and the produced image.
test.py:
import numpy as np
import os
from PIL import Image, ImageDraw
DATASET_PATH = "<DATASET PATH HERE>"
vld_path = os.path.join(DATASET_PATH, "velodyne/{:06d}.bin")
img_path = os.path.join(DATASET_PATH, "image_2/{:06d}.png")
clb_path = os.path.join(DATASET_PATH, "calib/{:06d}.txt")
frame_num = 58
# Load files
img = Image.open(img_path.format(frame_num))
clb = {}
with open(clb_path.format(frame_num), 'r') as clb_f:
for line in clb_f:
calib_line = line.split(':')
if len(calib_line) < 2:
continue
key = calib_line[0]
value = np.array(list(map(float, calib_line[1].split())))
value = value.reshape((3, -1))
clb[key] = value
vld = np.fromfile(vld_path.format(frame_num), dtype=np.float32)
vld = vld.reshape((-1, 4)).T
print("img.shape:", np.shape(img))
print("P2.shape:", clb['P2'].shape)
print("R0_rect.shape:", clb['R0_rect'].shape)
print("Tr_velo_to_cam.shape:", clb['Tr_velo_to_cam'].shape)
print("vld.shape:", vld.shape)
# Reshape calibration files
P2 = clb['P2']
R0 = np.eye(4)
R0[:-1, :-1] = clb['R0_rect']
Tr = np.eye(4)
Tr[:-1, :] = clb['Tr_velo_to_cam']
# Prepare 3d points
pts3d = vld[:, vld[-1, :] > 0].copy()
pts3d[-1, :] = 1
# Project 3d points
pts3d_cam = R0 @ Tr @ pts3d
mask = pts3d_cam[2, :] >= 0 # Z >= 0
pts2d_cam = P2 @ pts3d_cam[:, mask]
pts2d = (pts2d_cam / pts2d_cam[2, :])[:-1, :]
print("pts2d.shape:", pts2d.shape)
# Draw the points
img_draw = ImageDraw.Draw(img)
img_draw.point(pts2d, fill=(255, 0, 0))
img.show()
STDOUT:
$> python ./test.py
img.shape: (370, 1224, 3)
P2.shape: (3, 4)
R0_rect.shape: (3, 3)
Tr_velo_to_cam.shape: (3, 4)
vld.shape: (4, 115052)
pts2d.shape: (2, 53119)
Produced image:

python computer-vision python-imaging-library projection
add a comment |
I am trying to project the KITTI velodyne onto the left camera images. I followed the README in the KITTI devkit, but the result is off -- the points are projected as a narrow band on the top of the image. The band looks like it has some distribution, so I am suspecting I am doing something wrong with the calibration matrices. Or maybe in the PIL.ImageDraw.point?
The projection equation that I am using is per the KITTI devkit documentation:
x = P2 * R0_rect * Tr_velo_to_cam * y, where
yis a4xNmatrix withNpoints inXYZLformat (Lis the luminescence),
Tr_velo_to_camis the3x4velodyne to camera transformation matrix
R0_rectis the3x3extrinsic camera rotation matrix
P2is the3x3intrinsic camera projection matrix
Below is the code, STDIO of it, and the produced image.
test.py:
import numpy as np
import os
from PIL import Image, ImageDraw
DATASET_PATH = "<DATASET PATH HERE>"
vld_path = os.path.join(DATASET_PATH, "velodyne/{:06d}.bin")
img_path = os.path.join(DATASET_PATH, "image_2/{:06d}.png")
clb_path = os.path.join(DATASET_PATH, "calib/{:06d}.txt")
frame_num = 58
# Load files
img = Image.open(img_path.format(frame_num))
clb = {}
with open(clb_path.format(frame_num), 'r') as clb_f:
for line in clb_f:
calib_line = line.split(':')
if len(calib_line) < 2:
continue
key = calib_line[0]
value = np.array(list(map(float, calib_line[1].split())))
value = value.reshape((3, -1))
clb[key] = value
vld = np.fromfile(vld_path.format(frame_num), dtype=np.float32)
vld = vld.reshape((-1, 4)).T
print("img.shape:", np.shape(img))
print("P2.shape:", clb['P2'].shape)
print("R0_rect.shape:", clb['R0_rect'].shape)
print("Tr_velo_to_cam.shape:", clb['Tr_velo_to_cam'].shape)
print("vld.shape:", vld.shape)
# Reshape calibration files
P2 = clb['P2']
R0 = np.eye(4)
R0[:-1, :-1] = clb['R0_rect']
Tr = np.eye(4)
Tr[:-1, :] = clb['Tr_velo_to_cam']
# Prepare 3d points
pts3d = vld[:, vld[-1, :] > 0].copy()
pts3d[-1, :] = 1
# Project 3d points
pts3d_cam = R0 @ Tr @ pts3d
mask = pts3d_cam[2, :] >= 0 # Z >= 0
pts2d_cam = P2 @ pts3d_cam[:, mask]
pts2d = (pts2d_cam / pts2d_cam[2, :])[:-1, :]
print("pts2d.shape:", pts2d.shape)
# Draw the points
img_draw = ImageDraw.Draw(img)
img_draw.point(pts2d, fill=(255, 0, 0))
img.show()
STDOUT:
$> python ./test.py
img.shape: (370, 1224, 3)
P2.shape: (3, 4)
R0_rect.shape: (3, 3)
Tr_velo_to_cam.shape: (3, 4)
vld.shape: (4, 115052)
pts2d.shape: (2, 53119)
Produced image:

python computer-vision python-imaging-library projection
I am trying to project the KITTI velodyne onto the left camera images. I followed the README in the KITTI devkit, but the result is off -- the points are projected as a narrow band on the top of the image. The band looks like it has some distribution, so I am suspecting I am doing something wrong with the calibration matrices. Or maybe in the PIL.ImageDraw.point?
The projection equation that I am using is per the KITTI devkit documentation:
x = P2 * R0_rect * Tr_velo_to_cam * y, where
yis a4xNmatrix withNpoints inXYZLformat (Lis the luminescence),
Tr_velo_to_camis the3x4velodyne to camera transformation matrix
R0_rectis the3x3extrinsic camera rotation matrix
P2is the3x3intrinsic camera projection matrix
Below is the code, STDIO of it, and the produced image.
test.py:
import numpy as np
import os
from PIL import Image, ImageDraw
DATASET_PATH = "<DATASET PATH HERE>"
vld_path = os.path.join(DATASET_PATH, "velodyne/{:06d}.bin")
img_path = os.path.join(DATASET_PATH, "image_2/{:06d}.png")
clb_path = os.path.join(DATASET_PATH, "calib/{:06d}.txt")
frame_num = 58
# Load files
img = Image.open(img_path.format(frame_num))
clb = {}
with open(clb_path.format(frame_num), 'r') as clb_f:
for line in clb_f:
calib_line = line.split(':')
if len(calib_line) < 2:
continue
key = calib_line[0]
value = np.array(list(map(float, calib_line[1].split())))
value = value.reshape((3, -1))
clb[key] = value
vld = np.fromfile(vld_path.format(frame_num), dtype=np.float32)
vld = vld.reshape((-1, 4)).T
print("img.shape:", np.shape(img))
print("P2.shape:", clb['P2'].shape)
print("R0_rect.shape:", clb['R0_rect'].shape)
print("Tr_velo_to_cam.shape:", clb['Tr_velo_to_cam'].shape)
print("vld.shape:", vld.shape)
# Reshape calibration files
P2 = clb['P2']
R0 = np.eye(4)
R0[:-1, :-1] = clb['R0_rect']
Tr = np.eye(4)
Tr[:-1, :] = clb['Tr_velo_to_cam']
# Prepare 3d points
pts3d = vld[:, vld[-1, :] > 0].copy()
pts3d[-1, :] = 1
# Project 3d points
pts3d_cam = R0 @ Tr @ pts3d
mask = pts3d_cam[2, :] >= 0 # Z >= 0
pts2d_cam = P2 @ pts3d_cam[:, mask]
pts2d = (pts2d_cam / pts2d_cam[2, :])[:-1, :]
print("pts2d.shape:", pts2d.shape)
# Draw the points
img_draw = ImageDraw.Draw(img)
img_draw.point(pts2d, fill=(255, 0, 0))
img.show()
STDOUT:
$> python ./test.py
img.shape: (370, 1224, 3)
P2.shape: (3, 4)
R0_rect.shape: (3, 3)
Tr_velo_to_cam.shape: (3, 4)
vld.shape: (4, 115052)
pts2d.shape: (2, 53119)
Produced image:

python computer-vision python-imaging-library projection
python computer-vision python-imaging-library projection
edited Nov 24 '18 at 22:43
RafazZ
asked Nov 24 '18 at 21:51
RafazZRafazZ
1,097625
1,097625
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
Found the problem: Notice that the dimensions of the pts2d are (2, N), which means it has N points in total. However, the ImageDraw routine expects it to be either Nx2 or 1x2N row vector with alternating x and y values. Although I couldn't get the point routine to work with the Nx2 input, I put it in the for loop (after transposing the points), and it worked.
# ...
pts2d = (pts2d_cam / pts2d_cam[2, :])[:-1, :].T
print("pts2d.shape:", pts2d.shape)
# Draw the points
img_draw = ImageDraw.Draw(img)
for point in pts2d:
img_draw.point(point, fill=(255, 0, 0))
# ...

add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53462674%2fprojecting-kitti-velodyne-to-image-produces-a-narrow-strip%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
Found the problem: Notice that the dimensions of the pts2d are (2, N), which means it has N points in total. However, the ImageDraw routine expects it to be either Nx2 or 1x2N row vector with alternating x and y values. Although I couldn't get the point routine to work with the Nx2 input, I put it in the for loop (after transposing the points), and it worked.
# ...
pts2d = (pts2d_cam / pts2d_cam[2, :])[:-1, :].T
print("pts2d.shape:", pts2d.shape)
# Draw the points
img_draw = ImageDraw.Draw(img)
for point in pts2d:
img_draw.point(point, fill=(255, 0, 0))
# ...

add a comment |
Found the problem: Notice that the dimensions of the pts2d are (2, N), which means it has N points in total. However, the ImageDraw routine expects it to be either Nx2 or 1x2N row vector with alternating x and y values. Although I couldn't get the point routine to work with the Nx2 input, I put it in the for loop (after transposing the points), and it worked.
# ...
pts2d = (pts2d_cam / pts2d_cam[2, :])[:-1, :].T
print("pts2d.shape:", pts2d.shape)
# Draw the points
img_draw = ImageDraw.Draw(img)
for point in pts2d:
img_draw.point(point, fill=(255, 0, 0))
# ...

add a comment |
Found the problem: Notice that the dimensions of the pts2d are (2, N), which means it has N points in total. However, the ImageDraw routine expects it to be either Nx2 or 1x2N row vector with alternating x and y values. Although I couldn't get the point routine to work with the Nx2 input, I put it in the for loop (after transposing the points), and it worked.
# ...
pts2d = (pts2d_cam / pts2d_cam[2, :])[:-1, :].T
print("pts2d.shape:", pts2d.shape)
# Draw the points
img_draw = ImageDraw.Draw(img)
for point in pts2d:
img_draw.point(point, fill=(255, 0, 0))
# ...

Found the problem: Notice that the dimensions of the pts2d are (2, N), which means it has N points in total. However, the ImageDraw routine expects it to be either Nx2 or 1x2N row vector with alternating x and y values. Although I couldn't get the point routine to work with the Nx2 input, I put it in the for loop (after transposing the points), and it worked.
# ...
pts2d = (pts2d_cam / pts2d_cam[2, :])[:-1, :].T
print("pts2d.shape:", pts2d.shape)
# Draw the points
img_draw = ImageDraw.Draw(img)
for point in pts2d:
img_draw.point(point, fill=(255, 0, 0))
# ...

answered Nov 25 '18 at 0:16
RafazZRafazZ
1,097625
1,097625
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53462674%2fprojecting-kitti-velodyne-to-image-produces-a-narrow-strip%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown