% training program... reads RGB/YUV image data from a mat-file and extracts the colour information of
% a selectable region. Use in conjunction with capRGBnYUV()
% load testimages/testimages.mat
% load testimages/testimageYUYV.mat;
% rgb = uint8(convrt(double(YUYV)));
% load testimages/testimageYUYVrgb.mat;
% load testimages/testimageYUV.mat; % YUV, rgb
% load testimages/learnimageYUVRGB.mat; % YUV, rgb
load testimages/testimageYUYVRGB.mat; % YUYV, rgb
% open display and histogram window
trainFig = figure;
set(gcf, 'Position', [20 100 950 400]);
set(gcf, 'MenuBar', 'none');
set(gcf, 'Name', 'Object detection tool');
% display (empty) colour info histograms
subplot(3, 2, 2);
axis([0 255 0 1]);
ylabel('y');
subplot(3, 2, 4);
axis([0 255 0 1]);
ylabel('u');
subplot(3, 2, 6);
axis([0 255 0 1]);
ylabel('v');
% forever...
exitflag = 1;
while(exitflag)
% (re-)set loop control variable 'run' to active
run = 1;
% display original
subplot(3, 2, [1 3 5]);
image(rgb);
axis image xy;
% select object
title('Select object to be tracked...');
k = waitforbuttonpress;
point1 = get(gca,'CurrentPoint'); % button down detected
finalRect = rbbox; % return figure units
point2 = get(gca,'CurrentPoint'); % button up detected
point1 = floor(point1(1,1:2)); % extract x and y
point2 = floor(point2(1,1:2));
p1 = min(point1,point2); % calculate locations
offset = abs(point1-point2); % and dimensions
x = [p1(1) p1(1)+offset(1) p1(1)+offset(1) p1(1) p1(1)];
y = [p1(2) p1(2) p1(2)+offset(2) p1(2)+offset(2) p1(2)];
hold on
axis manual
plot(x,y) % redraw in dataspace units
% separate seletcted area (YUYV)
if(exist('yuyv'))
% get y, u, v indices
Yidx = 1:2:length(yuyv);
Uidx = 2:4:length(yuyv);
Vidx = 4:4:length(yuyv);
% turn YUYV into YUV
YY = yuyv(1:length(yuyv)/2, Yidx);
UU = zeros(size(YY));
UU(:, 1:2:length(UU)) = yuyv(1:length(yuyv)/2, Uidx);
UU(:, 2:2:length(UU)) = UU(:, 1:2:length(UU));
VV = zeros(size(YY));
VV(:, 1:2:length(VV)) = yuyv(1:length(yuyv)/2, Vidx);
VV(:, 2:2:length(VV)) = VV(:, 1:2:length(VV));
% create empty yuv object: (sizeX, sizeY, 3)
siX = max([x(2)-x(1), 1]); % rows
siY = max([y(3)-y(2), 1]); % columns
yuvObj = NaN*ones(siY, siX, 3);
% filter out Y, U, V component
for(cy = 1:siY)
for(cx = 1:siX)
% cy: row, cx: column
yuvObj(cy, cx, 1) = YY(y(1)+cy-1, x(1)+cx-1); % y
yuvObj(cy, cx, 2) = UU(y(1)+cy-1, x(1)+cx-1); % u
yuvObj(cy, cx, 3) = VV(y(1)+cy-1, x(1)+cx-1); % v
end
end
% yuv statistics of the seletcted object: min, max (???)
yMin = min(min(yuvObj(:,:,1)));
yMax = max(max(yuvObj(:,:,1)));
uMin = min(min(yuvObj(:,:,2)));
uMax = max(max(yuvObj(:,:,2)));
vMin = min(min(yuvObj(:,:,3)));
vMax = max(max(yuvObj(:,:,3)));
% yuv statistics of the selected object: mean +/- 1 STD
yAve = round(mean(mean(yuvObj(:,:,1))));
uAve = round(mean(mean(yuvObj(:,:,2))));
vAve = round(mean(mean(yuvObj(:,:,3))));
yStd = round(std(double(reshape(yuvObj(:,:,1),1,prod(size(yuvObj(:,:,1)))))));
uStd = round(std(double(reshape(yuvObj(:,:,2),1,prod(size(yuvObj(:,:,2)))))));
vStd = round(std(double(reshape(yuvObj(:,:,3),1,prod(size(yuvObj(:,:,3)))))));
numberSTD = 2;
yMin = max([yAve - numberSTD*yStd, yMin]);
yMax = min([yAve + numberSTD*yStd, yMax]);
uMin = max([uAve - numberSTD*uStd, uMin]);
uMax = min([uAve + numberSTD*uStd, uMax]);
vMin = max([vAve - numberSTD*vStd, vMin]);
vMax = min([vAve + numberSTD*vStd, vMax]);
% display colour info histograms
subplot(3, 2, 2);
hist(reshape(yuvObj(:,:,1),1, prod(size(yuvObj(:,:,1)))), 0:255);
ax = axis;
axis([0 255 0 ax(4)]);
hold on;
plot([max(1, yMin) min(254, yMax)], 0.5*[ax(4) ax(4)], 'r');
hold off;
ylabel('y');
subplot(3, 2, 4);
hist(reshape(yuvObj(:,:,2),1, prod(size(yuvObj(:,:,2)))), 0:255);
ax = axis;
axis([0 255 0 ax(4)]);
hold on;
plot([max(1, uMin) min(254, uMax)], 0.5*[ax(4) ax(4)], 'r');
hold off;
ylabel('u');
subplot(3, 2, 6);
hist(reshape(yuvObj(:,:,3),1, prod(size(yuvObj(:,:,3)))), 0:255);
ax = axis;
axis([0 255 0 ax(4)]);
hold on;
plot([max(1, vMin) min(254, vMax)], 0.5*[ax(4) ax(4)], 'r');
hold off;
ylabel('v');
drawnow;
% create filtered output... turn YUYV to YUV first, then select matching object pixels
YY = yuyv(1:length(yuyv)/2, Yidx);
UU = zeros(size(YY));
UU(:, 1:2:length(UU)) = yuyv(1:length(yuyv)/2, Uidx);
UU(:, 2:2:length(UU)) = UU(:, 1:2:length(UU));
VV = zeros(size(YY));
VV(:, 1:2:length(VV)) = yuyv(1:length(yuyv)/2, Vidx);
VV(:, 2:2:length(VV)) = VV(:, 1:2:length(VV));
[obj_r, obj_c] = find(YY >= yMin & YY <= yMax & ...
UU >= uMin & UU <= uMax & ...
VV >= vMin & VV <= vMax);
else
% separate selected area (RGB)
rgbObj = rgb(y(2):y(3), x(1):x(2), :); % (row, column, colour)
% % rgb statistics of the seletcted object: min, max (???)
% rMin = min(min(rgbObj(:,:,1)));
% rMax = max(max(rgbObj(:,:,1)));
% gMin = min(min(rgbObj(:,:,2)));
% gMax = max(max(rgbObj(:,:,2)));
% bMin = min(min(rgbObj(:,:,3)));
% bMax = max(max(rgbObj(:,:,3)));
% rgb statistics of the selected object: mean +/- 1 STD
rAve = round(mean(mean(rgbObj(:,:,1))));
gAve = round(mean(mean(rgbObj(:,:,2))));
bAve = round(mean(mean(rgbObj(:,:,3))));
rStd = round(std(double(reshape(rgbObj(:,:,1),1,prod(size(rgbObj(:,:,1)))))));
gStd = round(std(double(reshape(rgbObj(:,:,2),1,prod(size(rgbObj(:,:,2)))))));
bStd = round(std(double(reshape(rgbObj(:,:,3),1,prod(size(rgbObj(:,:,3)))))));
rMin = rAve - 2*rStd;
rMax = rAve + 2*rStd;
gMin = gAve - 2*gStd;
gMax = gAve + 2*gStd;
bMin = bAve - 2*bStd;
bMax = bAve + 2*bStd;
% create filtered output
[obj_r,obj_c] = find(rgb(:,:,1)>=rMin & rgb(:,:,1)<=rMax & ...
rgb(:,:,2)>=gMin & rgb(:,:,2)<=gMax & ...
rgb(:,:,3)>=bMin & rgb(:,:,3)<=bMax);
end
% re-display RGB image indicating selected colour
rgbFILT = rgb;
% % redisplay original image with selected colour changed to black
% for(i = 1:length(obj_r))
% rgbFILT(obj_r(i),obj_c(i),:) = uint8(0);
% end
% % redisplay original image with selected colours changed to the complement of the average
% for(i = 1:length(obj_r))
% %rgbFILT(obj_r(i),obj_c(i),:) = [255 255 255] - [rAve gAve bAve];
% end
% split vector into even and odd elements... (shaded display)
idx = 1:length(obj_r);
oddx = find(mod(idx,2));
evex = setdiff(idx, oddx);
% redisplay original image with selected colours replaced by shades of black and white
for(i = 1:length(evex))
rgbFILT(obj_r(evex(i)),obj_c(evex(i)),:) = uint8(255);
end
% redisplay original image without selected colours
for(i = 1:length(oddx))
rgbFILT(obj_r(oddx(i)),obj_c(oddx(i)),:) = uint8(0);
end
subplot(3, 2, [1 3 5], 'replace');
image(rgbFILT);
axis image xy;
title('Current choice covers areas in black');
% display selected colour ranges (thresholds)
disp('-------------------------------------------------------------------')
if(exist('yuyv'))
disp('(Ymin:Ymax, Umin:Umax, Vmin:Vmax)');
disp(['(' num2str(double(yMin)) ':' num2str(double(yMax)) ...
', ' num2str(double(uMin)) ':' num2str(double(uMax)) ...
', ' num2str(double(vMin)) ':' num2str(double(vMax)) ')']);
else
disp(['<R>GB range: ' num2str(double(rMin)) '...' num2str(double(rMax))]);
disp(['R<G>B range: ' num2str(double(gMin)) '...' num2str(double(gMax))]);
disp(['RG<B> range: ' num2str(double(bMin)) '...' num2str(double(bMax))]);
disp(' ');
disp(['RGB average: [' num2str(double(rAve)) ' ' num2str(double(gAve)) ' ' num2str(double(bAve)) ']']);
end
disp('-------------------------------------------------------------------')
% push button to continue with data acquisition...
h1 = uicontrol('Style', 'pushbutton', 'String', 'CONTINUE',...
'Position', [20 170 70 40], 'Callback', 'run=0;');
% push button to continue with data acquisition...
h2 = uicontrol('Style', 'pushbutton', 'String', 'EXIT',...
'Position', [20 230 70 40], 'Callback', 'exitflag=0;');
while(run & exitflag)
title('Selected object');
drawnow;
end
% remove push buttons
delete(h1);
delete(h2);
end
% close figure
close(gcf);