I'm working on hand detection and tracking. the problem is i have developed the code(shown below) for detecting hand in an image and its works(shown in image) but the problem is this that when i use a recorded video to run the same code no hand is detected or even tracked(shown in image).
the code for the video is
filename = 'hand_2.wmv';
video = vision.VideoFileReader(filename);
player = vision.DeployableVideoPlayer('Location', [10,100],'FrameRate',60);
while ~isDone(video)
img_orig = step(video);
% Capture the dimensions
height = size(img_orig,1);
width = size(img_orig,2);
%Initialize the output images
out = img_orig;
bin = zeros(height,width);
%Convert the image from RGB to YCbCr
img_uint8 = uint8(img_orig);
img_ycbcr = rgb2ycbcr(img_uint8);
Cb = img_ycbcr(:,:,2);
Cr = img_ycbcr(:,:,3);
%Detect Skin
[r,c,v] = find(Cb>=67 & Cb<=137 & Cr>=133 & Cr<=173);
numind = size(r,1);
%Mark Skin Pixels
for i=1:numind
out(r(i),c(i),:) = [0 0 255];
bin(r(i),c(i)) = 1;
end
% Detect radius
[x1,y1] = find(out(:,:,3) == 255, 1,'first');
[x2,y2] = find(out(:,:,3) == 255, 1, 'last');
if isempty(y1) && isempty(y2)
y1 = 2; y2 = 0;
end
% Detect Hand Center
hits = 0;
hitsArr = zeros(1,height);
for i = 1:height
hits = numel(find(bin(i,:) == 1));
hitsArr(i) = hits;
end
maxHitr = max(hitsArr);
y = find(hitsArr == maxHitr,1,'first');
hitsArr = zeros(1,width);
for i = 1:width
hits = numel(find(bin(:,i) == 1));
hitsArr(i) = hits;
end
maxHitc = max(hitsArr);
x = find(hitsArr == maxHitc,1,'first');
label = 'Hand';
position = [x y abs(y2-y1)/2; x y 1];
img_out = insertObjectAnnotation(img_orig,'Circle',position,label);
step(player, img_out);
end
release(video);
release(player);
and for detecting a single image the code is:
%Read the image, and capture the dimensions
tic;
img_orig = imread('65.png');
height = size(img_orig,1);
width = size(img_orig,2);
%Initialize the output images
out = img_orig;
bin = zeros(height,width);
%Convert the image from RGB to YCbCr
img_ycbcr = rgb2ycbcr(img_orig);
Cb = img_ycbcr(:,:,2);
Cr = img_ycbcr(:,:,3);
%Detect Skin
[r,c,v] = find(Cb>=67 & Cb<=137 & Cr>=133 & Cr<=173);
numind = size(r,1);
numcol = size(r,2);
%Mark Skin Pixels
for i=1:numind
out(r(i),c(i),:) = [0 0 255];
bin(r(i),c(i)) = 1;
end
% Detect radius
[x1,y1] = find(out(:,:,3) == 255, 1,'first');
[x2,y2] = find(out(:,:,3) == 255, 1, 'last');
% Detect Hand Center
hits = 0;
hitsArr = zeros(1,height);
for i = 1:height
hits = numel(find(bin(i,:) == 1));
hitsArr(i) = hits;
end
maxHitr = max(hitsArr);
y = find(hitsArr == maxHitr,1,'first');
hitsArr = zeros(1,width);
for i = 1:width
hits = numel(find(bin(:,i) == 1));
hitsArr(i) = hits;
end
maxHitc = max(hitsArr);
x = find(hitsArr == maxHitc,1,'first');
label = 'Hand';
position = [x y abs(y2-y1)/2; x y 1];
img_out = insertObjectAnnotation(img_orig,'Circle',position,label);
imshow(img_orig);
figure; imshow(img_out);title('Detected hand');
imwrite(img_out,'hand_detect.jpg');
% viscircles([x y],abs(y2-y1)/2,'EdgeColor','r');
% viscircles([x y],1,'EdgeColor','r');
% figure; imshow(out);
figure; imshow(bin);
toc;
I first thought that it was because the frame rate of the video but changing it doesn't help either. and as said above when i run the video to do the detection and tracking the code fails. Any help will be appreciated.
This is happening because when you read an image from a png file you get a uint8
image with pixels values between 0 and 255. On the other hand, vision.VideoFileReader
gives you an image of class single
with pixel values normalized to be between 0 and 1. You can fix this by setting 'VideoOutputDataType' to 'uint8':
video = vision.VideoFileReader(filename, 'VideoOutputDataType', 'uint8');
On a different topic, if you want to track the hand you may want to try using vision.HistogramBasedTracker
or vision.PointTracker
.