FloorPlanTransformation / util /lua /pointcloud_utils.lua
rawanessam's picture
Upload 79 files
e9fe176 verified
require 'csvigo'
require 'image'
local pl = require 'pl.import_into' ()
cv = require 'cv'
require 'cv.imgproc'
local utils = {}
function utils.transform(transformation, points)
if points:dim() == 1 then
points = points:repeatTensor(1, 1)
end
points = torch.cat(points, torch.ones(points:size(1)), 2)
local newPoints = (transformation * points:transpose(1, 2)):transpose(1, 2)
newPoints = torch.cdiv(newPoints[{{}, {1, 3}}], newPoints[{{}, {4}}]:expand(newPoints:size(1), 3))
return newPoints
end
function utils.project(transformation, points)
if points:dim() == 1 then
points = points:repeatTensor(1, 1)
end
points = torch.cat(points, torch.ones(points:size(1)), 2)
local points2D = (transformation * points:transpose(1, 2)):transpose(1, 2)
points2D = torch.cdiv(points2D[{{}, {1, 2}}], points2D[{{}, {3}}]:expand(points2D:size(1), 2))
return points2D:squeeze()
end
function utils.unproject(transformation, points2D, additionalConstraint)
if points2D:dim() == 1 then
points2D = points2D:repeatTensor(1, 1)
end
points2D = torch.cat(points2D, torch.ones(points2D:size(1)), 2)
local A = torch.cat(transformation, additionalConstraint, 1)
local b = torch.cat(points2D, torch.zeros(points2D:size(1), additionalConstraint:size(1)), 2)
local points = (torch.inverse(A) * b:transpose(1, 2)):transpose(1, 2)
points = torch.cdiv(points[{{}, {1, 3}}], points[{{}, {4}}]:expand(points:size(1), 3))
return points:squeeze()
end
-- function utils.fitPlanes(points, numPlanes = 100, numIterations = 20)
-- local numPoints = points:size(1)
-- local numSampledPoints = 10000
-- local sampledPoints = points:index(1, perm:narrow(1, 1, numSampledPoints):long())
-- local perm = torch.randperm(numSampledPoints)
-- local indices = perm:narrow(1, 1, numIterations * 3):long()
-- local selectedPoints = sampledPoints:index(1, indices):reshape(numIterations, 3, 3)
-- local vectors_1 = selectedPoints[{{}, 1, {}}] - selectedPoints[{{}, 2, {}}]
-- local vectors_2 = selectedPoints[{{}, 1, {}}] - selectedPoints[{{}, 3, {}}]
-- local normals = torch.zeros(vectors_1:size())
-- normals[{{}, 1}] = vectors_1[{{}, 2}] * vectors_2[{{}, 3}] - vectors_1[{{}, 3}] * vectors_2[{{}, 2}]
-- normals[{{}, 2}] = vectors_1[{{}, 3}] * vectors_2[{{}, 1}] - vectors_1[{{}, 1}] * vectors_2[{{}, 3}]
-- normals[{{}, 3}] = vectors_1[{{}, 1}] * vectors_2[{{}, 2}] - vectors_1[{{}, 2}] * vectors_2[{{}, 1}]
-- local mean = torch.mean(selectedPoints, 2):squeeze()
-- local planeD = torch.sum(torch.cmul(normals, mean), 2)
-- local planes = normals * planeD:repeatTensor(1, 3)
-- end
function utils.projectLines(transformation, lines)
local lines2D
for lineIndex = 1, lines:size(1) do
local line = lines[lineIndex]
local points = torch.cat(line, torch.ones(2), 2)
local points2D = (transformation * points:transpose(1, 2)):transpose(1, 2)
points2D[{{}, 1}] = torch.cdiv(points2D[{{}, 1}], points2D[{{}, 3}])
points2D[{{}, 2}] = torch.cdiv(points2D[{{}, 2}], points2D[{{}, 3}])
local lineExists = false
for pointIndex = 1, 2 do
local point2D = points2D[pointIndex]
--if point2D[3] > 0 and point2D[1] >= 1 and point2D[1] <= width and point2D[2] >= 1 and point2D[2] <= height then
if point2D[3] > 0 then
lineExists = true
end
end
lineExists = true
local line2D = torch.zeros(1, 2, 2)
if lineExists then
line2D = points2D[{{}, {1, 2}}]:repeatTensor(1, 1, 1)
end
if not lines2D then
lines2D = line2D
else
lines2D = torch.cat(lines2D, line2D, 1)
end
end
return lines2D
end
function utils.loadPointCloud(filename)
local representationExists, representationInfo = pcall(function()
return csvigo.load({path=filename, mode="large", header=false, separator=' ', verbose=false})
end)
local points = {}
if representationExists and representationInfo ~= nil then
local numPoints = tonumber(representationInfo[1][3])
for pointIndex, point in pairs(representationInfo) do
if pointIndex >= 3 then
table.insert(points, {point[2], point[3], point[4]})
end
if pointIndex - 2 == numPoints then
break
end
end
end
return torch.Tensor(points)
end
function utils.samplePoints(points, numSampledPoints)
local indices = torch.randperm(points:size(1)):narrow(1, 1, numSampledPoints):long()
local sampledPoints = points:index(1, indices)
return sampledPoints
end
function utils.drawTopDownView(width, height, points, angle, transformation)
local X = points[{{}, 1}]
local Y = points[{{}, 2}]
local points2D = torch.cat(X, Y, 2)
local mean = torch.mean(points2D, 1)
points2D = points2D - mean:expandAs(points2D)
points2D:div(math.sqrt(points2D:size(1) - 1))
if not transformation then
if not angle then
--local w, _, _ = torch.svd(points2D:t())
--angle = torch.atan2(w[1][2], w[1][1])
angle = 0
end
local newX = X * torch.cos(angle) + Y * torch.sin(angle)
local newY = X * torch.sin(angle) - Y * torch.cos(angle)
local newPoints2D = torch.cat(newX, newY, 2)
local mins = torch.min(newPoints2D, 1)[1]
local maxs = torch.max(newPoints2D, 1)[1]
local paddingRatio = 0.05
local padding = (maxs - mins) * paddingRatio
mins = mins - padding
maxs = maxs + padding
local scaleFactor = math.min(width / (maxs[1] - mins[1]), height / (maxs[2] - mins[2]))
transformation = torch.zeros(3, 4)
transformation[1][1] = torch.cos(angle)
transformation[1][2] = torch.sin(angle)
transformation[1][4] = -mins[1]
transformation[2][1] = torch.sin(angle)
transformation[2][2] = -torch.cos(angle)
transformation[2][4] = -mins[2]
transformation[3][4] = 1
transformation[1] = transformation[1] * scaleFactor
transformation[2] = transformation[2] * scaleFactor
--transformation[1], transformation[2] = transformation[2], transformation[1]\
end
local uv = utils.project(transformation, points)
local topDownView = torch.zeros(height, width)
for i = 1, uv:size(1) do
local point = uv[i]
topDownView[math.min(math.max(point[2], 1), height)][math.min(math.max(point[1], 1), width)] = topDownView[math.min(math.max(point[2], 1), height)][math.min(math.max(point[1], 1), width)] + 1
end
--image.save('test/pointcloud.png', topDownView)
local pointDensity = 1
topDownView = topDownView / topDownView:max()
-- topDownView[topDownView:gt(1)] = 1
topDownView = torch.repeatTensor(topDownView, 3, 1, 1)
return topDownView, transformation
end
function utils.getRotationMatrix(quaternion)
qi = quaternion[1]
qj = quaternion[2]
qk = quaternion[3]
qr = quaternion[4]
local rotation = torch.zeros(4, 4)
rotation[1][1] = 1 - 2 * (qj^2 + qk^2)
rotation[1][2] = 2 * (qi * qj - qk * qr)
rotation[1][3] = 2 * (qi * qk + qj * qr)
rotation[2][1] = 2 * (qi * qj + qk * qr)
rotation[2][2] = 1 - 2 * (qi^2 + qk^2)
rotation[2][3] = 2 * (qj * qk - qi * qr)
rotation[3][1] = 2 * (qi * qk - qj * qr)
rotation[3][2] = 2 * (qj * qk + qi * qr)
rotation[3][3] = 1 - 2 * (qi^2 + qj^2)
rotation[4][4] = 1
return rotation
end
function utils.getTransformation(camera, pose, orientation)
local K = torch.zeros(3, 3)
K[1][2] = 1
K[2][1] = -1
K[3][3] = 1
local intrinsics = camera.intrinsics:clone()
if not orientation or orientation == 1 then
intrinsics[{{}, 1}] = -intrinsics[{{}, 1}]
intrinsics[{{}, 3}] = -intrinsics[{{}, 3}]
elseif orientation == 2 then
intrinsics[{{}, 3}] = -intrinsics[{{}, 3}]
local temp = intrinsics[{{}, 1}]:clone()
intrinsics[{{}, 1}] = -intrinsics[{{}, 2}]
intrinsics[{{}, 2}] = -temp
local temp = intrinsics[1][3]
intrinsics[1][3] = intrinsics[2][3]
intrinsics[2][3] = temp
end
--intrinsics[2][2] = -intrinsics[2][2]
intrinsics = torch.cat(intrinsics, torch.zeros(3), 2)
local inverseQuaternion = pose[{{4, 7}}]:clone()
inverseQuaternion[{{1, 3}}] = -inverseQuaternion[{{1, 3}}]
local rotation = utils.getRotationMatrix(inverseQuaternion)
local translation = torch.zeros(4, 4)
translation[1][1] = 1
translation[2][2] = 1
translation[3][3] = 1
translation[1][4] = -pose[1]
translation[2][4] = -pose[2]
translation[3][4] = -pose[3]
translation[4][4] = 1
local transformation = intrinsics * rotation * translation
print('frame')
print(pose)
print(intrinsics)
-- print(K)
print(rotation)
print(translation)
print(transformation)
local point = torch.Tensor({-0.0527, 2.0441, 1.000, 1})
-- print(point)
-- print(rotation * point)
-- print(translation * rotation * point)
-- print(transformation * point)
return transformation
end
-- function utils.getRotationFromAngle(angle)
-- rotation[1][1] = torch.cos(angle)
-- rotation[1][2] = torch.sin(angle)
-- rotation[2][1] = torch.sin(angle)
-- rotation[2][2] = -torch.cos(angle)
-- rotation[3][3] = 1
-- return rotation
-- end
return utils