Этот пример показывает, как захватывать и анализировать изображения объекта в движении.
Этот пример захватывает изображения маятника в движении. Маятник состоит из синего мяча, прикрепленного к нейлоновой строке. Данные изображения получаются, когда маятник качается. После захвата изображения обрабатываются, чтобы определить длину маятника.
Изображения получают с помощью Image Acquisition Toolbox™ и анализируют с помощью Image Processing Toolbox™.
Получите серию изображений для анализа.
% Access an image acquisition device. vid = videoinput('winvideo', 1, 'RGB24_352x288'); vid.Timeout = 12; % Configure object to capture every fifth frame. vid.FrameGrabInterval = 5; % Configure the number of frames to be logged. vid.FramesPerTrigger = 50; % Access the device's video source object selected for acquisition. src = getselectedsource(vid); % Configure the device to provide 30 frames per second. src.FrameRate = '30'; % Open a live preview window. Focus camera onto a moving pendulum. preview(vid); % Initiate the acquisition. start(vid); % Extract frames from memory. frames = getdata(vid); % Remove video input object from memory. delete(vid) clear vid % Display the first frame in the series. imshow( frames(:, :, :, 1) );
% Display all acquired images.
imaqmontage(frames);
Поскольку движение маятника ограничено верхней половиной ряда изображений. Создайте новую серию систем координат, которые содержат необходимую область.
Чтобы обрезать серию систем координат с помощью imcrop
, сначала выполните imcrop
на одной системе координат и хранить его выход. Затем создайте серию систем координат, имеющих размер предыдущего выхода.
% Determine the total number of frames acquired. nFrames = size(frames, 4); % Crop the first frame. roi = [50 16 222 68]; firstFrame = frames(:,:,:,1); frameRegion = imcrop(firstFrame, roi); % Create a storage for the modified image series. regions = repmat(uint8(0), [size(frameRegion) nFrames]); for count = 1:nFrames, regions(:,:,:,count) = imcrop(frames(:,:,:,count), roi); imshow(regions(:,:,:,count)); end
Поскольку маятник намного темнее фона, маятник может быть сегментирован в каждой системе координат путем преобразования системы координат в полутоновую, ее порогового значения и удаления фоновых структур.
% Initialize array to contain the segmented pendulum frames. segPend = false([size(frameRegion, 1) size(frameRegion, 2) nFrames]); centroids = zeros(nFrames, 2); structDisk = strel('disk', 3); for count = 1:nFrames, % Convert to grayscale. fr = regions(:,:,:,count); gfr = rgb2gray(fr); gfr = imcomplement(gfr); % Experimentally determine the threshold. bw = im2bw(gfr, .7); bw = imopen(bw, structDisk); bw = imclearborder(bw); segPend(:,:,count) = bw; imshow(bw); end
Форма сегментированного маятника в каждой системе координат не является серьезной проблемой, поскольку центр маятника является единственной характеристикой, необходимой для определения длины маятника.
% Calculate the pendulum centers. for count = 1:nFrames, property = regionprops(segPend(:, :, count), 'Centroid'); pendCenters(count,:) = property.Centroid; end % Display the pendulum centers and adjust the plot. figure; x = pendCenters(:, 1); y = pendCenters(:, 2); plot(x, y, 'm.'); axis ij; axis equal; hold on; xlabel('x'); ylabel('y'); title('Pendulum Centers');
Подгонкой окружности через центры маятника можно вычислить длину маятника. Переписать основное уравнение круга:
(x-xc) ^ 2 + (y-yc) ^ 2 = радиус ^ 2
где (xc, yc) - центр, с точки зрения параметров a, b и c:
x ^ 2 + y ^ 2 + a * x + b * y + c = 0
где:
a = -2 * xc
b = -2 * yc
c = xc ^ 2 + yc ^ 2 - радиус ^ 2.
Решая для параметров a, b и c с помощью метода наименьших квадратов, вышеописанное уравнение может быть переписано как:
a * x + b * y + c = - (x ^ 2 + y ^ 2)
который также может быть переписан как:
[а; b; c] * [x y 1] = -x ^ 2 - y ^ 2
Это уравнение можно решить в MATLAB ® с помощью оператора обратной косой черты (\).
% Solve the equation. abc = [x y ones(length(x),1)] \ [-(x.^2 + y.^2)]; a = abc(1); b = abc(2); c = abc(3); xc = -a/2; yc = -b/2; circleRadius = sqrt((xc^2 + yc^2) - c); % Circle radius is the length of the pendulum in pixels. pendulumLength = round(circleRadius)
pendulumLength = 253
% Superimpose results onto the pendulum centers circle_theta = pi/3:0.01:pi*2/3; x_fit = circleRadius*cos(circle_theta) + xc; y_fit = circleRadius*sin(circle_theta) + yc; plot(x_fit, y_fit, 'b-'); plot(xc, yc, 'bx', 'LineWidth', 2); plot([xc x(1)], [yc y(1)], 'b-'); titleStr = sprintf('Pendulum Length = %d pixels', pendulumLength); text(xc-110, yc+100, titleStr);