File size: 3,927 Bytes
da15776
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
#!/usr/bin/env bash
# SPDX-License-Identifier: MIT
# Copyright (C) Intel Corporation
#
# Export a community YOLOv26 fire/smoke detector to OpenVINO IR for the
# fire-and-smoke-detection use case. The model detects the "fire" and
# "smoke" classes.
# Usage: ./export_and_quantize.sh [PRECISION]
# Example: ./export_and_quantize.sh FP16

set -euo pipefail

PRECISION="${1:-FP16}"
PRECISION="$(echo "${PRECISION}" | tr '[:lower:]' '[:upper:]')"

MODEL_NAME="yolov26_fire"
MODEL_URL="https://huggingface.co/SalahALHaismawi/yolov26-fire-detection/resolve/main/best.pt"

# CC0 / Pexels-licensed sample video: "Aerial view of wildfire in forested
# area" by K (Kelly), free to use via Pexels.
VIDEO_URL="https://www.pexels.com/download/video/30937716/"

if [[ "${PRECISION}" != "FP32" && "${PRECISION}" != "FP16" && "${PRECISION}" != "INT8" ]]; then
    echo "ERROR: unsupported precision '${PRECISION}'. Choose FP32, FP16, or INT8." >&2
    exit 1
fi

echo "--- Installing dependencies ---"
if [[ "${PRECISION}" == "INT8" ]]; then
    pip install -qU openvino nncf ultralytics
else
    pip install -qU openvino ultralytics
fi

# Ask for approval before downloading models and sample files
echo ""
echo "This script will download:"
echo "  - Community YOLOv26 fire/smoke model weights"
echo "  - A Pexels-licensed sample wildfire video"
echo ""
read -p "Continue with downloads? (yes/no): " APPROVAL
if [[ "${APPROVAL}" != "yes" ]]; then
    echo "Download cancelled by user."
    exit 0
fi
echo ""

echo "--- Downloading fire/smoke model weights ---"
if [[ ! -f "${MODEL_NAME}.pt" ]]; then
    curl -sL -o "${MODEL_NAME}.pt" "${MODEL_URL}"
    echo "Downloaded: ${MODEL_NAME}.pt"
else
    echo "Already present: ${MODEL_NAME}.pt"
fi

echo "--- Downloading and transcoding sample test video ---"
# Both samples run on an H.264 MP4. A fire/smoke-rich 8-second window is
# trimmed, center-cropped to a square (so the fixed 640x640 resize does not
# distort the aspect ratio the model is sensitive to), and transcoded with
# ffmpeg.
if [[ ! -f test_video.mp4 ]]; then
    if ! command -v ffmpeg >/dev/null 2>&1; then
        echo "ERROR: ffmpeg is required to transcode the sample video." >&2
        echo "Install it (e.g. 'sudo apt-get install ffmpeg') and re-run." >&2
        exit 1
    fi
    curl -sL -o fire_source.mp4 "${VIDEO_URL}"
    ffmpeg -y -loglevel error -ss 2 -t 8 -i fire_source.mp4 \
        -vf "crop=ih:ih,scale=736:736,format=yuv420p" \
        -c:v libx264 -preset veryfast -an test_video.mp4
    rm -f fire_source.mp4
    echo "Downloaded and transcoded: test_video.mp4"
else
    echo "Already present: test_video.mp4"
fi

if [[ "${PRECISION}" == "FP32" ]]; then
    HALF_FLAG="False"
    EXPORT_LABEL="FP32"
else
    HALF_FLAG="True"
    EXPORT_LABEL="FP16"
fi

echo "--- Exporting ${MODEL_NAME} to OpenVINO IR (${EXPORT_LABEL}) ---"
python3 -c "
from ultralytics import YOLO

model = YOLO('${MODEL_NAME}.pt')
model.export(format='openvino', half=${HALF_FLAG}, dynamic=False, imgsz=640)
print('Export complete: ${MODEL_NAME}_openvino_model/')
"

if [[ "${PRECISION}" == "INT8" ]]; then
    echo "--- Quantizing to INT8 with NNCF ---"
    python3 -c "
import nncf
import openvino as ov
import numpy as np
import cv2

core = ov.Core()
model = core.read_model('${MODEL_NAME}_openvino_model/${MODEL_NAME}.xml')

cap = cv2.VideoCapture('test_video.mp4')
ok, frame = cap.read()
cap.release()
img = cv2.resize(frame, (640, 640))
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB).astype(np.float32) / 255.0
img = img.transpose(2, 0, 1)[np.newaxis, ...]

def transform_fn(data_item):
    return img

calibration_dataset = nncf.Dataset(list(range(300)), transform_fn)

quantized = nncf.quantize(
    model,
    calibration_dataset,
    preset=nncf.QuantizationPreset.MIXED,
    subset_size=300,
)

ov.save_model(quantized, '${MODEL_NAME}_int8.xml')
print('Quantization complete: ${MODEL_NAME}_int8.xml')
"
fi
echo "--- Done ---"