-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Dockerfile with example cpp to reconstruct 3D points from multiple 2D…
… images
- Loading branch information
0 parents
commit aed6c4c
Showing
4 changed files
with
240 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
FROM python:3.5 | ||
MAINTAINER Alyssa Quek | ||
|
||
# Common libs and for OpenCV | ||
RUN apt-get update && \ | ||
apt-get install -y \ | ||
build-essential \ | ||
cmake \ | ||
git \ | ||
wget \ | ||
unzip \ | ||
yasm \ | ||
vim \ | ||
ninja-build \ | ||
pkg-config \ | ||
libswscale-dev \ | ||
libtbb2 \ | ||
libtbb-dev \ | ||
libjpeg-dev \ | ||
libpng-dev \ | ||
libtiff-dev \ | ||
libjasper-dev \ | ||
libavformat-dev \ | ||
libpq-dev \ | ||
libeigen3-dev | ||
|
||
# SFM dependencies: google-glog + gflags, blas + lapack, suitespare, VTK (viz toolkit) | ||
RUN apt-get install -y \ | ||
libgoogle-glog-dev \ | ||
libatlas-base-dev \ | ||
libsuitesparse-dev \ | ||
libvtk5-dev \ | ||
python-vtk \ | ||
libgtk2.0-dev \ | ||
libqt4-dev | ||
|
||
RUN pip install --upgrade pip && pip install numpy | ||
|
||
# Install Ceres Solver | ||
WORKDIR / | ||
RUN git clone https://ceres-solver.googlesource.com/ceres-solver \ | ||
&& cd ceres-solver \ | ||
&& mkdir build && cd build \ | ||
&& cmake -G Ninja .. \ | ||
&& ninja -j4 \ | ||
&& ninja install \ | ||
&& ldconfig | ||
|
||
ENV PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:/usr/local/share/pkgconfig:/usr/lib/pkgconfig | ||
# Include eigen into C++ build include | ||
ENV CPLUS_INCLUDE_PATH=$CPLUS_INCLUDE_PATH:/usr/include/eigen3/:/usr/local/include/opencv:/usr/local/include/opencv2 | ||
ENV LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib | ||
|
||
WORKDIR / | ||
|
||
# Force HAVE_EIGEN and GFLAGS_FOUND to TRUE as cmake does not seem to set those flags correctly | ||
RUN cv_version=master \ | ||
&& wget https://github.com/opencv/opencv/archive/"$cv_version".zip -O opencv.zip \ | ||
&& unzip opencv.zip \ | ||
&& wget https://github.com/opencv/opencv_contrib/archive/"$cv_version".zip -O opencv_contrib.zip \ | ||
&& unzip opencv_contrib \ | ||
&& mkdir /opencv-"$cv_version"/cmake_binary \ | ||
&& cd /opencv-"$cv_version"/cmake_binary \ | ||
&& cmake -G Ninja \ | ||
-DOPENCV_EXTRA_MODULES_PATH=/opencv_contrib-"$cv_version"/modules \ | ||
-DHAVE_EIGEN=TRUE -DGFLAGS_FOUND=TRUE \ | ||
-DBUILD_TIFF=ON \ | ||
-DENABLE_AVX=ON \ | ||
-DWITH_OPENGL=ON \ | ||
-DWITH_OPENCL=ON \ | ||
-DWITH_IPP=ON \ | ||
-DWITH_TBB=ON \ | ||
-DWITH_EIGEN=ON \ | ||
-DWITH_VTK=ON \ | ||
-DWITH_V4L=ON \ | ||
-DBUILD_EXAMPLES=ON \ | ||
-DINSTALL_C_EXAMPLES=ON \ | ||
-DINSTALL_PYTHON_EXAMPLES=ON \ | ||
-DBUILD_TESTS=OFF \ | ||
-DBUILD_PERF_TESTS=OFF \ | ||
-DCMAKE_BUILD_TYPE=RELEASE \ | ||
-DCMAKE_INSTALL_PREFIX=$(python3.5 -c "import sys; print(sys.prefix)") \ | ||
-DPYTHON_EXECUTABLE=$(which python3.5) \ | ||
-DPYTHON_INCLUDE_DIR=$(python3.5 -c "from distutils.sysconfig import get_python_inc; print(get_python_inc())") \ | ||
-DPYTHON_PACKAGES_PATH=$(python3.5 -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())") .. \ | ||
&& ninja -j4 install \ | ||
&& rm /opencv.zip \ | ||
&& rm /opencv_contrib.zip | ||
|
||
RUN pip install -r requirements.txt | ||
|
||
# Define default command | ||
CMD ["bash"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
# 3D reconstruction from multiple 2D images | ||
|
||
The current structure from motion (SFM) module only runs in Linux. | ||
As such, I used [docker](https://www.docker.com) on my Mac to reconstruct the 3D points. | ||
|
||
## Docker Dev Environment | ||
```sh | ||
# Build the docker image | ||
docker build -t python-opencv . | ||
# Run the docker container mounting `reconstruction` folder to `/app` | ||
docker run -it -v <path_to_reconstruction_folder>:/app python-opencv /bin/bash | ||
``` | ||
|
||
## Run | ||
1) Download 2D temple images from <http://vision.middlebury.edu/mview/data> | ||
2) Save list of images to `images.txt`: | ||
```sh | ||
# images.txt will contain lines of filepath | ||
# /app/temple/temple0302.png | ||
ls temple/*.png > images.txt | ||
sed -i -e 's/^/\/app\//' images.txt | ||
``` | ||
3) In the docker container, compile the cpp file | ||
``` | ||
g++ example_sfm.cpp -L/usr/local/lib/ -lopencv_core -lopencv_sfm -lopencv_viz | ||
``` | ||
4) Run the example with the list of images | ||
``` | ||
./a.out images.txt 350 240 360 | ||
``` | ||
|
||
## Test | ||
```sh | ||
# Test eigen | ||
g++ -I /usr/local/Cellar/eigen/3.2.10/include/eigen3/ eigen_test.cpp -o eigen | ||
./a.out | ||
|
||
|
||
# Test with full includes | ||
g++ example_sfm.cpp -I /usr/include/eigen3/ -I/usr/local/include/opencv -I/usr/local/include/opencv2 -L /usr/local/share/OpenCV/3rdparty/lib/ -L/usr/local/lib/ -L /usr/include/eigen3/ -lopencv_core -lopencv_imgproc -lopencv_highgui -lopencv_ml -lopencv_optflow -lopencv_sfm -lopencv_viz | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
#define CERES_FOUND true | ||
|
||
#include <opencv2/sfm.hpp> | ||
#include <opencv2/viz.hpp> | ||
#include <opencv2/calib3d.hpp> | ||
#include <opencv2/core.hpp> | ||
#include <iostream> | ||
#include <fstream> | ||
#include <string> | ||
#include <iomanip> | ||
using namespace std; | ||
using namespace cv; | ||
using namespace cv::sfm; | ||
|
||
static void help() { | ||
cout | ||
<< "\n------------------------------------------------------------------------------------\n" | ||
<< " This program shows the multiview reconstruction capabilities in the \n" | ||
<< " OpenCV Structure From Motion (SFM) module.\n" | ||
<< " It reconstruct a scene from a set of 2D images \n" | ||
<< " Usage:\n" | ||
<< " example_sfm_scene_reconstruction <path_to_file> <f> <cx> <cy>\n" | ||
<< " where: path_to_file is the file absolute path into your system which contains\n" | ||
<< " the list of images to use for reconstruction. \n" | ||
<< " f is the focal lenght in pixels. \n" | ||
<< " cx is the image principal point x coordinates in pixels. \n" | ||
<< " cy is the image principal point y coordinates in pixels. \n" | ||
<< "------------------------------------------------------------------------------------\n\n" | ||
<< endl; | ||
} | ||
int getdir(const string _filename, vector<string> &files) | ||
{ | ||
ifstream myfile(_filename.c_str()); | ||
if (!myfile.is_open()) { | ||
cout << "Unable to read file: " << _filename << endl; | ||
exit(0); | ||
} else {; | ||
size_t found = _filename.find_last_of("/\\"); | ||
string line_str, path_to_file = _filename.substr(0, found); | ||
while ( getline(myfile, line_str) ) { | ||
cout << line_str << endl; | ||
files.push_back(line_str); | ||
} | ||
} | ||
return 1; | ||
} | ||
int main(int argc, char* argv[]) | ||
{ | ||
// Read input parameters | ||
if ( argc != 5 ) | ||
{ | ||
help(); | ||
exit(0); | ||
} | ||
// Parse the image paths | ||
vector<string> images_paths; | ||
getdir( argv[1], images_paths ); | ||
// Build instrinsics | ||
float f = atof(argv[2]), | ||
cx = atof(argv[3]), cy = atof(argv[4]); | ||
Matx33d K = Matx33d( f, 0, cx, | ||
0, f, cy, | ||
0, 0, 1); | ||
bool is_projective = true; | ||
vector<Mat> Rs_est, ts_est, points3d_estimated; | ||
sfm::reconstruct(images_paths, Rs_est, ts_est, K, points3d_estimated, is_projective); | ||
|
||
// Print output | ||
cout << "\n----------------------------\n" << endl; | ||
cout << "Reconstruction: " << endl; | ||
cout << "============================" << endl; | ||
cout << "Estimated 3D points: " << points3d_estimated.size() << endl; | ||
cout << "Estimated cameras: " << Rs_est.size() << endl; | ||
cout << "Refined intrinsics: " << endl << K << endl << endl; | ||
cout << "3D Visualization: " << endl; | ||
cout << "============================" << endl; | ||
viz::Viz3d window("Coordinate Frame"); | ||
window.setWindowSize(Size(500,500)); | ||
window.setWindowPosition(Point(150,150)); | ||
window.setBackgroundColor(); // black by default | ||
// Create the pointcloud | ||
cout << "Recovering points ... "; | ||
|
||
// recover estimated points3d | ||
ofstream points_file; | ||
cv::MatIterator_<double> mat_it; | ||
points_file.open("points.txt"); | ||
points_file.precision(std::numeric_limits<double>::digits10); | ||
for (int i = 0; i < points3d_estimated.size(); ++i) { | ||
std::cout << points3d_estimated[i] << std::endl; | ||
for(mat_it = points3d_estimated[i].begin<double>(); mat_it != points3d_estimated[i].end<double>(); mat_it++){ | ||
points_file << *mat_it << " "; | ||
} | ||
points_file << "\n"; | ||
} | ||
cout << "Done. Points saved to points.txt" << endl; | ||
points_file.close(); | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
matplotlib | ||
scipy | ||
docopt | ||
Pillow | ||
future | ||
ipython |