create mask for constant (nonchanging) portion of video

Questions and postings pertaining to the usage of ImageMagick regardless of the interface. This includes the command-line utilities, as well as the C and C++ APIs. Usage questions are like "How do I use ImageMagick to create drop shadows?".
Post Reply
utnuc
Posts: 12
Joined: 2014-09-17T06:41:13-07:00
Authentication code: 6789

create mask for constant (nonchanging) portion of video

Post by utnuc »

I have been a long time ImageMagick user, huge fan. This question is more about theory than syntax.

I have a compressed ultrasound video clip that has a portion at the top (usually 25-75 pixels) that has personal patient information. I'd like to get this value automatically. This upper portion of the clip does not change. Here's a sample clip:
http://www.ultrasoundoftheweek.com/clip ... 1_copy.mp4.

My original theory was to take a still every 5 seconds using ffmpeg:

Code: Select all

ffmpeg -i test.mp4 -vf fps=1 -y out%04d.bmp
Then resize to 1 pixel wide using mogrify to average out changes across the clip:

Code: Select all

mogrify -resize 1x600! *.bmp
Then look at the difference between images:

Code: Select all

convert *.bmp -compose difference -composite  -threshold 0 -separate -evaluate-sequence Add difference.jpg

Last, use trim to determine how much would come off the top.

Code: Select all

Code?
1) At this point, I'm not satisfied with the output I'm getting from the difference step. I'm getting difference at the top when I can see no appreciable difference between stills. Playing with threshold doesn't seem to effect much.

2) Also, can anyone help me with the trim output step (looking for first grey pixel from top)?

3) Would another approach be more reliable?

Thanks in advance!
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: create mask for constant (nonchanging) portion of video

Post by snibgo »

Never use JPG unless you really really have to.

IM can easily find the difference between two images. For finding what changes in a sequence, you need to define what you mean. If something changes between frames 1 and 2 but not between 2 and 3, does this count as a change or not?

MP4 files are lossy-compressed. This means that pixels will change slightly from one frame to the next, so you need to find how much it has changed.

The clock in the top-right corner is upsetting your "has it changed" process.

I wouldn't shrink to a single column. Instead, find the mean of a sequence of frames, and the mean for another sequence. Find the difference between these means. I crop out the last 10% of width to remove the clock.

Then I threshold to remove most noise, and blur and threshold to remove the rest. Then a process module finds the first white pixel. Windows BAT syntax:

Code: Select all

%IMDEV%convert ^
  ( hb0001.png hb0002.png hb0003.png -evaluate-sequence mean ) ^
  ( hb0004.png hb0005.png hb0006.png -evaluate-sequence mean ) ^
  -crop 90%%x+0+0 +repage ^
  -compose difference -composite -separate -evaluate-sequence Add ^
  -threshold 30%% ^
  -blur 0x1 -threshold 30%% ^
  -process onewhite ^
  diff4.png

onewhite: 460,67
The top of the scan is at 460,67.
snibgo's IM pages: im.snibgo.com
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: create mask for constant (nonchanging) portion of video

Post by fmw42 »

2) Also, can anyone help me with the trim output step (looking for first grey pixel from top)?
Take your 1 column image, threshold and convert to txt: format. See http://www.imagemagick.org/Usage/files/#txt. Then extract the graylevel values and find the center of the first black area that follows the first white area. You will need to write some code in the OS to do the latter search. If your background is not pure black, then pick an appropriate threshold value other than 0 to separate the dark background from the whitish text.

What platform and version of IM are you using?

If on Windows, see http://im.snibgo.com/histopeaks.htm. A similar concept should be applicable to your txt output to get the valleys.


Another way would be to use compare to find the first white to black transition. Something like (unix syntax)

Code: Select all

compare -metric rmse 1columnimage \( xc:white xc:black -append \) null:
Then add at least one to the Y coordinate for the crop so that you are at the black pixel. If you know the approximate height of the gap, then you could add gap/2 to the Y coordinate to crop at the approximate middle of the gap.


EDIT: Sorry snibgo, we were posting at about the same time.
utnuc
Posts: 12
Joined: 2014-09-17T06:41:13-07:00
Authentication code: 6789

Re: create mask for constant (nonchanging) portion of video

Post by utnuc »

@snibgo

Brilliant post. Can you format that code for linux / bash?

@fmw42

Great suggestion, I can write the code with the text values.
Post Reply