This first cell is largely book keeping and environment setup. The second line places a configuration file into the environment that provides URLs, paths, and login information for the services that AutoCNet uses, as well as information about the spatial reference system the project is going to use.
Lines 4-6 get the USGS Community Sensor Model plugin loaded and ready for use.
%% Cell type:code id: tags:
``` python
importos
os.environ['autocnet_config']='config/sample.yml'
os.environ['PROJ_LIB']='/home/ladoramkershner/miniconda3/env/autocnet_local/share/proj'#point to you local environment path
os.environ['PROJ_LIB']='/home/ladoramkershner/miniconda3/envs/autocnet_local/share/proj'#point to you local environment path
The primary way to use AutoCNet is through the CandidateGraph object. In this demo, the derived, NetworkCandidateGraph is used. This object has an identical interface to the CandidateGraph. The difference lies in where the data are stored. In the CandidateGraph everything is stored in memory and all processing occurs in serial. On the NetworkCandidateGraph, data are stored in a database and processing occurs either in serial or on a compute cluster.
Below, the `from_filelist` method is used to perform an initial database populate. A few things are happening here behind the scenes:
* The database (name specified in the configuration file) is being created if it does not already exist. This creates all of the tables, relationships, and triggers.
* The `images` table is being populated with metadata about the images in the file list including a lat/lon footprint.
* The `cameras` table is being populated with a CSM compliant state string.
For a one-and-done style project, this cell should be run once.
The cell below is the primary mechanism for accessing an existing project. Here, the `from_database` class method is used. This method makes a spatial query to the `images` table and builds a graph object where the nodes are images and the edges linking nodes indicate that the footprints overlap. This call makes no modifications to the database.
%% Cell type:code id: tags:
``` python
# On subsequent runs
ncg=NetworkCandidateGraph().from_database()
```
%% Cell type:markdown id: tags:
The database currently contains a populated `images` table and a populated `cameras` table. In the current pipeline style flow, we now need to compute polygons generated by the overlaps of footprints. It is within those polygons that correspondences can be found. We run two SQL queries (found in the `sql` directory).
The first query computes the n-wise overlapping polygons and the second query identifies those polygons that contributed to the overlapping geometry. The picture below illustrates what the result looks like.

Each polygon (A, B, AB, ABC, BC) will be an independent row in the database. The `intersections` column will be populated with an array where the values in the array are the `id`s of the image that contributed to the particular overlap.
%% Cell type:code id: tags:
``` python
# Run the 2 sql commands in the sql directory of the autocnet repo to compute overlaps and get the overlap arrays populates
```
%% Cell type:markdown id: tags:
Once overlaps have been computed, points are placed into the overlapping geometries. This process adds points to the `points` table and measures to the `measures` table. These points and measures are synonymous with the points and measures in an ISIS control network. This code is making use of the `images` and `cameras` tables that have been previously populated.
%% Cell type:code id: tags:
``` python
# This block is used to compute the overlapping polygon components and then place points into them.
place_points_in_overlaps(ncg,height=-3000)# This value is good for elysium, but needs to be more granularly parameterizable
# A bad height value results in very poor results... The height is height above (below) the sphere (the aeroid).
# To generalize this, we would spawn a new cluster job for each geomety and pull a height dynamically from from reference
place_points_in_overlaps(ncg)
```
%% Cell type:markdown id: tags:
Next, the points/measures are converted to be pairwise matches between images. Instead of a point-centric representation where a point has many measures, this representation is image-to-image centric where a pair of images has some set of shared correspondences. This command results in the `matches` table being populated with the pairwise matches between edges. Using the above example, all of the points/measures placed in the overlapping ABC polygon are decomposed into matches between AB, AC, and BC. The data are identical, but the representation has changed.
We do this because now we want to use classic computer vision techniques that generally operate best with pairwise representations.
%% Cell type:code id: tags:
``` python
# This block converts the points into matches
fors,d,einncg.edges(data='data'):# intentionally in a loop so this doesn't spawn a cluster job
e.network_to_matches()
```
%% Cell type:markdown id: tags:
Now that a pairwise representation exists, we apply a standard CV technique (computation of the fundamental matrix (F)). This operation updates the `edges` table to add the F matrix and a mask to the `masks` column indicating whether a particular match has been flagged as a blunder by the ransac procedure. This code is making use of the `matches` table that has been previously populated.
/home/jlaura/autocnet/autocnet/transformation/fundamental_matrix.py:310: UserWarning: F Computation Failed.
warnings.warn("F Computation Failed.")
%% Cell type:markdown id: tags:
Finally, the next three cells are a janky heuristic designed to use the F matrix to remove blunders in the `points` and `measures` tables. This is an aggregation step whereby we seek to determine if a measure should be made inactive. This code makes use of the `edges` table (`masks` column) and updates the `measures` table (`active` column).
These three cells are not well integrated into the NetworkCandidateGraph and provide the best view of the type of operations happening under the hood in the previous steps.
%% Cell type:code id: tags:
``` python
# This block converts the points into matches
counters=[]
fors,d,einncg.edges(data='data'):# intentionally in a loop so this doesn't spawn a cluster job
counters.append(e.mask_to_counter('fundamental'))
```
%% Cell type:code id: tags:
``` python
fromcollectionsimportCounter
fromautocnetimportSession
fromautocnet.io.db.modelimportMeasures
aggregate=sum(counters,Counter())
# Now I need to take the output here and then look in qnet to see wtf is going on. Do we have a threshold here
# for blowing away bad stuff? If so, where? I should probably normalize all of these too based on the number of other
# images that they exist in. In other words, count/n-images