use of boofcv.alg.geo.bundle.cameras.BundlePinholeSimplified in project BoofCV by lessthanoptimal.
the class MetricMergeScenes method merge.
/**
* Merges the 'src' scene into 'dst'. Both scenes are only modified if true is returned.
*
* @param dbSimilar Contains image related information
* @param src The scene being merged into 'dst'
* @param dst Where the combined scene will be stored. This is assumed to be the 'more correct' scene
* @return true if src was merged into dst or false if it failed and nothing has been modified
*/
public boolean merge(LookUpSimilarImages dbSimilar, SceneWorkingGraph src, SceneWorkingGraph dst) {
// Find the common views
findCommonViews(src, dst, commonViews, verbose);
if (commonViews.isEmpty())
return false;
// Sort in order of "best" last
Collections.sort(commonViews.toList(), (a, b) -> Double.compare(a.score, b.score));
// Compute the coordinate transform between the scenes using the "best" pair of views
CommonView best = commonViews.getTail();
if (!mergingOps.computeSceneTransform(dbSimilar, src, dst, best.src, best.dst, src_to_dst))
return false;
src_to_dst.transform.invert(transform_dst_to_src);
// Creates a working scene from 'src' but adding values from 'dst' as needed
createWorkScene(src, dst);
// Refine the working scene. This will help mend the differences between the two scenes
if (!refiner.process(dbSimilar, workScene, utils -> {
for (int i = 0; i < knownCameras.size; i++) {
utils.structure.cameras.get(i).known = knownCameras.get(i);
}
for (int i = 0; i < knownViews.size; i++) {
utils.structure.motions.get(i).known = knownViews.get(i);
}
})) {
if (verbose != null)
verbose.println("FAiLED: Refiner return false");
return false;
}
// If they are, fix minor errors, then the merge is considered to be successful
if (!verifyAndFixConstraints(dbSimilar))
return false;
// Print the state of views which are not common so you can see how much they have changed.
if (verbose != null) {
for (int i = 0; i < workScene.listViews.size(); i++) {
SceneWorkingGraph.View wview = workScene.listViews.get(i);
if (dst.views.get(wview.pview.id) != null)
continue;
BundlePinholeSimplified intrinsic = workScene.getViewCamera(wview).intrinsic;
verbose.printf("After id='%s' src={ f=%.1f k1=%.1e k2=%.1e }\n", wview.pview.id, intrinsic.f, intrinsic.k1, intrinsic.k2);
}
}
// Copy the results to 'dst'.
mergeWorkIntoDst(dst);
return true;
}
use of boofcv.alg.geo.bundle.cameras.BundlePinholeSimplified in project BoofCV by lessthanoptimal.
the class MetricMergeScenes method findCommonViews.
/**
* Finds all views which are common between the two scenes
*/
static void findCommonViews(SceneWorkingGraph src, SceneWorkingGraph dst, DogArray<CommonView> commonViews, @Nullable PrintStream verbose) {
commonViews.reset();
// Go through all the views in the src list
for (int srcViewIdx = 0; srcViewIdx < src.listViews.size(); srcViewIdx++) {
SceneWorkingGraph.View srcView = src.listViews.get(srcViewIdx);
SceneWorkingGraph.View dstView = dst.views.get(srcView.pview.id);
if (dstView == null) {
if (verbose != null) {
BundlePinholeSimplified intrinsic = src.getViewCamera(srcView).intrinsic;
verbose.printf("id='%s' src={ f=%.1f k1=%.1e k2=%.1e }\n", srcView.pview.id, intrinsic.f, intrinsic.k1, intrinsic.k2);
}
continue;
}
// use the worst score of the pair as being pessimistic seems to work best in reconstruction
double score = Math.min(srcView.getBestInlierScore(), dstView.getBestInlierScore());
commonViews.grow().setTo(srcView, dstView, score);
if (verbose != null) {
BundlePinholeSimplified srcIntrinsic = src.getViewCamera(srcView).intrinsic;
BundlePinholeSimplified dstIntrinsic = dst.getViewCamera(dstView).intrinsic;
verbose.printf("id='%s' src={ f=%.1f k1=%.1e k2=%.1e } dst={ f=%.1f k1=%.1e k2=%.1e }\n", srcView.pview.id, srcIntrinsic.f, srcIntrinsic.k1, srcIntrinsic.k2, dstIntrinsic.f, dstIntrinsic.k1, dstIntrinsic.k2);
}
}
if (verbose != null) {
verbose.print("Common: size=" + commonViews.size + "/" + src.listViews.size() + " views={ ");
for (int i = 0; i < commonViews.size; i++) {
verbose.print("'" + commonViews.get(i).src.pview.id + "' ");
}
verbose.println("}");
}
}
use of boofcv.alg.geo.bundle.cameras.BundlePinholeSimplified in project BoofCV by lessthanoptimal.
the class ExampleMultiViewSparseReconstruction method compute.
public void compute(String videoName, boolean sequential) {
// Turn on threaded code for bundle adjustment
DDoglegConcurrency.USE_CONCURRENT = true;
// Create a directory to store the work space
String path = UtilIO.pathExample("mvs/" + videoName);
workDirectory = "mvs_work/" + FilenameUtils.getBaseName(videoName);
// Attempt to reload intermediate results if previously computed
if (!rebuild) {
try {
pairwise = MultiViewIO.load(new File(workDirectory, "pairwise.yaml").getPath(), (PairwiseImageGraph) null);
} catch (UncheckedIOException ignore) {
}
try {
working = MultiViewIO.load(new File(workDirectory, "working.yaml").getPath(), pairwise, null);
} catch (UncheckedIOException ignore) {
}
try {
scene = MultiViewIO.load(new File(workDirectory, "structure.yaml").getPath(), (SceneStructureMetric) null);
} catch (UncheckedIOException ignore) {
}
}
// Convert the video into an image sequence. Later on we will need to access the images in random order
var imageDirectory = new File(workDirectory, "images");
if (imageDirectory.exists()) {
imageFiles = UtilIO.listSmart(String.format("glob:%s/images/*.png", workDirectory), true, (f) -> true);
} else {
checkTrue(imageDirectory.mkdirs(), "Failed to image directory");
SimpleImageSequence<InterleavedU8> sequence = DefaultMediaManager.INSTANCE.openVideo(path, ImageType.IL_U8);
System.out.println("----------------------------------------------------------------------------");
System.out.println("### Decoding Video");
BoofMiscOps.profile(() -> {
int frame = 0;
while (sequence.hasNext()) {
InterleavedU8 image = sequence.next();
File imageFile = new File(imageDirectory, String.format("frame%04d.png", frame++));
imageFiles.add(imageFile.getPath());
// This is commented out for what appears to be a JRE bug.
// V [libjvm.so+0xdc4059] SWPointer::SWPointer(MemNode*, SuperWord*, Node_Stack*, bool)
UtilImageIO.saveImage(image, imageFile.getPath());
}
}, "Video Decoding");
}
// Only determine the visual relationship between images if needed
if (pairwise == null || working == null) {
if (sequential) {
similarImagesFromSequence();
} else {
similarImagesFromUnsorted();
}
}
if (pairwise == null)
computePairwiseGraph();
if (working == null)
metricFromPairwise();
if (scene == null)
bundleAdjustmentRefine();
var rod = new Rodrigues_F64();
System.out.println("----------------------------------------------------------------------------");
for (PairwiseImageGraph.View pv : pairwise.nodes.toList()) {
if (!working.containsView(pv.id))
continue;
SceneWorkingGraph.View wv = working.lookupView(pv.id);
int order = working.listViews.indexOf(wv);
ConvertRotation3D_F64.matrixToRodrigues(wv.world_to_view.R, rod);
BundlePinholeSimplified intrinsics = working.getViewCamera(wv).intrinsic;
System.out.printf("view[%2d]='%2s' f=%6.1f k1=%6.3f k2=%6.3f T={%5.1f,%5.1f,%5.1f} R=%4.2f\n", order, wv.pview.id, intrinsics.f, intrinsics.k1, intrinsics.k2, wv.world_to_view.T.x, wv.world_to_view.T.y, wv.world_to_view.T.z, rod.theta);
}
System.out.println(" Views used: " + scene.views.size + " / " + pairwise.nodes.size);
}
Aggregations