From: William Frane on
Hello all,

I've been working on some code that (at the most basic level) goes through every frame of an uncompressed AVI file and superimposes a transparent PNG file at a user-specified location on each frame to create a new video.

The code essentially works, except for two bugs, one of which doesn't appear to have any actual effect on the functionality of the code and one which renders the output video unsatisfactory. The second bug is the only one I really care about.

The problem is this: when the transparent PNG is superimposed over a frame of the original video, setting its alphadata property causes two problems with the underlying frame. Firstly, the frame shifts down by 1 pixel. Secondly, a column of pixels near the middle of the frame is duplicated, which causes the right-most column of pixels in the frame to be pushed to the right into the non-visible part of the figure. Although this is a "minor" issue, it's unacceptable for the output video to be altered in this way.

Interestingly, if the alphadata property for the transparent PNG is not set (i.e., the PNG is superimposed but not made transparent in the appropriate areas), this problem does not occur.

I would appreciate any suggestions as to how I might resolve this problem. I've tried several different things (e.g. using imshow instead of image) but nothing made any difference. I should also note that I'm using version 2007a.

The code is reproduced below.

Thanks for your help.

William Frane

% CODE STARTS HERE ===============

function video_test(fn_video,fn_image)
% VIDEO_TEST Trying to resolve bugs present in basic ROI handling and
% image overlay code for a video tracking program.
% Input:
% fn_video: the filename for an uncompressed AVI video (e.g.
% 'test_video.avi')
% fn_image: the filename for a PNG image with transparency (e.g.
% 'test_image.png')

% UNSOLVED BUGS:
% - An ROI with dimensions that are altered from those used when the ROI is
% created will sometimes cause strange handle/callback errors when image()
% is called to display the current frame (this is mildly irritating, but
% doesn't seem to impact the actual functionality of the code).
% - Setting the alphadata for the superimposed image messes up the underlying
% image in two ways: the underlying image is shifted down by 1 pixel and a
% vertical line of pixels near the middle of the image is displayed twice,
% forcing the rightmost column of pixels out of the frame (the overall
% dimensions are not changed).

% Image to superimpose
[im, im_map, im_alpha] = imread(fn_image);
im_w = size(im,2);
im_h = size(im,1);

% Frame numbers to process
num_first_frame = 1;
num_last_frame = 10;

% Loading the reference frame (the frame displayed for the purposes of
% allowing the user to adjust the ROI)
temp = aviread(fn_video,num_first_frame);
ref_frame = temp.cdata;

% Values for altering the appearance of the figure (these just ensure that
% the figure frame is tight around the video frame without any white space)
screen_size = get(0,'ScreenSize');
screen_width = screen_size(3);
screen_height = screen_size(4);
fig_width = 640;
fig_height = 480;

% Display first frame and set attributes necessary for proper appearance
fig = figure;
set(fig,'Position',[round(screen_width/2 - fig_width/2), round(screen_height/2 - fig_height/2), fig_width, fig_height],'Color','white');
image(ref_frame);
set(gca,'Units','pixels');
set(gca,'Position',[1, 1, 640, 480]);
axis image;
axis off;

% Create tracking (ROI) rectangle (needs to work in 2007a, otherwise impoly
% would probably be used)
roi = imrect(gca,[50 50 25 25]);

% User must press any key to indicate selection of ROI
w = waitforbuttonpress;
while (w == 0) % Mouse click
w = waitforbuttonpress;
end

% Get ROI position
roi_api = iptgetapi(roi);
roi_pos = roi_api.getPosition();

% Store ROI info
roi_x = round(roi_pos(1));
roi_y = round(roi_pos(2));
roi_w = round(roi_pos(3));
roi_h = round(roi_pos(4));

% Store reference ROI info
roi_x_ref = roi_x;
roi_y_ref = roi_y;

% Remove ROI object
delete(roi);
display('STAGE 1');

% Movie stuff
avi_obj = avifile('superimpose.avi', 'compression', 'none', 'fps', 30);

for i = num_first_frame:num_last_frame
temp = aviread(fn_video, i);
cur_frame = temp.cdata;

% Movie stuff
image(cur_frame);

set(gca,'Units','pixels');
set(gca,'Position',[1, 1, 640, 480]);
axis off;

% Add image to frame
hold on
im_x = round(roi_x + roi_w/2 - im_w/2);
im_y = round(roi_y + roi_h/2 - im_h/2);
ih = image(im_x, im_y, im);
% ========================
% Commenting the line below removes the underlying frame problem
set(ih,'AlphaData',im_alpha);
% ========================
hold off

avi_frame = getframe(fig);
avi_obj = addframe(avi_obj, avi_frame);

display(['Frame ' num2str(i) ' processed.']);

end


avi_obj = close(avi_obj);
close(fig);


% CODE ENDS HERE ===============