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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
#!/usr/bin/env python
import math
import re
from argaze.RegionOfInterest import ROI2DScene
import numpy
import cv2 as cv
import matplotlib.path as mpath
class ROI3DScene(list):
"""List of ROI3D dictionary.
```
{
'NAME': str,
'VERTICES': array of (x, y, z) tuples
}
```
"""
def __new__(cls):
return super(ROI3DScene, cls).__new__(cls)
def __init__(self):
# define rotation and translation matrix
self.__rotation = [0, 0, 0]
self.__translation = [0, 0, 0]
def __del__(self):
pass
def load(self, obj_filepath: str):
"""Load ROI3D scene from .obj file."""
# regex rules for .obj file parsing
OBJ_RX_DICT = {
'comment': re.compile(r'#(.*)\n'),
'name': re.compile(r'o (\w+)(.*)\n'),
'vertice': re.compile(r'v ([+-]?[0-9]*[.]?[0-9]+) ([+-]?[0-9]*[.]?[0-9]+) ([+-]?[0-9]*[.]?[0-9]+)\n'),
'face': re.compile(r'f (.*)\n')
}
# regex .obj line parser
def __parse_obj_line(line):
for key, rx in OBJ_RX_DICT.items():
match = rx.search(line)
if match:
return key, match
# if there are no matches
return None, None
# start parsing
try:
roi3D = {}
vertices = []
faces = []
# open the file and read through it line by line
with open(obj_filepath, 'r') as file:
line = file.readline()
while line:
# at each line check for a match with a regex
key, match = __parse_obj_line(line)
# extract comment
if key == 'comment':
pass
# extract roi3D name
elif key == 'name':
roi3D['NAME'] = str(match.group(1))
# fill vertices array
elif key == 'vertice':
vertices.append(tuple([float(match.group(1)), float(match.group(2)), float(match.group(3))]))
# extract roi3D vertice id
elif key == 'face':
roi3D['FACE'] = [int(i) for i in match.group(1).split()]
# store roi3D dict into scene array
self.append(roi3D)
# clear roi3D dict
roi3D = {}
# go to next line
line = file.readline()
file.close()
# retreive all roi3D vertices
for roi3D in self:
roi3D['VERTICES'] = [ vertices[i-1] for i in roi3D['FACE'] ]
roi3D.pop('FACE', None)
except IOError:
raise IOError(f'File not found: {obj_filepath}')
def set_rotation(self, rvec: list):
"""Set scene rotation vector."""
self.__rotation = rvec
def set_translation(self, tvec: list):
"""Set scene translation vector."""
self.__translation = tvec
def project(self, K, D):
"""Project 3D scene onto 2D scene according optical parameters.
**Returns:** AOI2DScene"""
roi2D_scene = ROI2DScene.ROI2DScene()
for roi3D in self:
vertices_3D = numpy.array(roi3D['VERTICES']).astype('float32')
vertices_2D, J = cv.projectPoints(vertices_3D, self.__rotation, self.__translation, K, D)
vertices_2D = vertices_2D.astype('int').reshape((len(vertices_2D), 2))
roi2D = {
'NAME': roi3D['NAME'],
'VERTICES': vertices_2D,
'POINTER_INSIDE': False
}
roi2D_scene.append(roi2D)
return roi2D_scene
|