aboutsummaryrefslogtreecommitdiff
path: root/src/argaze/AreaOfInterest/AOI3DScene.py
blob: 28150c6b74a739b26b1abc379dce592673179991 (plain)
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
#!/usr/bin/env python

from dataclasses import dataclass, field
import math
import re

from argaze import DataStructures
from argaze.AreaOfInterest import AOIFeatures, AOI2DScene

import numpy
import cv2 as cv

@dataclass
class AOI3DScene(AOIFeatures.AOIScene):
	"""Define AOI 3D scene."""

	rotation: list = field(init=False, default=numpy.asarray([0., 0., 0.]))
	translation: list = field(init=False, default=numpy.asarray([0., 0., 0.]))

	def __post_init__(self, **aois):

		# set dimension member
		self.dimension = 3

	def load(self, obj_filepath: str):
		"""Load AOI3D 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:

			name = None
			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 aoi3D name
					elif key == 'name':

						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 aoi3D vertice id
					elif key == 'face':

						faces[name] = [int(i) for i in match.group(1).split()]

					# go to next line
					line = file.readline()

				file.close()

				# retreive all aoi3D vertices
				for name, face in faces.items():
					aoi3D = numpy.array([ vertices[i-1] for i in face ]).astype('float32').view(AOIFeatures.AreaOfInterest)
					self.append(name, aoi3D)

		except IOError:
			raise IOError(f'File not found: {obj_filepath}')

	def project(self, K, D):
		"""Project 3D scene onto 2D scene according optical parameters.
		**Returns:** AOI2DScene"""

		aoi2D_scene = AOI2DScene.AOI2DScene()

		for name, aoi3D in self.areas.items():

			vertices_2D, J = cv.projectPoints(aoi3D, self.rotation, self.translation, K, D)
			vertices_2D = vertices_2D.astype('int').reshape((len(vertices_2D), 2)).tolist()

			aoi2D = numpy.array(vertices_2D).view(AOIFeatures.AreaOfInterest)

			aoi2D_scene.append(name, aoi2D)

		return aoi2D_scene