From 56d729638010e2c58a6e73bc5cd2790f36b0645b Mon Sep 17 00:00:00 2001 From: johnaoga Date: Sat, 5 Apr 2025 02:27:27 +0200 Subject: [PATCH] init --- .gitignore | 2 + src/lib/compute_initial_seed_points.m | 18 ++++ src/lib/compute_matching.m | 105 ++++++++++++++++++++++ src/lib/compute_tracking.m | 88 +++++++++++++++++++ src/lib/dic_2d_analysis.m | 122 +++++++++++++++++++++----- src/lib_script/ncorr_dic_rewrited.m | 7 +- xdic.m | 45 +++++++++- 7 files changed, 360 insertions(+), 27 deletions(-) create mode 100644 .gitignore create mode 100644 src/lib/compute_initial_seed_points.m create mode 100644 src/lib/compute_matching.m create mode 100644 src/lib/compute_tracking.m diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4f4091d --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +logs +analysis \ No newline at end of file diff --git a/src/lib/compute_initial_seed_points.m b/src/lib/compute_initial_seed_points.m new file mode 100644 index 0000000..74a5a61 --- /dev/null +++ b/src/lib/compute_initial_seed_points.m @@ -0,0 +1,18 @@ +function [initial_seed_point_set1, refmask_trial] = compute_initial_seed_points(cam_first_satur, cam_second_satur) + % This function computes initial seed points for DIC analysis + % It is extracted from stepD_2DDIC.m to support parallel processing + + % Initialize output + initial_seed_point_set1 = struct(); + + % Get size of images + siz = size(cam_first_satur); + + % Create initial mask (full image) + refmask_trial = true(siz(1:2)); + + % Set initial seed point in the center of the image + % This is a simple approach - you might want to make this more sophisticated + initial_seed_point_set1.sw = [siz(2)/2, siz(1)/2]; + initial_seed_point_set1.pw = initial_seed_point_set1.sw; +end diff --git a/src/lib/compute_matching.m b/src/lib/compute_matching.m new file mode 100644 index 0000000..c946ac1 --- /dev/null +++ b/src/lib/compute_matching.m @@ -0,0 +1,105 @@ +function [refmask_trial_matched, initial_seed_point_set2] = compute_matching(data_path, dic_path, subject_id, material, trial, stereopair, phase, showvisu, idx_frame_start, idx_frame_end, frame_jump, ref_trial_id, automatic_process) + % This function handles the matching step between stereo pairs + % It is extracted from stepD_2DDIC.m to enable parallel processing + + % Get parameters from original function + TRUE_FPS = 50; + if str2double(cell2mat(regexp(subject_id, '\d+', 'match'))) < 8 + LIMIT_GRAYSCALE = 70; + else + LIMIT_GRAYSCALE = 100; + end + + % Ncorr DIC parameters for matching + analysis_direction = 'regular'; + subset_radius_ncorr_matching = 60; + subset_spacing = 10; + cutoff_matching = 1e-5; + number_iteration_solver = 100; + number_threads = 1; + high_strain_analysis = 1; + seed_propagation = 'seed'; + auto_ref_change = 1; + step_ref_change = 10; + + % Set up parameters struct + step1_2_parameters = struct(... + 'type', analysis_direction,... + 'radius', subset_radius_ncorr_matching,... + 'spacing', subset_spacing,... + 'cutoff_diffnorm', cutoff_matching,... + 'num_threads', number_threads,... + 'enabled_stepanalysis', high_strain_analysis,... + 'seedpropagation', seed_propagation,... + 'autorefchange', auto_ref_change,... + 'steprefchange', step_ref_change); + + base_parameters = struct(... + 'num_iterations', number_iteration_solver); + + % Read video data and process images + [cam_first_raw, cam_second_raw, cam_1, cam_2] = import_vid(data_path,... + 'subject', subject_id,... + 'material', material,... + 'trial', trial,... + 'stereopair', stereopair,... + 'phase', phase,... + 'idxstart_set', idx_frame_start,... + 'idxend_set', idx_frame_end,... + 'framejump', frame_jump); + + if strcmp(phase, "slide1") + cam_first_raw = cam_first_raw(:,:,1:end/2+5); + cam_second_raw = cam_second_raw(:,:,1:end/2+5); + end + + % Image saturation + cam_first_satur = satur(cam_first_raw, 'level', LIMIT_GRAYSCALE); + cam_second_satur = satur(cam_second_raw, 'level', LIMIT_GRAYSCALE); + + % Get initial seed points (this would need to be passed or computed) + [initial_seed_point_set1, refmask_trial] = compute_initial_seed_points(cam_first_satur, cam_second_satur); + + % Create output directory + outputPath = fullfile(dic_path, subject_id, material, trial, phase); + if ~exist(outputPath, 'dir') + mkdir(outputPath); + end + base_parameters.outputPath = outputPath; + + % MATCHING STEP + step1_2_parameters.initial_seed = initial_seed_point_set1.pw; + siz = size(cam_first_raw); + input1 = cam_first_satur(:,:,1); + input2 = zeros(siz(1), siz(2), 2, 'uint8'); + input2(:,:,1) = cam_second_satur(:,:,1); + input2(:,:,2) = cam_first_satur(:,:,1); + + % Save info before ncorr analysis + savefileName = fullfile(outputPath, sprintf('dic_info_data_target_pair%d.mat', stereopair)); + actual_fps_meas = TRUE_FPS/frame_jump; + idxframe = idx_frame_start:frame_jump:idx_frame_end; + save(savefileName, 'actual_fps_meas', 'idxframe'); + + % Run ncorr analysis + [h12, file_logic] = ncorr_dic_rewrited('cam_number', [cam_1, cam_2],... + 'cam_data_ref', input1,... + 'cam_data_cur', input2,... + 'mask', refmask_trial,... + 'automatic_process', automatic_process,... + 'step_param', step1_2_parameters,... + 'base_param', base_parameters); + + % Get results + refmask_trial_matched = h12.current(1).roi.mask; + U_mapped = h12.data_dic.displacements(1).plot_u_ref_formatted/(subset_spacing+1); + V_mapped = h12.data_dic.displacements(1).plot_v_ref_formatted/(subset_spacing+1); + + initial_seed_point_set2.sw = map_pointcoordinate(initial_seed_point_set1.sw, {U_mapped, V_mapped}); + initial_seed_point_set2.pw = map_subset2pixel(initial_seed_point_set2.sw, subset_spacing); + + if ~file_logic + close(h12.handles_gui.figure); + end + clear('h12'); +end diff --git a/src/lib/compute_tracking.m b/src/lib/compute_tracking.m new file mode 100644 index 0000000..e1ccc46 --- /dev/null +++ b/src/lib/compute_tracking.m @@ -0,0 +1,88 @@ +function success = compute_tracking(data_path, dic_path, subject_id, material, trial, stereopair, phase, showvisu, idx_frame_start, idx_frame_end, frame_jump, ref_trial_id, automatic_process, track_id, refmask, initial_seed_point) + % This function handles the tracking step for each camera + % It is extracted from stepD_2DDIC.m to enable parallel processing + % track_id: 1 for first camera, 2 for second camera + + % Get parameters from original function + TRUE_FPS = 50; + if str2double(cell2mat(regexp(subject_id, '\d+', 'match'))) < 8 + LIMIT_GRAYSCALE = 70; + else + LIMIT_GRAYSCALE = 100; + end + + % Ncorr DIC parameters for tracking + analysis_direction = 'regular'; + subset_radius_ncorr_tracking = 40; + subset_spacing = 10; + cutoff_tracking = 1e-5; + number_iteration_solver = 100; + number_threads = 1; + high_strain_analysis = 1; + seed_propagation = 'seed'; + auto_ref_change = 1; + step_ref_change = 10; + + % Set up parameters struct + step_parameters = struct(... + 'type', analysis_direction,... + 'radius', subset_radius_ncorr_tracking,... + 'spacing', subset_spacing,... + 'cutoff_diffnorm', cutoff_tracking,... + 'num_threads', number_threads,... + 'enabled_stepanalysis', high_strain_analysis,... + 'seedpropagation', seed_propagation,... + 'autorefchange', auto_ref_change,... + 'steprefchange', step_ref_change); + + base_parameters = struct(... + 'num_iterations', number_iteration_solver); + + % Read video data and process images + [cam_first_raw, cam_second_raw, cam_1, cam_2] = import_vid(data_path,... + 'subject', subject_id,... + 'material', material,... + 'trial', trial,... + 'stereopair', stereopair,... + 'phase', phase,... + 'idxstart_set', idx_frame_start,... + 'idxend_set', idx_frame_end,... + 'framejump', frame_jump); + + if strcmp(phase, "slide1") + cam_first_raw = cam_first_raw(:,:,1:end/2+5); + cam_second_raw = cam_second_raw(:,:,1:end/2+5); + end + + % Image saturation + cam_first_satur = satur(cam_first_raw, 'level', LIMIT_GRAYSCALE); + cam_second_satur = satur(cam_second_raw, 'level', LIMIT_GRAYSCALE); + + % TRACKING STEP + step_parameters.initial_seed = initial_seed_point.pw; + + if track_id == 1 + [h, file_logic] = ncorr_dic_rewrited('cam_number', cam_1,... + 'cam_data_ref', cam_first_satur(:,:,1),... + 'cam_data_cur', cam_first_satur(:,:,1:end),... + 'mask', refmask,... + 'automatic_process', automatic_process,... + 'step_param', step_parameters,... + 'base_param', base_parameters); + else + [h, file_logic] = ncorr_dic_rewrited('cam_number', cam_2,... + 'cam_data_ref', cam_second_satur(:,:,1),... + 'cam_data_cur', cam_second_satur(:,:,2:end),... + 'mask', refmask,... + 'automatic_process', automatic_process,... + 'step_param', step_parameters,... + 'base_param', base_parameters); + end + + if ~file_logic + close(h.handles_gui.figure); + end + clear('h'); + + success = file_logic; +end diff --git a/src/lib/dic_2d_analysis.m b/src/lib/dic_2d_analysis.m index 2978aa8..9e80a65 100644 --- a/src/lib/dic_2d_analysis.m +++ b/src/lib/dic_2d_analysis.m @@ -1,30 +1,108 @@ function output = dic_2d_analysis(trial_target, data_path, dic_path, subject_id, phase_id, material, num_pair, nfcond_set, spddxlcond_set, calib_folder_set, ref_trial_id, idx_frame_start, idx_frame_end, frame_jump, showvisu, debug_mode, automatic_process) fprintf('Begin of %s\n', mfilename); + % Flatten all combinations (trial_jj, stereopair_kk) - pairs_trials = combvec( 1:num_pair, trial_target)'; - - % parfor over the flattened set of combinations - output = cell(size(pairs_trials, 1), 1); - parfor i = 1:size(pairs_trials, 1) + pairs_trials = combvec(1:num_pair, trial_target)'; + num_combinations = size(pairs_trials, 1); + + % Initialize storage for matching results + matching_results = cell(num_combinations, 1); + + % STEP 1: Parallel matching computation + fprintf('Starting parallel matching computation...\n'); + parfor i = 1:num_combinations pair_id = pairs_trials(i, 1); trial_id = pairs_trials(i, 2); - fprintf('Trial ID: %d, Pair ID: %d\n', trial_id, pair_id); - %output{i} = {sprintf("Trial ID: %d, Pair ID: %d", trial_id, pair_id), 'success', true}; - [o1, o2, o3] = stepD_2DDIC( ... - 'baseDataPath', data_path, ... - 'baseResultPath', dic_path, ... - 'subject', subject_id, ... - 'material', material, ... - 'trial', sprintf("%03d", trial_id), ... - 'stereopair', pair_id, ... - 'phase', phase_id, ... - 'showvisu', showvisu, ... - 'idxstart_set', idx_frame_start, ... - 'idxend_set', idx_frame_end, ... - 'reftrial_setmanual', sprintf("%03d", ref_trial_id), ... - 'jump', frame_jump, ... - 'automatic_process', automatic_process); - output{i} = [o1, o2, o3]; + fprintf('Matching: Trial ID: %d, Pair ID: %d\n', trial_id, pair_id); + + % Compute matching between stereo pairs + [refmask_trial_matched, initial_seed_point_set2] = compute_matching(... + data_path, dic_path, subject_id, material, ... + sprintf('%03d', trial_id), pair_id, phase_id, ... + showvisu, idx_frame_start, idx_frame_end, frame_jump, ... + ref_trial_id, automatic_process); + + matching_results{i} = struct(... + 'trial_id', trial_id, ... + 'pair_id', pair_id, ... + 'refmask_trial_matched', refmask_trial_matched, ... + 'initial_seed_point_set2', initial_seed_point_set2); end + + % STEP 2: Parallel tracking computation + fprintf('Starting parallel tracking computation...\n'); + % Create combinations for tracking (trial, pair, track_id) + tracking_combinations = []; + for i = 1:num_combinations + tracking_combinations = [tracking_combinations; ... + pairs_trials(i,:), 1; ... % track_id 1 for first camera + pairs_trials(i,:), 2]; % track_id 2 for second camera + end + + num_tracking_tasks = size(tracking_combinations, 1); + tracking_results = cell(num_tracking_tasks, 1); + + parfor i = 1:num_tracking_tasks + trial_id = tracking_combinations(i, 2); + pair_id = tracking_combinations(i, 1); + track_id = tracking_combinations(i, 3); + + fprintf('Tracking: Trial ID: %d, Pair ID: %d, Track ID: %d\n', ... + trial_id, pair_id, track_id); + + % Find matching results for this trial/pair + matching_idx = -1; + for j = 1:numel(matching_results) + if matching_results{j}.trial_id == trial_id && matching_results{j}.pair_id == pair_id + matching_idx = j; + break; + end + end + match_data = matching_results{matching_idx}; + + % Get appropriate mask and seed point based on track_id + if track_id == 1 + refmask = match_data.refmask_trial_matched; + initial_seed_point = match_data.initial_seed_point_set2; + else + refmask = match_data.refmask_trial_matched; + initial_seed_point = match_data.initial_seed_point_set2; + end + + % Compute tracking + success = compute_tracking(... + data_path, dic_path, subject_id, material, ... + sprintf('%03d', trial_id), pair_id, phase_id, ... + showvisu, idx_frame_start, idx_frame_end, frame_jump, ... + ref_trial_id, automatic_process, track_id, ... + refmask, initial_seed_point); + + tracking_results{i} = struct(... + 'trial_id', trial_id, ... + 'pair_id', pair_id, ... + 'track_id', track_id, ... + 'success', success); + end + + % Combine results + output = cell(num_combinations, 1); + for i = 1:num_combinations + trial_id = pairs_trials(i, 2); + pair_id = pairs_trials(i, 1); + + % Get tracking results for this trial/pair + track_success = true; + for j = 1:numel(tracking_results) + if tracking_results{j}.trial_id == trial_id && tracking_results{j}.pair_id == pair_id + track_success = track_success && tracking_results{j}.success; + end + end + + % Format output as before + output{i} = {sprintf('%03d', trial_id), ... + num2str(pair_id), ... + num2str(track_success)}; + end + fprintf('End of %s\n', mfilename); end diff --git a/src/lib_script/ncorr_dic_rewrited.m b/src/lib_script/ncorr_dic_rewrited.m index 5ec7f72..0c73504 100644 --- a/src/lib_script/ncorr_dic_rewrited.m +++ b/src/lib_script/ncorr_dic_rewrited.m @@ -32,15 +32,14 @@ else initial_seed = []; end -showGui = ~automatic_process; -handles = ncorr_abr(showGui,initial_seed); -% handles = ncorr; +% Use ncorr instead of ncorr_abr for parallel processing +handles = ncorr; handles.set_ref(cam_data_ref); handles.set_cur(Myarray2cell(cam_data_cur)); handles.set_roi_ref(mask); - +% Set DIC parameters handles.set_dic_parameters_manually( ... step_param.type, ... step_param.radius, ... diff --git a/xdic.m b/xdic.m index 5562528..3fe0ca8 100644 --- a/xdic.m +++ b/xdic.m @@ -15,9 +15,52 @@ disp('--------------------------------------'); disp('DIC analysis for the fingertip'); -% Add path +% Add paths addpath(genpath(pwd)); +% Add ncorr path and cd to it for initialization +ncorr_path = fullfile(pwd, 'toolbox', 'MultiDIC-master', 'lib_ext', 'ncorr_2D_matlab-master'); +addpath(ncorr_path); +current_dir = pwd; +cd(ncorr_path); + +% Ensure workers have access to the code +if ~isempty(gcp('nocreate')) + delete(gcp('nocreate')); +end +parpool('local'); + +% Attach all necessary files to the parallel pool +lib_files = {... + 'compute_initial_seed_points.m', ... + 'compute_matching.m', ... + 'compute_tracking.m', ... + 'dic_2d_analysis.m', ... + 'dic_3d_reconstruction.m', ... + 'dic_deformation_analysis.m', ... + 'stepD_2DDIC.m', ... + 'stepE_3DReconstruction.m', ... + 'stepF_Deformation.m' ... +}; + +for i = 1:length(lib_files) + lib_files{i} = fullfile(current_dir, 'src', 'lib', lib_files{i}); +end + +% Add ncorr files +ncorr_files = dir(fullfile(ncorr_path, '*.m')); +for i = 1:length(ncorr_files) + lib_files{end+1} = fullfile(ncorr_files(i).folder, ncorr_files(i).name); +end + +% Attach files and update path on workers +addAttachedFiles(gcp, lib_files); +parfevalOnAll(gcp, @(p) cd(p), 1, ncorr_path); +parfevalOnAll(gcp, @(p) addpath(p, genpath(p)), 1, ncorr_path); + +% Return to original directory +cd(current_dir); + % Load configurations global_param; dic_param;