Hardware components | ||||||
![]() |
| × | 1 | |||
| × | 1 | ||||
![]() |
| × | 1 |
The goal of this project was to make a goose like robot that quacks when it got close to a certain object. In order to achieve that end I used three devices: an orange pi zero, a web-camera, and a buzzer. The idea was that the orange pi zero would detect an object using its camera and OpenCV. The goose would then move towards a given object and stop/honk when it got close.
In order to do that I had the goose start by spinning in a circle. When the desired object, pink paper, was detected at the center of the frame, the spinning stops and a follow state is initiated. The follow state consisted of a given forward movement speed and a turn rate proportional to the difference of the horizontal components of the center of object on camera and the center of the frame. This is seen in the video below.
Since the paper had a vibrant color it was straightforward to both threshold HSV values for and for OpenCV to filter. This process is seen in the image below.
When the goose was fairly close to the object after approaching it, the goose entered the stop state. It then proceeded to softly honk via the buzzer. This buzzer made sound by changing the duration of a PWM signal. Again, seen the video below.
Similarly, the movement of the goose was done by two front wheels with their own PWN signals.
An summery of all the hardware is presented in the video below.
TI 28379D Launchpad Code
C/C++No preview (download only).
Image Thresholding Code
MATLABfunction ME461_ColorThreshold(image_name)
% ColorThreshold performs custom color thresholding on the image 'image_name'.
% Arguments: 'image_name', filename of the image to threshold
%
% The user can zoom in on a region, then add/remove pixels from the thresholding
% program. When you are satisfied, print the filter and the program will
% display the RGB or HSV statistics. You can also handtune filters using slider
% bars for RGB or HSV filters. The Hue filter can optionally be split for
% Hues that wraparound zero. The ROIs can be moved around as needed.
% My bitmaps came from a print screen % of an Image Graph in Code ComposerStudio.
% send suggestions/problems to abecker5@uiuc.edu
%
% NOTE: non GE423 students, switch rgb2hsvGE423 to the standard rgb2hsv
% Matlab function.
% TODO: 1.) use standard HSV
% 2.)allow function to be called with filter points.
% 3.) as soon as I move the mouse, the first image wobbles
if( nargin > 0)
Original_img = imread(image_name);
else
%%%%%%%%%%%%% YOU CAN EDIT THIS PART WITH A DEFAULT IMAGE NAME %%%%%%
%Original_img = imread('can2RGB.bmp'); %red pop can
Original_img = imread('ExampleRGB.bmp'); %orange & blue golf balls
%Original_img = imread('lena.bmp'); %famous image
%%%%%%%%%%%%% END EDIT %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
end
close all; format compact %my preferences
scrsz = get(0,'ScreenSize');
h1.fig = figure(1);
set(h1.fig,'Name','Original Image', 'Position',[10 scrsz(4)*.05 scrsz(3)*1/3 scrsz(4)*.9]);
set(h1.fig,'MenuBar','none'); %hide menu bars
subplot(2,1,1)
image(Original_img)
axis image
title('select your{\it region of interest} (ROI) by clicking twice','FontWeight','bold')
% Select corner points of a rectangular
% region by pointing and clicking the mouse twice
BOX = [];
% Select location of the rectangles 1st pt.
%set(gcf, 'Pointer', 'fullcross') was this
set(gcf, 'Pointer', 'cross')
waitforbuttonpress;
[h1.x0,h1.y0] = selectOnScreenPt();
% Select second point
set(gcf, 'Pointer', 'fleur')
set(gcf,'WindowButtonMotionFcn', @select_p0)
waitforbuttonpress;
set(gcf, 'Pointer', 'arrow')
set(gcf,'WindowButtonMotionFcn', '')
set(gcf,'WindowButtonDownFcn', @h1butdown)
title('Original Image')
% Index into the original image to create the new image
% by getting the x and y corner coordinates as integers
ROI = Original_img(floor(min(h1.y0,h1.y1)):ceil(max(h1.y0,h1.y1)), floor(min(h1.x0,h1.x1)):ceil(max(h1.x0,h1.x1)),:);
h2.numValidPX = 0;
% Display the subsetted image with appropriate axis ratio
% this image can be clicked on to add pixels to the thresholding list
h2.fig = figure(2); %start horz start vert width height
set(h2.fig,'Name','ROI', 'Position',[scrsz(3)*2/5 -30+scrsz(4)*.5 scrsz(3)*3/5 scrsz(4)*.5]);
set(h2.fig,'MenuBar','none');
image(ROI); axis image
title({'{\it left click} to select pixels, deselect with{\it right click}';'{\it drag} to select multiple pixels'},'FontWeight','bold')
Original_imgHSV = []; IsHSplit = 0; IsRGB = 1;%initialize variables for thresholding
h3 = initfig3();
set(0,'CurrentFigure',h1.fig); %now that the other 2 images are initialized, add thresholded image to fig1
th_imag_axis = subplot(2,1,2); select_thesh('', '');
figure(h2.fig);
% set(h2.fig, 'Pointer', 'fullcross') was this
set(h2.fig, 'Pointer', 'cross')
h2.ValidPX = zeros(numel(ROI)/3,2); h2.Patches = zeros(numel(ROI)/3,1); %variables to show selected pixels
set(h2.fig,'WindowButtonDownFcn', @h2buttondown);
set(h2.fig,'WindowButtonUpFcn', @h2buttonup);
set(h2.fig,'CloseRequestFcn', @threshCloseFig);
set(h3.fig,'CloseRequestFcn', @threshCloseFig);
%%% END OF PROGRAM
%%%%%%%%% Start of functions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function str = strThreshedVals( IsRGB, rHmin, rHmax, gSmin, gSmax, bVmin, bVmax, IsHsplit)
if IsRGB
str = ['R [',num2str(rHmin),':',num2str(rHmax),'], G [',num2str(gSmin),':',num2str(gSmax),'], B [',num2str(bVmin),':',num2str(bVmax),']'];
else
if IsHsplit
str = ['H [0:',num2str(rHmin),',',num2str(rHmax),':255]'];
else
str = ['H [',num2str(rHmin),':',num2str(rHmax),']'];
end
str = [str,', S [',num2str(gSmin),':',num2str(gSmax),'], V [',num2str(bVmin),':',num2str(bVmax),']'];
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [h3] = initfig3()
IsRGB = 1;
h3.boolHandTune = false;
h3.fig = figure(3); %start horz start vert width height
set(h3.fig,'Name','Range Values', 'Position',[scrsz(3)*2/5 40 scrsz(3)*3/5 scrsz(4)*.4]);
set(h3.fig,'MenuBar','none');
h3.rgbplot = subplot(1,3,1);
axis([0 4 0 255]);
xVals = [0.8,0.8,1.8,1.8,2.8,2.8];
yVals = [100,200,100,200,100,200];
for n=1:6
h3.h(n)=plot(xVals(n),yVals(n),'sk','LineWidth',2,'markerEdgecolor','k','markersize',8,'Marker','none','MarkerFaceColor',[.8 .8 .8]);
hold on
end
h3.R = plot(1*ones(size(0)),0,'.r', 'HitTest','off');
h3.G = plot(2*ones(size(0)),0,'.g', 'HitTest','off');
h3.B = plot(3*ones(size(0)),0,'.b', 'HitTest','off');
set(h3.R, 'Xdata', [], 'Ydata', []);
set(h3.G, 'Xdata', [], 'Ydata', []);
set(h3.B, 'Xdata', [], 'Ydata', []);
axis([0 4 0 255]);
set(gca,'XTick',[1,2,3]);
set(gca,'XTickLabel',{'R','G','B'});
title({'RGB values selected';' '});
h3.hsvplot = subplot(1,3,2);
set(h3.fig,'CurrentAxes',h3.hsvplot);
for n=1:6
h3.h(n+6)=plot(xVals(n),yVals(n),'sk','LineWidth',2,'markerEdgecolor','k','markersize',8,'Marker','none','MarkerFaceColor',[.8 .8 .8]);
hold on
end
h3.H = plot(1*ones(size(0)),0,'.m', 'HitTest','off');
h3.S = plot(2*ones(size(0)),0,'.c', 'HitTest','off');
h3.V = plot(3*ones(size(0)),0,'.k', 'HitTest','off');
set(h3.H,'Xdata', [], 'Ydata', []);
set(h3.S,'Xdata', [], 'Ydata', []);
set(h3.V,'Xdata', [], 'Ydata', []);
axis([0 4 0 255]);
set(gca,'XTick',[1,2,3]);
set(gca,'XTickLabel',{'H','S','V'});
title({'HSV values selected';'\itnote: there may be wraparounds'});
h3.buttonArea = init_RGBbut; %setup the buttons and their callbacks
set(gcf, 'WindowButtonDownFcn', {@select_thesh})
title({'Thresholding';' Options'});
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [rHmin, rHmax, gSmin, gSmax, bVmin, bVmax] = RangeValues(IsRGB, h2, IsHSplit)
R = zeros(h2.numValidPX,1);
G = zeros(h2.numValidPX,1);
B = zeros(h2.numValidPX,1);
H = zeros(h2.numValidPX,1);
S = zeros(h2.numValidPX,1);
V = zeros(h2.numValidPX,1);
for in = 1:h2.numValidPX
R(in) = (ROI(h2.ValidPX(in,2),h2.ValidPX(in,1),1));
G(in) = (ROI(h2.ValidPX(in,2),h2.ValidPX(in,1),2));
B(in) = (ROI(h2.ValidPX(in,2),h2.ValidPX(in,1),3));
% [H(in) S(in) V(in)] = rgb2hsv(R(in)/255,G(in)/255,B(in)/255); %Matlab rgb2hsv is different than on robots
% H(in)=255*H(in);S(in)=255*S(in);V(in)=255*V(in);
[H(in) S(in) V(in)] = rgb2hsvME461(R(in),G(in),B(in)); %Matlab rgb2hsv is different than on robots
end
if h2.numValidPX > 0
if(IsRGB)
rHmax = max(R);
rHmin = min(R);
gSmax = max(G);
gSmin = min(G);
bVmax = max(B);
bVmin = min(B);
else
rHmax = max(H);
rHmin = min(H);
gSmax = max(S);
gSmin = min(S);
bVmax = max(V);
bVmin = min(V);
if(IsHSplit)
H = sort(H); %arranges all hues from smallest to largest
bigSplit = 0; % we want the largest possible split
for splitpt = 1:255
ind1 = find(H <splitpt,1, 'last' );
ind2 = find(H>=splitpt,1, 'first');
if(~isempty(ind1))
bot = H(ind1);
else
bot = 0;
end
if(~isempty(ind2))
top = H(ind2);
else
top = 255;
end
if top-bot-1 > bigSplit
bigSplit = top-bot-1;
rHmax = top;
rHmin = bot;
end
end % end for
end %end if hsplit
end
else %end if Valid PX
rHmax = 0;
rHmin = 255;
gSmax = 0;
gSmin = 255;
bVmax = 0;
bVmin = 255;
end
try %update the figure 3 if it exists
set(h3.R,'Xdata', 1*ones(size(R)), 'Ydata', R);
set(h3.G,'Xdata', 2*ones(size(G)), 'Ydata', G);
set(h3.B,'Xdata', 3*ones(size(B)), 'Ydata', B);
set(h3.H,'Xdata', 1*ones(size(H)), 'Ydata', H);
set(h3.S,'Xdata', 2*ones(size(S)), 'Ydata', S);
set(h3.V,'Xdata', 3*ones(size(V)), 'Ydata', V);
if h3.boolHandTune
if IsRGB
rHmin = min( get(h3.h(1),'ydata'),get(h3.h(2),'ydata'));
rHmax = max( get(h3.h(1),'ydata'),get(h3.h(2),'ydata'));
gSmin = min( get(h3.h(3),'ydata'),get(h3.h(4),'ydata'));
gSmax = max( get(h3.h(3),'ydata'),get(h3.h(4),'ydata'));
bVmin = min( get(h3.h(5),'ydata'),get(h3.h(6),'ydata'));
bVmax = max( get(h3.h(5),'ydata'),get(h3.h(6),'ydata'));
else
rHmin = min( get(h3.h(7),'ydata'),get(h3.h(8),'ydata'));
rHmax = max( get(h3.h(7),'ydata'),get(h3.h(8),'ydata'));
gSmin = min( get(h3.h(9),'ydata'),get(h3.h(10),'ydata'));
gSmax = max( get(h3.h(9),'ydata'),get(h3.h(10),'ydata'));
bVmin = min( get(h3.h(11),'ydata'),get(h3.h(12),'ydata'));
bVmax = max( get(h3.h(11),'ydata'),get(h3.h(12),'ydata'));
end
end
catch
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%thresh takes a color filter and applies it to the given image
function thresh(Original_img, IsRGB, rHmin, rHmax, gSmin, gSmax, bVmin, bVmax, IsHSplit, figure_handle, axes_handle)
if(IsRGB)
Thresh_img = Original_img(:,:,1) >= rHmin & Original_img(:,:,1) <= rHmax ...
& Original_img(:,:,2) >= gSmin & Original_img(:,:,2) <= gSmax ...
& Original_img(:,:,3) >= bVmin & Original_img(:,:,3) <= bVmax;
threshed = cast(repmat(Thresh_img,[1,1,3]),'uint8').*Original_img; % threshold the original image
else
if ~exist('Original_imgHSV','var') || isempty(Original_imgHSV)
Original_imgHSV = Original_img;
for in = 1:numel(Original_img(:,1,1))
for ij = 1:numel(Original_img(1,:,1))
R = Original_img(in,ij,1);
G = Original_img(in,ij,2);
B = Original_img(in,ij,3);
% [H, S, V] = rgb2hsv(R/255,G/255,B/255);
% H=255*H;S=255*S;V=255*V;
[H, S, V] = rgb2hsvME461(R,G,B);
Original_imgHSV(in,ij,1) = H;
Original_imgHSV(in,ij,2) = S;
Original_imgHSV(in,ij,3) = V;
end
end
end
if IsHSplit
Thresh_img = (Original_imgHSV(:,:,1) <= rHmin | Original_imgHSV(:,:,1) >= rHmax) ...
& Original_imgHSV(:,:,2) >= gSmin & Original_imgHSV(:,:,2) <= gSmax ...
& Original_imgHSV(:,:,3) >= bVmin & Original_imgHSV(:,:,3) <= bVmax;
else
Thresh_img = Original_imgHSV(:,:,1) >= rHmin & Original_imgHSV(:,:,1) <= rHmax ...
& Original_imgHSV(:,:,2) >= gSmin & Original_imgHSV(:,:,2) <= gSmax ...
& Original_imgHSV(:,:,3) >= bVmin & Original_imgHSV(:,:,3) <= bVmax;
end
threshed = cast(repmat(Thresh_img,[1,1,3]),'uint8').*Original_imgHSV; % threshold the HSV image
end %IsRGB
currfig = get(0,'CurrentFigure'); %save the currently highlighted figure
if( nargin >= 11)
set(0,'CurrentFigure',figure_handle) %adjust the figure without setting it as selected
set(figure_handle,'CurrentAxes',axes_handle);
end
image(threshed)
axis image
threshedVals = strThreshedVals( IsRGB, rHmin, rHmax, gSmin, gSmax, bVmin, bVmax, IsHSplit);
title({strcat('Threshed Image, ',num2str(sum(sum(Thresh_img))), ' px detected');threshedVals});
set(0,'CurrentFigure',currfig);
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function[H S V] = rgb2hsvGE423(R,G,B)
red = (double(R)-16)*255/224;
green = (double(G)-16)*255/224;
blue = (min(double(B)*2,240)-16)*255/224;
minV = min(red,min(green,blue));
value = max(red,max(green,blue));
delta = value - minV;
if(value~=0)
sat = (delta*255) / value;% s
if (delta ~= 0)
if( red == value )
hue = 60*( green - blue ) / delta; % between yellow & magenta
elseif( green == value )
hue = 120 + 60*( blue - red ) / delta; % between cyan & yellow
else
hue = 240 + 60*( red - green ) / delta; % between magenta & cyan
end
if( hue < 0 )
hue = hue + 360;
end
else
hue = 0;
sat = 0;
end
else
% r = g = b = 0 // s = 0, v is undefined
sat = 0;
hue = 0;
end
H = max(min(floor(((hue*255)/360)),255),0);
S = max(min(floor(sat),255),0);
V = max(min(floor(value),255),0);
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function[H S V] = rgb2hsvME461(R,G,B)
red = double(R);
green = double(G);
blue = double(B);
minV = min(red,min(green,blue));
value = max(red,max(green,blue));
delta = value - minV;
if(value~=0)
sat = (delta*255) / value;% s
if (delta ~= 0)
if( red == value )
hue = 60*( green - blue ) / delta; % between yellow & magenta
elseif( green == value )
hue = 120 + 60*( blue - red ) / delta; % between cyan & yellow
else
hue = 240 + 60*( red - green ) / delta; % between magenta & cyan
end
if( hue < 0 )
hue = hue + 360;
end
else
hue = 0;
sat = 0;
end
else
% r = g = b = 0 // s = 0, v is undefined
sat = 0;
hue = 0;
end
H = max(min(floor(((hue*255)/360)),255),0);
S = max(min(floor(sat),255),0);
V = max(min(floor(value),255),0);
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function buttonArea = init_RGBbut(src, eventdata) %#ok<*INUSD>
IsRGB = 1;
IsHSplit = 0;
buttonArea.plot = subplot(1,3,3);
set(gca,'XTick',[]); %turn off ticks
set(gca,'YTick',[]);
buttonArea.butBkgOnC = [.5 .5 .5];
buttonArea.butBkgOffC = [.8 .8 .8];
butX = [0,1,1,0,0];
butY = [0,0,0.5,0.5,0];
buttonArea.butFontOffC = [.7 .7 .7];
buttonArea.butFontOnC = [0.0 0.0 0.0];
buttonArea.RGBbut = patch(butX,butY+0.5,buttonArea.butBkgOnC);
buttonArea.RGBtext = text(0.1,0.75,{'Using RGB'},'FontSize',14);
buttonArea.HSVbut = patch(butX,butY,buttonArea.butBkgOffC);
buttonArea.HSVtext = text(0.1,0.25,{'Use HSV'},'FontSize',14, 'Color',buttonArea.butFontOffC);
buttonArea.HSVSPLITbut = patch(butX,butY-0.5,buttonArea.butBkgOffC);
buttonArea.HSVSPLITtext = text(0.1,-0.25,{'Split H'},'FontSize',14, 'Color',buttonArea.butFontOffC);
buttonArea.HANDTUNEbut = patch(butX,butY-1,buttonArea.butBkgOffC);
buttonArea.HANDTUNEtext = text(0.1,-0.75,{'Hand Tune Limits'},'FontSize',10, 'Color',buttonArea.butFontOffC);
buttonArea.PRINTbut = patch(butX,butY-1.5,buttonArea.butBkgOffC);
buttonArea.PRINTtext = text(0.1,-1.25,{'Print Filter'},'FontSize',14, 'Color',buttonArea.butFontOffC);
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function[] = select_thesh(src, eventdata)
if (h3.buttonArea.plot == gca)
cp=get(gca,'CurrentPoint');
y0 = cp(1,2);
if(y0 >0.5)
IsRGB = 1;
set(h3.buttonArea.RGBbut,'FaceColor',h3.buttonArea.butBkgOnC );
set(h3.buttonArea.HSVbut,'FaceColor',h3.buttonArea.butBkgOffC );
set(h3.buttonArea.RGBtext,'String','Using RGB', 'Color',h3.buttonArea.butFontOnC);
set(h3.buttonArea.HSVtext,'String','Use HSV', 'Color',h3.buttonArea.butFontOffC);
elseif(y0 > 0)
IsRGB = 0;
set(h3.buttonArea.HSVbut,'FaceColor',h3.buttonArea.butBkgOnC );
set(h3.buttonArea.RGBbut,'FaceColor',h3.buttonArea.butBkgOffC );
set(h3.buttonArea.HSVtext,'String','Using HSV', 'Color',h3.buttonArea.butFontOnC);
set(h3.buttonArea.RGBtext,'String','Use RGB', 'Color',h3.buttonArea.butFontOffC);
elseif(y0 > -0.5)
IsHSplit = ~IsHSplit;
if(~IsHSplit)
set(h3.buttonArea.HSVSPLITbut,'FaceColor',h3.buttonArea.butBkgOffC);
set(h3.buttonArea.HSVSPLITtext,'Color',h3.buttonArea.butFontOffC);
else
set(h3.buttonArea.HSVSPLITbut,'FaceColor',h3.buttonArea.butBkgOnC);
set(h3.buttonArea.HSVSPLITtext,'Color',h3.buttonArea.butFontOnC);
end
elseif(y0 > -1)
if h3.boolHandTune
h3.boolHandTune = false;
set(h3.buttonArea.HANDTUNEbut,'FaceColor',h3.buttonArea.butBkgOffC);
set(h3.buttonArea.HANDTUNEtext,'Color',h3.buttonArea.butFontOffC);
else
h3.boolHandTune = true;
set(h3.buttonArea.HANDTUNEbut,'FaceColor',h3.buttonArea.butBkgOnC);
set(h3.buttonArea.HANDTUNEtext,'Color',h3.buttonArea.butFontOnC);
end
elseif(y0 >-1.5) %print the filter coefficients
set(h3.buttonArea.PRINTbut,'FaceColor',h3.buttonArea.butBkgOnC);
set(h3.buttonArea.PRINTtext,'Color',h3.buttonArea.butFontOnC);
[rHmin, rHmax, gSmin, gSmax, bVmin, bVmax] = RangeValues(IsRGB, h2, IsHSplit);
threshedStr = strThreshedVals( IsRGB, rHmin, rHmax, gSmin, gSmax, bVmin, bVmax, IsHSplit);
display(['Selected Threshold: ', threshedStr]);
pause(0.5)
set(h3.buttonArea.PRINTbut,'FaceColor',h3.buttonArea.butBkgOffC);
set(h3.buttonArea.PRINTtext,'Color',h3.buttonArea.butFontOffC);
end %button click
for icont=1:6
if( IsRGB && h3.boolHandTune )
set(h3.h(icont),'Marker','>')
else
set(h3.h(icont),'Marker','none')
end
end
for icont=7:12
if( ~IsRGB && h3.boolHandTune )
set(h3.h(icont),'Marker','>')
else
set(h3.h(icont),'Marker','none')
end
end
end
for icont = 1:12
if gco == h3.h(icont)
set(h3.h(icont),'MarkerFaceColor',h3.buttonArea.butBkgOnC );
set(h3.fig, 'WindowButtonMotionFcn', {@select_level, h3.h(icont)})
set(h3.fig,'WindowButtonDownFcn','')
set(h3.fig,'WindowButtonUpFcn', 'uiresume')
uiwait
set(h3.fig,'WindowButtonMotionFcn','')
set(h3.fig,'WindowButtonDownFcn',{@select_thesh})
set(h3.h(icont),'MarkerFaceColor',h3.buttonArea.butBkgOffC );
end
end
%update limits
[rHmin, rHmax, gSmin, gSmax, bVmin, bVmax] = RangeValues(IsRGB, h2, IsHSplit);
thresh(Original_img, IsRGB, rHmin, rHmax, gSmin, gSmax, bVmin, bVmax, IsHSplit, h1.fig, th_imag_axis)
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function[x,y] = selectOnScreenPt()
cp=get(gca,'CurrentPoint');
x=max(1,min(cp(1,1), size(Original_img,2)));
y=max(1,min(cp(1,2), size(Original_img,1)));
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function[] = select_p0(src, eventdata) % Interactively select first point
[h1.x1,h1.y1] = selectOnScreenPt();
draw_fig(h1.x0, h1.y0, h1.x1,h1.y1)
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function[] = h1butdown(src, eventdata) % Interactively select first point
if gco == BOX(1)
%BOX(2) = patch(x,y
[h1.xs,h1.ys] = selectOnScreenPt();
%display(num2str([xs,ys]))
set(gcf,'WindowButtonMotionFcn', {@movebox})
set(gcf,'WindowButtonUpFcn', {@h1butup})
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function[] = h1butup(src, eventdata)% Interactively select first point
set(gcf,'WindowButtonMotionFcn', '');
set(gcf,'WindowButtonUpFcn', '');
[h1.xf,h1.yf] = selectOnScreenPt();
dx =h1.xf-h1.xs;
dy =h1.yf-h1.ys;
x0n = min(h1.x0+dx, h1.x1+dx);
y0n = min(h1.y0+dy, h1.y1+dy);
x1n = max(h1.x0+dx, h1.x1+dx);
y1n = max(h1.y0+dy, h1.y1+dy);
if( x1n > size(Original_img,2) )
x1n = size(Original_img,2); x0n = size(Original_img,2) - (h1.x1-h1.x0);
end
if( x0n < 1)
x0n = 1; x1n = 1+(h1.x1-h1.x0);
end
if( y1n > size(Original_img,1) )
y1n = size(Original_img,1); y0n = size(Original_img,1) - (h1.y1-h1.y0);
end
if( y0n < 1)
y0n = 1; y1n = 1+(h1.y1-h1.y0);
end
h1.x0 = x0n; h1.x1 = x1n; h1.y0 = y0n; h1.y1 = y1n;
draw_fig(h1.x0, h1.y0, h1.x1,h1.y1)
ROI = Original_img(floor(min(h1.y0,h1.y1)):ceil(max(h1.y0,h1.y1)), floor(min(h1.x0,h1.x1)):ceil(max(h1.x0,h1.x1)),:);
currfig = get(0,'CurrentFigure'); %save the currently highlighted figure
set(0,'CurrentFigure',h2.fig)
for c=1:h2.numValidPX
delete(h2.Patches(c))
end
h2.numValidPX = 0;
image(ROI)
axis image
title({'{\it left click} to select pixels, deselect with{\it right click}';'{\it drag} to select multiple pixels'},'FontWeight','bold')
% learn about the hue wrapparound by making another plot
[rHmin, rHmax, gSmin, gSmax, bVmin, bVmax] = RangeValues(IsRGB, h2, IsHSplit);
% threshold original image using min and max values
thresh(Original_img, IsRGB, rHmin, rHmax, gSmin, gSmax, bVmin, bVmax, IsHSplit, h1.fig, th_imag_axis);
set(0,'CurrentFigure',currfig )
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function[] = movebox(src, eventdata)% % Ensure the box never leaves the region
[xf,yf] = selectOnScreenPt();
dx =xf-h1.xs;
dy =yf-h1.ys;
x0n = min(h1.x0+dx, h1.x1+dx);
y0n = min(h1.y0+dy, h1.y1+dy);
x1n = max(h1.x0+dx, h1.x1+dx);
y1n = max(h1.y0+dy, h1.y1+dy);
if( x1n > size(Original_img,2) )
x1n = size(Original_img,2); x0n = size(Original_img,2) - (h1.x1-h1.x0);
end
if( x0n < 1)
x0n = 1; x1n = 1+(h1.x1-h1.x0);
end
if( y1n > size(Original_img,1) )
y1n = size(Original_img,1); y0n = size(Original_img,1) - (h1.y1-h1.y0);
end
if( y0n < 1)
y0n = 1; y1n = 1+(h1.y1-h1.y0);
end
draw_fig(x0n, y0n, x1n,y1n)
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function[] = select_level(src, eventdata, pt)%#ok<INUSL>
cp=get(gca,'CurrentPoint'); %sets a color hand-tuned limit
y = cp(1,2);
x = cp(1,1);
if( x<-1 || x > 4 ||y<-40 || y>290 )
uiresume
end
y = max(min(255,round(y)),0);
set(pt,'ydata',y);
[rHmin, rHmax, gSmin, gSmax, bVmin, bVmax] = RangeValues(IsRGB, h2, IsHSplit);
thresh(Original_img, IsRGB, rHmin, rHmax, gSmin, gSmax, bVmin, bVmax, IsHSplit, h1.fig, th_imag_axis)
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function[] = h2buttondown(src, eventdata)
cp=get(gca,'CurrentPoint');
h2.x1 = round(cp(1,1));
h2.y1 = round(cp(1,2));
if strcmp(get(gcf,'selectiontype'), 'normal')
h2.but = 1;
elseif strcmp(get(gcf,'selectiontype'), 'alt')
h2.but = 3;
else
h2.but = [];
end
rbbox;
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function[] = threshCloseFig(src, eventdata)
% [rHmin, rHmax, gSmin, gSmax, bVmin, bVmax] = RangeValues(IsRGB, h2, IsHSplit);
% threshedStr = strThreshedVals( IsRGB, rHmin, rHmax, gSmin, gSmax, bVmin, bVmax, IsHSplit);
% display(['Selected Threshold: ', threshedStr]);
delete(get(0,'CurrentFigure'));
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function[] = h2buttonup(src, eventdata) % select/deselect pixels
set(gcf,'Pointer','watch'); drawnow expose
point2 = get(gca,'CurrentPoint'); % button up detected
%limit the points
h2.x1 = min(max(1, h2.x1), size(ROI,2));
h2.y1 = min(max(1, h2.y1), size(ROI,1));
x2 = min(max(1, round(point2(1,1))),size(ROI,2));
y2 = min(max(1, round(point2(1,2))),size(ROI,1));
xts = min(h2.x1,x2):max(h2.x1,x2);
yts = min(h2.y1,y2):max(h2.y1,y2);
for k = 1:numel(xts) %loop to step though all (de)selected pixels.
for j = 1:numel(yts)
xt = xts(k);
yt = yts(j);
newPixel = [xt,yt];
i = 1; %variable to step through ValidPX
foundpx = 0;
while foundpx == 0 && i <= h2.numValidPX %search to see if the pixel has already been selected
if h2.ValidPX(i,:) == round(newPixel);
foundpx = 1; %mark that we found it!
if(h2.but == 3) % remove this pixel
h2.numValidPX = h2.numValidPX -1;
delete(h2.Patches(i)) %remove the patch from plot window
if( i <= h2.numValidPX) %remove when not last item
h2.ValidPX(i:h2.numValidPX,:) = h2.ValidPX(i+1:h2.numValidPX+1,:);
h2.Patches(i:h2.numValidPX) = h2.Patches(i+1:h2.numValidPX+1);
end
end
end
i = i+1;
end %end while
if (foundpx == 0 && h2.but ==1) %add the patch to the screen
h2.numValidPX = h2.numValidPX +1;
h2.ValidPX(h2.numValidPX,:) = newPixel;
h2.Patches(h2.numValidPX)= patch([xt+0.5,xt+0.5,xt-0.5,xt-0.5],[yt+0.5,yt-0.5,yt-0.5,yt+0.5],'r');
end
end %column loop
end %row loop
%set(gcf,'Pointer','fullcross'); was this
set(gcf,'Pointer','cross');
% learn about the hue wrapparound by making another plot
[rHmin, rHmax, gSmin, gSmax, bVmin, bVmax] = RangeValues(IsRGB, h2, IsHSplit);
% threshold original image using min and max values
thresh(Original_img, IsRGB, rHmin, rHmax, gSmin, gSmax, bVmin, bVmax, IsHSplit, h1.fig, th_imag_axis);
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function[] = draw_fig(x0, y0, x1,y1) % Draws a rectangle patch
x=[x0,x1,x1,x0,x0];
y=[y0,y0,y1,y1,y0];
if isempty(BOX) % New patch
BOX(1) = patch(x,y,'k','edgecolor','k','LineStyle','-','facealpha',0,'LineWidth',2);
BOX(2) = patch(x,y,'k','edgecolor','w','LineStyle',':','facealpha',0,'HitTest','off','LineWidth',2);
else % Modify patch
set(BOX(1),'xdata',x,'ydata',y);
set(BOX(2),'xdata',x,'ydata',y);
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
end %end function
Comments