Skip to content

Commit

Permalink
rebase
Browse files Browse the repository at this point in the history
  • Loading branch information
kikislater authored May 5, 2022
1 parent 3877163 commit 4c9e431
Show file tree
Hide file tree
Showing 5 changed files with 218 additions and 15 deletions.
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ RUN cd micmac && \
ENV PATH "$PATH:/code/micmac/bin"

RUN ln -s "$(which python3)" /usr/bin/python
ENV python "$(which python3)"
RUN figlet -f slant NodeMICMAC

RUN mkdir /code/opendm
Expand Down
20 changes: 9 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# NodeMICMAC
<img src="https://dsy5mvbgl2i1x.cloudfront.net/wp-content/uploads/2018/01/dm_logo1_inv.png" width="300px"><br/><br/>

NodeMICMAC is a Node.js App and REST API to access [MicMac](https://github.com/micmacIGN/micmac). It exposes an API which is used by [WebODM](https://github.com/OpenDroneMap/WebODM) or other projects.
This project is sponsored and developed by [DroneMapper](https://dronemapper.com). This repository was originally forked from [NodeODM](https://github.com/OpenDroneMap/NodeODM), which is part of the [OpenDroneMap](https://www.opendronemap.org/) Project.
Expand Down Expand Up @@ -27,7 +28,7 @@ This list is not by order of importance.
- [ ] Oblique Imagery and/or 3D Model
- [x] Conform / Rename Outputs to ODM Conventions
- [x] Wire Up 2D and Potree Tile Creation
- [x] Multi-Scale Tie-Point Generation (Speed up processing by switching to image resolution)
- [x] Multi-Scale Tie-Point Generation (Similar to Photoscan)
- [ ] Export Undistorted Images
- [ ] Utilize RPY Omega Phi Kappa
- [x] Sparse Point Cloud w/ Camera Position
Expand Down Expand Up @@ -60,7 +61,7 @@ Note: This project currently creates a geo-referenced DEM and Ortho from our 4th
![Greg12 Ortho](docs/readme_greg12_ortho_gcp.png)
![Greg12 GCP1](docs/readme_greg12_gcp1.png)

* Results clipped to an AOI
* Results clipped to an AOI and displayed using Global Mapper [GlobalMapper](https://bluemarblegeo.com)

## Mission Planning / Execution

Expand All @@ -76,12 +77,12 @@ We recommend that you setup NodeMICMAC using [Docker](https://www.docker.com/).

* Docker image build:
```
docker build -t odm/node-micmac .
docker build -t dronemapper/node-micmac .
```

* From the Docker Quickstart Terminal (Windows / OSX) or from the command line (Linux) type:
```
docker run -p 3000:3000 odm/node-micmac
docker run -p 3000:3000 dronemapper/node-micmac
```

* If you're on Windows/OSX, find the IP of your Docker machine by running this command from your Docker Quickstart Terminal:
Expand All @@ -104,7 +105,7 @@ If the computer running NodeMICMAC is using an old or 32bit CPU, you need to com
For GCP processing, you will need to include two files in txt format. Examples of the files are shown
below.

`GCP_3D.txt`
`DroneMapperGCP_3D.txt`

`GCPNAME UTMX UTMY Z PRECISIONXY PRECISIONZ`
```$xslt
Expand All @@ -121,7 +122,7 @@ hg2 250117.42 4319009.086 2565.418 0.005 0.005
sw2 250159.165 4319019.774 2567.198 0.005 0.005
```

`GCP_2D.txt`
`DroneMapperGCP_2D.txt`

`GCPNAME IMAGENAME PIXELX PIXELY`
```$xslt
Expand Down Expand Up @@ -218,7 +219,7 @@ optional arguments:
Distance threshold in meters to find pre-matching
images based on GPS exif data. Default: 0 (use auto-distance)
--multi-scale Uses an image file pair based multi-scale tie-point
generation routine.
generation routine similar to Photoscan.
--remove-ortho-tiles Remove every other ortho tile. Speeds up ortho creation and radiometric equalization.
--camera-cloud Creates a sparse point cloud with camera positions
--image-footprint Creates a point cloud and geojson with image footprints
Expand Down Expand Up @@ -282,7 +283,7 @@ make && sudo make install
```bash
sudo curl --silent --location https://deb.nodesource.com/setup_6.x | sudo bash -
sudo apt-get install -y nodejs python-gdal
git clone hhttps://github.com/OpenDroneMap/NodeMICMAC.git
git clone hhttps://github.com/dronemapper-io/NodeMICMAC.git
cd NodeMICMAC
npm install
```
Expand Down Expand Up @@ -366,6 +367,3 @@ Stay current with upstream MicMac development providing an easy to use interface
## MicMac Version

Cloned: 04-26-2019 Commit: [fec03b2](https://github.com/micmacIGN/micmac/commit/fec03b2b9596886f9b929f5b663bbded3ae591c0)
MicMac is under CeCill-B License
Original running project could be find following this link : http://logiciels.ign.fr/?Micmac

28 changes: 24 additions & 4 deletions helpers/odmOptionsToJson.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,20 @@
import imp
import argparse
import json
import os

dest_file = os.environ.get("ODM_OPTIONS_TMP_FILE")

sys.path.append(sys.argv[2])

imp.load_source('context', sys.argv[2] + '/opendm/context.py')
try:
imp.load_source('opendm', sys.argv[2] + '/opendm/__init__.py')
except:
pass
try:
imp.load_source('context', sys.argv[2] + '/opendm/context.py')
except:
pass
odm = imp.load_source('config', sys.argv[2] + '/opendm/config.py')

options = {}
Expand All @@ -38,6 +48,16 @@ def add_argument(self, *args, **kwargs):
def add_mutually_exclusive_group(self):
return ArgumentParserStub()

odm.parser = ArgumentParserStub()
odm.config()
print json.dumps(options)
if not hasattr(odm, 'parser'):
# ODM >= 2.0
odm.config(parser=ArgumentParserStub())
else:
# ODM 1.0
odm.parser = ArgumentParserStub()
odm.config()

out = json.dumps(options)
print(out)
if dest_file is not None:
with open(dest_file, "w") as f:
f.write(out)
136 changes: 136 additions & 0 deletions libs/odmRunner.js.bak
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/*
Node-OpenDroneMap Node.js App and REST API to access OpenDroneMap.
Copyright (C) 2016 Node-OpenDroneMap Contributors

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
let fs = require('fs');
let path = require('path');
let assert = require('assert');
let spawn = require('child_process').spawn;
let config = require('../config.js');
let logger = require('./logger');


module.exports = {
run: function(options, projectName, done, outputReceived){
assert(projectName !== undefined, "projectName must be specified");
assert(options["project-path"] !== undefined, "project-path must be defined");

const command = path.join(config.odm_path, "run.sh"),
params = [];

for (var name in options){
let value = options[name];

// Skip false booleans
if (value === false) continue;

params.push("--" + name);

// We don't specify "--time true" (just "--time")
if (typeof value !== 'boolean'){
params.push(value);
}
}

params.push(projectName);

logger.info(`About to run: ${command} ${params.join(" ")}`);

if (config.test){
logger.info("Test mode is on, command will not execute");

let outputTestFile = path.join("..", "tests", "odm_output.txt");
fs.readFile(path.resolve(__dirname, outputTestFile), 'utf8', (err, text) => {
if (!err){
let lines = text.split("\n");
lines.forEach(line => outputReceived(line));

done(null, 0, null);
}else{
logger.warn(`Error: ${err.message}`);
done(err);
}
});

return; // Skip rest
}

// Launch
let childProcess = spawn(command, params, {cwd: config.odm_path});

childProcess
.on('exit', (code, signal) => done(null, code, signal))
.on('error', done);

childProcess.stdout.on('data', chunk => outputReceived(chunk.toString()));
childProcess.stderr.on('data', chunk => outputReceived(chunk.toString()));

return childProcess;
},

getVersion: function(done){
fs.readFile(path.join(config.odm_path, 'VERSION'), {encoding: 'utf8'}, (err, content) => {
if (err) done(null, "?");
else done(null, content.split("\n").map(l => l.trim())[0]);
});
},

getJsonOptions: function(done){
// In test mode, we don't call ODM,
// instead we return a mock
if (config.test){
let optionsTestFile = path.join("..", "tests", "odm_options.json");
fs.readFile(path.resolve(__dirname, optionsTestFile), 'utf8', (err, json) => {
if (!err){
try{
let options = JSON.parse(json);
done(null, options);
}catch(e){
logger.warn(`Invalid test options ${optionsTestFile}: ${err.message}`);
done(e);
}
}else{
logger.warn(`Error: ${err.message}`);
done(err);
}
});

return; // Skip rest
}

// Launch
let childProcess = spawn("python", [path.join(__dirname, "..", "helpers", "odmOptionsToJson.py"),
"--project-path", config.odm_path, "bogusname"]);
let output = [];

childProcess
.on('exit', (code, signal) => {
try{
let json = JSON.parse(output.join(""));
done(null, json);
}catch(err){
done(new Error(`Could not load list of options from OpenDroneMap. Is OpenDroneMap installed in ${config.odm_path}? Make sure that OpenDroneMap is installed and that --odm_path is set properly: ${err.message}`));
}
})
.on('error', done);

let processOutput = chunk => output.push(chunk.toString());

childProcess.stdout.on('data', processOutput);
childProcess.stderr.on('data', processOutput);
}
};
48 changes: 48 additions & 0 deletions libs/utils.js.bak
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
"use strict";

const path = require('path');

module.exports = {
get: function(scope, prop, defaultValue){
let parts = prop.split(".");
let current = scope;
for (let i = 0; i < parts.length; i++){
if (current[parts[i]] !== undefined && i < parts.length - 1){
current = current[parts[i]];
}else if (current[parts[i]] !== undefined && i < parts.length){
return current[parts[i]];
}else{
return defaultValue;
}
}
return defaultValue;
},

sanitize: function(filePath){
filePath = filePath.replace(/[^\w.-]/g, "_");
return filePath;
},

parseUnsafePathsList: function(paths){
// Parse a list (or a JSON encoded string representing a list)
// of paths and remove all traversals (., ..) and guarantee
// that the paths are relative

if (typeof paths === "string"){
try{
paths = JSON.parse(paths);
}catch(e){
return [];
}
}

if (!Array.isArray(paths)){
return [];
}

return paths.map(p => {
const safeSuffix = path.normalize(p).replace(/^(\.\.(\/|\\|$))+/, '');
return path.join('./', safeSuffix);
});
}
};

0 comments on commit 4c9e431

Please sign in to comment.