How to detect red objects from a video and also find its centroid. I have written code for it but i am getting error

10 views (last 30 days)
sampling_factor = 1;
resizing_params = [500 500];
%%// Input video
xyloObj = VideoReader('myVideo.avi');
%%// Setup other parameters
nFrames = floor(xyloObj.NumberOfFrame/sampling_factor); %%// xyloObj.NumberOfFrames;
vidHeight = resizing_params(1); %// xyloObj.Height;
vidWidth = resizing_params(1); %// xyloObj.Width;
%// Preallocate movie structure.
mov(1:nFrames) = struct('cdata', zeros(vidHeight, vidWidth, 3, 'uint8'),'colormap',[]);
%// Read one frame at a time.
for k = 1 :nFrames
IMG = read(xyloObj, (k-1)*sampling_factor+1);
%// IMG = some_operation(IMG);
mov(k).cdata = imresize(IMG,[vidHeight vidWidth]);
%// Size a figure based on the video's width and height.
hf = figure;
set(hf, 'position', [150 150 vidWidth vidHeight])
%// Play back the movie once at the video's frame rate.
%movie(hf, mov, 1, xyloObj.FrameRate);
while i=1:nFrames
im_in = frame2im(i);
diff_im = imsubtract(im_in(:,:,1), rgb2gray(im_in));
diff_im = medfilt2(diff_im, [3 3]);
diff_im = im2bw(diff_im,0.18);
diff_im = bwareaopen(diff_im,300);
bw = bwlabel(diff_im, 8);
stats = regionprops(bw, 'BoundingBox', 'Centroid');
hold on
%This is a loop to bound the red objects in a rectangular box.
for im_in = 1:length(stats)
bb = stats(im_in).BoundingBox;
bc = stats(im_in).Centroid;
plot(bc(1),bc(2), '-m+')
a=text(bc(1)+15,bc(2), strcat('X: ', num2str(round(bc(1))), ' Y: ', num2str(round(bc(2)))));
set(a, 'FontName', 'Arial', 'FontWeight', 'bold', 'FontSize', 12, 'Color', 'yellow');
im_out = double(im_outs);
hold off
% Both the loops end here.
frm = im2frame(im_outs);
aviobj = addframe(aviobj,frm);
aviobj = close(aviobj);

Accepted Answer

Image Analyst
Image Analyst on 6 Oct 2014
You didn't say what your error is, but I'll just assume that it's not finding the red things. It's easy to understand why when you look at your code. You convert the image to gray scale and subtract it from the red channel, and you assume that it will find pixels where the red signal is higher than the blue or green signal. The problem is that the grayscale image is not the unweighted average of the red, green, and blue channels. The green channel is weighted higher, for reasons that go beyond what I can explain here. So it's possible that you can have something with a red signal that's higher than the green or blue signal but not higher than the gray scale image, and thus does not get detected by your thresholding operation.
So, how to fix? Look at my hsv color segmentation demo. You can convert your RGB image into hsv and find where the hue channel is red, which will be where the h values are more than around 0.9 or less than about 0.1. You might have to adjust those threshold numbers to narrow in on the exact shades (hues) of red that you want. You can also require that the saturation values be more than .3 or .5 or so to make sure you get a vivid red and not some very faded pastel pink.
You can take my demo, substitute your image, and play around with the HSV thresholds to get it segment out the reds that you're dealing with.
Hope that helps.
Image Analyst
Image Analyst on 14 Oct 2014
You have not posted your code so I don't know what you're doing. All I know is that my code worked. Maybe just keep tract of xcentroids and y centroids and plot them
xCentroid(frameNumber) = thisCentroid(1);
yCentroid(frameNumber) = thisCentroid(2);
plot(1:frameNumber, xCentroid, 'bs-');
hold on;
plot(1:frameNumber, yCentroid, 'rd-');
If you post again, attach your m-file so I don't have to guess at what you're doing.

Sign in to comment.

More Answers (1)

Bruno Pop-Stefanov
Bruno Pop-Stefanov on 6 Oct 2014
I would recommend to do some color thresholding to isolate the red objects. Image Processing Toolbox has a useful Color Thresholder app that you can use to easily generate code to do color thresholding. For example, you could extract one frame from the video and open it in Color Thresholder, set the parameters the way you want in order to isolate the red objects using an appropriate color space, and then generate M code that you can use on all frames of the video.
You can read more about Color Thresholder here:
Once you have a black and white mask representing the red objects, it's easy to find the centroids of the objects using the regionprops function as you are already doing in the code.
As for the error that you are getting: can you copy and paste the entire error message?
I can't run your code because I don't have the appropriate data to run it. Having the exact error message could help us figure out what is going wrong.

Community Treasure Hunt

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

Start Hunting!