g2o: A General Framework for Graph Optimization (Python bindings)
Project description
g2o - General Graph Optimization
Ubicoders g2opy edition
This project is based on the original g2o maintainer as below.
This porject provide windows and linux off the shelf packge including .dll and .so files as well as the types of the apis for intellisense.
Otherthan that, same as g2o's pymem branch
Latest Commit base:
- 70f058fde4516505ecb3b392b25bd66b2f4fdf47 (Sep 21, 2025)
How it works
Built the .whl with the damn .dll and .so files for god xxxxing sake.
The pip packge name is pyg2o. But import with import g2opy as g2o
Intellisense Enhanced
Supported Python Versions
- 3.10 ⬜
- 3.11 ⬜
- 3.12 ✅
Supproted Numpy Version
- numpy 1 ⬜
- numpy 2 ✅
Tested OS and Python
- Windows 11 ✅
- Ubuntu 20 ⬜
- Ubuntu 22 ⬜
- Ubuntu 24 ✅
- Ubuntu 25 ✅
ubuntu dependencies
sudo apt-get install -qq qtdeclarative5-dev qt5-qmake libqglviewer-dev-qt5 libsuitesparse-dev libeigen3-dev -y
pip install "numpy>=2.0"
For the new conda env
conda install -y -c conda-forge "libstdcxx-ng>=12" "libgcc-ng>=12" libgomp
Test the installaton
import numpy as np
import g2opy as g2o
np.set_printoptions(precision=3)
np.set_printoptions(suppress=True)
from collections import defaultdict
def showCameraPoses(optim, idx, N):
for i in range(idx, idx + N):
T = optim.vertex(i).estimate().matrix()
trans = T[:3, 3]
print('camera pose at ', i, ': ', trans)
def calcSSE(optim, idx, wPts):
sse = 0
N = wPts.shape[0]
for i in range(idx, idx + N):
guessedWpt = optim.vertex(i)
error = guessedWpt.estimate() - wPts[i-idx]
sse += np.sum(error ** 2)
return sse
def showWpts(optim, idx, N):
for i in range(idx, idx + N):
T = optim.vertex(i).estimate()
#T = np.round(T, 0)
print('guessed wPt at ', i-idx, ': ', T)
def main():
optimizer = g2o.SparseOptimizer()
solver = g2o.BlockSolverSE3(g2o.LinearSolverCSparseSE3())
solver = g2o.OptimizationAlgorithmLevenberg(solver)
optimizer.set_algorithm(solver)
f, p = 200, 256
baseline = 0.3
K = np.array([[f, 0, p],
[0, f, p],
[0, 0, 1]])
wPts = np.array([
[0, 0, 10],
[-1, 3, 30],
[2, 2, 37.2],
])
num_pose = 10
for i in range(0, int(num_pose/2)):
pose = g2o.Isometry3d(np.identity(3), [(i-2)*10, 0, 0])
v_se3 = g2o.VertexSCam()
v_se3.set_cam(f, f, p, p, baseline)
v_se3.set_id(i)
v_se3.set_estimate(pose)
if i < 2:
v_se3.set_fixed(True)
v_se3.set_all() # sets transfrom, projection, dR (angle)
optimizer.add_vertex(v_se3)
for i in range(int(num_pose/2), num_pose):
pose = g2o.Isometry3d(np.identity(3), [0, (i - int(num_pose/2)- 2) * 10, 0])
v_se3 = g2o.VertexSCam()
v_se3.set_cam(f, f, p, p, baseline)
v_se3.set_id(i)
v_se3.set_estimate(pose)
v_se3.set_fixed(False)
v_se3.set_all() # sets transfrom, projection, dR (angle)
optimizer.add_vertex(v_se3)
point_id = 0
for i, wpt in enumerate(wPts):
guessed_wPt = g2o.VertexPointXYZ()
guessed_wPt.set_id(num_pose + point_id)
guessed_wPt.set_marginalized(True)
guessed_wPt.set_estimate(wpt + np.random.randn(3) )
optimizer.add_vertex(guessed_wPt)
for j in range(num_pose):
z = optimizer.vertex(j).map_point(wpt)
if i > 1:
z += np.random.randn(3)
edge = g2o.EdgeXyzVsc()
edge.set_vertex(0, guessed_wPt)
edge.set_vertex(1, optimizer.vertex(j))
edge.set_measurement(z)
edge.set_information(np.identity(3))
optimizer.add_edge(edge)
point_id += 1
sse0 = calcSSE(optimizer, num_pose, wPts)
print('\nRMSE (inliers only):')
print('before optimization:', np.sqrt(sse0 / wPts.shape[0]))
showCameraPoses(optimizer, 0, num_pose)
showWpts(optimizer, num_pose, 3)
print('Performing full BA:')
optimizer.initialize_optimization()
optimizer.set_verbose(False)
optimizer.optimize(100)
sse1 = calcSSE(optimizer, num_pose, wPts)
print('\nRMSE (inliers only):')
print('after optimization:', np.sqrt(sse1 / wPts.shape[0]))
showCameraPoses(optimizer, 0, num_pose)
showWpts(optimizer, num_pose, 3)
if __name__ == '__main__':
main()
see the orignal readme at https://github.com/RainerKuemmerle/g2o
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ubicoders_g2opy-2.1.1-cp312-cp312-win_amd64.whl.
File metadata
- Download URL: ubicoders_g2opy-2.1.1-cp312-cp312-win_amd64.whl
- Upload date:
- Size: 9.5 MB
- Tags: CPython 3.12, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f65f59549382ed63cff8d8e90806541d3652ee022f59ae4570d98beae42b91d0
|
|
| MD5 |
11dcbe12e93f0c2605252feb668e67ce
|
|
| BLAKE2b-256 |
f1a2070b8d0816f2e8a6a794d075ed46b07d5e0098615f3edf710431b4dbe92b
|
File details
Details for the file ubicoders_g2opy-2.1.1-cp312-cp312-manylinux_2_39_x86_64.whl.
File metadata
- Download URL: ubicoders_g2opy-2.1.1-cp312-cp312-manylinux_2_39_x86_64.whl
- Upload date:
- Size: 17.4 MB
- Tags: CPython 3.12, manylinux: glibc 2.39+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
122e4ce04336c5518a0a245bee1214c2694b105027664587c9120de9d80c6194
|
|
| MD5 |
157a47090a2a2ed2a0fbfda84f65d3a4
|
|
| BLAKE2b-256 |
53dab9ac858925f8867f34638dba50d503c3c05a82cbc9137c763215566f577e
|