Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

framepos.sh script #2

Open
allanhummer opened this issue Nov 17, 2020 · 11 comments
Open

framepos.sh script #2

allanhummer opened this issue Nov 17, 2020 · 11 comments

Comments

@allanhummer
Copy link

allanhummer commented Nov 17, 2020

Hi!

I would really like to use your framepos.sh script to search for a provided keyframe in a video.
Unfortunately I can't get it to work. Could you maybe help me out?

I'm on Ubuntu 18.04 and installed ffmpeg and findimagedupes via apt.

Then I provided a ~10 min long .mp4 video and a .png keyframe which I extracted from this video and ran the script via "framepos.sh test.mp4 keyframe.png" and the default settings.

I think the script detects the frame but I get an error. My output looks like this:

framepos.sh test.mp4 keyframe.png

fps = 60
dur = 615.570
near T1 = 0
near T2 = -1
exact T2 = 614.5667
extract frames to /tmp/mv-1605621455.frame-%04d.bmp
extract ... 33 81 86 89 92 94 97 99 103
compare 103 frames from /tmp/mv-1605621455.frame-0001.bmp
search for keyframe.png
extract ... 0 48 82 83 90 96 99 101
compare 101 frames from /tmp/mv-1605621455.frame-0104.bmp
search for keyframe.png
awk: cmd. line:1: (FILENAME=- FNR=1) fatal: division by zero attempted
match t =

Do you have an idea on how I can get it to work?

best,
Allan

@milahu
Copy link
Owner

milahu commented Nov 17, 2020

I would really like to use your framepos.sh script

cool : ) thanks for the bug report

awk: cmd. line:1: (FILENAME=- FNR=1) fatal: division by zero attempted

looks like $fps is unset somehow ..
awk always divides something by $fps

ive added some debug prints:
https://github.com/milahu/random/blob/debug/framepos.sh

could be an issue with for/while loops, bash is a little tricky here

another bug:
"exact T2" should equal "dur"
the default value for T2 should be zero, not -1
thats why T2 is one seconds too small

@allanhummer
Copy link
Author

Thanks for the quick reply!
I now set a=0 and b=0. This should process the whole video, right?

Here the new output:

framepos test.mp4 keyframe.png
fps = 60
dur = 615.570
near T1 = 0
near T2 = 0
extract frames to /tmp/mv-1605639640.frame-%04d.bmp
extract ... 24 40 52 56 58 61 63 66 69 71 73 80 82 85 86 88 90 91 93 95 96 99 102
compare 102 frames from /tmp/mv-1605639640.frame-0001.bmp
search for keyframe.png
extract ... 0 43 86 92 96 98 101
compare 101 frames from /tmp/mv-1605639640.frame-0103.bmp
search for keyframe.png
awk: cmd. line:1: (FILENAME=- FNR=1) fatal: division by zero attempted
match t = i =

I also tried to do some debugging using echoes, but some of them won't show up (Like your "echo "found res: $res"" in line 316). Do you know why that is?

Thanks again!

@milahu
Copy link
Owner

milahu commented Nov 18, 2020

I now set a=0 and b=0. This should process the whole video, right?

yes

some of them won't show up

aah, my bad, we need echo .... >&2 to print to stderr
cos stdout is sent to the pipe

@allanhummer
Copy link
Author

Thanks for the hint! Got the echoes to work now and I think I found the problem :) :
In line 206
echo -ne "\t\t\t\t"
should be
echo -n "\t\t\t\t"

@milahu
Copy link
Owner

milahu commented Nov 18, 2020

so its working now?

the -e option tells echo to convert \t to a tab character
that part is fine

the bug could be in sed 's/\t\t\t\t/\n/g'
but that works too:

echo -e 'a\tb\tc\td' | sed 's/\t/\n/g'
a
b
c
d

whats the value of $res?

			if [ ! -z "$res" ]
			then
				echo "found res: $res" >&2 # debug print
				res=$(

@allanhummer
Copy link
Author

Oh ok. It worked when removing the -e option.

Without removing it I get the following output:
framepos test.mp4 keyframe.png

fps = 60
dur = 615.570
near T1 = 0
near T2 = 0
extract frames to /tmp/mv-1605699241.frame-%04d.bmp
extract ... 15 19 21 24 26 29 32 34 35 40 41 43 44 46 48 49 51 52 56 57 58 60 62 63 64 70 71 74 75 77 79 80 82 84 85 87 89 90 92 94 95 97 98 100
compare 100 frames from /tmp/mv-1605699241.frame-0001.bmp
search for keyframe.png
extract ... 0 32 51 53 56 59 61 64 66 69 71 73 75 76 78 79 81 82 86 87 88 90 92 93 95 96 100
compare 100 frames from /tmp/mv-1605699241.frame-0101.bmp
search for keyframe.png
found res: /home/allan/Desktop/keyframe.png-ne
awk: t = 0 + ( ( - 2 ) / 60
awk: cmd. line:1: (FILENAME=- FNR=1) fatal: division by zero attempted
match t = i =
error frame not found

@milahu
Copy link
Owner

milahu commented Nov 18, 2020

found res: /home/allan/Desktop/keyframe.png-ne

this is bad .. looks like your echo doesnt know the -e option
but the fix is easy:

		VIEW () {
			for f in "$@"
			do
				printf "%s\t\t\t\t" "$f"
			done
			echo
		}

also, the "found res" line should look more like

found res: /tmp/framepos-120208.frame-0644.bmp /tmp/framepos-120208.frame-0645.bmp /tmp/framepos-120208.frame-0646.bmp /path/to/input/image/file.png /tmp/framepos-120208.frame-0647.bmp

so there should be the input image file, and at least one frame image file

awk: t = 0 + ( ( - 2 ) / 60

this just confirms that $res is empty, which makes sense:
before this

res=$(
	echo "$res" \
	| sed 's/\t\t\t\t/\n/g' \
	| grep -v '^$' \
	| grep -v "$pattern" \
	| sort \
	| head -n 1 \
	| sed -E 's/^.*frame-(.*?)\.bmp$/\1/'
)

res only contains the input image file
which is removed in the echo-sed-grep-grep-sort-head-sed expression

could be an issue with your findimagedupes
does this work?

#!/bin/bash

script_include=$(cat <<-'EOF'
	VIEW () {
		for f in "$@"
		do
			echo -n "$f"
			echo -n "||||"
		done
		echo
	}
EOF
)

# img1.png img2.png should be identic or similar
findimagedupes -t 90 -i "$script_include" img1.png img2.png

# output should be
# img1.png||||img2.png||||

@allanhummer
Copy link
Author

So I think your fix works. I get this output:
awk: t = 0 + ( ( 181 - 2 ) / 60
match t = 2.9833 i = 181

However, if I run the test script you provided (with identical img1 and img2) I get no output at all.

@milahu
Copy link
Owner

milahu commented Nov 18, 2020

$ file $(which findimagedupes) 
/usr/bin/findimagedupes: Perl script text executable

$ head $(which findimagedupes) 
#!/usr/bin/perl -w
my $Id = "2.19";
#
# findimagedupes - Finds visually similar or duplicate images
#
# Copyright 2006-2019 by Jonathan H N Chin <[email protected]>.

do you get the same output?

"findimagedupes" is ambiguous

@allanhummer
Copy link
Author

I think I've the correct version. But an old one (got it via "sudo apt install findimagedupes"). This is my output:

file $(which findimagedupes) 
/usr/bin/findimagedupes: Perl script text executable

head $(which findimagedupes)
#!/usr/bin/perl -w
# $Id: findimagedupes,v 2.18 2008/12/19 01:04:36 jhnc Exp jhnc $
#
# findimagedupes - Finds visually similar or duplicate images
#
# Copyright 2006-2008 by Jonathan H N Chin <[email protected]>.

Do you think this is an issue?
Not really sure how to correctly update either.

Thanks again for the help!

@milahu
Copy link
Owner

milahu commented Nov 19, 2020

Thanks again for the help!

youre testing my patience ; )

i did the test with version 2.18 from https://github.com/jhnc/findimagedupes/releases
and i get

$ ./framepos.test.sh 
/tmp/img1.jpg||||/tmp/img2.jpg||||

as expected

still, this could be a bug in findimagedupes
to test the latest version, run

#!/bin/bash

# download
git clone --depth 1 https://github.com/jhnc/findimagedupes.git
cd findimagedupes

# patch the 'inline directory'
# the value '/tmp' is used on arch linux
sed -i.bak 's/\/usr\/local\/lib\/findimagedupes/\/tmp/' findimagedupes

# verify patch
diff -u findimagedupes.bak findimagedupes

# run test

script_include=$(cat <<-'EOF'
	VIEW () {
		for f in "$@"
		do
			echo -n "$f"
			echo -n "||||"
		done
		echo
	}
EOF
)

# img1.png img2.png should be identic or similar

echo global version
findimagedupes -t 90 -i "$script_include" img1.png img2.png

echo git version
./findimagedupes -t 90 -i "$script_include" img1.png img2.png

echo git version verbose
./findimagedupes -v md5,fingerprint -t 90 -i "$script_include" img1.png img2.png

# change script - add line #!/bin/sh
script_include=$(cat <<-'EOF'
	#!/bin/sh
	VIEW () {
		for f in "$@"
		do
			echo -n "$f"
			echo -n "||||"
		done
		echo
	}
EOF
)

echo git version script 2
./findimagedupes -t 90 -i "$script_include" img1.png img2.png

# change script - use printf
script_include=$(cat <<-'EOF'
	#!/bin/sh
	VIEW () {
		for f in "$@"
		do
			printf "%s||||" "$f"
		done
		printf "\n"
	}
EOF
)

echo git version script 3
./findimagedupes -t 90 -i "$script_include" img1.png img2.png

# output should be
# img1.png||||img2.png||||

However, if I run the test script you provided (with identical img1 and img2) I get no output at all.

no output = no matches were found = images should be different (?)
try with a lower threshod value (1 percent)

findimagedupes -t 1 -i "$script_include" img1.png img2.png

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants