Subtract average image from a series of images

I'm having some difficulty subtracting an averaged image from a series of images from which the average was obtained. The images have been obtained from a MP4 video file.
This is what i have done:
Ven23 = VideoReader('MyVideo23.MP4'); %Read in the video file
Ven23frame1 = read(Ven23,1); % Read in the first frame of the video
sumImage23 = im2double(Ven23frame1); %Double the accuracy of the frame
for i=2:30
Ven23Frames= read(Ven23,i);
sumImage23 = sumImage23 + im2double(Ven23Frames);
end
avgVen23= imshow(sumImage23/30);
This all seems to work; I get an image which looks like the average. However, whenever I try to subtract this average image from any particular frame from the video I get this error:
Undefined operator '-' for
input arguments of type
'matlab.graphics.primitive.Image'.
Then I tried to save the average image and frames as bmp files, load them back in and subtract them. Doing this just returns a black screen. I also tried doubling the accuracy of the reloaded images to no avail.
I'm obviously doing something wrong and I would be grateful if anyone could point it out to me. Thanks.

댓글 수: 3

You forgot to show the line of code that generated the error! What does this show:
whos avgVen23
And did you use im2double on the image you're going to subtract from also?
Thanks.
>> whos avgVen23
Name Size Bytes Class Attributes
avgVen23 1x1 104 matlab.graphics.primitive.Image
Is this the info you're after?
I did try im2double on the image, that is what returned the totally black image.
Taking into account Guillaume's help, I think this is what you meant?
>> whos avgVen23
Name Size Bytes Class Attributes
avgVen23 1080x1920x3

댓글을 달려면 로그인하십시오.

 채택된 답변

Guillaume
Guillaume 2016년 3월 2일

0 개 추천

In view of the error, I would suspect that you're trying to subtract your mean image from a variable called exactly image. Unfortunately, at the point where you're doing the subtraction, the variable image does not exist, so instead matlab calls the function image which returns an object of type 'matlab.graphics.primitive.Image'. Subtraction is not defined for that (a graphics object), hence the error message. At the same time, you probably have an upside down picture of a boy's head popping up in a figure.
In conclusion:
  1. you have a bug in that you're using a variable you've never defined. Can't help you more, since you didn't show that part of the code.
  2. do not name your variable image

댓글 수: 10

Hi, appreciate the answers.
This is the code from where i try to subtract the images:
Ven23frame2 = Ven23frame2 = read(Ven23,2);
im2double(Ven23frame2)-avgVen23;
Does that clarify things?
Oh! I've just spotted the problem. Ignore the above. The problem is this:
avgVen23 = imshow(sumImage23/30);
Which should be:
avgVen23 = sumImage23/30;
imshow(avgVen23);
You're assigning the return value of imshow to your avgVen23. imshow returns a handle to a graphics object, not the original image.
On the other hand, the whole code can be simplified to:
Ven23 = VideoReader('MyVideo23.MP4'); %Read in the video file
avgVen23 = mean(read(Ven23, [1 30]), 4, 'native')
N B
N B 2016년 3월 3일
Thanks, it worked in that I don't get the error. However, it's just returning a black image now.
I wonder whether it's just that the images are so similar that I can't see the subtraction by eye. Is that possible?
If you're subtracting images, make sure you convert them to double first.
If you used double() and the differences are in the range of 0 - 5 or 10, then it's possible it will be too dark. I think if you used im2double() it would probably be okay, but it depends on how imshow() is scaling it. Either way, use [] in imshow() to "fix" the problem:
imshow(avgVen23, []);
N B
N B 2016년 3월 3일
Yeah, I was doing that. I'm stumped.
What is the maximum and minimum of the difference between the 2 images:
max(double(Ven23frame2(:)) - double(avgVen23(:))
min(double(Ven23frame2(:)) - double(avgVen23(:))
I must say you are being most helpful.
>> max(double(Ven23frame2(:)) - double(avgVen23(:)))
min(double(Ven23frame2(:)) - double(avgVen23(:)))
ans =
163.3820
ans =
-0.0294
So that means there is a difference between the two frames?
Additionally, whenever I try:
imshow(double(Ven23frame2));
I just get a totally white image. Therefore i've been using
im2double(Ven23frame2).
The min and max using this are quite small:
>> max(im2double(Ven23frame2(:)) - im2double(avgVen23(:)))
min(im2double(Ven23frame2(:)) - im2double(avgVen23(:)))
ans =
0.1069
ans =
-0.0763
These values seem very small - is that why i get a black image back?
I suspect that
class(Ven23frame2)
class(avgVen23)
will return 'uint8' and 'double' respectively, since the min/max in the first case (with double) is not an integer. That means you didn't use
avgVen23 = mean(read(Ven23, [1 30]), 4, 'native')
to generate the mean image but some other way, where at some point you converted the image with im2double.
You need to learn the difference between the classes of arrays, what arithmetic operations are possible with them and the effect it has on display.
An array can be of class uint8. That means pixel values are in the range 0-255. When you imshow such an array (without using [] in the imshow call), matlab assumes that range and display 0 as black and 255 as white. It's not a good idea to perform arithmetic on uint8 arrays as any result below 0 gets clamped to 0 and any result above 255 gets clamped to 255.
If the array is of class double. imshow (and most image processing functions) assume that the intensities are in the range 0-1. 0 and anything below 0 gets displayed as black, 1 and anything higher gets displayed as white.
If you convert a uint8 array to double using double(img), the intensities do not change (they're still in the range 0-255) and if you try to display that, because it is double intensities 1 to 254 will show as white. im2double on the other hand rescale the intensities in the range 0-1.
To avoid all this trouble with display always use imshow with []. It will use whatever range is in the array:
imshow(img , [])
When you do the min/max difference with im2double the difference is 0.1, which is 10% of the intensity range (0-1), so you should see some colour.
If you don't get anywhere, attach save the output of
read(Ven23, [1 30])
in a mat file and post that.
N B
N B 2016년 3월 3일
You suspect correctly.
I have now managed to return an coherent image. I've even learnt something, which is a rarity.
Many thanks.

댓글을 달려면 로그인하십시오.

추가 답변 (0개)

질문:

N B
2016년 3월 2일

댓글:

N B
2016년 3월 3일

Community Treasure Hunt

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

Start Hunting!

Translated by