Этот пример показывает вам, как вычислить длину маятника в движении. Можно получить изображения во временных рядах с Image Acquisition Toolbox™ и анализировать их с Image Processing Toolbox™.
Загрузите фреймы изображения маятника в движении. Кадры в MAT-файле pendulum.mat
были получены с помощью следующих функций в Image Acquisition Toolbox.
% Access an image acquisition device (video object). % vidimage=videoinput('winvideo',1,'RGB24_352x288'); % Configure object to capture every fifth frame. % vidimage.FrameGrabInterval = 5; % Configure the number of frames to be logged. % nFrames=50; % vidimage.FramesPerTrigger = nFrames; % Access the device's video source. % src=getselectedsource(vidimage); % Configure device to provide thirty frames per second. % src.FrameRate = 30; % Open a live preview window. Focus camera onto a moving pendulum. % preview(vidimage); % Initiate the acquisition. % start(vidimage); % Wait for data logging to finish before retrieving the data. % wait(vidimage, 10); % Extract frames from memory. % frames = getdata(vidimage); % Clean up. Delete and clear associated variables. % delete(vidimage) % clear vidimage % load MAT-file load pendulum;
Запустите следующую команду, чтобы исследовать последовательность изображений в implay
.
implay(frames);
Вы видите, что маятник качается в верхней половине каждого кадра в ряду изображений. Создайте новую серию кадров, которая содержит только область, где маятник качается.
Чтобы обрезать серию кадров с помощью imcrop
, сначала выполните imcrop
на одном кадре и сохраните его выходное изображение. Затем используйте размер предыдущего вывода, чтобы создать серию областей кадра. Для удобства используйте rect
, который загрузился pendulum.mat
в imcrop
.
nFrames = size(frames,4); first_frame = frames(:,:,:,1); first_region = imcrop(first_frame,rect); frame_regions = repmat(uint8(0), [size(first_region) nFrames]); for count = 1:nFrames frame_regions(:,:,:,count) = imcrop(frames(:,:,:,count),rect); end imshow(frames(:,:,:,1))
Заметьте, что маятник является намного более темным, чем фон. Можно сегментировать маятник в каждом кадре путем преобразования кадра в шкалу полутонов, пороговая обработка это с помощью imbinarize
, и удалив фоновые структуры с помощью imopen
и imclearborder
.
инициализируйте массив, чтобы содержать сегментированные кадры маятника.
seg_pend = false([size(first_region,1) size(first_region,2) nFrames]); centroids = zeros(nFrames,2); se_disk = strel('disk',3); for count = 1:nFrames fr = frame_regions(:,:,:,count); gfr = rgb2gray(fr); gfr = imcomplement(gfr); bw = imbinarize(gfr,.7); % threshold is determined experimentally bw = imopen(bw,se_disk); bw = imclearborder(bw); seg_pend(:,:,count) = bw; montage({fr,labeloverlay(gfr,bw)}); pause(0.2) end
Вы видите, что форма маятника отличалась по различным кадрам. Это не серьезная проблема, потому что вам только нужен ее центр. Вы будете использовать центры маятника, чтобы найти длину маятника.
Используйте regionprops
, чтобы вычислить центр маятника.
pend_centers = zeros(nFrames,2); for count = 1:nFrames property = regionprops(seg_pend(:,:,count), 'Centroid'); pend_centers(count,:) = property.Centroid; end
Отобразите центры маятника с помощью plot
.
x = pend_centers(:,1); y = pend_centers(:,2); figure plot(x,y,'m.') axis ij axis equal hold on; xlabel('x'); ylabel('y'); title('Pendulum Centers');
Перепишите основное уравнение круга:
(x-xc)^2 + (y-yc)^2 = radius^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 - radius^2
.
Можно решить для параметров a
, b
и c
с помощью метода наименьших квадратов. Перепишите вышеупомянутое уравнение как
a*x + b*y + c = -(x^2 + y^2)
который может также быть переписан как
[x y 1] * [a;b;c] = -x^2 - y^2
.
Решите это уравнение с помощью наклонной черты влево (\
) оператор.
Круговой радиус является длиной маятника в пикселях.
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; circle_radius = sqrt((xc^2 + yc^2) - c); pendulum_length = round(circle_radius)
pendulum_length = 253
Круг наложения и центр круга на графике центров маятника.
circle_theta = pi/3:0.01:pi*2/3; x_fit = circle_radius*cos(circle_theta)+xc; y_fit = circle_radius*sin(circle_theta)+yc; plot(x_fit,y_fit,'b-'); plot(xc,yc,'bx','LineWidth',2); plot([xc x(1)],[yc y(1)],'b-'); text(xc-110,yc+100,sprintf('Pendulum length = %d pixels', pendulum_length));
imbinarize
| imclearborder
| imcomplement
| imopen
| labeloverlay
| regionprops