| # Migration Guide - Old to New Structure |
|
|
| ## Overview |
|
|
| This guide explains how to update your code imports from the old structure to the new reorganized structure. |
|
|
| ## Old Structure vs New Structure |
|
|
| ### Model Imports |
|
|
| #### BEFORE (Old Structure) |
| ```python |
| from NETRA.violence_detector import ViolenceDetector |
| from NETRA.yolo_detector import YOLODetector |
| from NETRA.weapon_person_detector import WeaponPersonDetector |
| from NETRA.anomaly_detector import AnomalyDetector |
| from NETRA.video_capture import VideoCapture |
| from pose_detection import PoseDetection |
| ``` |
|
|
| #### AFTER (New Structure) |
| ```python |
| from src.detectors import ( |
| ViolenceDetector, |
| YOLODetector, |
| WeaponPersonDetector, |
| PoseDetection, |
| AnomalyDetector, |
| ) |
| from src.pipeline import VideoCapture |
| ``` |
|
|
| **Or use the main src module:** |
| ```python |
| from src import ( |
| ViolenceDetector, |
| YOLODetector, |
| WeaponPersonDetector, |
| PoseDetection, |
| AnomalyDetector, |
| VideoCapture, |
| ) |
| ``` |
|
|
| ### Configuration Imports |
|
|
| #### BEFORE (Hardcoded paths in code) |
| ```python |
| # Scattered throughout app.py |
| violence_model_path = Path(__file__).parent.parent / "NETRA" / "model" / "violence_model.h5" |
| yolo_model_candidates = [ |
| Path(__file__).parent.parent / "ai_models" / "object_detection" / "yolov8n.pt", |
| ... |
| ] |
| ``` |
|
|
| #### AFTER (Centralized in config) |
| ```python |
| from config import MODEL_PATHS, get_model_path, DETECTION_THRESHOLDS, PROCESSING_PARAMS |
| |
| # Get a specific model path |
| violence_model = get_model_path('violence') |
| |
| # Get threshold |
| yolo_threshold = DETECTION_THRESHOLDS['yolo'] # 0.25 |
| |
| # Get processing parameters |
| frame_skip = PROCESSING_PARAMS['frame_skip'] # 10 |
| ``` |
|
|
| ### Settings Imports |
|
|
| #### BEFORE (Config spread throughout app.py) |
| ```python |
| app.config['SECRET_KEY'] = 'netra-surveillance-secret-key-2024' |
| app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///netra.db' |
| app.config['MAX_CONTENT_LENGTH'] = 500 * 1024 * 1024 |
| ``` |
|
|
| #### AFTER (Centralized in config) |
| ```python |
| from config import SECRET_KEY, DATABASE_URI, MAX_CONTENT_LENGTH |
| |
| app.config['SECRET_KEY'] = SECRET_KEY |
| app.config['SQLALCHEMY_DATABASE_URI'] = DATABASE_URI |
| app.config['MAX_CONTENT_LENGTH'] = MAX_CONTENT_LENGTH |
| ``` |
|
|
| ## Step-by-Step webapp/app.py Update |
|
|
| ### Step 1: Update Imports (Top of file) |
|
|
| **REPLACE:** |
| ```python |
| from NETRA.violence_detector import ViolenceDetector |
| from NETRA.yolo_detector import YOLODetector |
| from NETRA.weapon_person_detector import WeaponPersonDetector |
| from NETRA.anomaly_detector import AnomalyDetector |
| from NETRA.video_capture import VideoCapture |
| from pose_detection import PoseDetection |
| ``` |
|
|
| **WITH:** |
| ```python |
| from src import ( |
| ViolenceDetector, |
| YOLODetector, |
| WeaponPersonDetector, |
| PoseDetection, |
| AnomalyDetector, |
| VideoCapture, |
| ) |
| from config import ( |
| MODEL_PATHS, |
| get_model_path, |
| DETECTION_THRESHOLDS, |
| PROCESSING_PARAMS, |
| SECRET_KEY, |
| DATABASE_URI, |
| MAX_CONTENT_LENGTH, |
| UPLOAD_FOLDER, |
| PROCESSED_FOLDER, |
| INSTANCE_FOLDER, |
| ) |
| ``` |
|
|
| ### Step 2: Update sys.path (No longer needed!) |
|
|
| **REMOVE THIS:** |
| ```python |
| sys.path.append(str(Path(__file__).parent.parent)) |
| sys.path.append(str(Path(__file__).parent.parent / "NETRA")) |
| sys.path.append(str(Path(__file__).parent.parent / "detection logic")) |
| ``` |
|
|
| **INSTEAD:** Just add project root if needed: |
| ```python |
| sys.path.insert(0, str(Path(__file__).parent.parent)) |
| ``` |
|
|
| ### Step 3: Update Configuration |
|
|
| **REPLACE:** |
| ```python |
| app.config['SECRET_KEY'] = 'netra-surveillance-secret-key-2024' |
| app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///netra.db' |
| app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False |
| app.config['UPLOAD_FOLDER'] = str(Path(__file__).parent / 'uploads') |
| app.config['PROCESSED_FOLDER'] = str(Path(app.config['UPLOAD_FOLDER']) / 'processed') |
| app.config['MAX_CONTENT_LENGTH'] = 500 * 1024 * 1024 |
| |
| os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True) |
| os.makedirs(app.config['PROCESSED_FOLDER'], exist_ok=True) |
| ``` |
|
|
| **WITH:** |
| ```python |
| app.config['SECRET_KEY'] = SECRET_KEY |
| app.config['SQLALCHEMY_DATABASE_URI'] = DATABASE_URI |
| app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False |
| app.config['UPLOAD_FOLDER'] = str(UPLOAD_FOLDER) |
| app.config['PROCESSED_FOLDER'] = str(PROCESSED_FOLDER) |
| app.config['MAX_CONTENT_LENGTH'] = MAX_CONTENT_LENGTH |
| |
| # Folders already created by config/settings.py |
| ``` |
|
|
| ### Step 4: Update Model Loading in ModelManager |
|
|
| **REPLACE hardcoded paths like:** |
| ```python |
| violence_model_path = Path(__file__).parent.parent / "NETRA" / "model" / "violence_model.h5" |
| yolo_model_candidates = [...] |
| ``` |
|
|
| **WITH:** |
| ```python |
| violence_model_path = get_model_path('violence') |
| yolo_model_path = get_model_path('yolo') |
| weapon_gun_path = get_model_path('weapon') |
| pose_model_path = get_model_path('pose') |
| anomaly_model_path = get_model_path('anomaly') |
| ``` |
|
|
| ### Step 5: Update Detection Thresholds |
|
|
| **REPLACE:** |
| ```python |
| detections = yolo_model.detect(frame, conf_threshold=0.25) |
| violence_result = violence_model.detect_violence(frame, confidence_threshold=0.6) |
| ``` |
|
|
| **WITH:** |
| ```python |
| detections = yolo_model.detect(frame, conf_threshold=DETECTION_THRESHOLDS['yolo']) |
| violence_result = violence_model.detect_violence(frame, confidence_threshold=DETECTION_THRESHOLDS['violence']) |
| ``` |
|
|
| ### Step 6: Update Video Processing Parameters |
|
|
| **REPLACE:** |
| ```python |
| if frame_count % 10 == 0: # Magic number |
| results = video_processor.process_frame(frame) |
| ``` |
|
|
| **WITH:** |
| ```python |
| if frame_count % PROCESSING_PARAMS['frame_skip'] == 0: |
| results = video_processor.process_frame(frame) |
| ``` |
|
|
| ## Benefits of Migration |
|
|
| ✅ **Cleaner Imports** - All imports from organized src/ and config/ |
| ✅ **Centralized Configuration** - Single source of truth for paths and thresholds |
| ✅ **Easier Maintenance** - Update model paths once in config/model_config.py |
| ✅ **Better Scalability** - Easy to add new models or modules |
| ✅ **Less Code Duplication** - No scattered hardcoded paths |
| |
| ## Testing After Migration |
| |
| After updating app.py, verify: |
| |
| ```bash |
| # Test imports work |
| python -c "from src import YOLODetector; print('✓ Imports OK')" |
| |
| # Test config loads |
| python -c "from config import get_all_available_models; print(get_all_available_models())" |
| |
| # Test app starts |
| python webapp/app.py |
| ``` |
| |
| ## Summary of Changes |
| |
| | What Changed | Was | Now | |
| |--------------|-----|-----| |
| | **Detector location** | `NETRA/` | `src/detectors/` | |
| | **Pipeline location** | `NETRA/` | `src/pipeline/` | |
| | **Model paths** | Hardcoded | `config/model_config.py` | |
| | **Settings** | Scattered | `config/settings.py` | |
| | **Models organization** | `ai_models/mixed` | `models/type/` | |
| | **Documentation** | `webapp/ARCHITECTURE.md` | `docs/` | |
|
|
| ## If You Need Help |
|
|
| Refer to `docs/PROJECT_STRUCTURE.md` for detailed explanation of each component. |
|
|