%% Acquire Images Using Parallel Workers
% This example shows how to use the Parallel Computing Toolbox™ together with the Image Acquisiton Toolbox™ to acquire and save images in a separate MATLAB® worker.
% Doing so allows you to perform other operations in the main MATLAB worker with minimal impact on the image acquisition. As a result, your image acquisition is more consistent and you can run more CPU-intensive operations in parallel on multicore CPUs.
%
%% Set Up Image Acquistion
% This example uses the parfeval function from the Parallel Computing Toolbox to asynchronously execute a specified function. You can run the specified function in the background of your main MATLAB worker without waiting for it to complete. For more information about this function, see parfeval.
% Create a function called captureVideo to execute on the parallel MATLAB worker. This function creates a new videoinput object and sets the FramesAcquiredFcn property. It then configures the frames to acquire and starts the acquisition. See the captureVideo function at the end of this example. You can modify captureVideo to fit your image acquisition needs and setup.
% The captureVideo function sets the FramesAcquiredFcn property to a handle to the saveImages callback function. The saveImages function saves acquired images to a folder in your current working directory. See the saveImages function at the end of this example.
% Before you start the image acquisition, create a folder called data, where the parallel worker saves your acquired images.

mkdir("data\")

%
%% Start Image Acquisition on Parallel Worker
% Create a parallel pool with one worker on your local machine using parpool.

parpool('local',1);

% Run the captureVideo function in your parallel worker using parfeval. Since captureVideo does not have any output, specify the number of output arguments as 0.

f = parfeval(@captureVideo,0)

% The output shows that the status of the parfeval future is running.
% If you want to block MATLAB until parfeval completes, you can use the wait function on the future f. Using the wait function is useful when subsequent code depends on the completion of parfeval.

wait(f);

% Display the parfeval future to confirm that its status is finished.

disp(f);

% Your images are acquired and saved to the data folder in your current working directory.
%
%% Shut Down Parallel Pool
% When you finish working with the parallel pool, clear the future and shut down the parallel pool.

clear f
delete(gcp("nocreate"))

%
%% Helper Functions
%% Function to Capture Video
% The parallel worker executes the captureVideo function. This function creates a videoinput object and sets the appropriate properties. You can modify it to fit your image acquisition needs.

function captureVideo()
    % Create videoinput object.
    v = videoinput('winvideo');
    
    % Specify a custom callback to save images.
    v.FramesAcquiredFcn = @saveImages;
    
    % Specify the number of frames to acquire before calling the callback.
    v.FramesAcquiredFcnCount = 60;
    
    % Specify the total number of frames to acquire.
    v.FramesPerTrigger = 120;
    
    % Start recording.
    start(v);
    
    % Wait for the acquision to finish.
    wait(v);
end

%% Callback Function to Save Images
% The captureVideo function sets the saveImages callback as the FramesAcquiredFcn for the videoinput object. This function reads the number of frames specified by the FramesAcquiredFcnCount from the buffer and saves them to the data folder. You can modify this callback to fit your needs.

function saveImages(src,obj)
    % Calculate the total frame number for each frame, 
    % in order to save the files in order.
    currframes = src.FramesAcquired - src.FramesAcquiredFcnCount;
    
    % Read images from the videoinput buffer.
    imgs = getdata(src,src.FramesAvailable);
    
    % Save each image to a file in order.
    for i = 1:src.FramesAcquiredFcnCount
        imname = "data\img_" + (currframes + i) + ".TIFF";
        imwrite(imgs(:,:,:,i),imname);
    end
end

% Copyright 2020 The MathWorks, Inc.