diff --git a/README.md b/README.md index 33e7618..8d3c63c 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,9 @@ Structs for interacting with reconstruction data from different SFM programs ## COLMAP -Interact with COLMAPS's `points3D.bin` file output under the sparse reconstruction data. +### Point Data +Interact with COLMAPS's `points3D.bin` file output under the sparse reconstruction data. ```golang package example @@ -17,18 +18,40 @@ import ( ) func main() { - points, err := colmap.ReadPoints3D("ColmapProject/sparse/0/points3D.bin") - + points, err := colmap.ReadPoints3DBinary("ColmapProject/sparse/0/points3D.bin") if err != nil { panic(err) } - fmt.Printf("File contains %d points", len(points)) } ``` +### Cameras + +Interact with COLMAPS's `cameras.bin` file output under the sparse reconstruction data. + +```golang +package example + +import ( + "fmt" + + "github.com/EliCDavis/sfm/colmap" +) + +func main() { + cameras, err := colmap.ReadCamerasBinary("ColmapProject/sparse/0/cameras.bin") + if err != nil { + panic(err) + } + + fmt.Printf("File contains %d cameras", len(cameras)) +} + +``` + ## Meshroom Interact with Meshroom's `cameras.sfm` file output from the `StructureFromMotion` step. @@ -44,7 +67,6 @@ import ( func main() { cameras, err := meshroom.LoadCameras("MeshroomProject/MeshroomCache/StructureFromMotion/abc123/cameras.sfm") - if err != nil { panic(err) } @@ -68,7 +90,6 @@ import ( func main() { reconstructions, err := opensfm.LoadReconstruction("MyOpenSFMProject/reconstruction.json") - if err != nil { panic(err) } diff --git a/colmap/cameras.go b/colmap/cameras.go new file mode 100644 index 0000000..81eee07 --- /dev/null +++ b/colmap/cameras.go @@ -0,0 +1,103 @@ +package colmap + +import ( + "encoding/binary" + "fmt" + "os" + + "github.com/EliCDavis/bitlib" +) + +type CameraModel int + +const ( + SIMPLE_PINHOLE CameraModel = iota + PINHOLE + SIMPLE_RADIAL + RADIAL + OPENCV + OPENCV_FISHEYE + FULL_OPENCV + FOV + SIMPLE_RADIAL_FISHEYE + RADIAL_FISHEYE + THIN_PRISM_FISHEYE +) + +func (cm CameraModel) NumParameters() int { + switch cm { + case SIMPLE_PINHOLE: + return 3 + + case PINHOLE: + return 4 + + case SIMPLE_RADIAL: + return 4 + + case RADIAL: + return 5 + + case OPENCV: + return 8 + + case OPENCV_FISHEYE: + return 8 + + case FULL_OPENCV: + return 12 + + case FOV: + return 5 + + case SIMPLE_RADIAL_FISHEYE: + return 4 + + case RADIAL_FISHEYE: + return 5 + + case THIN_PRISM_FISHEYE: + return 12 + } + panic(fmt.Errorf("unimplemented Camera Model Parameter Count %d", cm)) +} + +type Camera struct { + ID int + Model CameraModel + Width uint64 + Height uint64 + Params []float64 +} + +func ReadCamerasBinary(filename string) ([]Camera, error) { + f, err := os.Open(filename) + if err != nil { + return nil, err + } + defer f.Close() + + reader := bitlib.NewReader(f, binary.LittleEndian) + + numCameras := reader.UInt64() + cameras := make([]Camera, numCameras) + + for i := uint64(0); i < numCameras; i++ { + c := Camera{} + + c.ID = int(reader.Int32()) + c.Model = CameraModel(reader.Int32()) + c.Width = reader.UInt64() + c.Height = reader.UInt64() + + paramCount := c.Model.NumParameters() + c.Params = make([]float64, paramCount) + for pI := 0; pI < paramCount; pI++ { + c.Params[pI] = reader.Float64() + } + + cameras[i] = c + } + + return cameras, reader.Error() +}