PySceneDetect
PySceneDetect copied to clipboard
Performance Improvement for ThresholdDetector
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
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).
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.
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?
Also just to clarify, I was calling frame.mean()
instead of using cv2.mean()
as in your example.
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!