PySceneDetect icon indicating copy to clipboard operation
PySceneDetect copied to clipboard

Performance Improvement for ThresholdDetector

Open bubalazi opened this issue 5 years ago • 4 comments

Hi,

Frame averaging currently is done via

numpy.sum(frame[:,:,:]) / num_pixel_values

I've experimented a bit and found that a substantial improvement can be made by using OpenCV built-in methods for this purpose. For example:

cv2.mean(cv2.mean(frame))[0] / 3

The resulting compute_frame_average() method runs ~10% faster on the test video.

Example:

# Test with the proposed change
$ scenedetect -i goldeneye.mp4  -s output.csv -l
[PySceneDetect] Detecting scenes (threshold mode)...
[PySceneDetect] Parsing video goldeneye.mp4...
[PySceneDetect] Video Resolution / Framerate: 1280 x 544 / 23.976 FPS
Verify that the above parameters are correct (especially framerate, use --force-fps to correct if required).
[PySceneDetect] Processing complete, found 0 scenes in video.
[PySceneDetect] Processed 1980 / 1980 frames read in 7.8 secs (avg 254.5 FPS).
# Test with current method
$ scenedetect -i goldeneye.mp4  -s output.csv -l
[PySceneDetect] Detecting scenes (threshold mode)...
[PySceneDetect] Parsing video goldeneye.mp4...
[PySceneDetect] Video Resolution / Framerate: 1280 x 544 / 23.976 FPS
Verify that the above parameters are correct (especially framerate, use --force-fps to correct if required).
[PySceneDetect] Processing complete, found 0 scenes in video.
[PySceneDetect] Processed 1980 / 1980 frames read in 8.6 secs (avg 229.4 FPS).

Unit-Testing for performance of the proposed vs existing solution

print(frame.shape)
print("Proposed Solution results:")
%timeit compute_frame_average_PROPOSED(frame)
print("Existing Solution results:")
%timeit compute_frame_average_EXISTING(frame)

results in:

(1080, 1980, 3)
Proposed Solution results:
100 loops, best of 3: 4.92 ms per loop
Existing Solution results:
100 loops, best of 3: 6.32 ms per loop

bubalazi avatar Jul 29 '18 05:07 bubalazi

Excellent, thank you for this submission! These improvements will be added to the next official PySceneDetect release (v0.5), and have also been merged into the current master branch.

I will leave this issue open until I have merged your changes into my development branch (v0.5-dev).

Breakthrough avatar Jul 29 '18 17:07 Breakthrough

After review, I will defer this enhancement to the backlog for a release in v0.5.1/v0.6 pending further testing, to expedite the release of v0.5.

Breakthrough avatar Aug 01 '18 16:08 Breakthrough

I just did a quick test of this again, and seem to get very close results.

Would you be able to re-test this with a newer version of OpenCV and let me know if you still get the same results?

Breakthrough avatar Feb 17 '22 01:02 Breakthrough

Also just to clarify, I was calling frame.mean() instead of using cv2.mean() as in your example.

Breakthrough avatar Feb 17 '22 01:02 Breakthrough

I wasn't able to see any notable performance improvement, so I'll close this issue out. However, feel free to submit a pull request should you find any other optimizations. Thank you!

Breakthrough avatar Jul 17 '23 00:07 Breakthrough