7.7. Нормалізація¶
ml.Model.predict() приймає список входів, оскільки деякі мережі мають більше одного вхідного тензора, але список не має можливості передавати аргументи для конкретного входу рядково – немає слота kwarg для «обрізати цей вхід до (x, y, w, h), але залишити інші входи без змін». ml.preprocessing.Normalization – це обгортка, що заповнює цей пробіл. Екземпляр Normalization зберігає параметри для одного входу; скрипт передає обгорнутий вхід у списку predict, коли потрібно щось відмінне від стандартних налаштувань.
Найпоширеніша причина звертатись до нього – обрізати конкретну область захопленого кадру для подання в мережу замість цілого зображення.
7.7.1. Параметри¶
Normalization(scale=(0.0, 1.0),
mean=(0.0, 0.0, 0.0),
stdev=(1.0, 1.0, 1.0),
roi=None)
roi– прямокутник(x, y, w, h)у вихідному кадрі для обрізки перед масштабуванням. За замовчуванням – весь кадр. Більшість використаньNormalizationвстановлюють лише цей параметр.scale– діапазон(min, max)числа з плаваючою комою, який очікують вхідні тензори після нормалізації. Діапазон пікселів0..255лінійно відображається в цей діапазон. Поширені значення:(0.0, 1.0)для мереж, навчених з ReLU, та(-1.0, 1.0)для симетрично нормалізованих мереж.mean– середнє по каналах(R, G, B), що віднімається від зображення після масштабування. Відповідає статистиці каналів, на якій навчалась мережа –(0.485, 0.456, 0.406)для мереж на основі ImageNet є канонічним прикладом. Для мереж у відтінках сірого середнє зводиться до значення яскравості за стандартною формулою0.299*R + 0.587*G + 0.114*B.stdev– стандартне відхилення по каналах(R, G, B), на яке ділиться зображення після віднімання середнього, також відповідає статистиці навчання мережі. Зводиться до яскравості так само для мереж у відтінках сірого.
7.7.2. Коли параметри важливі¶
scale, mean та stdev ігноруються, коли input_dtype мережі дорівнює int8 або uint8. Для мереж із цілочисельним входом байти обрізаного зображення записуються безпосередньо в тензор, а власні input_scale та input_zero_point мережі обробляють перетворення між цілим числом і дійсним. Три параметри важливі лише тоді, коли мережа очікує вхід у форматі числа з плаваючою комою.
roi зчитується у кожному випадку – він контролює, яка частина вихідного кадру надходить у мережу незалежно від типу вхідних даних.
7.7.3. Область інтересу (ROI) та масштабування¶
Область інтересу (ROI) білінійно масштабується від своїх вихідних розмірів до вхідних розмірів мережі. Зображення центрується в місці призначення, а масштабування заповнює місце призначення – пропорції не зберігаються. Не квадратна область інтересу (ROI), подана на квадратний вхід мережі, виходить горизонтально або вертикально розтягнутою.
Чи важливе розтягнення, залежить від мережі. Моделі виявлення облич та визначення орієнтирів, як-от сімейство MediaPipe (BlazeFace, FaceLandmarks, HandLandmarks, MoveNet), навчались на квадратних обрізках і швидко погіршуються, коли співвідношення сторін входу відхиляється; для них додаток повинен надавати квадратну область інтересу (ROI) – або захоплюючи при квадратному розмірі кадру через window(), або обрізаючи за допомогою параметра roi=. Детектори об’єктів сімейства YOLO зазвичай навчаються з аугментацією, що включає випадкові розтягнення, і приймають не квадратні ROI без значних втрат точності; як правило, можна передавати захоплений кадр повністю.
Коли вхідні розміри мережі точно збігаються з ROI, масштабування зводиться до копіювання, що є найдешевшим варіантом.
7.7.4. Перевизначення стандартних налаштувань¶
predict() автоматично обгортає кожен вхід image.Image у Normalization() – зі стандартними параметрами, зазначеними вище. Більшість моделей, що постачаються з камерою, навчались на діапазонах пікселів, які вже охоплюють стандартні налаштування, тому у звичайному випадку зображення передається безпосередньо:
result = model.predict([img])
Щоб використовувати власну ROI – найпоширеніше перевизначення – побудуйте Normalization із встановленою ROI та прив’яжіть до неї зображення:
from ml.preprocessing import Normalization
norm = Normalization(roi=(80, 60, 160, 120))
result = model.predict([norm(img)])
Щоб відповідати статистиці каналів під час навчання мережі, встановіть параметри числа з плаваючою комою:
norm = Normalization(scale=(0.0, 1.0),
mean=(0.485, 0.456, 0.406),
stdev=(0.229, 0.224, 0.225))
result = model.predict([norm(img)])
Виклик екземпляра Normalization на зображенні повертає новий прив’язаний екземпляр, з якого двигун заповнює тензор. Прив’язаний екземпляр – це те, що predict приймає замість необробленого зображення, і оскільки це об’єкт для одного входу, мережа з кількома входами може змішувати зображення з різними ROI в одному списку predict.
Для мереж, що очікують входи, які додаток вже підготував у вигляді тензора – буфер від периферійного пристрою, ndarray, обчислений іншим конвеєром, нечислові дані не-зображення – пропустіть Normalization повністю та передайте ndarray або виклик, що його виробляє. predict() передає їх безпосередньо до двигуна без обгортання.