Receiving this error code when extracting centroid and plotting motion

조회 수: 4(최근 30일)
I keep getting this error when running my code:
Intermediate dot '.' indexing produced a comma-separated list with 2 values, but
it must produce a single value when followed by subsequent indexing operations.
Error in referencemotionplot (line 57)
xhand1(frameIndex) = props.Centroid(1);
This is the code I am running on 2021b MATLAB to plot the coordinates of my hand motion:
% Clear the command windowv1
close all; % Close all figures (except those of imtool.)
clear; % Erase all existing variables. Or clearvars if you want.
workspace; % Make sure the workspace panel is showing.
format long
format compact
fontSize = 14;
vidObj = VideoReader('v3.MOV');
numberOfFrames = 50;
for frameIndex = 1 : numberOfFrames
frame = read(vidObj, frameIndex);
subplot(2, 3, 1);
axis('on', 'image');
caption = sprintf('Original Image Frame %d of %d', frameIndex, numberOfFrames);
title(caption, 'fontSize', fontSize);
% Convert to gray scale
grayImage = rgb2gray(frame);
% Crop frame to get rid of white window to the right.
grayImage = grayImage(:, 1 : 500); % You need to determine the column
subplot(2, 3, 2);
axis('on', 'image');
caption = sprintf('Gray Scale Image Frame %d of %d', frameIndex, numberOfFrames);
title(caption, 'fontSize', fontSize);
% First find the white paddle.
% Threshold or call imbinarize()
hand = imbinarize(grayImage);
% Fill holes
hand = imfill(hand, 'holes');
% Take largest blob only. That's the white paddle
hand = bwareafilt(hand, 1);
% We need to shrink the paddle because the edges are less bright and they
% get detected when we try to get the dot. So let's explude edges.
se = strel('disk', 15, 0);
hand = imerode(hand, se);
subplot(2, 3, 3);
axis('on', 'image');
title('hand', 'fontSize', fontSize);
% Find centroid of white paddle.
props = regionprops(hand, 'Centroid');
% Skip it if the paddle can't be found, like it's too dark or something.
if isempty(props)
% Get x and y
xhand1(frameIndex) = props.Centroid(1);
yhand1(frameIndex) = props.Centroid(2);
% Now get the black dot.
thresholdValue = 0;
whiteBlobs = grayImage > thresholdValue;
% Erase junk outside the paddle
whiteBlobs = whiteBlobs & hand;
% Erase the axle.
whiteBlobs(104:157, 264:319) = false;
% Note, black dot might not be resolved enough to find it!
% Take blobs only if they're in the 2-50 pixel range.
% That should get us the black dot.
props = regionprops(whiteBlobs, 'Centroid', 'Area');
allAreas = [props.Area];
whiteBlobs = bwareafilt(whiteBlobs,1, "smallest");
% Sometimes there is noise, and we get 2 blobs, so just take the largest blob in that range.
whiteBlobs = bwareafilt(whiteBlobs, 1);
subplot(2, 3, 4);
axis('on', 'image');
title('Black Dot', 'fontSize', fontSize);
% Find centroid of black dot.
props = regionprops(whiteBlobs, 'Centroid', 'Area');
allAreas = [props.Area];
% Skip it if the dot can't be found, like it's too blurred or something.
if isempty(props)
fprintf('No dot found on frame #%d of %d.\n', frameIndex, numberOfFrames);
% Get x and y
xDot(frameIndex) = props.Centroid(1);
yDot(frameIndex) = props.Centroid(2);
subplot(2, 3, 5:6);
plot(xDot, yDot, 'r');
hold on;
grid off;
xlabel('x', 'fontSize', fontSize);
ylabel('y', 'fontSize', fontSize);
xlim([100 500])
ylim([1000 2000])
if frameIndex == 1
% Maximize the figure window.
g = gcf;
g.WindowState = 'maximized';
% Interpolate any missing ones.
missingIndexes = isnan(xDot);
if any(missingIndexes)
xFit = 1 : numberOfFrames;
xDot = interp1(find(~missingIndexes), xDot(~missingIndexes), xFit, 'spline');
yDot = interp1(find(~missingIndexes), yDot(~missingIndexes), xFit, 'spline');
subplot(2, 3, 5:6);
hold on;
grid on;
title('horizontal_plot1. X = Blue, y = red', 'fontSize', fontSize);
xlabel('Frame Number', 'fontSize', fontSize);
ylabel('Column or Row', 'fontSize', fontSize);
Here is the video I am using:
Does anyone know why I am getting this error?

채택된 답변

Image Analyst
Image Analyst 2023년 4월 1일
@Sara K Takiguchi this seems to work fine for finding one white paper on your hand.
% Demo to track green color. Finds and annotates centroid and bounding box of green blobs.
% Modify thresholds to detect different colors.
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
imtool close all; % Close all imtool figures if you have the Image Processing Toolbox.
clear; % Erase all existing variables. Or clearvars if you want.
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 20;
% Specify input video file name.
folder = pwd;
% fullFileName = 'rhinos.avi';
% fullFileName = 'traffic.avi';
baseFileName = 'hand.mp4';
fullFileName = fullfile(folder, baseFileName);
% Check if the video file actually exists in the current folder or on the search path.
if ~exist(fullFileName, 'file')
% File doesn't exist -- didn't find it there. Check the search path for it.
fullFileNameOnSearchPath = baseFileName; % No path this time.
if ~exist(fullFileNameOnSearchPath, 'file')
% Still didn't find it. Alert user.
errorMessage = sprintf('Error: %s does not exist in the search path folders.', fullFileName);
% Instantiate a video reader object for this video.
videoObject = VideoReader(fullFileName);
% Setup other parameters
numberOfFrames = videoObject.NumberOfFrame;
% Preallocate x and y centroids.
xCentroid = nan(numberOfFrames, 1);
yCentroid = nan(numberOfFrames, 1);
% Read one frame at a time, and find specified color.
for k = 1 : numberOfFrames
% Read one frame
hImage=subplot(2, 2, 1);
% Display it.
axis on;
caption = sprintf('Original RGB image, frame #%d of %d', k, numberOfFrames);
title(caption, 'FontSize', fontSize);
% Get the mask for this frame.
[mask,maskedRGBImage] = createMask(thisFrame);
% Get the largest blob only.
mask = bwareafilt(mask, 1);
subplot(2, 2, 2);
imshow(mask, []);
axis on;
title('Mask', 'FontSize', fontSize);
subplot(2, 2, 3);
if k == 1
% Enlarge figure to full screen.
set(gcf, 'Units', 'Normalized', 'OuterPosition', [0 0 1 1]);
% Give a name to the title bar.
set(gcf, 'Name', 'Demo by ImageAnalyst', 'NumberTitle', 'Off')
hCheckbox = uicontrol('Style','checkbox',...
'Units', 'Normalized',...
'String', 'Finish Now',...
'Value',0,'Position', [.02 .5 .4 .05], ...
'FontSize', 30, 'ForegroundColor', 'r');
[labeledImage, numberOfRegions] = bwlabel(mask);
if numberOfRegions >= 1
stats = regionprops(labeledImage, 'BoundingBox', 'Centroid');
% Delete old texts and rectangles
if exist('hRect', 'var')
if exist('hText', 'var')
% Display the original image again.
hImage=subplot(2, 2, 3);
axis on;
hold on;
caption = sprintf('%d blobs found in frame #%d of %d', numberOfRegions, k, numberOfFrames);
title(caption, 'FontSize', fontSize);
% This is a loop to bound the colored objects in a rectangular box.
for r = 1 : numberOfRegions
% Find location for this blob.
thisBB = stats(r).BoundingBox;
thisCentroid = stats(r).Centroid;
hRect(r) = rectangle('Position', thisBB, 'EdgeColor', 'r', 'LineWidth', 2);
hSpot = plot(thisCentroid(1), thisCentroid(2), 'y+', 'MarkerSize', 10, 'LineWidth', 2);
hText(r) = text(thisBB(1), thisBB(2)-20, strcat('X: ', num2str(round(thisCentroid(1))), ' Y: ', num2str(round(thisCentroid(2)))));
set(hText(r), 'FontName', 'Arial', 'FontWeight', 'bold', 'FontSize', 12, 'Color', 'yellow');
hold off
% Plot centroid in plot #4
subplot(2, 2, 4);
xCentroid(k) = stats(1).Centroid(1);
yCentroid(k) = stats(1).Centroid(2);
plot(xCentroid, yCentroid, 'b-', 'LineWidth', 2);
grid on;
title('Track of Centroid', 'FontSize',fontSize);
xlabel('X Centroid', 'FontSize',fontSize);
ylabel('Y Centroid', 'FontSize',fontSize);
axis ij; % Flip vertically
% See if they want to bail out
if get(hCheckbox, 'Value')
% Finish now checkbox is checked.
msgbox('Done with demo.');
msgbox('Done with demo.');
function [BW,maskedRGBImage] = createMask(RGB)
%createMask Threshold RGB image using auto-generated code from colorThresholder app.
% [BW,MASKEDRGBIMAGE] = createMask(RGB) thresholds image RGB using
% auto-generated code from the colorThresholder app. The colorspace and
% range for each channel of the colorspace were set within the app. The
% segmentation mask is returned in BW, and a composite of the mask and
% original RGB images is returned in maskedRGBImage.
% Auto-generated by colorThresholder app on 01-Apr-2023
% Convert RGB image to chosen color space
I = RGB;
% Define thresholds for channel 1 based on histogram settings
channel1Min = 231.000;
channel1Max = 255.000;
% Define thresholds for channel 2 based on histogram settings
channel2Min = 221.000;
channel2Max = 255.000;
% Define thresholds for channel 3 based on histogram settings
channel3Min = 189.000;
channel3Max = 255.000;
% Create mask based on chosen histogram thresholds
sliderBW = (I(:,:,1) >= channel1Min ) & (I(:,:,1) <= channel1Max) & ...
(I(:,:,2) >= channel2Min ) & (I(:,:,2) <= channel2Max) & ...
(I(:,:,3) >= channel3Min ) & (I(:,:,3) <= channel3Max);
BW = sliderBW;
% Initialize output masked image based on input image.
maskedRGBImage = RGB;
% Set background pixels where BW is false to zero.
maskedRGBImage(repmat(~BW,[1 1 3])) = 0;

추가 답변(2개)

Image Analyst
Image Analyst 2023년 3월 22일
Not having run the code, it looks like your binary image may have two blobs in it. Even though you used bwareafilt to get just one blob, you then eroded it which may have produced two or more blobs. If you're expecting just one blob, then you had better call bwareafilt again to get just one blob.
  댓글 수: 8
Sara K Takiguchi
Sara K Takiguchi 2023년 3월 31일
Hi, I ran your demo but I am not sure how to extract the coordinates of the two centroids for each frame so that I can plot its motion.

댓글을 달려면 로그인하십시오.

Sara K Takiguchi
Sara K Takiguchi 2023년 3월 24일
Thank you! I'll give it a try and let you know if it works.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by