|
7 | 7 | # This Python program implements a more advanced and optimized threshold- |
8 | 8 | # based scene detection algorithm, and improves the output format so |
9 | 9 | # the scene cuts can be more easily imported into other programs (e.g. |
10 | | -# ffmpeg, mkvmerge). Usage: |
| 10 | +# ffmpeg, mkvmerge). Basic usage is: |
11 | 11 | # |
12 | | -# > python part2-adaptive.py [video] [intensity] [min %] [blocksize] |
| 12 | +# > python part2-adaptive.py [-h] -i VIDEO_FILE |
13 | 13 | # |
14 | | -# Where [video] is a path to the video to be parsed, [intensity] is the |
15 | | -# pixel intensity from 0 to 255 to be used as a cut-off (default 16), |
16 | | -# [min %] is the minimum percent of pixels in the frame from 0 to 100 |
17 | | -# that must fall under the threshold (default 90%), and [blocksize] is |
18 | | -# the amount of rows in the image to check at once (default 32, can be |
19 | | -# changed/tuned to optimize performance). Example: |
| 14 | +# Where -i denotes the input video, and -h shows the help message. |
| 15 | +# Optional arguments that can be passed after VIDEO_FILE are: |
20 | 16 | # |
21 | | -# > python part2-adaptive.py testvideo.mp4 16 90 32 |
| 17 | +# -h, --help show this help message and exit |
| 18 | +# -i VIDEO_FILE, --input VIDEO_FILE |
| 19 | +# [REQUIRED] Path to input video. (default: None) |
| 20 | +# -t intensity, --threshold intensity |
| 21 | +# 8-bit intensity value, from 0-255, to use as a fade |
| 22 | +# in/out detection threshold. (default: 8) |
| 23 | +# -m percent, --minpercent percent |
| 24 | +# Amount of pixels in a frame, from 0-100%, that must |
| 25 | +# fall under [intensity]. (default: 95) |
| 26 | +# -b rows, --blocksize rows |
| 27 | +# Number of rows in frame to check at once, can be tuned |
| 28 | +# for performance. (default: 32) |
| 29 | +# -s offset, --startindex offset |
| 30 | +# Starting index for chapter/scene output. (default: 0) |
22 | 31 | # |
23 | | -# Note that you must specify all options, unless you want to use the |
24 | | -# above default values, in which case simply specify [video]: |
25 | | -# |
26 | | -# > python part2-adaptive.py testvideo.mp4 |
| 32 | +# Example: |
| 33 | +# > python part2-adaptive.py -i testvideo.mp4 |
| 34 | +# > python part2-adaptive.py -i testvideo.mp4 -t 8 -m 95 -b 32 -s 0 |
27 | 35 | # |
28 | 36 | # For each fade/cut that is detected, the timecodes and frame numbers |
29 | 37 | # are printed to stdout. Note that this program depends on the Python |
|
40 | 48 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
41 | 49 | # OTHER DEALINGS IN THE SOFTWARE. |
42 | 50 | # |
| 51 | + |
| 52 | + |
| 53 | +import sys |
| 54 | +import argparse |
| 55 | + |
| 56 | +import cv2 |
| 57 | +import numpy as np |
| 58 | + |
| 59 | + |
| 60 | +def int_type_check(min_val, max_val = None, metavar = None): |
| 61 | + if metavar == None: metavar = 'value' |
| 62 | + def _type_check(value): |
| 63 | + value = int(value) |
| 64 | + valid = True |
| 65 | + msg = '' |
| 66 | + if (max_val == None): |
| 67 | + if (value < min_val): valid = False |
| 68 | + msg = 'invalid choice: %d (%s must be at least %d)' % ( |
| 69 | + value, metavar, min_val ) |
| 70 | + else: |
| 71 | + if (value < min_val or value > max_val): valid = False |
| 72 | + msg = 'invalid choice: %d (%s must be between %d and %d)' % ( |
| 73 | + value, metavar, min_val, max_val ) |
| 74 | + if not valid: |
| 75 | + raise argparse.ArgumentTypeError(msg) |
| 76 | + return value |
| 77 | + return _type_check |
| 78 | + |
| 79 | + |
| 80 | +def get_cli_parser(): |
| 81 | + parser = argparse.ArgumentParser( |
| 82 | + formatter_class = argparse.ArgumentDefaultsHelpFormatter) |
| 83 | + parser._optionals.title = 'arguments' |
| 84 | + |
| 85 | + parser.add_argument('-i', '--input', metavar = 'VIDEO_FILE', |
| 86 | + type = file, required = True, |
| 87 | + help = '[REQUIRED] Path to input video.') |
| 88 | + parser.add_argument('-t', '--threshold', metavar = 'intensity', |
| 89 | + type = int_type_check(0, 255, 'intensity'), default = 8, |
| 90 | + help = '8-bit intensity value, from 0-255, to use as a fade in/out detection threshold.') |
| 91 | + parser.add_argument('-m', '--minpercent', metavar = 'percent', |
| 92 | + type = int_type_check(0, 100, 'percentage'), default = 95, |
| 93 | + help = 'Amount of pixels in a frame, from 0-100%%, that must fall under [intensity].') |
| 94 | + parser.add_argument('-b', '--blocksize', metavar = 'rows', |
| 95 | + type = int_type_check(0, None, 'number of rows'), default = 32, |
| 96 | + help = 'Number of rows in frame to check at once, can be tuned for performance.') |
| 97 | + parser.add_argument('-s', '--startindex', metavar = 'offset', |
| 98 | + type = int, default = 0, |
| 99 | + help = 'Starting index for chapter/scene output.') |
| 100 | + |
| 101 | + return parser |
| 102 | + |
| 103 | + |
| 104 | +def main(): |
| 105 | + args = get_cli_parser().parse_args() |
| 106 | + |
| 107 | + print args |
| 108 | + |
| 109 | + pass |
| 110 | + |
| 111 | + |
| 112 | +if __name__ == "__main__": |
| 113 | + main() |
0 commit comments