Усе робимо на тому самому синтетичному фото телефона, що й у практиці: функція
make_phone_photo() уже написана в зошиті, скопіюй її до себе й працюй далі.
Нічого завантажувати не треба.
рівень 1Рівень 1 — База
Паспорт чужого зображення.
Зміни в генераторі три числа: висоту й ширину знімка (наприклад, на 480 × 640) і колір
корпусу (зроби його світлим, скажімо 200, 205, 210). Згенеруй фото заново й склади
для нього паспорт: shape, dtype, min, max, size, nbytes, а також середнє
по кожному з трьох каналів окремо.
Потім візьми будь-який квадрат 8 × 8 усередині нового корпусу й роздрукуй його числами в сірому.
Зроблено, якщо:
- надруковано всі шість пунктів паспорта й три середні по каналах;
nbytesзбігається з тим, що ти порахував руками яквисота × ширина × 3;- фрагмент 8 × 8 надруковано, і ти можеш сказати словами, чому в ньому всі числа близькі одне до одного, а на межі корпусу — ні.
рівень 2Рівень 2 — Плюс
Виділення за кольором, яке не боїться освітлення.
Напиши дві функції, кожна повертає булеву маску того самого розміру, що знімок:
select_by_rgb(image)— три пороги по каналах R, G, B;select_by_hue(image)— один поріг по відтінку H у HSV.
Обидві мають шукати зелений індикатор. Далі побудуй серію з семи варіантів освітлення: помнож знімок на 0.4, 0.55, 0.7, 0.85, 1.0, 1.15 і 1.3 (з обрізанням по 255) і для кожного порахуй, скільки пікселів знайшла кожна функція.
Побудуй графік: по горизонталі — множник яскравості, по вертикалі — кількість знайдених пікселів, дві криві й горизонтальна пряма на рівні справжньої кількості (1439 пікселів для оригінального розміру знімка).
Зроблено, якщо:
- графік побудовано, обидві криві підписані;
- крива HSV лежить на прямій «скільки треба» майже на всьому діапазоні, а крива RGB відходить від неї;
- у висновку двома-трьома реченнями сказано, чому так, а не просто «HSV кращий».
рівень 3Рівень 3 — Виклик
Розтягування гістограми з нуля.
Реалізуй функцію stretch_contrast(gray_image), яка приймає сіре зображення
й повертає нове, де найтемніший піксель став 0, а найсвітліший — 255, а всі проміжні
розтягнуті пропорційно. Формулу виведи сам: тобі потрібні лише мінімум, максимум
і одна лінійна залежність.
Вимоги до реалізації:
- жодного
cv2.normalizeі жодного циклу по пікселях — тільки арифметика над масивом; - проміжні обчислення у
float32абоint16, обрізання один раз наприкінці; - функція має коректно поводитись, якщо на вхід прийшло однорідне зображення, де мінімум дорівнює максимуму (ділення на нуль ловимо самі).
Застосуй до притемненого варіанта (gray × 0.45) і покажи чотири речі поруч:
притемнене фото, його гістограму, розтягнуте фото, його гістограму.
Зроблено, якщо:
- після розтягування
minдорівнює 0, аmaxдорівнює 255 — перевіреноassert-ом; - обидві гістограми показано поруч, і видно, що друга займає всю ширину;
- ти можеш пояснити, що саме розтягування не повертає: якщо в притемненому знімку кілька різних яскравостей злилися в одне число, розтягування їх не розділить.
Підказки
-
Порядок каналів. Кожного разу, коли передаєш масив у будь-яку функцію
cv2, спитай себе: вона чекає RGB чи BGR? Помилка тут не викидає винятку — вона просто дає неправильну відповідь. -
Рівень 2. Пороги по RGB підбирай на оригінальному знімку, а потім більше не чіпай. Якщо підганяти їх під кожен рівень освітлення окремо, дослід втрачає сенс: уся суть у тому, що в реальній задачі ти не знаєш наперед, яке буде світло.
-
Рівень 3. Лінійна залежність, яка переводить відрізок
[min, max]у відрізок[0, 255], будується у два кроки: спершу зсунь так, щоб мінімум став нулем, потім розтягни так, щоб максимум став 255. Обидва кроки — одна дія над усім масивом. -
Якщо результат виглядає зашумленим сильніше за оригінал — так і має бути. Розтягування підсилює все підряд, шум матриці зокрема.