exponenta event banner

Выполнение сбора изображений и параллельной обработки изображений

В этом примере показано, как параллельно выполнять сбор изображений с веб-камеры и постобработку данных.

В этом примере клиент MATLAB получает кадры от видеоустройства и затем выгружает постобработку параллельным рабочим, которые отфильтровывают шум от каждого кадра, используя помехоустойчивую нейронную сеть. Кадры затем записываются в видео.

В этом примере используется parfeval для выполнения постобработки в работниках и parallel.pool.Constant для создания экземпляра запрещающей сети в работниках, которая будет использоваться во время постобработки. Чтобы отправить кадры обратно от работников и убедиться, что они написаны по порядку, в этом примере используется OrderedDataQueue объект.

Извлечение информации об устройстве и настройка видеовыхода

Очистить предыдущие объекты получения изображения и извлечь информацию о видеоустройстве, подключенном в данный момент к машине.

objects = imaqfind;
delete(objects);
imaqreset;
deviceInfo = imaqhwinfo('winvideo')
deviceInfo = struct with fields:
       AdaptorDllName: 'adaptor.dll'
    AdaptorDllVersion: '6.1 (R2019b)'
          AdaptorName: 'winvideo'
            DeviceIDs: {[1]}
           DeviceInfo: [1×1 struct]

Проверьте, существует ли папка для выходного видео в текущем каталоге. Если папка для вывода видео не существует, создайте ее.

if ~isfolder('OutputFolder')
    mkdir OutputFolder
end 

Чтобы записать видеоданные в AVI-файл в папке вывода, создайте VideoWriter объект.

videoOut = VideoWriter('OutputFolder/myVideo.avi');

Настройка параллельной среды

Чтобы разрешить разгрузку постобработки для работников, сначала запустите параллельный пул.

p = parpool('local');
Starting parallel pool (parpool) using the 'local' profile ...
Connected to the parallel pool (number of workers: 6).

Создать parallel.pool.Constant объект для создания помехоустойчивой сети только один раз в рабочих и использовать ее для фильтрации шума из кадров.

C = parallel.pool.Constant(@() denoisingNetwork('dncnn'));

Чтобы отправить постобработанные кадры обратно от работников и написать их в порядке, используйте OrderedDataQueue. Установка обратного вызова для записи кадров на диск с помощью afterEach.

Q = OrderedDataQueue;
afterEach(Q,@(frame) writeVideo(videoOut,frame));

OrderedDataQueue В этом примере объект определен в файле поддержки. Если вы хотите использовать его в собственном коде, скопируйте и поместите его вместе с остальными файлами.

Настройка объекта ввода видео

Создание объекта ввода видео. Установка объекта для выполнения сбора данных в клиентском кадре по кадрам.

videoIn = videoinput('winvideo',1,'YUY2_800x600')
Summary of Video Input Object Using 'Microsoft® LifeCam Cinema(TM)'.

   Acquisition Source(s):  input1 is available.

  Acquisition Parameters:  'input1' is the current selected source.
                           10 frames per trigger using the selected source.
                           'YUY2_800x600' video data to be logged upon START.
                           Grabbing first of every 1 frame(s).
                           Log data to 'memory' on trigger.

      Trigger Parameters:  1 'immediate' trigger(s) on START.

                  Status:  Waiting for START.
                           0 frames acquired since starting.
                           0 frames available for GETDATA.
videoIn.ReturnedColorSpace = 'RGB';
videoIn.FramesPerTrigger = Inf;
videoIn.FramesAcquiredFcnCount = 1;

Установите частоту кадров записи видео на ту же, что и при считывании видео, и откройте объект вывода видео.

src = videoIn.Source;
videoOut.FrameRate = str2double(src.FrameRate);
open(videoOut);

Для запуска операций постобработки после получения каждого кадра определите FramesAcquiredFcn обратный вызов для объекта ввода видео и запуск сбора данных.

videoIn.FramesAcquiredFcn = {@postProcessAndWrite,C,Q};
start(videoIn);

Создание окна предварительного просмотра. Вы можете остановить видео, как только предварительный просмотр будет закрыт вручную с помощью waitfor на ручке фигуры hPreviewFig. Для этого примера остановите получение видео через 2 секунды.

hPreviewImg = preview(videoIn);
hPreviewFig = ancestor(hPreviewImg,'figure');
pause(2);
stop(videoIn);

Функция постобработки сохраняет будущую переменную в UserData свойства видеообъекта. Эта переменная представляет будущее выполнение операций записи видео. Чтобы закрыть устройство записи видео после записи всех данных в выходной файл, используйте afterAll на этой будущей переменной.

postProcessFutures = videoIn.UserData;
closeVideoFuture = afterAll(postProcessFutures,@() close(videoOut),0);

Постобработка в этом примере может занять несколько минут. В ОС Windows 10 процессор Intel ® Xeon ® W-2133 3,60 ГГц с 6 ядрами постобработка заняла 4 минут.

Для отслеживания хода постобработки можно использовать панель ожидания. Для обновления панели ожидания после завершения каждой операции постобработки используйте afterEach. Чтобы закрыть официоз после завершения всех операций, используйте afterAll. Дополнительные сведения см. в разделе Асинхронное обновление интерфейса пользователя с помощью afterEach и afterAll.

h = waitbar(0,'Postprocessing...');
updateWaitbarFuture = afterEach(postProcessFutures, ...
    @(~) waitbar(sum(strcmp('finished',{postProcessFutures.State}))/numel(postProcessFutures),h), 1);
afterAll(closeVideoFuture, @() close(h),0);

Блокировать выполнение в клиентском сеансе, пока запись не завершится ожиданием будущей переменной.

wait(closeVideoFuture);

По завершении удалите объект ввода видео.

delete(videoIn);

Визуализация результатов

После создания видеофайла можно визуализировать результаты.

Использовать VideoReader объект для чтения видеофайла.

vidObj = VideoReader('OutputFolder/MyVideo.avi');

Прочитайте некоторые кадры с помощью readFrame функция.

images = cell(1,5);
times = .4:.4:2;
for ii = 1:numel(times)
    vidObj.CurrentTime = times(ii);
    images{ii} = readFrame(vidObj);
end

Для визуализации кадров используйте montage функция.

montage(images,'Size',[1 5])

Определение вспомогательных функций

Определите основную подпрограмму постобработки, которая выполняется после каждого получения кадра. Эта функция postProcessAndWrite извлекает данные из объекта ввода видео и вызывает parfeval для запуска обличения кадра в параллельном работнике.

function postProcessAndWrite(videoIn,~,C,Q)
    [frame,~,metadata] = getdata(videoIn,1); 
    postProcessFuture = parfeval(@postProcess,0,frame,C,Q,metadata.FrameNumber);
    videoIn.UserData = [videoIn.UserData postProcessFuture];
end

Определите функцию постобработки для выполнения в работнике. Для этого примера, чтобы упростить вычисление, преобразуйте каждый кадр в серый, а затем обесценивайте его с помощью denoiseImage функция. Функция postProcess принимает кадр и запрещающий сетевой объект, сохраненный в Value области parallel.pool.Constant объект в качестве входных данных. Для получения дополнительной информации о денонсировании изображений с помощью денонсирующей нейронной сети см. раздел Получение предварительно обученной сети деноизирования изображений (инструментарий обработки изображений).

function postProcess(frame,C,Q,frameNumber)
    grayFrame = im2double(rgb2gray(frame));
    denoisedGrayFrame = denoiseImage(grayFrame,C.Value);
    denoisedGrayFrame = im2uint8(denoisedGrayFrame);
    send(Q,frameNumber,denoisedGrayFrame)
end

См. также

| | | | | (инструментарий для получения изображений) | (Панель инструментов для получения изображений) | (Панель инструментов для получения изображений) | (Панель инструментов обработки изображений)

Связанные примеры

Подробнее