В этом примере показано, как выполнить сбор изображений из веб-камеры и последующую обработку данных параллельно.
В этом примере клиент 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));
The 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 минуты.
Можно использовать waitbar для отслеживания прогресса постобработки. Чтобы обновить панель ожидания после концов каждой операции постобработки, используйте 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
объект как входы. Для получения дополнительной информации о шумоподавлении изображений с помощью обесценивающей нейронной сети, смотрите Get Pretrained Image Denoising Network (Image Processing Toolbox).
function postProcess(frame,C,Q,frameNumber) grayFrame = im2double(rgb2gray(frame)); denoisedGrayFrame = denoiseImage(grayFrame,C.Value); denoisedGrayFrame = im2uint8(denoisedGrayFrame); send(Q,frameNumber,denoisedGrayFrame) end
afterAll
| afterEach
| parallel.pool.Constant
| parfeval
| VideoWriter
| FramesAcquiredFcn
(Image Acquisition Toolbox) | imaqfind
(Image Acquisition Toolbox) | videoinput
(Image Acquisition Toolbox) | denoiseImage
(Набор Image Processing Toolbox)