diff --git a/src/main/java/object_detection/types/BoundingBox2D.java b/src/main/java/object_detection/types/BoundingBox2D.java index 51a9dbfa6ad68c53f7f74ca1db009b50d7dfec2d..04bcecac4ba249e3d7afed16fa522dac95a92ecf 100644 --- a/src/main/java/object_detection/types/BoundingBox2D.java +++ b/src/main/java/object_detection/types/BoundingBox2D.java @@ -17,6 +17,28 @@ public class BoundingBox2D { && p.getY() <= (this.y + this.h); } + /* ########## + Getters + ########## */ + public String getPredClass() { + return predClass; + } + + public int getX() { + return x; + } + + public int getY() { + return y; + } + + public int getW() { + return w; + } + + public int getH() { + return h; + } // members int x; diff --git a/src/main/java/object_detection/types/CameraPose.java b/src/main/java/object_detection/types/CameraPose.java index 47c123c99a7ea52f576f7345e8cf0605863d332a..1f543146c4b68e2199830b049ebc290a00a960b0 100644 --- a/src/main/java/object_detection/types/CameraPose.java +++ b/src/main/java/object_detection/types/CameraPose.java @@ -50,6 +50,17 @@ public class CameraPose { return translation; } + /* ########## + Getters + ########## */ + public DMatrixRMaj getR() { + return R; + } + + public DMatrixRMaj getTranslation() { + return translation; + } + /* ################## Members #################### */ diff --git a/src/main/java/object_detection/types/Frame.java b/src/main/java/object_detection/types/Frame.java index e8364c54a8a0454f602b0ef8ed9b58f1dd6c7ebb..a47ad0d7046bfff6c4ab2a57ad216391941f4847 100644 --- a/src/main/java/object_detection/types/Frame.java +++ b/src/main/java/object_detection/types/Frame.java @@ -92,6 +92,21 @@ public class Frame { return res; } + /* ########## + Getters + ########## */ + public String getBboxPath() { + return bboxpath; + } + + public List getBoxes() { + return boxes; + } + + public CameraPose getCamera() { + return camera; + } + /* ######################### Members ########################### */ diff --git a/src/test/java/object_detection/FrameTests.java b/src/test/java/object_detection/FrameTests.java new file mode 100644 index 0000000000000000000000000000000000000000..66d03b6d5043ccd70b5c577352456967b3dc933e --- /dev/null +++ b/src/test/java/object_detection/FrameTests.java @@ -0,0 +1,38 @@ +package object_detection; + +import org.junit.jupiter.api.BeforeEach; +import object_detection.types.*; + +import java.io.FileWriter; +import java.io.IOException; +import java.io.FileNotFoundException; + +class FrameTests { + + private CameraPose cameraPose; + private Frame frame; + + @BeforeEach + void setUp() throws IOException, FileNotFoundException { + // Create a CameraPose for the frame + String tempPoseFile = "test_pose.csv"; + try (FileWriter writer = new FileWriter(tempPoseFile)) { + writer.write("1.0,2.0,3.0\n"); // Translation vector + writer.write("1.0,0.0,0.0\n"); // R matrix rows + writer.write("0.0,1.0,0.0\n"); + writer.write("0.0,0.0,1.0\n"); + } + cameraPose = new CameraPose(tempPoseFile); + + // Create a temporary bbox file for the frame + String tempBboxFile = "test_bbox.csv"; + try (FileWriter writer = new FileWriter(tempBboxFile)) { + writer.write("Class,x,y,w,h\n"); // Header + writer.write("vehicle,10,10,20,20\n"); + writer.write("animal,50,50,30,30\n"); + } + + // Initialize the Frame object + frame = new Frame(tempBboxFile, cameraPose); + } +} diff --git a/target/classes/.DS_Store b/target/classes/.DS_Store deleted file mode 100644 index 126c679b58893cbc25f95559ddb8efe7b9a9d6dd..0000000000000000000000000000000000000000 Binary files a/target/classes/.DS_Store and /dev/null differ diff --git a/target/classes/database/MongoDBInteraction.class b/target/classes/database/MongoDBInteraction.class index 874eee73353f3caf1a22d1e95c7f15feda500cc0..df001b6ca1398e60717338bc83022b5f977c1ab4 100644 Binary files a/target/classes/database/MongoDBInteraction.class and b/target/classes/database/MongoDBInteraction.class differ diff --git a/target/classes/object_detection/.DS_Store b/target/classes/object_detection/.DS_Store deleted file mode 100644 index aff5713ce0a01c7592b2fac9d9fad1c285ba7641..0000000000000000000000000000000000000000 Binary files a/target/classes/object_detection/.DS_Store and /dev/null differ diff --git a/target/classes/object_detection/types/BoundingBox2D.class b/target/classes/object_detection/types/BoundingBox2D.class index 1416df28631dc1c808ca26722452863608c13e7e..029ba6260727cb58286c71f9773334cc4d56ab39 100644 Binary files a/target/classes/object_detection/types/BoundingBox2D.class and b/target/classes/object_detection/types/BoundingBox2D.class differ diff --git a/target/classes/object_detection/types/CameraPose.class b/target/classes/object_detection/types/CameraPose.class index d102f73c6dc1dadc3731300c4cb78b023881e507..a1a946766d583996b40ccce20436c5237c256dcc 100644 Binary files a/target/classes/object_detection/types/CameraPose.class and b/target/classes/object_detection/types/CameraPose.class differ diff --git a/target/classes/object_detection/types/Frame.class b/target/classes/object_detection/types/Frame.class index 437cb66f95c3425ea084877cd1fb766b558a3f03..0a9a8dda070cf308473eb792667abfe30b4c63fa 100644 Binary files a/target/classes/object_detection/types/Frame.class and b/target/classes/object_detection/types/Frame.class differ diff --git a/target/classes/object_detection/types/ObjectSet.class b/target/classes/object_detection/types/ObjectSet.class index 67a9c2b84d9dcce795586e9c7f0cf6e3a55d4df8..e04f5c2a8b407c7957a9655f8879106aa2599829 100644 Binary files a/target/classes/object_detection/types/ObjectSet.class and b/target/classes/object_detection/types/ObjectSet.class differ diff --git a/target/classes/object_detection/types/Point.class b/target/classes/object_detection/types/Point.class index cd48191aba342a8453e3d6e2289d9a912c0ed125..7adc6dcd1d32bd9f49fe5a6970eb372c9a36baac 100644 Binary files a/target/classes/object_detection/types/Point.class and b/target/classes/object_detection/types/Point.class differ diff --git a/target/classes/object_detection/types/PointSet.class b/target/classes/object_detection/types/PointSet.class index bdb368791ce44390baed9d451d486bfe3e866c4a..e2ffce92e86cac6a13a0549468368dbf2854ad7d 100644 Binary files a/target/classes/object_detection/types/PointSet.class and b/target/classes/object_detection/types/PointSet.class differ diff --git a/target/classes/vslam/tum_rgbd/.DS_Store b/target/classes/vslam/tum_rgbd/.DS_Store deleted file mode 100644 index 764b3f2a720f236b901a4bb88f0cfa0ea685aa07..0000000000000000000000000000000000000000 Binary files a/target/classes/vslam/tum_rgbd/.DS_Store and /dev/null differ diff --git a/target/classes/vslam/tum_rgbd/KeyFrames/KeyFrame_0022.png b/target/classes/vslam/tum_rgbd/KeyFrames/KeyFrame_0022.png deleted file mode 100644 index 65ee37f540c18af3b54228783d32733f61e3134f..0000000000000000000000000000000000000000 Binary files a/target/classes/vslam/tum_rgbd/KeyFrames/KeyFrame_0022.png and /dev/null differ diff --git a/target/classes/vslam/tum_rgbd/KeyFrames/KeyFrame_0026.png b/target/classes/vslam/tum_rgbd/KeyFrames/KeyFrame_0026.png deleted file mode 100644 index 912808f6640c610c6c42ff41a9054ccf3599b641..0000000000000000000000000000000000000000 Binary files a/target/classes/vslam/tum_rgbd/KeyFrames/KeyFrame_0026.png and /dev/null differ diff --git a/target/classes/vslam/tum_rgbd/KeyFrames/KeyFrame_0042.png b/target/classes/vslam/tum_rgbd/KeyFrames/KeyFrame_0042.png deleted file mode 100644 index 453267a487af8297aff893a965e75a9b536e1014..0000000000000000000000000000000000000000 Binary files a/target/classes/vslam/tum_rgbd/KeyFrames/KeyFrame_0042.png and /dev/null differ diff --git a/target/classes/vslam/tum_rgbd/KeyFrames/KeyFrame_0046.png b/target/classes/vslam/tum_rgbd/KeyFrames/KeyFrame_0046.png deleted file mode 100644 index 7b9a94ffa544f2f6871ed57279812ef71c32f527..0000000000000000000000000000000000000000 Binary files a/target/classes/vslam/tum_rgbd/KeyFrames/KeyFrame_0046.png and /dev/null differ diff --git a/target/classes/vslam/vslam_implementation.m b/target/classes/vslam/vslam_implementation.m deleted file mode 100644 index 3751f844577eef317246f2c361525dff4e1c3008..0000000000000000000000000000000000000000 --- a/target/classes/vslam/vslam_implementation.m +++ /dev/null @@ -1,576 +0,0 @@ -function vslam_implementation(dataset_name) - % Import dependencies - addpath('./Mathworks_VSLAM_Example/'); - - % Define the base folder for datasets - datasetFolder = [dataset_name, '/']; - - imageFolder = [datasetFolder, 'images/']; - imds = imageDatastore(imageFolder); - - % Process the image sequence - [worldPointSetOutput] = ProcessImageSequence(imds); - - % Save the outputs to .mat files - save('worldPointSetOutput.mat', 'worldPointSetOutput'); - - % Iterate over KeyFrames and execute extractPointsByViewId - keyFramesDir = './KeyFrames'; - keyFrameFiles = dir(fullfile(keyFramesDir, 'KeyFrame_*.png')); - - for i = 1:length(keyFrameFiles) - filename = keyFrameFiles(i).name; - viewId = str2double(regexp(filename, '\d+', 'match', 'once')); % Extracting the numeric part from filename - extractPointsByViewId(viewId, worldPointSetOutput); - end -end - - - -function worldPointSetOutput = ProcessImageSequence(imds) - currFrameIdx = 1; - currI = readimage(imds, currFrameIdx); - - %% Map Initilization - % Set random seed for reproducibility - rng(0); - - % Create a cameraIntrinsics object to store the camera intrinsic parameters. - % The intrinsics for the dataset can be found at the following page: - % https://vision.in.tum.de/data/datasets/rgbd-dataset/file_formats - % Note that the images in the dataset are already undistorted, hence there - % is no need to specify the distortion coefficients. - focalLength = [535.4, 539.2]; % in units of pixels - principalPoint = [320.1, 247.6]; % in units of pixels - imageSize = size(currI,[1 2]); % in units of pixels - intrinsics = cameraIntrinsics(focalLength, principalPoint, imageSize); - - % Detect and extract ORB features - scaleFactor = 1.2; - numLevels = 8; - numPoints = 1000; - [preFeatures, prePoints] = helperDetectAndExtractFeatures(currI, scaleFactor, numLevels, numPoints); - - currFrameIdx = currFrameIdx + 1; - firstI = currI; % Preserve the first frame - - isMapInitialized = false; - - % Map initialization loop - while ~isMapInitialized && currFrameIdx < numel(imds.Files) - currI = readimage(imds, currFrameIdx); - - [currFeatures, currPoints] = helperDetectAndExtractFeatures(currI, scaleFactor, numLevels, numPoints); - - currFrameIdx = currFrameIdx + 1; - - % Find putative feature matches - indexPairs = matchFeatures(preFeatures, currFeatures, Unique=true, ... - MaxRatio=0.9, MatchThreshold=40); - - preMatchedPoints = prePoints(indexPairs(:,1),:); - currMatchedPoints = currPoints(indexPairs(:,2),:); - - % If not enough matches are found, check the next frame - minMatches = 100; - if size(indexPairs, 1) < minMatches - continue - end - - preMatchedPoints = prePoints(indexPairs(:,1),:); - currMatchedPoints = currPoints(indexPairs(:,2),:); - - % Compute homography and evaluate reconstruction - [tformH, scoreH, inliersIdxH] = helperComputeHomography(preMatchedPoints, currMatchedPoints); - - % Compute fundamental matrix and evaluate reconstruction - [tformF, scoreF, inliersIdxF] = helperComputeFundamentalMatrix(preMatchedPoints, currMatchedPoints); - - % Select the model based on a heuristic - ratio = scoreH/(scoreH + scoreF); - ratioThreshold = 0.45; - if ratio > ratioThreshold - inlierTformIdx = inliersIdxH; - tform = tformH; - else - inlierTformIdx = inliersIdxF; - tform = tformF; - end - - % Computes the camera location up to scale. Use half of the - % points to reduce computation - inlierPrePoints = preMatchedPoints(inlierTformIdx); - inlierCurrPoints = currMatchedPoints(inlierTformIdx); - [relPose, validFraction] = estrelpose(tform, intrinsics, ... - inlierPrePoints(1:2:end), inlierCurrPoints(1:2:end)); - - % If not enough inliers are found, move to the next frame - if validFraction < 0.9 || numel(relPose)==3 - continue - end - - % Triangulate two views to obtain 3-D map points - minParallax = 1; % In degrees - [isValid, xyzWorldPoints, inlierTriangulationIdx] = helperTriangulateTwoFrames(... - rigidtform3d, relPose, inlierPrePoints, inlierCurrPoints, intrinsics, minParallax); - - if ~isValid - continue - end - - % Get the original index of features in the two key frames - indexPairs = indexPairs(inlierTformIdx(inlierTriangulationIdx),:); - - isMapInitialized = true; - - disp(['Map initialized with frame 1 and frame ', num2str(currFrameIdx-1)]) - end % End of map initialization loop - - %% Store initial key frames and map points - % Create an empty imageviewset object to store key frames - vSetKeyFrames = imageviewset; - - % Create an empty worldpointset object to store 3-D map points - mapPointSet = worldpointset; - - % Add the first key frame. Place the camera associated with the first - % key frame at the origin, oriented along the Z-axis - preViewId = 1; - vSetKeyFrames = addView(vSetKeyFrames, preViewId, rigidtform3d, Points=prePoints,... - Features=preFeatures.Features); - - % Add the second key frame - currViewId = 2; - vSetKeyFrames = addView(vSetKeyFrames, currViewId, relPose, Points=currPoints,... - Features=currFeatures.Features); - - % Add connection between the first and the second key frame - vSetKeyFrames = addConnection(vSetKeyFrames, preViewId, currViewId, relPose, Matches=indexPairs); - - % Add 3-D map points - [mapPointSet, newPointIdx] = addWorldPoints(mapPointSet, xyzWorldPoints); - - % Add observations of the map points - preLocations = prePoints.Location; - currLocations = currPoints.Location; - preScales = prePoints.Scale; - currScales = currPoints.Scale; - - % Add image points corresponding to the map points in the first key frame - mapPointSet = addCorrespondences(mapPointSet, preViewId, newPointIdx, indexPairs(:,1)); - - % Add image points corresponding to the map points in the second key frame - mapPointSet = addCorrespondences(mapPointSet, currViewId, newPointIdx, indexPairs(:,2)); - - % Initialize place recognition database - % Load the bag of features data created offline - bofData = load("bagOfFeaturesDataSLAM.mat"); - - % Initialize the place recognition database - loopDatabase = invertedImageIndex(bofData.bof,SaveFeatureLocations=false); - - % Add features of the first two key frames to the database - addImageFeatures(loopDatabase, preFeatures, preViewId); - addImageFeatures(loopDatabase, currFeatures, currViewId); - - %% Refine and visualize initial reconstruction - % Run full bundle adjustment on the first two key frames - tracks = findTracks(vSetKeyFrames); - cameraPoses = poses(vSetKeyFrames); - - [refinedPoints, refinedAbsPoses] = bundleAdjustment(xyzWorldPoints, tracks, ... - cameraPoses, intrinsics, FixedViewIDs=1, ... - PointsUndistorted=true, AbsoluteTolerance=1e-7,... - RelativeTolerance=1e-15, MaxIteration=20, ... - Solver="preconditioned-conjugate-gradient"); - - % Scale the map and the camera pose using the median depth of map points - medianDepth = median(vecnorm(refinedPoints.')); - refinedPoints = refinedPoints / medianDepth; - - refinedAbsPoses.AbsolutePose(currViewId).Translation = ... - refinedAbsPoses.AbsolutePose(currViewId).Translation / medianDepth; - relPose.Translation = relPose.Translation/medianDepth; - - % Update key frames with the refined poses - vSetKeyFrames = updateView(vSetKeyFrames, refinedAbsPoses); - vSetKeyFrames = updateConnection(vSetKeyFrames, preViewId, currViewId, relPose); - - % Update map points with the refined positions - mapPointSet = updateWorldPoints(mapPointSet, newPointIdx, refinedPoints); - - % Update view direction and depth - mapPointSet = updateLimitsAndDirection(mapPointSet, newPointIdx, vSetKeyFrames.Views); - - % Update representative view - mapPointSet = updateRepresentativeView(mapPointSet, newPointIdx, vSetKeyFrames.Views); - - % Visualize matched features in the current frame - % close(hfeature.Parent.Parent); - featurePlot = helperVisualizeMatchedFeatures(currI, currPoints(indexPairs(:,2))); - - % Visualize initial map points and camera trajectory - mapPlot = helperVisualizeMotionAndStructure(vSetKeyFrames, mapPointSet); - - % Show legend - showLegend(mapPlot); - - %% Tracking - % ViewId of the current key frame - currKeyFrameId = currViewId; - - % ViewId of the last key frame - lastKeyFrameId = currViewId; - - % Index of the last key frame in the input image sequence - lastKeyFrameIdx = currFrameIdx - 1; - - % Indices of all the key frames in the input image sequence - addedFramesIdx = [1; lastKeyFrameIdx]; - - isLoopClosed = false; - - % Main loop (attempt to close loop while iterating over all images in - % dataset) - isLastFrameKeyFrame = true; - while ~isLoopClosed && currFrameIdx < numel(imds.Files) - currI = readimage(imds, currFrameIdx); - - [currFeatures, currPoints] = helperDetectAndExtractFeatures(currI, scaleFactor, numLevels, numPoints); - - % Track the last key frame - % mapPointsIdx: Indices of the map points observed in the current frame - % featureIdx: Indices of the corresponding feature points in the - % current frame - [currPose, mapPointsIdx, featureIdx] = helperTrackLastKeyFrame(mapPointSet, ... - vSetKeyFrames.Views, currFeatures, currPoints, lastKeyFrameId, intrinsics, scaleFactor); - - % Track the local map and check if the current frame is a key frame. - % A frame is a key frame if both of the following conditions are satisfied: - % - % 1. At least 20 frames have passed since the last key frame or the - % current frame tracks fewer than 100 map points. - % 2. The map points tracked by the current frame are fewer than 90% of - % points tracked by the reference key frame. - % - % Tracking performance is sensitive to the value of numPointsKeyFrame. - % If tracking is lost, try a larger value. - % - % localKeyFrameIds: ViewId of the connected key frames of the current frame - numSkipFrames = 20; - numPointsKeyFrame = 80; - [localKeyFrameIds, currPose, mapPointsIdx, featureIdx, isKeyFrame] = ... - helperTrackLocalMap(mapPointSet, vSetKeyFrames, mapPointsIdx, ... - featureIdx, currPose, currFeatures, currPoints, intrinsics, scaleFactor, numLevels, ... - isLastFrameKeyFrame, lastKeyFrameIdx, currFrameIdx, numSkipFrames, numPointsKeyFrame); - - - % Visualize matched features - updatePlot(featurePlot, currI, currPoints(featureIdx)); - - if ~isKeyFrame - currFrameIdx = currFrameIdx + 1; - isLastFrameKeyFrame = false; - continue - else - isLastFrameKeyFrame = true; - end - - % Update current key frame ID - currKeyFrameId = currKeyFrameId + 1; - - %% Local mapping - % Add the new key frame - [mapPointSet, vSetKeyFrames] = helperAddNewKeyFrame(mapPointSet, vSetKeyFrames, ... - currPose, currFeatures, currPoints, mapPointsIdx, featureIdx, localKeyFrameIds); - - % Remove outlier map points that are observed in fewer than 3 key frames - outlierIdx = setdiff(newPointIdx, mapPointsIdx); - if ~isempty(outlierIdx) - mapPointSet = removeWorldPoints(mapPointSet, outlierIdx); - end - - % Create new map points by triangulation - minNumMatches = 10; - minParallax = 3; - [mapPointSet, vSetKeyFrames, newPointIdx] = helperCreateNewMapPoints(mapPointSet, vSetKeyFrames, ... - currKeyFrameId, intrinsics, scaleFactor, minNumMatches, minParallax); - - % Local bundle adjustment - [refinedViews, dist] = connectedViews(vSetKeyFrames, currKeyFrameId, MaxDistance=2); - refinedKeyFrameIds = refinedViews.ViewId; - fixedViewIds = refinedKeyFrameIds(dist==2); - fixedViewIds = fixedViewIds(1:min(10, numel(fixedViewIds))); - - % Refine local key frames and map points - [mapPointSet, vSetKeyFrames, mapPointIdx] = bundleAdjustment(... - mapPointSet, vSetKeyFrames, [refinedKeyFrameIds; currKeyFrameId], intrinsics, ... - FixedViewIDs=fixedViewIds, PointsUndistorted=true, AbsoluteTolerance=1e-7,... - RelativeTolerance=1e-16, Solver="preconditioned-conjugate-gradient", ... - MaxIteration=10); - - % Update view direction and depth - mapPointSet = updateLimitsAndDirection(mapPointSet, mapPointIdx, vSetKeyFrames.Views); - - % Update representative view - mapPointSet = updateRepresentativeView(mapPointSet, mapPointIdx, vSetKeyFrames.Views); - - % Check if the KeyFrames directory exists; if not, create it - keyFramesDir = './KeyFrames_Mono'; - if ~exist(keyFramesDir, 'dir') - mkdir(keyFramesDir); - end - - % Store feature locations for this key frame - keyFramePointsDir = './KeyFramePoints_Mono'; - if ~exist(keyFramePointsDir, 'dir') - mkdir(keyFramePointsDir); - end - - % Save the current key frame image using currKeyFrameId - filename = sprintf('%s/KeyFrame_%04d.png', keyFramesDir, currKeyFrameId); - imwrite(currI, filename); - - % Save feature points information - saveKeyFramePoints(keyFramePointsDir, currKeyFrameId, currPoints(featureIdx), mapPointsIdx); - - - % Visualize 3D world points and camera trajectory - updatePlot(mapPlot, vSetKeyFrames, mapPointSet); - - %% Loop closure - % Check loop closure after some key frames have been created - if currKeyFrameId > 20 - - % Minimum number of feature matches of loop edges - loopEdgeNumMatches = 50; - - % Detect possible loop closure key frame candidates - [isDetected, validLoopCandidates] = helperCheckLoopClosure(vSetKeyFrames, currKeyFrameId, ... - loopDatabase, currI, loopEdgeNumMatches); - - if isDetected - % Add loop closure connections - [isLoopClosed, mapPointSet, vSetKeyFrames] = helperAddLoopConnections(... - mapPointSet, vSetKeyFrames, validLoopCandidates, currKeyFrameId, ... - currFeatures, loopEdgeNumMatches); - end - end - - % If no loop closure is detected, add current features into the database - if ~isLoopClosed - addImageFeatures(loopDatabase, currFeatures, currKeyFrameId); - end - - % Update IDs and indices - lastKeyFrameId = currKeyFrameId; - lastKeyFrameIdx = currFrameIdx; - addedFramesIdx = [addedFramesIdx; currFrameIdx]; %#ok - currFrameIdx = currFrameIdx + 1; - end % End of main loop - - %% Optimizing - if isLoopClosed - % Optimize the poses - minNumMatches = 20; - vSetKeyFramesOptim = optimizePoses(vSetKeyFrames, minNumMatches, Tolerance=1e-16); - - % Update map points after optimizing the poses - mapPointSet = helperUpdateGlobalMap(mapPointSet, vSetKeyFrames, vSetKeyFramesOptim); - - updatePlot(mapPlot, vSetKeyFrames, mapPointSet); - - % Plot the optimized camera trajectory - optimizedPoses = poses(vSetKeyFramesOptim); - plotOptimizedTrajectory(mapPlot, optimizedPoses) - - % Update legend - showLegend(mapPlot); - - worldPointSetOutput = mapPointSet; - end - -end - - -%% Helper functions -% The following funciton definitions are provied in the -% Mathworks_VSLAM_Example Directory -% helperAddLoopConnections add connections between the current keyframe and the valid loop candidate. -% helperAddNewKeyFrame add key frames to the key frame set. -% helperCheckLoopClosure detect loop candidates key frames by retrieving visually similar images from the database. -% helperCreateNewMapPoints create new map points by triangulation. -% helperORBFeatureExtractorFunction implements the ORB feature extraction used in bagOfFeatures. -% helperTrackLastKeyFrame estimate the current camera pose by tracking the last key frame. -% helperTrackLocalMap refine the current camera pose by tracking the local map. -% helperVisualizeMatchedFeatures show the matched features in a frame. -% helperVisualizeMotionAndStructure show map points and camera trajectory. -% helperImportGroundTruth import camera pose ground truth from the downloaded data. - -% helperDetectAndExtractFeatures detect and extract and ORB features from the image. -function [features, validPoints] = helperDetectAndExtractFeatures(Irgb, ... - scaleFactor, numLevels, numPoints, varargin) - - % In this example, the images are already undistorted. In a general - % workflow, uncomment the following code to undistort the images. - % - % if nargin > 4 - % intrinsics = varargin{1}; - % end - % Irgb = undistortImage(Irgb, intrinsics); - - % Detect ORB features - Igray = im2gray(Irgb); - - points = detectORBFeatures(Igray, ScaleFactor=scaleFactor, NumLevels=numLevels); - - % Select a subset of features, uniformly distributed throughout the image - points = selectUniform(points, numPoints, size(Igray, 1:2)); - - % Extract features - [features, validPoints] = extractFeatures(Igray, points); -end - -% helperComputeHomography compute homography and evaluate reconstruction. -function [H, score, inliersIndex] = helperComputeHomography(matchedPoints1, matchedPoints2) - - [H, inliersLogicalIndex] = estgeotform2d( ... - matchedPoints1, matchedPoints2, "projective", ... - MaxNumTrials=1e3, MaxDistance=4, Confidence=90); - - inlierPoints1 = matchedPoints1(inliersLogicalIndex); - inlierPoints2 = matchedPoints2(inliersLogicalIndex); - - inliersIndex = find(inliersLogicalIndex); - - locations1 = inlierPoints1.Location; - locations2 = inlierPoints2.Location; - xy1In2 = transformPointsForward(H, locations1); - xy2In1 = transformPointsInverse(H, locations2); - error1in2 = sum((locations2 - xy1In2).^2, 2); - error2in1 = sum((locations1 - xy2In1).^2, 2); - - outlierThreshold = 6; - - score = sum(max(outlierThreshold-error1in2, 0)) + ... - sum(max(outlierThreshold-error2in1, 0)); -end - -% helperComputeFundamentalMatrix compute fundamental matrix and evaluate reconstruction. -function [F, score, inliersIndex] = helperComputeFundamentalMatrix(matchedPoints1, matchedPoints2) - - [F, inliersLogicalIndex] = estimateFundamentalMatrix( ... - matchedPoints1, matchedPoints2, Method="RANSAC",... - NumTrials=1e3, DistanceThreshold=4); - - inlierPoints1 = matchedPoints1(inliersLogicalIndex); - inlierPoints2 = matchedPoints2(inliersLogicalIndex); - - inliersIndex = find(inliersLogicalIndex); - - locations1 = inlierPoints1.Location; - locations2 = inlierPoints2.Location; - - % Distance from points to epipolar line - lineIn1 = epipolarLine(F', locations2); - error2in1 = (sum([locations1, ones(size(locations1, 1),1)].* lineIn1, 2)).^2 ... - ./ sum(lineIn1(:,1:2).^2, 2); - lineIn2 = epipolarLine(F, locations1); - error1in2 = (sum([locations2, ones(size(locations2, 1),1)].* lineIn2, 2)).^2 ... - ./ sum(lineIn2(:,1:2).^2, 2); - - outlierThreshold = 4; - - score = sum(max(outlierThreshold-error1in2, 0)) + ... - sum(max(outlierThreshold-error2in1, 0)); -end - -% helperTriangulateTwoFrames triangulate two frames to initialize the map. -function [isValid, xyzPoints, inlierIdx] = helperTriangulateTwoFrames(... - pose1, pose2, matchedPoints1, matchedPoints2, intrinsics, minParallax) - - camMatrix1 = cameraProjection(intrinsics, pose2extr(pose1)); - camMatrix2 = cameraProjection(intrinsics, pose2extr(pose2)); - - [xyzPoints, reprojectionErrors, isInFront] = triangulate(matchedPoints1, ... - matchedPoints2, camMatrix1, camMatrix2); - - % Filter points by view direction and reprojection error - minReprojError = 1; - inlierIdx = isInFront & reprojectionErrors < minReprojError; - xyzPoints = xyzPoints(inlierIdx ,:); - - % A good two-view with significant parallax - ray1 = xyzPoints - pose1.Translation; - ray2 = xyzPoints - pose2.Translation; - cosAngle = sum(ray1 .* ray2, 2) ./ (vecnorm(ray1, 2, 2) .* vecnorm(ray2, 2, 2)); - - % Check parallax - isValid = all(cosAngle < cosd(minParallax) & cosAngle>0); -end - -% helperEstimateTrajectoryError calculate the tracking error. -function rmse = helperEstimateTrajectoryError(gTruth, cameraPoses) - locations = vertcat(cameraPoses.AbsolutePose.Translation); - gLocations = vertcat(gTruth.Translation); - scale = median(vecnorm(gLocations, 2, 2))/ median(vecnorm(locations, 2, 2)); - scaledLocations = locations * scale; - - rmse = sqrt(mean( sum((scaledLocations - gLocations).^2, 2) )); - disp(['Absolute RMSE for key frame trajectory (m): ', num2str(rmse)]); -end - -% helperUpdateGlobalMap update 3-D locations of map points after pose graph optimization -function mapPointSet = helperUpdateGlobalMap(... - mapPointSet, vSetKeyFrames, vSetKeyFramesOptim) - %helperUpdateGlobalMap update map points after pose graph optimization - posesOld = vSetKeyFrames.Views.AbsolutePose; - posesNew = vSetKeyFramesOptim.Views.AbsolutePose; - positionsOld = mapPointSet.WorldPoints; - positionsNew = positionsOld; - indices = 1:mapPointSet.Count; - - % Update world location of each map point based on the new absolute pose of - % the corresponding major view - for i = indices - majorViewIds = mapPointSet.RepresentativeViewId(i); - poseNew = posesNew(majorViewIds).A; - tform = affinetform3d(poseNew/posesOld(majorViewIds).A); - positionsNew(i, :) = transformPointsForward(tform, positionsOld(i, :)); - end - mapPointSet = updateWorldPoints(mapPointSet, indices, positionsNew); -end - -% function saveKeyFramePoints(dirPath, frameIndex, featurePoints) -% % Extract locations and corresponding point indices -% locations = featurePoints.Location; -% indices = (1:size(locations, 1))'; % Create an index array -% dataMatrix = [indices, locations]; -% -% % Define filename for CSV -% csvFilename = sprintf('%s/KeyFramePoints_%04d.csv', dirPath, frameIndex); -% -% % Write matrix to CSV -% writematrix(dataMatrix, csvFilename); -% end - -function saveKeyFramePoints(dirPath, keyFrameId, featurePoints, mapPointsIdx) - % Ensure the directory exists - if ~exist(dirPath, 'dir') - mkdir(dirPath); - end - - % Define the filename for the CSV file - csvFilename = sprintf('%s/KeyFramePoints_%04d.csv', dirPath, keyFrameId); - - % Extract pixel locations from the feature points - pixelLocations = featurePoints.Location; % This should be an Nx2 matrix - - % Combine the indices, pixel locations, and corresponding world points indices into one matrix - dataMatrix = [pixelLocations, mapPointsIdx]; % Concatenate horizontally - - % Write the combined data to a CSV file - writematrix(dataMatrix, csvFilename); -end - - diff --git a/target/classes/vslam/vslam_implementation_rgbd.m b/target/classes/vslam/vslam_implementation_rgbd.m deleted file mode 100755 index b32fa8d4700cd7be40e269ab25361ddb6aaf16e6..0000000000000000000000000000000000000000 --- a/target/classes/vslam/vslam_implementation_rgbd.m +++ /dev/null @@ -1,657 +0,0 @@ -function vslam_implementation_rgbd(dataset_name) - - % Import dependencies - addpath('./Mathworks_VSLAM_RGBD/'); - - % Define the base folder for datasets - datasetFolder = [dataset_name, '/']; - - % Check if the dataset exists, if not download and prepare it - if ~exist(datasetFolder, 'dir') - if strcmp(dataset_name, 'tum_rgbd_dataset') - % Define the URL and local folder for download - baseDownloadURL = "https://cvg.cit.tum.de/rgbd/dataset/freiburg3/rgbd_dataset_freiburg3_long_office_household.tgz"; - dataFolder = fullfile('tum_rgbd_dataset', filesep); - tgzFileName = [dataFolder, 'fr3_office.tgz']; - - % Create a folder to save the downloaded file - if ~exist(dataFolder, 'dir') - mkdir(dataFolder); - disp('Downloading fr3_office.tgz (1.38 GB). This download can take a few minutes.'); - h = waitbar(0, 'Downloading Dataset... Please wait.', 'Name', 'Downloading fr3_office'); - websave(tgzFileName, baseDownloadURL, weboptions('Timeout', Inf)); - % Update and close waitbar after download completes - waitbar(1, h, 'Download Complete. Extracting...'); - pause(1); % Pause to show complete message - close(h); - - % Extract contents of the downloaded file - disp('Extracting fr3_office.tgz (1.38 GB) ...'); - h = waitbar(0, 'Extracting files... This may take a while.', 'Name', 'Extracting Data'); - untar(tgzFileName, dataFolder); - - % Close waitbar after extraction completes - waitbar(1, h, 'Extraction Complete.'); - pause(1); % Pause to show complete message - close(h); - end - - imageFolder = [dataFolder, 'rgbd_dataset_freiburg3_long_office_household/']; - - % Initialize image dataset stores for color and depth images - imgFolderColor = [imageFolder, 'rgb/']; - imgFolderDepth = [imageFolder, 'depth/']; - imdsColor = imageDatastore(imgFolderColor); - imdsDepth = imageDatastore(imgFolderDepth); - - % Note that the color and depth images are generated in an un-synchronized way in the dataset. Therefore, we need to associate color images to depth images based on the time stamp. - % Load time stamp data of color images - timeColor = helperImportTimestampFile([imageFolder, 'rgb.txt']); - - % Load time stamp data of depth images - timeDepth = helperImportTimestampFile([imageFolder, 'depth.txt']); - - % Align the time stamp - indexPairs = helperAlignTimestamp(timeColor, timeDepth); - - % Select the synchronized image data - imdsColor = subset(imdsColor, indexPairs(:, 1)); - imdsDepth = subset(imdsDepth, indexPairs(:, 2)); - - elseif strcmp(dataset_name, 'imperial_college_london') - % Define the URL and local folder for download - baseDownloadURL = "http://www.doc.ic.ac.uk/~ahanda/living_room_traj2_frei_png.tar.gz"; - dataFolder = fullfile('imperial_college_london', filesep); - tgzFileName = [dataFolder, 'living_room_traj2_frei_png.tar.gz']; - - % Create a folder to save the downloaded file - if ~exist(dataFolder, 'dir') - mkdir(dataFolder); - disp('Downloading living_room_traj2_frei_png.tar.gz (486 MB). This download can take a few minutes.'); - h = waitbar(0, 'Downloading Dataset... Please wait.', 'Name', 'Downloading living_room_traj2'); - websave(tgzFileName, baseDownloadURL, weboptions('Timeout', Inf)); - % Update and close waitbar after download completes - waitbar(1, h, 'Download Complete. Extracting...'); - pause(1); % Pause to show complete message - close(h); - - % Extract contents of the downloaded file - disp('Extracting living_room_traj2 (486 MB) ...'); - h = waitbar(0, 'Extracting files... This may take a while.', 'Name', 'Extracting Data'); - untar(tgzFileName, dataFolder); - - % Close waitbar after extraction completes - waitbar(1, h, 'Extraction Complete.'); - pause(1); % Pause to show complete message - close(h); - end - - imageFolder = [dataFolder]; - - % Initialize image dataset stores for color and depth images - imgFolderColor = [imageFolder, 'rgb/']; - imgFolderDepth = [imageFolder, 'depth/']; - imdsColor = imageDatastore(imgFolderColor); - imdsDepth = imageDatastore(imgFolderDepth); - else - error('Dataset name not recognized or dataset-specific download steps not defined.'); - end - else - % If dataset is already present, set the image folder path - if strcmp(dataset_name, 'tum_rgbd_dataset') - imageFolder = [datasetFolder, 'rgbd_dataset_freiburg3_long_office_household/']; - % Initialize image dataset stores for color and depth images - imgFolderColor = [imageFolder, 'rgb/']; - imgFolderDepth = [imageFolder, 'depth/']; - imdsColor = imageDatastore(imgFolderColor); - imdsDepth = imageDatastore(imgFolderDepth); - - % Note that the color and depth images are generated in an un-synchronized way in the dataset. Therefore, we need to associate color images to depth images based on the time stamp. - % Load time stamp data of color images - timeColor = helperImportTimestampFile([imageFolder, 'rgb.txt']); - - % Load time stamp data of depth images - timeDepth = helperImportTimestampFile([imageFolder, 'depth.txt']); - - % Align the time stamp - indexPairs = helperAlignTimestamp(timeColor, timeDepth); - - % Select the synchronized image data - imdsColor = subset(imdsColor, indexPairs(:, 1)); - imdsDepth = subset(imdsDepth, indexPairs(:, 2)); - elseif strcmp(dataset_name, 'imperial_college_london') - imageFolder = [datasetFolder]; - - % Initialize image dataset stores for color and depth images - imgFolderColor = [imageFolder, 'rgb/']; - imgFolderDepth = [imageFolder, 'depth/']; - imdsColor = imageDatastore(imgFolderColor); - imdsDepth = imageDatastore(imgFolderDepth); - end - end - - % Process the image sequence - [worldPointSetOutput, optimizedPoses, pointCloudsAll, intrinsics] = ProcessImageSequence(imdsColor, imdsDepth); - - % Save the outputs to .mat files - % save('worldPointSetOutput.mat', 'worldPointSetOutput'); - % save('optimizedPoses.mat', 'optimizedPoses'); - % save('pointCloudsAll.mat', 'pointCloudsAll'); - % save('cameraIntrinsics.mat', 'intrinsics'); - - % save outputs to CSV files in directories given as name: - savePosesToCSV(optimizedPoses, 'CameraPoses'); - savePointCloudToCSV(pointCloudsAll); - saveIntrinsicsToCSV(intrinsics); - - % Iterate over KeyFrames and execute extractPointsByViewId - keyFramesDir = './KeyFrames'; - keyFrameFiles = dir(fullfile(keyFramesDir, 'KeyFrame_*.png')); - - for i = 1:length(keyFrameFiles) - filename = keyFrameFiles(i).name; - viewId = str2double(regexp(filename, '\d+', 'match', 'once')); % Extracting the numeric part from filename - extractPointsByViewId(viewId, worldPointSetOutput); - end - -end - - -function [worldPointSetOutput, optimizedPoses, pointCloudsAll, intrinsics] = ProcessImageSequence(imdsColor, imdsDepth) - % Inspect the first RGB-D image - currFrameIdx = 1; - currIcolor = readimage(imdsColor, currFrameIdx); - currIdepth = readimage(imdsDepth, currFrameIdx); - % imshowpair(currIcolor, currIdepth, "montage"); - - % Map Initialization: The pipeline starts by initializing the map that holds 3-D world points. - % This step is crucial and has a significant impact on the accuracy of the final SLAM result. - % Initial ORB feature points are extracted from the first color image using helperDetectAndExtractFeatures. - % Their corresponding 3-D world locations can be computed from the pixel coordinates of the feature - % points and the depth value using helperReconstructFromRGBD. - - % Set random seed for reproducibility - rng(0); - - % Create a cameraIntrinsics object to store the camera intrinsic parameters. - % The intrinsics for the dataset can be found at the following page: - % https://vision.in.tum.de/data/datasets/rgbd-dataset/file_formats - focalLength = [535.4, 539.2]; % in units of pixels - principalPoint = [320.1, 247.6]; % in units of pixels - imageSize = size(currIcolor,[1,2]); % in pixels [mrows, ncols] - depthFactor = 5e3; - intrinsics = cameraIntrinsics(focalLength,principalPoint,imageSize); - - % Detect and extract ORB features from the color image - scaleFactor = 1.2; - numLevels = 8; - [currFeatures, currPoints] = helperDetectAndExtractFeatures(currIcolor, scaleFactor, numLevels); - - initialPose = rigidtform3d(); - [xyzPoints, validIndex] = helperReconstructFromRGBD(currPoints, currIdepth, intrinsics, initialPose, depthFactor); - - % Initialize Place Recognition Database - % Loop detection is performed using the bags-of-words approach. A visual vocabulary represented as a bagOfFeatures object is created offline with the ORB descriptors extracted from a large set of images in the dataset by calling: - % bag = bagOfFeatures(imds,CustomExtractor=@helperORBFeatureExtractorFunction, TreeProperties=[5, 10], StrongestFeatures=1); - % where imds is an imageDatastore object storing the training images and helperORBFeatureExtractorFunction is the ORB feature extractor function. See Image Retrieval with Bag of Visual Words for more information. - % The loop closure process incrementally builds a database, represented as an invertedImageIndex object, that stores the visual word-to-image mapping based on the bag of ORB features. - - % Load the bag of features data created offline - bofData = load("bagOfFeaturesDataSLAM.mat"); - - % Initialize the place recognition database - loopDatabase = invertedImageIndex(bofData.bof, SaveFeatureLocations=false); - - % Add features of the first key frame to the database - currKeyFrameId = 1; - addImageFeatures(loopDatabase, currFeatures, currKeyFrameId); - - % Data Management and Visualization - % After the map is initialized using the first pair of color and depth image, you can use imageviewset and worldpointset to store the first key frames and the corresponding map points: - - % Create an empty imageviewset object to store key frames - vSetKeyFrames = imageviewset; - - % Create an empty worldpointset object to store 3-D map points - mapPointSet = worldpointset; - - % Add the first key frame - vSetKeyFrames = addView(vSetKeyFrames, currKeyFrameId, initialPose, Points=currPoints,... - Features=currFeatures.Features); - - % Add 3-D map points - [mapPointSet, rgbdMapPointsIdx] = addWorldPoints(mapPointSet, xyzPoints); - - % Add observations of the map points - mapPointSet = addCorrespondences(mapPointSet, currKeyFrameId, rgbdMapPointsIdx, validIndex); - - % Update view direction and depth - mapPointSet = updateLimitsAndDirection(mapPointSet, rgbdMapPointsIdx, vSetKeyFrames.Views); - - % Update representative view - mapPointSet = updateRepresentativeView(mapPointSet, rgbdMapPointsIdx, vSetKeyFrames.Views); - - % Visualize matched features in the first key frame - featurePlot = helperVisualizeMatchedFeaturesRGBD(currIcolor, currIdepth, currPoints(validIndex)); - - % Visualize initial map points and camera trajectory - xLim = [-4 4]; - yLim = [-3 1]; - zLim = [-1 6]; - mapPlot = helperVisualizeMotionAndStructure(vSetKeyFrames, mapPointSet, xLim, yLim, zLim); - - % Show legend - showLegend(mapPlot); - - % Tracking - % The tracking process is performed using every RGB-D image and determines when to insert a new key frame. - % ViewId of the last key frame - lastKeyFrameId = currKeyFrameId; - - % Index of the last key frame in the input image sequence - lastKeyFrameIdx = currFrameIdx; - - % Indices of all the key frames in the input image sequence - addedFramesIdx = lastKeyFrameIdx; - - currFrameIdx = 2; - isLoopClosed = false; - - % Each frame is processed as follows: - % ORB features are extracted for each new color image and then matched (using matchFeatures), with features in the last key frame that have known corresponding 3-D map points. - % Estimate the camera pose using Perspective-n-Point algorithm, which estimates the pose of a calibrated camera given a set of 3-D points and their corresponding 2-D projections using estworldpose. - % Given the camera pose, project the map points observed by the last key frame into the current frame and search for feature correspondences using matchFeaturesInRadius. - % With 3-D to 2-D correspondences in the current frame, refine the camera pose by performing a motion-only bundle adjustment using bundleAdjustmentMotion. - % Project the local map points into the current frame to search for more feature correspondences using matchFeaturesInRadius and refine the camera pose again using bundleAdjustmentMotion. - % The last step of tracking is to decide if the current frame should be a new key frame. A frame is a key frame if both of the following conditions are satisfied: - % At least 20 frames have passed since the last key frame or the current frame tracks fewer than 100 map points or 25% of points tracked by the reference key frame. - % The map points tracked by the current frame are fewer than 90% of points tracked by the reference key frame. - % If the current frame is to become a key frame, continue to the Local Mapping process. Otherwise, start Tracking for the next frame. - - % Main loop - isLastFrameKeyFrame = true; - while ~isLoopClosed && currFrameIdx < numel(imdsColor.Files) - - currIcolor = readimage(imdsColor, currFrameIdx); - currIdepth = readimage(imdsDepth, currFrameIdx); - - [currFeatures, currPoints] = helperDetectAndExtractFeatures(currIcolor, scaleFactor, numLevels); - - % Track the last key frame - % trackedMapPointsIdx: Indices of the map points observed in the current left frame - % trackedFeatureIdx: Indices of the corresponding feature points in the current left frame - [currPose, trackedMapPointsIdx, trackedFeatureIdx] = helperTrackLastKeyFrame(mapPointSet, ... - vSetKeyFrames.Views, currFeatures, currPoints, lastKeyFrameId, intrinsics, scaleFactor); - - if isempty(currPose) || numel(trackedMapPointsIdx) < 30 - currFrameIdx = currFrameIdx + 1; - continue - end - - % Track the local map and check if the current frame is a key frame. - % A frame is a key frame if both of the following conditions are satisfied: - % - % 1. At least 20 frames have passed since the last key frame or the - % current frame tracks fewer than 100 map points. - % 2. The map points tracked by the current frame are fewer than 90% of - % points tracked by the reference key frame. - % - % localKeyFrameIds: ViewId of the connected key frames of the current frame - numSkipFrames = 20; - numPointsKeyFrame = 100; - [localKeyFrameIds, currPose, trackedMapPointsIdx, trackedFeatureIdx, isKeyFrame] = ... - helperTrackLocalMap(mapPointSet, vSetKeyFrames, trackedMapPointsIdx, ... - trackedFeatureIdx, currPose, currFeatures, currPoints, intrinsics, scaleFactor, numLevels, ... - isLastFrameKeyFrame, lastKeyFrameIdx, currFrameIdx, numSkipFrames, numPointsKeyFrame); - - % Visualize matched features - updatePlot(featurePlot, currIcolor, currIdepth, currPoints(trackedFeatureIdx)); - - if ~isKeyFrame - currFrameIdx = currFrameIdx + 1; - isLastFrameKeyFrame = false; - continue - else - % Match feature points between the stereo images and get the 3-D world positions - [xyzPoints, validIndex] = helperReconstructFromRGBD(currPoints, currIdepth, ... - intrinsics, currPose, depthFactor); - - [untrackedFeatureIdx, ia] = setdiff(validIndex, trackedFeatureIdx); - xyzPoints = xyzPoints(ia, :); - isLastFrameKeyFrame = true; - end - - % Update current key frame ID - currKeyFrameId = currKeyFrameId + 1; - - % Local Mapping - % Local mapping is performed for every key frame. When a new key frame is determined, add it to the key frames and update the attributes of the map points observed by the new key frame. To ensure that mapPointSet contains as few outliers as possible, a valid map point must be observed in at least 3 key frames. - % New map points are created by triangulating ORB feature points in the current key frame and its connected key frames. For each unmatched feature point in the current key frame, search for a match with other unmatched points in the connected key frames using matchFeatures. The local bundle adjustment refines the pose of the current key frame, the poses of connected key frames, and all the map points observed in these key frames. - - % Add the new key frame - [mapPointSet, vSetKeyFrames] = helperAddNewKeyFrame(mapPointSet, vSetKeyFrames, ... - currPose, currFeatures, currPoints, trackedMapPointsIdx, trackedFeatureIdx, localKeyFrameIds); - - % Remove outlier map points that are observed in fewer than 3 key frames - if currKeyFrameId == 2 - triangulatedMapPointsIdx = []; - end - - [mapPointSet, trackedMapPointsIdx] = ... - helperCullRecentMapPoints(mapPointSet, trackedMapPointsIdx, triangulatedMapPointsIdx, ... - rgbdMapPointsIdx); - - % Add new map points computed from disparity - [mapPointSet, rgbdMapPointsIdx] = addWorldPoints(mapPointSet, xyzPoints); - mapPointSet = addCorrespondences(mapPointSet, currKeyFrameId, rgbdMapPointsIdx, ... - untrackedFeatureIdx); - - % Create new map points by triangulation - minNumMatches = 10; - minParallax = 0.35; - [mapPointSet, vSetKeyFrames, triangulatedMapPointsIdx, rgbdMapPointsIdx] = helperCreateNewMapPointsStereo( ... - mapPointSet, vSetKeyFrames, currKeyFrameId, intrinsics, scaleFactor, minNumMatches, minParallax, ... - untrackedFeatureIdx, rgbdMapPointsIdx); - - % Update view direction and depth - mapPointSet = updateLimitsAndDirection(mapPointSet, [triangulatedMapPointsIdx; rgbdMapPointsIdx], ... - vSetKeyFrames.Views); - - % Update representative view - mapPointSet = updateRepresentativeView(mapPointSet, [triangulatedMapPointsIdx; rgbdMapPointsIdx], ... - vSetKeyFrames.Views); - - % Local bundle adjustment - [mapPointSet, vSetKeyFrames, triangulatedMapPointsIdx, rgbdMapPointsIdx] = ... - helperLocalBundleAdjustmentStereo(mapPointSet, vSetKeyFrames, ... - currKeyFrameId, intrinsics, triangulatedMapPointsIdx, rgbdMapPointsIdx); - - % Check if the KeyFrames directory exists; if not, create it - keyFramesDir = './KeyFrames'; - if ~exist(keyFramesDir, 'dir') - mkdir(keyFramesDir); - end - - % Store feature locations for this key frame - keyFramePointsDir = './KeyFramePoints'; - if ~exist(keyFramePointsDir, 'dir') - mkdir(keyFramePointsDir); - end - - % Save the current key frame image using currKeyFrameId - filename = sprintf('%s/KeyFrame_%04d.png', keyFramesDir, currKeyFrameId); - imwrite(currIcolor, filename); - - % Save feature points information - saveKeyFramePoints(keyFramePointsDir, currKeyFrameId, currPoints(trackedFeatureIdx), trackedMapPointsIdx); - - % Visualize 3-D world points and camera trajectory - updatePlot(mapPlot, vSetKeyFrames, mapPointSet); - - % Loop Closure - % The loop closure detection step takes the current key frame processed by the local mapping process and tries to detect and close the loop. Loop candidates are identified by querying images in the database that are visually similar to the current key frame using evaluateImageRetrieval. A candidate key frame is valid if it is not connected to the last key frame and three of its neighbor key frames are loop candidates. - % When a valid loop candidate is found, use estgeotform3d to compute the relative pose between the loop candidate frame and the current key frame. The relative pose represents a 3-D rigid transformation stored in a rigidtform3d object. Then add the loop connection with the relative pose and update mapPointSet and vSetKeyFrames. - % Check loop closure after some key frames have been created - if currKeyFrameId > 20 - - % Minimum number of feature matches of loop edges - loopEdgeNumMatches = 120; - - % Detect possible loop closure key frame candidates - [isDetected, validLoopCandidates] = helperCheckLoopClosure(vSetKeyFrames, currKeyFrameId, ... - loopDatabase, currIcolor, loopEdgeNumMatches); - - if isDetected - % Add loop closure connections - maxDistance = 0.1; - [isLoopClosed, mapPointSet, vSetKeyFrames] = helperAddLoopConnectionsStereo(... - mapPointSet, vSetKeyFrames, validLoopCandidates, currKeyFrameId, ... - currFeatures, currPoints, loopEdgeNumMatches, maxDistance); - end - end - - % If no loop closure is detected, add current features into the database - if ~isLoopClosed - addImageFeatures(loopDatabase, currFeatures, currKeyFrameId); - end - - % Update IDs and indices - lastKeyFrameId = currKeyFrameId; - lastKeyFrameIdx = currFrameIdx; - addedFramesIdx = [addedFramesIdx; currFrameIdx]; %#ok - currFrameIdx = currFrameIdx + 1; - end % End of main loop - - % Finally, apply pose graph optimization over the essential graph in vSetKeyFrames to correct the drift. The essential graph is created internally by removing connections with fewer than minNumMatches matches in the covisibility graph. After pose graph optimization, update the 3-D locations of the map points using the optimized poses. - - % Optimize the poses - minNumMatches = 50; - vSetKeyFramesOptim = optimizePoses(vSetKeyFrames, minNumMatches, Tolerance=1e-16); - - % Update map points after optimizing the poses - mapPointSet = helperUpdateGlobalMap(mapPointSet, vSetKeyFrames, vSetKeyFramesOptim); - - updatePlot(mapPlot, vSetKeyFrames, mapPointSet); - - % Plot the optimized camera trajectory - optimizedPoses = poses(vSetKeyFramesOptim); - plotOptimizedTrajectory(mapPlot, optimizedPoses) - - % Update legend - showLegend(mapPlot); - - worldPointSetOutput = mapPointSet; - - % Dense Reconstruction from Depth Image - % Given the refined camera poses, you can reproject all the valid image points in the associated depth images back to the 3-D space to perform dense reconstruction. - % Create an array of pointCloud objects to store the world points constructed - - % from the key frames - ptClouds = repmat(pointCloud(zeros(1, 3)), numel(addedFramesIdx), 1); - - % Ignore image points at the boundary - offset = 40; - [X, Y] = meshgrid(offset:2:imageSize(2)-offset, offset:2:imageSize(1)-offset); - - for i = 1: numel(addedFramesIdx) - Icolor = readimage(imdsColor, addedFramesIdx(i)); - Idepth = readimage(imdsDepth, addedFramesIdx(i)); - - [xyzPoints, validIndex] = helperReconstructFromRGBD([X(:), Y(:)], ... - Idepth, intrinsics, optimizedPoses.AbsolutePose(i), depthFactor); - - colors = zeros(numel(X), 1, 'like', Icolor); - for j = 1:numel(X) - colors(j, 1:3) = Icolor(Y(j), X(j), :); - end - ptClouds(i) = pointCloud(xyzPoints, Color=colors(validIndex, :)); - end - - % Concatenate the point clouds - pointCloudsAll = pccat(ptClouds); - - figure - pcshow(pointCloudsAll,VerticalAxis="y", VerticalAxisDir="down"); - xlabel('X') - ylabel('Y') - zlabel('Z') -end - -%% Helper functions - -% helperImportTimestampFile Import time stamp file - -function timestamp = helperImportTimestampFile(filename) - % Input handling - dataLines = [4, Inf]; - - %% Set up the Import Options and import the data - opts = delimitedTextImportOptions("NumVariables", 2); - - % Specify range and delimiter - opts.DataLines = dataLines; - opts.Delimiter = " "; - - % Specify column names and types - opts.VariableNames = ["VarName1", "Var2"]; - opts.SelectedVariableNames = "VarName1"; - opts.VariableTypes = ["double", "string"]; - - % Specify file level properties - opts.ExtraColumnsRule = "ignore"; - opts.EmptyLineRule = "read"; - opts.ConsecutiveDelimitersRule = "join"; - opts.LeadingDelimitersRule = "ignore"; - - % Specify variable properties - opts = setvaropts(opts, "Var2", "WhitespaceRule", "preserve"); - opts = setvaropts(opts, "Var2", "EmptyFieldRule", "auto"); - - % Import the data - data = readtable(filename, opts); - - % Convert to output type - timestamp = table2array(data); -end - -% helperAlignTimestamp align time stamp of color and depth images. -function indexPairs = helperAlignTimestamp(timeColor, timeDepth) - idxDepth = 1; - indexPairs = zeros(numel(timeColor), 2); - for i = 1:numel(timeColor) - for j = idxDepth : numel(timeDepth) - if abs(timeColor(i) - timeDepth(j)) < 1e-4 - idxDepth = j; - indexPairs(i, :) = [i, j]; - break - elseif timeDepth(j) - timeColor(i) > 1e-3 - break - end - end - end - indexPairs = indexPairs(indexPairs(:,1)>0, :); -end - -% helperDetectAndExtractFeatures detect and extract and ORB features from the image. -function [features, validPoints] = helperDetectAndExtractFeatures(Irgb, scaleFactor, numLevels) - - numPoints = 1000; - - % Detect ORB features - Igray = rgb2gray(Irgb); - - points = detectORBFeatures(Igray, ScaleFactor=scaleFactor, NumLevels=numLevels); - - % Select a subset of features, uniformly distributed throughout the image - points = selectUniform(points, numPoints, size(Igray, 1:2)); - - % Extract features - [features, validPoints] = extractFeatures(Igray, points); -end - -% helperReconstructFromRGBD reconstruct scene from color and depth image. - -function [xyzPoints, validIndex] = helperReconstructFromRGBD(points, ... - depthMap, intrinsics, currPose, depthFactor) - - ptcloud = pcfromdepth(depthMap,depthFactor,intrinsics,ImagePoints=points, DepthRange=[0.1, 5]); - - isPointValid = ~isnan(ptcloud.Location(:, 1)); - xyzPoints = ptcloud.Location(isPointValid, :); - xyzPoints = transformPointsForward(currPose, xyzPoints); - validIndex = find(isPointValid); -end - -% helperCullRecentMapPoints cull recently added map points. -function [mapPointSet, mapPointsIdx] = ... - helperCullRecentMapPoints(mapPointSet, mapPointsIdx, newPointIdx, rgbdMapPointsIndices) - outlierIdx = setdiff([newPointIdx; rgbdMapPointsIndices], mapPointsIdx); - if ~isempty(outlierIdx) - mapPointSet = removeWorldPoints(mapPointSet, outlierIdx); - mapPointsIdx = mapPointsIdx - arrayfun(@(x) nnz(x>outlierIdx), mapPointsIdx); - end -end - -% helperEstimateTrajectoryError calculate the tracking error. -function rmse = helperEstimateTrajectoryError(gTruth, cameraPoses) - locations = vertcat(cameraPoses.AbsolutePose.Translation); - gLocations = vertcat(gTruth.Translation); - scale = median(vecnorm(gLocations, 2, 2))/ median(vecnorm(locations, 2, 2)); - scaledLocations = locations * scale; - - rmse = sqrt(mean( sum((scaledLocations - gLocations).^2, 2) )); - disp(['Absolute RMSE for key frame trajectory (m): ', num2str(rmse)]); -end - -% helperUpdateGlobalMap update 3-D locations of map points after pose graph optimization -function mapPointSet = helperUpdateGlobalMap(mapPointSet, vSetKeyFrames, vSetKeyFramesOptim) - - posesOld = vSetKeyFrames.Views.AbsolutePose; - posesNew = vSetKeyFramesOptim.Views.AbsolutePose; - positionsOld = mapPointSet.WorldPoints; - positionsNew = positionsOld; - indices = 1:mapPointSet.Count; - - % Update world location of each map point based on the new absolute pose of - % the corresponding major view - for i = 1: mapPointSet.Count - majorViewIds = mapPointSet.RepresentativeViewId(i); - tform = rigidtform3d(posesNew(majorViewIds).A/posesOld(majorViewIds).A); - positionsNew(i, :) = transformPointsForward(tform, positionsOld(i, :)); - end - mapPointSet = updateWorldPoints(mapPointSet, indices, positionsNew); -end - -% CSV file creation for points within keyframe -function saveKeyFramePoints(dirPath, keyFrameId, featurePoints, mapPointsIdx) - % Ensure the directory exists - if ~exist(dirPath, 'dir') - mkdir(dirPath); - end - - % Define the filename for the CSV file - csvFilename = sprintf('%s/KeyFramePoints_%04d.csv', dirPath, keyFrameId); - - % Extract pixel locations from the feature points - pixelLocations = featurePoints.Location; % This should be an Nx2 matrix - - % Combine the indices, pixel locations, and corresponding world points indices into one matrix - dataMatrix = [pixelLocations, mapPointsIdx]; % Concatenate horizontally - - % Write the combined data to a CSV file - writematrix(dataMatrix, csvFilename); -end - - -function savePointCloudToCSV(pointCloudsAll) - mat = [pointCloudsAll.Location, cast(pointCloudsAll.Color, "single")]; - writematrix(mat, "pointcloud.csv"); -end - - -function savePosesToCSV(optimizedPoses, dirPath) - mkdir(dirPath) - - t_size = size(optimizedPoses); - for i=1:t_size(1) - p = optimizedPoses.AbsolutePose(i, 1); - % first row will be translation - % second-fifth row will be rotation - mat = [p.Translation; p.R]; - idx = optimizedPoses.ViewId(i,1); - - % save to directory - fname = sprintf('%s/Pose_%04d.csv', dirPath, idx); - writematrix(mat, fname); - end -end - - -function saveIntrinsicsToCSV(intrinsics) - mat = [intrinsics.FocalLength, 0 ; - intrinsics.PrincipalPoint, 0 ; - intrinsics.ImageSize, 0 ; - intrinsics.K]; - - writematrix(mat, 'CameraIntrinsics.csv') -end \ No newline at end of file diff --git a/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst b/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst index 9ed0cd1af0980717fffc73a9f4157439ffba674d..a0fbad47412565c4e0f52b2c97e4379f8d71c90e 100644 --- a/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst +++ b/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst @@ -1,2 +1,20 @@ -yolo/YOLONet$ObjectDetectionResult.class +object_detection/types/Frame.class +object_detection/Downsampler.class +database/MongoDBInteraction.class +object_detection/types/BoundingBox3D.class +object_detection/types/BoundingBox2D.class yolo/YOLONet.class +object_detection/types/CameraIntrinsics.class +top/BackendJava$BackendService.class +object_detection/types/Point.class +object_detection/types/CameraPose.class +vid2frames/Vid2Frames.class +top/BackendJava$ObjectSetController.class +top/BackendJava.class +yolo/YOLODetector.class +yolo/YOLONet$ObjectDetectionResult.class +object_detection/types/ObjectSet.class +object_detection/ObjectDetector.class +top/BackendJava$WebMvcConfig.class +object_detection/types/Point2D.class +object_detection/types/PointSet.class diff --git a/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst b/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst index aede6fb4c2cff93d65d71f3e57063c7f11326e6c..299399467a6030396beb313eb677ca90c8c2e82c 100644 --- a/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst +++ b/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst @@ -1,16 +1,16 @@ -/Users/jack.edelist/Desktop/group8/src/main/java/object_detection/types/ObjectSet.java -/Users/jack.edelist/Desktop/group8/src/main/java/object_detection/types/CameraPose.java -/Users/jack.edelist/Desktop/group8/src/main/java/object_detection/types/Point2D.java -/Users/jack.edelist/Desktop/group8/src/main/java/object_detection/types/BoundingBox2D.java -/Users/jack.edelist/Desktop/group8/src/main/java/top/BackendJava.java -/Users/jack.edelist/Desktop/group8/src/main/java/vid2frames/Vid2Frames.java -/Users/jack.edelist/Desktop/group8/src/main/java/object_detection/types/CameraIntrinsics.java -/Users/jack.edelist/Desktop/group8/src/main/java/object_detection/types/PointSet.java -/Users/jack.edelist/Desktop/group8/src/main/java/database/MongoDBInteraction.java -/Users/jack.edelist/Desktop/group8/src/main/java/object_detection/ObjectDetector.java -/Users/jack.edelist/Desktop/group8/src/main/java/object_detection/types/BoundingBox3D.java -/Users/jack.edelist/Desktop/group8/src/main/java/object_detection/types/Frame.java -/Users/jack.edelist/Desktop/group8/src/main/java/object_detection/types/Point.java -/Users/jack.edelist/Desktop/group8/src/main/java/yolo/YOLODetector.java -/Users/jack.edelist/Desktop/group8/src/main/java/yolo/YOLONet.java -/Users/jack.edelist/Desktop/group8/src/main/java/object_detection/Downsampler.java +/Users/jack.edelist/Downloads/group8/src/main/java/object_detection/types/BoundingBox2D.java +/Users/jack.edelist/Downloads/group8/src/main/java/yolo/YOLODetector.java +/Users/jack.edelist/Downloads/group8/src/main/java/object_detection/types/ObjectSet.java +/Users/jack.edelist/Downloads/group8/src/main/java/object_detection/types/BoundingBox3D.java +/Users/jack.edelist/Downloads/group8/src/main/java/object_detection/Downsampler.java +/Users/jack.edelist/Downloads/group8/src/main/java/top/BackendJava.java +/Users/jack.edelist/Downloads/group8/src/main/java/object_detection/types/Point2D.java +/Users/jack.edelist/Downloads/group8/src/main/java/object_detection/types/CameraIntrinsics.java +/Users/jack.edelist/Downloads/group8/src/main/java/vid2frames/Vid2Frames.java +/Users/jack.edelist/Downloads/group8/src/main/java/database/MongoDBInteraction.java +/Users/jack.edelist/Downloads/group8/src/main/java/object_detection/ObjectDetector.java +/Users/jack.edelist/Downloads/group8/src/main/java/object_detection/types/CameraPose.java +/Users/jack.edelist/Downloads/group8/src/main/java/object_detection/types/Point.java +/Users/jack.edelist/Downloads/group8/src/main/java/object_detection/types/PointSet.java +/Users/jack.edelist/Downloads/group8/src/main/java/yolo/YOLONet.java +/Users/jack.edelist/Downloads/group8/src/main/java/object_detection/types/Frame.java diff --git a/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst b/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst index 9ed0cd1af0980717fffc73a9f4157439ffba674d..ef7190d15bf968b38047ba8c9d5c594c56353668 100644 --- a/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst +++ b/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst @@ -1,2 +1,12 @@ +object_detection/Point2DTests.class +object_detection/ObjectSetTests.class +yolo/YOLOTest.class +object_detection/BoundingBox3DTests.class +object_detection/CameraPoseTests.class +object_detection/PointSetTests.class +object_detection/PointTests.class yolo/YOLONet$ObjectDetectionResult.class +object_detection/FrameTests.class +object_detection/CameraIntrinsicsTests.class +object_detection/BoundingBox2DTests.class yolo/YOLONet.class diff --git a/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst b/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst index eeea1718facfff2846db25447deac20997b40825..e5dae0af94243b0a16fe95743e2b76fd5a90c4b9 100644 --- a/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst +++ b/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst @@ -1,10 +1,11 @@ -/Users/jack.edelist/Desktop/group8/src/test/java/object_detection/BoundingBox3DTests.java -/Users/jack.edelist/Desktop/group8/src/test/java/object_detection/PointTests.java -/Users/jack.edelist/Desktop/group8/src/test/java/object_detection/ObjectSetTests.java -/Users/jack.edelist/Desktop/group8/src/test/java/object_detection/CameraPoseTests.java -/Users/jack.edelist/Desktop/group8/src/test/java/object_detection/Point2DTests.java -/Users/jack.edelist/Desktop/group8/src/test/java/yolo/YOLOTest.java -/Users/jack.edelist/Desktop/group8/src/test/java/object_detection/BoundingBox2DTests.java -/Users/jack.edelist/Desktop/group8/src/test/java/yolo/YOLONet.java -/Users/jack.edelist/Desktop/group8/src/test/java/object_detection/PointSetTests.java -/Users/jack.edelist/Desktop/group8/src/test/java/object_detection/CameraInstrinsicsTests.java +/Users/jack.edelist/Downloads/group8/src/test/java/object_detection/CameraInstrinsicsTests.java +/Users/jack.edelist/Downloads/group8/src/test/java/yolo/YOLONet.java +/Users/jack.edelist/Downloads/group8/src/test/java/object_detection/BoundingBox2DTests.java +/Users/jack.edelist/Downloads/group8/src/test/java/object_detection/PointTests.java +/Users/jack.edelist/Downloads/group8/src/test/java/yolo/YOLOTest.java +/Users/jack.edelist/Downloads/group8/src/test/java/object_detection/Point2DTests.java +/Users/jack.edelist/Downloads/group8/src/test/java/object_detection/PointSetTests.java +/Users/jack.edelist/Downloads/group8/src/test/java/object_detection/CameraPoseTests.java +/Users/jack.edelist/Downloads/group8/src/test/java/object_detection/BoundingBox3DTests.java +/Users/jack.edelist/Downloads/group8/src/test/java/object_detection/FrameTests.java +/Users/jack.edelist/Downloads/group8/src/test/java/object_detection/ObjectSetTests.java diff --git a/target/surefire-reports/TEST-object_detection.BoundingBox2DTests.xml b/target/surefire-reports/TEST-object_detection.BoundingBox2DTests.xml index f5378d5425571c58b99079ff14dce1c5523690c0..5a1a5e5404ed9dbc1803f0931201a2c10a3a5a4a 100644 --- a/target/surefire-reports/TEST-object_detection.BoundingBox2DTests.xml +++ b/target/surefire-reports/TEST-object_detection.BoundingBox2DTests.xml @@ -1,9 +1,9 @@ - + - + @@ -12,10 +12,10 @@ - + - + @@ -23,13 +23,13 @@ - + - + @@ -45,7 +45,7 @@ - + @@ -60,6 +60,6 @@ - - + + \ No newline at end of file diff --git a/target/surefire-reports/TEST-object_detection.BoundingBox3DTests.xml b/target/surefire-reports/TEST-object_detection.BoundingBox3DTests.xml index 6d43e092deb0e41d7f644b31f27b5ee7077efa69..14101704f306f05d2bece32fa4d1c53911b32c91 100644 --- a/target/surefire-reports/TEST-object_detection.BoundingBox3DTests.xml +++ b/target/surefire-reports/TEST-object_detection.BoundingBox3DTests.xml @@ -1,9 +1,9 @@ - + - + @@ -12,10 +12,10 @@ - + - + @@ -23,13 +23,13 @@ - + - + @@ -45,7 +45,7 @@ - + @@ -58,5 +58,5 @@ - + \ No newline at end of file diff --git a/target/surefire-reports/TEST-object_detection.CameraIntrinsicsTests.xml b/target/surefire-reports/TEST-object_detection.CameraIntrinsicsTests.xml index 91120a65e388d949fe5ba1b1e8eab1411fbf702f..fc280a99ad01b051b12e9df64bf6d04b08300383 100644 --- a/target/surefire-reports/TEST-object_detection.CameraIntrinsicsTests.xml +++ b/target/surefire-reports/TEST-object_detection.CameraIntrinsicsTests.xml @@ -1,9 +1,9 @@ - + - + @@ -12,10 +12,10 @@ - + - + @@ -23,13 +23,13 @@ - + - + @@ -45,7 +45,7 @@ - + diff --git a/target/surefire-reports/TEST-object_detection.CameraPoseTests.xml b/target/surefire-reports/TEST-object_detection.CameraPoseTests.xml index b7f6e1fb0570c79f9646d16a0eebaaa9caf6d999..91d8b94cc549165fd5cb543974e70373f996303b 100644 --- a/target/surefire-reports/TEST-object_detection.CameraPoseTests.xml +++ b/target/surefire-reports/TEST-object_detection.CameraPoseTests.xml @@ -3,7 +3,7 @@ - + @@ -12,10 +12,10 @@ - + - + @@ -23,13 +23,13 @@ - + - + @@ -45,7 +45,7 @@ - + diff --git a/target/surefire-reports/TEST-object_detection.ObjectSetTests.xml b/target/surefire-reports/TEST-object_detection.ObjectSetTests.xml index 99b94a7e2e689b40c79b68d1a067091b85b7f145..b1585981c629572ce20dc7481bb3ee3b6f58b338 100644 --- a/target/surefire-reports/TEST-object_detection.ObjectSetTests.xml +++ b/target/surefire-reports/TEST-object_detection.ObjectSetTests.xml @@ -1,9 +1,9 @@ - + - + @@ -12,10 +12,10 @@ - + - + @@ -23,13 +23,13 @@ - + - + @@ -45,7 +45,7 @@ - + @@ -59,6 +59,6 @@ - - + + \ No newline at end of file diff --git a/target/surefire-reports/TEST-object_detection.Point2DTests.xml b/target/surefire-reports/TEST-object_detection.Point2DTests.xml index 44d623d1e005d1016e72b07f6f2b63ba9d808e0e..df7be9b4c44885070e6ebdfb3a6578ba43fe32bf 100644 --- a/target/surefire-reports/TEST-object_detection.Point2DTests.xml +++ b/target/surefire-reports/TEST-object_detection.Point2DTests.xml @@ -1,9 +1,9 @@ - + - + @@ -12,10 +12,10 @@ - + - + @@ -23,13 +23,13 @@ - + - + @@ -45,7 +45,7 @@ - + @@ -58,7 +58,7 @@ - - - + + + \ No newline at end of file diff --git a/target/surefire-reports/TEST-object_detection.PointSetTests.xml b/target/surefire-reports/TEST-object_detection.PointSetTests.xml index 3d3c3f207ee197a5848318204c1ac8b189dcf00f..a156437cd380965865ffac88957b7dfe04ae9b06 100644 --- a/target/surefire-reports/TEST-object_detection.PointSetTests.xml +++ b/target/surefire-reports/TEST-object_detection.PointSetTests.xml @@ -1,9 +1,9 @@ - + - + @@ -12,10 +12,10 @@ - + - + @@ -23,13 +23,13 @@ - + - + @@ -45,7 +45,7 @@ - + @@ -58,7 +58,9 @@ + - + + \ No newline at end of file diff --git a/target/surefire-reports/TEST-object_detection.PointTests.xml b/target/surefire-reports/TEST-object_detection.PointTests.xml index 8aa3231dfa3a4566206008f958471afb21e69eb8..10cc2f3022bda1313149985f97a6e79b933ce996 100644 --- a/target/surefire-reports/TEST-object_detection.PointTests.xml +++ b/target/surefire-reports/TEST-object_detection.PointTests.xml @@ -1,9 +1,9 @@ - + - + @@ -12,10 +12,10 @@ - + - + @@ -23,13 +23,13 @@ - + - + @@ -45,7 +45,7 @@ - + @@ -59,12 +59,12 @@ - + - - + + - - + + \ No newline at end of file diff --git a/target/surefire-reports/object_detection.BoundingBox2DTests.txt b/target/surefire-reports/object_detection.BoundingBox2DTests.txt index f001e8df274646fe8fdf5f134e8d08b8a2645fc2..b0a0b5b82773e7bb7ec36309f352015b5dd143d8 100644 --- a/target/surefire-reports/object_detection.BoundingBox2DTests.txt +++ b/target/surefire-reports/object_detection.BoundingBox2DTests.txt @@ -1,4 +1,4 @@ ------------------------------------------------------------------------------- Test set: object_detection.BoundingBox2DTests ------------------------------------------------------------------------------- -Tests run: 4, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.004 s -- in object_detection.BoundingBox2DTests +Tests run: 4, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.005 s -- in object_detection.BoundingBox2DTests diff --git a/target/surefire-reports/object_detection.BoundingBox3DTests.txt b/target/surefire-reports/object_detection.BoundingBox3DTests.txt index d8e3531225fcfc385d3781e5167a7a5c1c21fe68..53e08d887f0c7b687ef7e128db94b374bd475ded 100644 --- a/target/surefire-reports/object_detection.BoundingBox3DTests.txt +++ b/target/surefire-reports/object_detection.BoundingBox3DTests.txt @@ -1,4 +1,4 @@ ------------------------------------------------------------------------------- Test set: object_detection.BoundingBox3DTests ------------------------------------------------------------------------------- -Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.006 s -- in object_detection.BoundingBox3DTests +Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.005 s -- in object_detection.BoundingBox3DTests diff --git a/target/surefire-reports/object_detection.CameraIntrinsicsTests.txt b/target/surefire-reports/object_detection.CameraIntrinsicsTests.txt index 83544e4bfc1fc1757f0a701c39e7204fbb9b9281..08affe29e5e9b6935dd58aae8c0af39fdd914dbd 100644 --- a/target/surefire-reports/object_detection.CameraIntrinsicsTests.txt +++ b/target/surefire-reports/object_detection.CameraIntrinsicsTests.txt @@ -1,4 +1,4 @@ ------------------------------------------------------------------------------- Test set: object_detection.CameraIntrinsicsTests ------------------------------------------------------------------------------- -Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.045 s -- in object_detection.CameraIntrinsicsTests +Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.046 s -- in object_detection.CameraIntrinsicsTests diff --git a/target/surefire-reports/object_detection.ObjectSetTests.txt b/target/surefire-reports/object_detection.ObjectSetTests.txt index 240d0b1079b6778a896284e84c52fe69e113ca9f..50171b321d6a5d584ad5003ad1f86655be7d6e09 100644 --- a/target/surefire-reports/object_detection.ObjectSetTests.txt +++ b/target/surefire-reports/object_detection.ObjectSetTests.txt @@ -1,4 +1,4 @@ ------------------------------------------------------------------------------- Test set: object_detection.ObjectSetTests ------------------------------------------------------------------------------- -Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.014 s -- in object_detection.ObjectSetTests +Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.017 s -- in object_detection.ObjectSetTests diff --git a/target/surefire-reports/object_detection.Point2DTests.txt b/target/surefire-reports/object_detection.Point2DTests.txt index 5b17a8b00d0fce223b1246d4350779c40984379a..39a051aea9d9fa1ee2760ad2f278b3f99aa051fd 100644 --- a/target/surefire-reports/object_detection.Point2DTests.txt +++ b/target/surefire-reports/object_detection.Point2DTests.txt @@ -1,4 +1,4 @@ ------------------------------------------------------------------------------- Test set: object_detection.Point2DTests ------------------------------------------------------------------------------- -Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.011 s -- in object_detection.Point2DTests +Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.012 s -- in object_detection.Point2DTests diff --git a/target/surefire-reports/object_detection.PointSetTests.txt b/target/surefire-reports/object_detection.PointSetTests.txt index e09b8f5bd7234d2bdd317961e93973926275523a..58b51484d9b984e23682d01c0feeb5072ec6a7b1 100644 --- a/target/surefire-reports/object_detection.PointSetTests.txt +++ b/target/surefire-reports/object_detection.PointSetTests.txt @@ -1,4 +1,4 @@ ------------------------------------------------------------------------------- Test set: object_detection.PointSetTests ------------------------------------------------------------------------------- -Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.002 s -- in object_detection.PointSetTests +Tests run: 5, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.007 s -- in object_detection.PointSetTests diff --git a/target/surefire-reports/object_detection.PointTests.txt b/target/surefire-reports/object_detection.PointTests.txt index 8e99a6442bad7ef100d89fc59ba1208360faa3ce..e8a46d038d862c20ebe24e8189cec3a28cd88ef7 100644 --- a/target/surefire-reports/object_detection.PointTests.txt +++ b/target/surefire-reports/object_detection.PointTests.txt @@ -1,4 +1,4 @@ ------------------------------------------------------------------------------- Test set: object_detection.PointTests ------------------------------------------------------------------------------- -Tests run: 9, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.008 s -- in object_detection.PointTests +Tests run: 9, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.013 s -- in object_detection.PointTests diff --git a/target/test-classes/object_detection/BoundingBox3DTests.class b/target/test-classes/object_detection/BoundingBox3DTests.class index 56dc08bf4c3a5276333db5c60d4e3b5596448193..0658931127cd77232a5f84dcdc22457fbd72eb4e 100644 Binary files a/target/test-classes/object_detection/BoundingBox3DTests.class and b/target/test-classes/object_detection/BoundingBox3DTests.class differ diff --git a/target/test-classes/object_detection/FrameTests.class b/target/test-classes/object_detection/FrameTests.class new file mode 100644 index 0000000000000000000000000000000000000000..5450785054c639f3be6e0df183f8eae670f03d8f Binary files /dev/null and b/target/test-classes/object_detection/FrameTests.class differ diff --git a/target/test-classes/object_detection/ObjectSetTests.class b/target/test-classes/object_detection/ObjectSetTests.class index 0dcdfeddf9dab13b445b02796b4bb746a5637d0a..d188d50fb2aaabfac33f1f77b15f0f8550426106 100644 Binary files a/target/test-classes/object_detection/ObjectSetTests.class and b/target/test-classes/object_detection/ObjectSetTests.class differ diff --git a/target/test-classes/object_detection/PointSetTests.class b/target/test-classes/object_detection/PointSetTests.class index dff964f08e5d65d5a9150abd39ee3f0d3d431d0d..01e939b364a162ad7a1d3c6643d9b5777d1a4645 100644 Binary files a/target/test-classes/object_detection/PointSetTests.class and b/target/test-classes/object_detection/PointSetTests.class differ