-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathmain.py
More file actions
155 lines (127 loc) · 5.14 KB
/
main.py
File metadata and controls
155 lines (127 loc) · 5.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
import argparse
import logging
import os
import sys
import time
from Application.Config import Config
from Application.ContourExctractor import ContourExtractor
from Application.Exporter import Exporter
from Application.HeatMap import HeatMap
from Application.Importer import Importer
from Application.LayerFactory import LayerFactory
from Application.LayerManager import LayerManager
from Application.Logger import get_logger, setup_logger
from Application.VideoReader import VideoReader
# Setup logging
setup_logger()
logger = get_logger(__name__)
def main(config: Config) -> int:
"""
Main processing pipeline for video summarization.
Args:
config: Configuration object with processing parameters
Returns:
Exit code (0 for success, 1 for failure)
"""
start_total = time.time()
try:
# Check if cached data exists
cache_path = config["cachePath"] + "_layers.txt"
if os.path.exists(cache_path):
logger.info(f"Loading cached data from {cache_path}")
layers, contours, masks = Importer(config).import_raw_data()
layers = LayerFactory(config).extract_layers(contours, masks)
else:
logger.info("Extracting contours from video...")
contours, masks = ContourExtractor(config).extract_contours()
logger.info("Extracting layers from contours...")
layers = LayerFactory(config).extract_layers(contours, masks)
logger.info("Cleaning layers...")
layer_manager = LayerManager(config, layers)
layer_manager.clean_layers()
# Check if we have any layers to process
if len(layer_manager.layers) == 0:
logger.error("No layers found to process. Exiting.")
return 1
# Generate heatmap
logger.info("Generating heatmap...")
heatmap = HeatMap(
config["w"], config["h"], [contour for layer in layer_manager.layers for contour in layer.bounds], 1920 / config["resizeWidth"]
)
heatmap.show_image()
# Export results
logger.info(f"Exporting {len(contours)} Contours and {len(layer_manager.layers)} Layers")
Exporter(config).export(layer_manager.layers, contours, masks, raw=True, overlayed=True)
total_time = time.time() - start_total
logger.info(f"Total processing time: {total_time:.2f} seconds")
return 0
except Exception as e:
logger.error(f"Error during processing: {e}", exc_info=True)
return 1
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="Video-Summary: Extract movement from static camera recordings",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Examples:
%(prog)s input_video.mp4 output_dir
%(prog)s input_video.mp4 output_dir configs/default.yaml
%(prog)s input_video.mp4 output_dir configs/high-sensitivity.yaml --verbose
Configuration:
Supports both JSON and YAML config files.
Use environment variables for overrides: VIDEO_SUMMARY_THRESHOLD=10
For more information, see: https://github.com/Askill/Video-Summary
""",
)
parser.add_argument("input", metavar="input_file", type=str, help="Input video file to extract movement from")
parser.add_argument(
"output",
metavar="output_dir",
type=str,
nargs="?",
default="output",
help="Output directory to save results and cached files (default: output)",
)
parser.add_argument(
"config",
metavar="config",
type=str,
nargs="?",
default=None,
help="Path to configuration file (JSON or YAML, optional)",
)
parser.add_argument("--verbose", "-v", action="store_true", help="Enable verbose/debug logging")
parser.add_argument("--version", action="version", version="%(prog)s 0.1.0")
args = parser.parse_args()
# Setup logging level
if args.verbose:
setup_logger(level=logging.DEBUG)
try:
# Load configuration
config = Config(args.config)
# Resolve paths
input_path = os.path.join(os.path.dirname(__file__), args.input)
output_path = os.path.join(os.path.dirname(__file__), args.output)
# Validate input file exists
if not os.path.exists(input_path):
logger.error(f"Input file not found: {input_path}")
sys.exit(1)
# Create output directory if it doesn't exist
os.makedirs(output_path, exist_ok=True)
file_name = os.path.basename(input_path)
# Configure paths
config["inputPath"] = input_path
config["outputPath"] = os.path.join(output_path, file_name)
config["cachePath"] = os.path.join(output_path, os.path.splitext(file_name)[0])
# Get video dimensions
logger.info("Reading video dimensions...")
config["w"], config["h"] = VideoReader(config).get_wh()
# Run main processing
exit_code = main(config)
sys.exit(exit_code)
except KeyboardInterrupt:
logger.warning("Processing interrupted by user")
sys.exit(130)
except Exception as e:
logger.error(f"Unhandled exception: {e}", exc_info=True)
sys.exit(1)