function varargout = GUI_BenchAndBall(varargin) % GUI_BENCHANDBALL MATLAB code for GUI_BenchAndBall.fig % GUI_BENCHANDBALL, by itself, creates a new GUI_BENCHANDBALL or raises the existing % singleton*. % % H = GUI_BENCHANDBALL returns the handle to a new GUI_BENCHANDBALL or the handle to % the existing singleton*. % % GUI_BENCHANDBALL('CALLBACK',hObject,eventData,handles,...) calls the local % function named CALLBACK in GUI_BENCHANDBALL.M with the given input arguments. % % GUI_BENCHANDBALL('Property','Value',...) creates a new GUI_BENCHANDBALL or raises the % existing singleton*. Starting from the left, property value pairs are % applied to the GUI before GUI_BenchAndBall_OpeningFcn gets called. An % unrecognized property name or invalid value makes property application % stop. All inputs are passed to GUI_BenchAndBall_OpeningFcn via varargin. % % *See GUI Options on GUIDE's Tools menu. Choose "GUI allows only one % instance to run (singleton)". % % See also: GUIDE, GUIDATA, GUIHANDLES % Edit the above text to modify the response to help GUI_BenchAndBall % Last Modified by GUIDE v2.5 05-Jul-2016 12:43:13 % Begin initialization code - DO NOT EDIT gui_Singleton = 1; gui_State = struct('gui_Name', mfilename, ... 'gui_Singleton', gui_Singleton, ... 'gui_OpeningFcn', @GUI_BenchAndBall_OpeningFcn, ... 'gui_OutputFcn', @GUI_BenchAndBall_OutputFcn, ... 'gui_LayoutFcn', [] , ... 'gui_Callback', []); if nargin && ischar(varargin{1}) gui_State.gui_Callback = str2func(varargin{1}); end if nargout [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:}); else gui_mainfcn(gui_State, varargin{:}); end % End initialization code - DO NOT EDIT % --- Executes just before GUI_BenchAndBall is made visible. function GUI_BenchAndBall_OpeningFcn(hObject, eventdata, handles, varargin) % This function has no output args, see OutputFcn. % hObject handle to figure % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) % varargin command line arguments to GUI_BenchAndBall (see VARARGIN) % Choose default command line output for GUI_BenchAndBall handles.output = hObject; % Update handles structure guidata(hObject, handles); % UIWAIT makes GUI_BenchAndBall wait for user response (see UIRESUME) % uiwait(handles.figure1); % --- Outputs from this function are returned to the command line. function varargout = GUI_BenchAndBall_OutputFcn(hObject, eventdata, handles) % varargout cell array for returning output args (see VARARGOUT); % hObject handle to figure % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) % Get default command line output from handles structure varargout{1} = handles.output; % --- Executes on slider movement. function slider1_Callback(hObject, eventdata, handles) % hObject handle to slider1 (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) % Hints: get(hObject,'Value') returns position of slider % get(hObject,'Min') and get(hObject,'Max') to determine range of slider disp('slider says hello') get(hObject,'Value') % --- Executes during object creation, after setting all properties. function slider1_CreateFcn(hObject, eventdata, handles) % hObject handle to slider1 (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles empty - handles not created until after all CreateFcns called % Hint: slider controls usually have a light gray background. if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) set(hObject,'BackgroundColor',[.9 .9 .9]); end % --- Executes on button press in pushbutton1. function pushbutton1_Callback(hObject, eventdata, handles) % hObject handle to pushbutton1 (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) disp('hello from pushbutton1 - starting animation') % get slider value sliderVal = get(handles.slider1,'Value'); % pass slider value as input to animation function fBenchAndBall(sliderVal) % ---------- FUNCTION MAIN fBenchAndBall ------------ function fBenchAndBall(sliderVal) % WARNING - original script had 'clear' statement here % that cleared everthing GUI had set up! % MAIN % animation of object moving in scene % Uses user-written functions: % fLoadImageFile, fImageRotate % fGetCoordinates, fPlaceImageOnScene % this example moves one object across a scene % you can move more than one object, see OPTION notes below % LOAD BACKGROUND SCENE FROM JPG FILE IN MEMORY % file needs to be in this folder or use file path scene = fLoadImageFile('newscene.jpg'); % LOAD OBJECT FROM JPG FILE INTO MEMORY object = fLoadImageFile('ball.jpg'); % OPTION: load more objects % OPTION: rotate object and store images in cell array nr = -10; % number rotated images, nr > 0 is CCW, nr < 0 is CW, 1 for no rotation gs = 255; % background "green screen," varies with object image background thr = 15; % threshold for background green screen objectCellArray = fImageRotate(object,nr,gs,thr); % CALL FUNCTION fGetCoordinates TO GET x,y COORDINATES FOR ENTIRE ANIMATION % get number rows & columns of scene and object [sRows sCols p] = size(scene); [oRows oCols p] = size(objectCellArray{1}); % new here, we pass slider value to function % whereas in original value for vLoss below was fixed [x y c] = fGetCoordinates(sliderVal,oRows,oCols,sRows,sCols,abs(nr)); % each element in arrays x,y,c correspond to a different time step % array x contains horizontal coordinates of image location % array y contains vertical coordinates of image location % array c contains rotation angle index of object % OPTION: get coordinates for any additional objects % OPTION: start playing a sound track (not used here) % STEP THROUGH ANIMATION % when use getframe to make movie % make sure figure is separate floating window and not % docked in main Matlab master window fps = 16; % frames per second fpp = 1/fps; % frame period % frame rate won't be accurate in repeat % because of time to generate images % but will be accurate when movie has been captured and is replayed for i = 1:length(x) % OPTION: get desired rotation of object image object = objectCellArray{c(i)}; % place object on scene % gs (green screen) value here has values for all three RGB layers gs = [255 255 255]; compositeImage = fPlaceImageOnScene(scene,object,gs,x(i),y(i)); % OPTION: place any additional object(s) on composite image % display final composite image for this frame % options are to use imshow or image imFlag = 1; % choose 1 for imshow, 2 for image switch imFlag case 1 % imshowMag at 20 percent full scale saves as 8.3 MB avi movie % imshowMag at 40 percent full scale saves as 33.4 MB avi movie % WARNING: imshow at full scale takes too much memory imshowMag = 40; % percent of full scale imshow(compositeImage,'InitialMagnification',imshowMag) case 2 % image produces a 40.9 MB avi file image(compositeImage) axis off % on or off, on shows axis ticks and coordinate values end % control play rate pause(fpp) % OPTION: get movie frame M(i) = getframe; end % DEACTIVATE DURING DEVELOPMENT disp('MOVIE PLAYBACK DEACTIVATED DURING DEVELOPMENT') % % now play the movie we recorded % n = 1; % number times to play % movie(M,n,fps) % DEACTIVATE DURING DEVELOPMENT disp('MOVIE SAVING TO DISK FILE DEACTIVATED DURING DEVELOPMENT') % % now save movie % fprintf('SAVING MOVIE - THIS MAY TAKE SOME TIME - WAIT UNTIL MATLAB NOT BUSY') % fprintf('DO NOT TRY TO OPEN MOVIE DISK FILE UNTIL MATLAB NOT BUSY') % % Mac can only write with 'Compression','None' % % Win can also use 'Compression','Cinepak' % movie2avi(M,'benchAndBall.avi','Compression','None'); % ------- FUNCTION fGetCoordinates ------------- function [x y c] = fGetCoordinates(sliderVal,oRows,oCols,sRows,sCols,nr) % % FUNCTION: fGetBallCoordinates % INPUTS: % oRows and oCols are size of object image % sRows and sCols are size of scene image % nr > 0 is number of object rotation images % OUTPUTS: % each element in arrays x,y,c correspond to a different time step % array x contains horizontal coordinates of image location % array y contains vertical coordinates of image location % array c contains rotation angle index of object % This is one alternative method of computing the path. % In this alternative, we already had integrated % the differential equations of motion and have algebraic % solutions. Thus, we could use array expressions % to compute results and not repeats. % However, since we may want to do things along the % way such as show images, we use repeats here. % With either array equations or results of our repeats, % we have the coordinates in arrays, so we could do the % animation of the images in a separate repeat. % Another alternative would be to integrate the % differential equations approximately numerically % each time through a repeat loop as we step in time, e.g., % using Euler's method: y(i+1) = y(i) + g*t(i)*dt, which is obtained % after integrating dv/dt = d^2y/dt^2 = g once analytically % to obtain dy/dt = g*t % Dimensional units are not shown at this stage of development. ymax = sRows; yobj = oRows; t1 = 22; % time at drop y0 = 180; % initial y (row) position, object top-left x0 = 100; % initial x (column) position, object top-left y2 = ymax-yobj; % y position of bottom of object on floor % y2 = max rows of scene - row height of object g = 1; % vertical acceleration (length per time^2) dt = 1; % time increment xv = 9.7; % x velocity (length per time) i = 1; % index i is our frame counter t(i) = 0; y(i) = y0; % vLoss = 0.8; % energy lost on bounce vLoss = sliderVal; % energy lost on bounce % ball is rolling on bench before collision while t(i) < t1 i = i+1; t(i) = t(i-1) + dt; y(i) = y(i-1) + round(3*dt); end y1 = y(i); % y position at start of drop % now ball drops off bench while y(i) < y2 i = i+1; t(i) = t(i-1) + dt; y(i) = y1 + 0.5*g*(t(i)^2-t1^2)-g*t1*(t(i)-t1); y(i) = round(y(i)); % need integer for column end t2 = t(i); % check to make sure don't go past floor if y(i) > y2 y(i) = y2; end % now ball bounces while y(i) <= y2 i = i+1; t(i) = t(i-1) + dt; % vLoss = velocity lost on bounce y(i) = y2 + -g*vLoss*(t2-t1)*(t(i)-t2) + ... 0.5*g*(t(i)^2-t2^2)-g*t2*(t(i)-t2); y(i) = round(y(i)); % check to make sure it isn't off top of scene if y(i) < 1 y(i) = 1; end end t4 = t(i); % since y(i) > y2 to get out of repeat % we have gone past floor if y(i) > y2 y(i) = y2; end % compute x position from time % and constant x-velocity x = round(x0 + t*xv); % need integer for col % add check that object stays on scene horizontally f = find(x > (sCols-oCols)); x(f) = (sCols-oCols); f = find(x < 1); x(f) = 1; % compute c - object rotation c(1) = 1; for i = 1:length(t)-1 c(i+1) = c(i)+1; % increment by 1 each time step here if c(i+1) > nr c(i+1) = 1; end end % ---------- FUNCTION fImageRotate ---------------- function bb4 = fImageRotate(bb,nr,gs,thr) % FUNCTION: fImageRotate % RETURNS: cell array with copies of rotated image % INPUTS: % bb is 3D array of JPG image (bb from orig bouncing ball) % nr is number of rotations = number of images returned % nr < 0 for clockwise rotation, 1 for 1 unrotated image % gs is "green screen" setting, 0 for black background, % 255 for white % thr is threshold for setting background light gray to white, % and dark gray to black, that is % background > (255-thr) is set to 255, or < thr is set to 0 % needs improvement to handle more complex "green screening" c = 0; % initialize cell counter for cell array while c < abs(nr) % want nr total copies c = c+1; % increment cell counter a = (c-1)*360/nr; % angle in degrees br = imrotate(bb,a,'nearest','crop'); % rotate image % set "green screen" with threshold value for 0=black, 255=white switch gs case 255 % image has white background % rotating produces black corners % so set those corners to white % note: needs improvement, sets all black to white now filter = find(br == 0); % indices of br elements == 0 br(filter) = 255; % set those elements to gs value % change almost white pixels to white filter = find(br > 255-thr); br(filter) = 255; case 0 % image has black background filter = find(br < thr); br(filter) = 0; otherwise disp('NO THRESHOLD FOR GS NOT 0 OR 255') end bb4{c} = br; % add rotated image to new cell in cell array end % ----------- FUNCTION fLoadImageFile -------------- function im = fLoadImageFile(tFile) % FUNCTION: fLoadImageFile % RETURNS: array with JPG image data % INPUTS: tFile = file path to JPG image file im = imread(tFile); % ----------- FUNCTION fPlaceImageOnScreen ---------- function compImage = fPlaceImageOnScene(scene,obj,gs,x,y) % FUNCTION: fPlaceImageOnScene % RETURNS: 3D array with JPG image data % INPUTS: % scene is 3D array with background (scene) image data % obj is 3D array with object image data % gs is array of 3 RGB values of green screen (object background) % which is background of object image % x and y are coordinates of scene at which to place % top-left corner of object % places an image on a scene using "chroma key compositing" % using a "green screen" (or other color screen) % for object image background surrounding object % of irregular shape % see http://en.wikipedia.org/wiki/Chroma_key [srows scols spg] = size(scene); [orows ocols opg] = size(obj); % create our "green screen" % first, make one page of all zeros % JPG uses data type uint8 to save memory space % uint8 is 8-bit unsigned integers vs. default 64-bit double-precision % note binary 2^8 = 256, and 0-255 is 256 numbers pg = zeros(srows,scols,'uint8'); % make the green screen canvas canv = cat(3,pg+gs(1),pg+gs(2),pg+gs(3)); % put object on canvas at x,y coordinates canv(1+y : orows+y, 1+x : ocols+x, :) = obj; % find linear (sequential) indices of elements of object on canvas % whose values are not equal to green screen values ind1 = find(canv(:,:,1) ~= gs(1)); ind2 = find(canv(:,:,2) ~= gs(2)); ind3 = find(canv(:,:,3) ~= gs(3)); % put object from canvas onto scene to form composite image % make copies of each page of canvas and scene % since we have linear indices for each page canv1 = canv(:,:,1); canv2 = canv(:,:,2); canv3 = canv(:,:,3); scene1 = scene(:,:,1); scene2 = scene(:,:,2); scene3 = scene(:,:,3); % replace elements in scene pages with elements from canvas pages scene1(ind1) = canv1(ind1); scene2(ind2) = canv2(ind2); scene3(ind3) = canv3(ind3); % concatenate (cat) the pages into one composite image 3D array % which will be returned by this function compImage = cat(3,scene1,scene2,scene3);