From ac3ca4d04b5c16c1c51bc4075c49e42d7b4aeb48 Mon Sep 17 00:00:00 2001 From: "Olivier J.N. Bertrand" <olivier.bertrand@uni-bielefeld.de> Date: Tue, 25 Sep 2018 11:55:44 +0200 Subject: [PATCH] Update database to save frame # as well in order to avoid confusion in case of nans --- doc/source/tutorials/04-optic-flow.ipynb | 38 ++++++- navipy/database/__init__.py | 132 ++++++++++------------- 2 files changed, 89 insertions(+), 81 deletions(-) diff --git a/doc/source/tutorials/04-optic-flow.ipynb b/doc/source/tutorials/04-optic-flow.ipynb index 1b2bc3a..748a288 100644 --- a/doc/source/tutorials/04-optic-flow.ipynb +++ b/doc/source/tutorials/04-optic-flow.ipynb @@ -650,9 +650,41 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "ToDO:\n", - "* implement obpc in optic flow\n", - "* convert markers2bee_sh into obpc format. Need to create viewing dir for el and az, and scene from radius.\n" + "## Optic flow from a database\n", + "\n", + "Database of rendered views along a trajectory can be created by using the tool `blendalongtraj`. Once the database has been created, optic flow can be obtain by using the difference in the position orientation and the distance to surrounding objects (The 'D' channel)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import pkg_resources\n", + "from navipy.database import DataBase\n", + "mydbfile = pkg_resources.resource_filename(\n", + " 'navipy', 'resources/database.db')\n", + "mydb = DataBase(mydbfile)\n", + "mytraj = mydb.posorients\n", + "mytrajdiff = mytraj.differentiate(periods=1)\n", + "mytrajvel = mytraj.join(mytrajdiff)\n", + "mytrajvel.dropna().head()\n", + "\n", + "my_opticflow=pd.DataFrame(index=mytrajvel.index,\n", + " columns=pd.MultiIndex.from_product([points_name,['rof','hof','vof']]))\n", + "my_opticflow=my_opticflow.swaplevel(axis=1)\n", + "horizontal_of = np.zeros((mytrajvel.shape[0],*mydb.viewing_directions[...,0].shape))\n", + "vertical_of = horizontal_of.copy()\n", + "\n", + "for ii, (frame_i, velocity) in enumerate(mytrajvel.dropna().iterrows()):\n", + " scene = mydb.scene(velocity)\n", + " distance = scene[...,3,0]\n", + " # Calculate the optic flow of these points\n", + " _,hof,vof = optic_flow(distance,mydb.viewing_directions,velocity)\n", + " # save the results in df\n", + " horizontal_of[ii,...]=hof\n", + " vertical_of[ii,...]=vof" ] }, { diff --git a/navipy/database/__init__.py b/navipy/database/__init__.py index f7a84ab..0083324 100644 --- a/navipy/database/__init__.py +++ b/navipy/database/__init__.py @@ -137,6 +137,7 @@ class DataBase(): self.tablecolumns['position_orientation']['q_1'] = 'real' self.tablecolumns['position_orientation']['q_2'] = 'real' self.tablecolumns['position_orientation']['q_3'] = 'real' + self.tablecolumns['position_orientation']['frame_i'] = 'real' self.tablecolumns['position_orientation']['rotconv_id'] = 'string' self.tablecolumns['image'] = dict() self.tablecolumns['image']['data'] = 'array' @@ -292,6 +293,12 @@ class DataBase(): raise Exception(msg) found_convention = False index = posorient.index + if isinstance(posorient.name, int): + msg = 'posorient.name should give the frame #' + self._logger.exception(msg) + raise Exception(msg) + frame_i = posorient.name + if isinstance(index, pd.MultiIndex): convention = index.levels[0][-1] else: @@ -353,79 +360,35 @@ class DataBase(): msg = 'posorient must not contain nan\n {}'.format(posorient) self._logger.exception(msg) raise ValueError(msg) - cursor = self.db_cursor.execute('select * from position_orientation') - names = list(map(lambda x: x[0], cursor.description)) where = "" - params = None - if 'alpha_0' in names: - self._logger.warning("you are loading a database with an\ - old convention") - where += """x>=? and x<=?""" - where += """and y>=? and y<=?""" - where += """and z>=? and z<=?""" - where += """and alpha_0>=? and alpha_0<=?""" - where += """and alpha_1>=? and alpha_1<=?""" - where += """and alpha_2>=? and alpha_2<=?""" - params = ( - posorient['location']['x'] - self.__float_tolerance, - posorient['location']['x'] + self.__float_tolerance, - posorient['location']['y'] - self.__float_tolerance, - posorient['location']['y'] + self.__float_tolerance, - posorient['location']['z'] - self.__float_tolerance, - posorient['location']['z'] + self.__float_tolerance, - posorient[convention][naming_map[0]] - self.__float_tolerance, - posorient[convention][naming_map[0]] + self.__float_tolerance, - posorient[convention][naming_map[1]] - self.__float_tolerance, - posorient[convention][naming_map[1]] + self.__float_tolerance, - posorient[convention][naming_map[2]] - self.__float_tolerance, - posorient[convention][naming_map[2]] + self.__float_tolerance) - elif convention != 'quaternion': - where += """x>=? and x<=?""" - where += """and y>=? and y<=?""" - where += """and z>=? and z<=?""" - where += """and q_0>=? and q_0<=?""" - where += """and q_1>=? and q_1<=?""" - where += """and q_2>=? and q_2<=?""" - where += """and rotconv_id =?""" - params = ( - posorient['location']['x'] - self.__float_tolerance, - posorient['location']['x'] + self.__float_tolerance, - posorient['location']['y'] - self.__float_tolerance, - posorient['location']['y'] + self.__float_tolerance, - posorient['location']['z'] - self.__float_tolerance, - posorient['location']['z'] + self.__float_tolerance, - posorient[convention][naming_map[0]] - self.__float_tolerance, - posorient[convention][naming_map[0]] + self.__float_tolerance, - posorient[convention][naming_map[1]] - self.__float_tolerance, - posorient[convention][naming_map[1]] + self.__float_tolerance, - posorient[convention][naming_map[2]] - self.__float_tolerance, - posorient[convention][naming_map[2]] + self.__float_tolerance, - convention) - else: - where += """x>=? and x<=?""" - where += """and y>=? and y<=?""" - where += """and z>=? and z<=?""" - where += """and q_0>=? and q_0<=?""" - where += """and q_1>=? and q_1<=?""" - where += """and q_2>=? and q_2<=?""" + where += """x>=? and x<=?""" + where += """and y>=? and y<=?""" + where += """and z>=? and z<=?""" + where += """and q_0>=? and q_0<=?""" + where += """and q_1>=? and q_1<=?""" + where += """and q_2>=? and q_2<=?""" + where += """and rotconv_id =?""" + where += """and frame_i = ?""" + params = ( + posorient['location']['x'] - self.__float_tolerance, + posorient['location']['x'] + self.__float_tolerance, + posorient['location']['y'] - self.__float_tolerance, + posorient['location']['y'] + self.__float_tolerance, + posorient['location']['z'] - self.__float_tolerance, + posorient['location']['z'] + self.__float_tolerance, + posorient[convention][naming_map[0]] - self.__float_tolerance, + posorient[convention][naming_map[0]] + self.__float_tolerance, + posorient[convention][naming_map[1]] - self.__float_tolerance, + posorient[convention][naming_map[1]] + self.__float_tolerance, + posorient[convention][naming_map[2]] - self.__float_tolerance, + posorient[convention][naming_map[2]] + self.__float_tolerance, + convention, + frame_i) + if convention == 'quaternion': where += """and q_3>=? and q_3<=?""" - where += """and rotconv_id =?""" - params = ( - posorient['location']['x'] - self.__float_tolerance, - posorient['location']['x'] + self.__float_tolerance, - posorient['location']['y'] - self.__float_tolerance, - posorient['location']['y'] + self.__float_tolerance, - posorient['location']['z'] - self.__float_tolerance, - posorient['location']['z'] + self.__float_tolerance, - posorient[convention][naming_map[0]] - self.__float_tolerance, - posorient[convention][naming_map[0]] + self.__float_tolerance, - posorient[convention][naming_map[1]] - self.__float_tolerance, - posorient[convention][naming_map[1]] + self.__float_tolerance, - posorient[convention][naming_map[2]] - self.__float_tolerance, - posorient[convention][naming_map[2]] + self.__float_tolerance, + params = params + ( posorient[convention][naming_map[3]] - self.__float_tolerance, - posorient[convention][naming_map[3]] + self.__float_tolerance, - convention) + posorient[convention][naming_map[3]] + self.__float_tolerance) self.db_cursor.execute( """ SELECT count(*) @@ -445,8 +408,8 @@ class DataBase(): self.db_cursor.execute( """ INSERT - INTO position_orientation(x,y,z,q_0,q_1,q_2,q_3,rotconv_id) - VALUES (?,?,?,?,?,?,?,?) + INTO position_orientation(x,y,z,q_0,q_1,q_2,q_3,rotconv_id,frame_i) + VALUES (?,?,?,?,?,?,?,?,?) """, ( posorient['location']['x'], posorient['location']['y'], @@ -455,13 +418,13 @@ class DataBase(): posorient[convention]['alpha_1'], posorient[convention]['alpha_2'], np.nan, - convention)) + convention, frame_i)) else: self.db_cursor.execute( """ INSERT - INTO position_orientation(x,y,z,q_0,q_1,q_2,rotconv_id) - VALUES (?,?,?,?,?,?,?,?) + INTO position_orientation(x,y,z,q_0,q_1,q_2,rotconv_id,frame_i) + VALUES (?,?,?,?,?,?,?,?,?) """, ( posorient['location']['x'], posorient['location']['y'], @@ -470,7 +433,7 @@ class DataBase(): posorient[convention]['q_1'], posorient[convention]['q_2'], posorient[convention]['q_3'], - convention)) + convention, frame_i)) rowid = self.db_cursor.lastrowid self.db.commit() return rowid @@ -532,15 +495,20 @@ class DataBase(): return self.__convention @property - def posorients(self): + def posorients(self, indexby='frame_i'): """Return the position orientations of all points in the \ database + :params indexby: index posorients by 'frame_i' (default) or 'id' :returns: all position orientations :rtype: list of pd.Series """ posorient = pd.read_sql_query( "select * from position_orientation;", self.db) - posorient.set_index('id', inplace=True) + if indexby in posorient.columns: + posorient.set_index('frame_i', inplace=True) + else: # Handle older db version + print('Could not index by {}'.format(indexby)) + posorient.set_index('id', inplace=True) if self.rotation_convention is not None: posorients = Trajectory() posorients.from_dataframe(posorient, rotconv=self.__convention) @@ -562,6 +530,14 @@ class DataBase(): # Read from database # def read_posorient(self, posorient=None, rowid=None): + """Read posorient with a given posorient or rowid + + :param posorient: pd.Series with MuliIndex + :param rowid: integer, rowid of the database + :returns: return posorient + :rtype: pd.Series + + """ if rowid is not None: if not isinstance(rowid, int): msg = 'rowid must be an integer' -- GitLab