File size: 3,355 Bytes
e9fe176
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
require 'csvigo'
require 'image'
local pl = require 'pl.import_into' ()
cv = require 'cv'
require 'cv.imgproc'

local utils = {}

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)
   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.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.drawTopDownView(width, height, points)
   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))
   local indices = torch.randperm(points2D:size(1)):narrow(1, 1, 10000):long()
   points2D = points2D:index(1, indices)
   local w, _, _ = torch.svd(points2D:t())
   local angle = torch.atan2(w[1][2], w[1][1])
   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 u = torch.round((newX - mins[1]) / (maxs[1] - mins[1]) * width)   
   local v = torch.round((newY - mins[2]) / (maxs[2] - mins[2]) * height)
   local uv = torch.cat(u, v, 2)


   local transformation = torch.zeros(3, 4)
   transformation[2][1] = torch.cos(angle)   
   transformation[2][2] = torch.sin(angle)
   transformation[2][4] = -mins[1]
   transformation[1][1] = -torch.sin(angle)   
   transformation[1][2] = torch.cos(angle)
   transformation[1][4] = -mins[2]
   transformation[3][4] = 1
   transformation[2] = transformation[2] * width / (maxs[1] - mins[1])
   transformation[1] = transformation[1] * height / (maxs[2] - mins[2])
   --transformation[1], transformation[2] = transformation[2], transformation[1]

   uv = utils.project(transformation, points)
   print(transformation)
   print(points[{{1, 5}}])
   print(uv[{{1, 5}}])
   
   local topDownView = torch.zeros(height, width)   
   for i = 1, uv:size(1) do
      local point = uv[i]
      topDownView[math.max(point[2], 1)][math.max(point[1], 1)] = topDownView[math.max(point[2], 1)][math.max(point[1], 1)] + 1
   end
   --image.save('test/pointcloud.png', topDownView)
   local pointDensity = 10.0
   topDownView = topDownView / pointDensity
   topDownView[topDownView:gt(1)] = 1

   
   return topDownView, transformation
end

return utils