最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

geometry - Finding the deviation from a navigation trajectory to it's ideal path - Stack Overflow

programmeradmin3浏览0评论

Background: I have recorded navigation trajectory positional x,y and its time point (50hz) data from a virtual reality navigation in an empty room.

Problem: I want to calculate how much the navigation deviates from it's closest point to the ideal path and must calculate to the correct segment they are still "on"/furthest along the path currently.

Inputs:

Current output using KNN() only (upper left subplot) of a good (upper figure) and bad (lower) navigation. Note how on bad navigations it goes crazy and compares to any random point closest to it when it needs to compare to the current path segment it is on:

The current method using function KNN() to find the nearest neighbor works well sometimes but it will not work in cases where navigations are completely wrong and it begins comparing deviations to a whole different path it is not even on yet. It also entirely skips corners as the hypotenuse euclidean distance always going to be the furthest... Code blocks to process both images and the calculation/plotting below:

% Single line shortest path analyses                    
shortstimImg = imread(shorteststimFile);
if size(stimImg, 3) == 3
    shortstimImg = rgb2gray(shortstimImg);
end
% Convert the image to double precision
shortstimImg = im2double(shortstimImg);                 
% Resize the image to 600x600
shortstimImgResized = imresize(shortstimImg, [600, 600], 'nearest');

% Convert to binary and skeletonize
if size(shortstimImgResized, 3) == 3
    shorteststimImgGray = rgb2gray(shortstimImgResized);
else
    shorteststimImgGray = shortstimImgResized;
end

% Binarize and skeletonize

% Convert to binary image
binary = imbinarize(shorteststimImgGray);  % Automatic thresholding
% binary = imbinarize(shorteststimImgBW, 'adaptive'); % Alternative adaptive threshold

% Ensure white lines on black background (check top-left corner)
if mean(binary(1:10,1:10), 'all') > 0.5
    binary = ~binary;  % Invert image
end

% Clean up with morphological closing
kernel = strel('square', 3);  % 3x3 structuring element
closed = imclose(binary, kernel);

% Skeletonization with branch cleaning
skeleton = bwskel(closed, 'MinBranchLength', 20);  % Remove small branches
skeleton = bwmorph(skeleton, 'bridge');  % Connect nearby segments

% Convert to uint8 image (255 for lines, 0 for background)
skeleton_uint8 = uint8(skeleton) * 255;

% Extract coordinates from 1-pixel skeleton BEFORE any dilation
[stimY, stimX] = find(skeleton);  % MATLAB returns [rows, cols]

% Convert coordinates to 600x600 cm space (preserve aspect ratio)
[height, width] = size(skeleton);
stimX_cm = (stimX / width) * 600;
stimY_cm = (stimY / height) * 600;
idealTrajectory = [stimX_cm, stimY_cm];
% Read the PNG image from the matfile
matImg = imread(rawTrajectory.png);
% Convert the image to grayscale if it's not already in grayscale format
if size(matImg, 3) == 3
    matImg = rgb2gray(matImg);
end
% Convert the image to double precision
matImg = im2double(matImg);
% Convert the matImg to uint8
matImgUint8 = im2uint8(matImg);  
% Extract trajectory coordinates
skeletonizedImg = bwmorph(matImgUint8 == 0, 'skel', Inf);
[trajY, trajX] = find(skeletonizedImg);
trajectory = [trajX, trajY];
function plotPathDeviation(metrics, idealTrajectory, trajectory_raw)
    % Add input validation
    if size(trajectory_raw, 2) ~= 2
        error('Trajectory must be Nx2 matrix');
    end
    
    % Clean trajectory data
    validIdx = all(~isnan(trajectory_raw), 2);
    trajectory_valid = trajectory_raw(validIdx,:);
    
    % Ensure idealTrajectory is Nx2
    idealTrajectory = validateTrajectoryDimensions(idealTrajectory);
    % Set white background
    set(gca, 'Color', 'w');
    
    % Plot ideal path
    scatter(idealTrajectory(:,1), idealTrajectory(:,2), 10, 'g', 'DisplayName', 'Ideal Path');
    hold on;
    
    % Plot trajectory
    validIdx = all(~isnan(trajectory_raw), 2);
    trajectory_valid = trajectory_raw(validIdx, :);
    scatter(trajectory_valid(:,1), trajectory_valid(:,2), 10, 'b', 'filled', 'DisplayName', 'Trajectory');
    
    % Sample points for deviation lines
    sample_points = 1:size(trajectory_valid, 1);
    
    % Compute KNN distances for visualization
    [nearestIndices, ~] = knnsearch(idealTrajectory, trajectory_valid);
    
    maxDev = 0;
    meanDev = 0;
    count = 0;
    
    for i = sample_points
        trajPoint = trajectory_valid(i,:);
        nearestPoint = idealTrajectory(nearestIndices(i),:);
        
        % Plot deviation line
        plot([trajPoint(1) nearestPoint(1)], [trajPoint(2) nearestPoint(2)], ...
            'Color', [1 0 0 0.2], ... % Red with 0.2 alpha (80% transparent)
            'LineWidth', 0.75, ...     % Slightly thicker to compensate for transparency
            'HandleVisibility', 'off');
        
        % Update deviation metrics
        dist = norm(trajPoint - nearestPoint);
        maxDev = max(maxDev, dist);
        meanDev = meanDev + dist;
        count = count + 1;
    end
    
    meanDev = meanDev / (count + eps);
    title(sprintf('Path Deviation\nMean Dev: %.1f cm, Max Dev: %.1f cm', meanDev, maxDev));
    grid on;
    configureAxes();
    hold off;
end

Suggestion perhaps: Expanding/growing radii circle on each pixel point on one of the images until it matches/touches the closest comparison image point? Not sure if it's best to expand it from the template ideal path or the recorded trajectory. Leaning towards recorded trajectory as that always varies person-to-person

Will need to implement a sequential pathing processing so comparisons do not jump ahead to compare to a path further ahead.

I have each segment composing the entire ideal path classified of each segment's endpoints, orientation, angle, length.

If there are any other methods you guys think it best for my scenario, please let me know! Many thanks all.

发布评论

评论列表(0)

  1. 暂无评论