Виявлення обличчя на зображенні
Курсова
робота
Виявлення
обличчя на зображенні
АНОТАЦІЯ
У даній курсовій роботі реалізується
алгоритм виявлення обличчя на зображенні у візуальному середовищі Delphi.
інтерфейс програма локалізація особа зображення
Зміст
Вступ
Розділ 1. Завдання виявлення
обличчя в загальному
1.1 Виявлення і локалізація
обличчя на зображенні
1.2 Методи першої категорії -
емпіричне розпізнавання
1.3 Виявлення елементів і
особливостей, які характерні для зображення обличчя
1.4 Методи другої категорії,
моделювання зображення обличчя
1.5 Переваги і недоліки методів
першої і другої групи
Розділ 2. Алгоритми для
виявлення обличчя
2.1 Виділення областей за
кольором шкіри
2.2 Алгоритм аналізу форми
областей зображення
2.3 Визначення розривів
яскравості
2.3.1 Загальні положення
2.3.2 Визначення точок
2.3.3 Визначення ліній
2.3.4 Визначення перепадів
2.3.5 Оператори градієнта
Розділ 3. Опис програми
3.1 Структура програми
3.2 Інтерфейс користувача
Висновки
Список літератури
Додатки
Код програми
Вступ
За останні десять років дослідження
з виявлення обличчя людини значно активізувалися, що пояснюється виникненням
багатьох застосувань для даної задачі, коли виявлення обличчя є першим кроком
для будь-якої його обробки: розпізнавання обличчя, відео конференція, пошук зображень
за змістом, відео спостереження, людино-комп’ютерний інтерфейс, аналіз емоцій,
підрахунок відвідувачів, контроль доступу та інші.
Задача виявлення особи на зображенні
є більш ніж простою для людського зору, однак при спробі побудови автоматичної
системи виявлення осіб доводиться зіткнутися з наступними труднощами:
· Сильно варіюється зовнішній
вигляд обличчя у різних людей;
· Навіть відносно
невелика зміна орієнтації особи щодо камери тягне за собою серйозну зміну
зображення обличчя;
· Можлива присутність
індивідуальних особливостей (вуса, борода, окуляри, зморшки і т.д.) істотно
ускладнює автоматичне розпізнавання;
· Зміна виразу
обличчя може сильно позначитися на тому, як особа виглядає на зображенні;
· Частина обличчя
може бути невидима (закрита іншими предметами) на зображенні;
· Умови зйомки
(освітлення, спотворення зображення, що вноситься оптикою системи, якість
зображення) значною мірою впливають на зображення обличчя;
Розділ
1. Завдання виявлення обличчя в загальному
1.1
Виявлення і локалізація обличчя на зображенні
Існуючі алгоритми виявлення обличчя
можна розбити на дві широкі категорії. До першої категорії належать методи, що
опирається на досвід людини в розпізнаванні обличчя і які роблять спробу
формалізувати і алгоритмізувати цей досвід, побудувавши на його основі
автоматичну систему розпізнавання. Друга категорія спирається на інструментарій
розпізнавання образів, розглядаючи задачу виявлення особи, як окремий випадок
задачі розпізнавання.
1.2
Методи першої категорії - емпіричне розпізнавання
Людський мозок справляється із
завданням виявлення осіб на зображеннях більш ніж успішно. Природно було б
спробувати визначити і використовувати принципи, якими керується мозок при
вирішенні задачі розпізнавання. Серед методів, які роблять таку спробу, можна
виділити два напрями: методи розпізнавання "зверху-вниз" засновані на
знаннях і методи розпізнавання "знизу-вверх" засновані на
особливостях.
Розпізнавання
"зверху-вниз" означає побудову деякого набору правил, яким повинен
відповідати фрагмент зображення, для того щоб бути визнаним людським обличчям.
Цей набір правил є спробою
формалізувати емпіричні знання про те, як саме виглядає обличчя на зображеннях
і чим керується людина при прийнятті рішення обличчя вона бачить чи ні. Досить
легко побудувати набір простих і очевидних (як здається) властивостей
зображення обличчя, наприклад: обличчя зазвичай симетричне, риси обличчя (очі,
ніс, рот) відрізняються від шкіри по яскравості (зазвичай їм також відповідають
області різкої зміни яскравості), риси обличчя розташовані цілком певним чином.
Спираючись на перелічені властивості, можна побудувати алгоритм перевіряючий їх
наявність на фрагменті зображення. До цього ж сімейства методик можна також
віднести розпізнавання за допомогою шаблонів, заданих розробником (predefined
template matching). Шаблони задають якийсь стандартний образ зображення
обличчя, наприклад, шляхом опису властивостей окремих областей обличчя та їх
можливого взаємного розташування.
Виявлення обличчя за допомогою
шаблону полягає у перевірці кожної з областей зображення на відповідність
заданому шаблону.
Принципи шаблонів і інші методи
розпізнавання "зверху-вниз" використовувалися, в основному, в ранніх
роботах з виявлення обличчя. Це були перші спроби формалізації ознак зображень
обличчя, до того ж обчислювальні потужності комп'ютерів в ті роки не дозволяли
ефективно використовувати більш складні методи розпізнавання зображень.
Незважаючи на деяку наївність алгоритмів, не варто недооцінювати значення цих
робіт, оскільки багато методик, що успішно застосовуються в даний час, були
розроблені або адаптовані до даної конкретної проблеми саме в них.
Розпізнавання
"знизу-вверх" використовує інваріантні властивості (invariant
features) зображень облич, спираючись на припущення, що якщо людина може без
зусиль розпізнати обличчя на зображенні незалежно від його орієнтації, умов
освітлення і індивідуальних особливостей, то повинні існувати деякі ознаки
присутності осіб на зображень, інваріантні щодо умов зйомки.
Алгоритм роботи методів розпізнавання
"знизу-вверх" може бути коротко описаний таким чином:
. Виявлення елементів і особливостей
(features), які характерні для зображення обличчя;
. Аналіз виявлених особливостей,
винесення рішення про кількість і розташування облич.
1.3
Виявлення елементів і особливостей, які характерні для зображення обличчя
Краї (edges) - різкі переходи
яскравості. Краї зазвичай відповідають кордонам об'єктів на зображенні.
Використовуючи цей факт і те, що особа представляє собою еліпс певних пропорцій
(близьких для різних людей) були зроблені спроби розпізнавання особи за
допомогою карти країв (зображення, на якому позначені різкі переходи
яскравості) і характерної форми обличчя. Різкі переходи яскравості також часто
відповідають рисам обличчя - (facial features) - кордонам очей, брів, рота,
носа. Це властивість також використовується в ряді робіт, які розглядають краї
на зображенні як ознаки потенційної присутності обличчя.
Яскравість. Області зображення, що
відповідають рисами обличчя, часто темніші, ніж шкіра, що їх оточує.
Скориставшись цим спостереженням, ряд дослідників використовує алгоритми
виявлення і підкреслення областей локальних мінімумів яскравості, розглядаючи
їх як потенційні риси обличчя. У деяких роботах робиться спроба використовувати
певні схеми взаємин яскравості, характерних для деяких рис обличчя.
Колір - незважаючи на те, що
яскравість зазвичай є основним джерелом інформації в багатьох задачах машинного
зору, колір (завдяки додатковій інформації про відтінок об'єкта) є більш
потужним засобом розпізнавання об'єктів на зображенні. Як показали
експерименти, колір шкіри різних людей займає досить невелику обмежену
підобласть колірного простору, навіть при розгляданні кольорів шкіри різних
рас. Причому основна відмінність полягає в яскравості, а не відтінку кольору,
що дозволяє зробити висновок про близькість відтінку кольору шкіри різних людей
і використовувати характерний колір шкіри як ознаку для розпізнавання облич.
Характерна форма рис обличчя.
Виходячи з того, що процесам розпізнавання візуальних образів високого рівня в
мозку передує якась низькорівнева організація візуальної інформації, було
запропоновано кілька операторів, що підкреслюють області зображення, з
властивостями, характерними для рис обличчя. Такими, наприклад, як
симетричність, близькість кордону рис обличчя за формою до параболи.
Результатом застосування таких операторів є набір точок на зображенні, з
високою ймовірністю пов'язаних з рисами обличчя. Інший близький варіант
розпізнавання - використання жорстких шаблонів для виявлення рис обличчя
(наприклад, очей).
Після того, як на зображенні
виділені області, які мають властивості, характерні для людського обличчя,
проводиться їх комплексна перевірка для виявлення областей, які дійсно є
особами. Сутність цієї перевірки залежить від характеру ознак, що
використовуються, а також від обраної дослідниками стратегії. Наприклад, якщо в
якості ознак виступають потенційні риси обличчя, виявлені за допомогою аналізу
карти країв, то перевіркою буде аналіз їх взаємного розташування з метою визначення,
чи можуть вони утворювати людське обличчя. Якщо використовується також
розпізнавання за кольором, то може бути додано додаткову умову, що розглядатися
в якості потенційних осіб будуть тільки області близькі за кольором до відтінку
шкіри, причому форма областей повинна бути еліптичною. Перевірка співвідношення
виявлених ознак особи може бути заснована на: деякому емпіричному алгоритмі,
статистикою взаємного розташування ознак, зібраної по зображеннях облич,
моделюванні процесів, що відбуваються в людському мозку при розпізнаванні
візуальних образів, застосування шаблонів розташування рис обличчя і т.д.
1.4
Методи другої категорії, моделювання зображення обличчя
Друге сімейство методів підходить до
проблеми з іншого боку, і, не намагаючись в явному вигляді формалізувати
процеси, що відбуваються в людському мозку, намагається виявити закономірності
і властивості зображення обличчя неявно, застосовуючи методи математичної
статистики і машинного навчання. Методи цієї категорії спираються на
інструментарій розпізнавання образів, розглядаючи задачу виявлення обличчя, як
окремий випадок задачі розпізнавання. Зображенню (або його фрагменту) ставиться
у відповідність певним чином обчислений вектор ознак, який використовується для
класифікації зображень на два класи - обличчя / не обличчя. Найпоширеніший
спосіб отримання вектора ознак це використання самого зображення: кожен піксель
стає компонентом вектора, перетворюючи чорно-біле зображення n ×
m у вектор простору Rn ×
m. Недоліком такого подання є надзвичайно висока
розмірність простору ознак. Перевага полягає тому, що використовуючи всі
зображення цілком замість обчислених на його основі характеристик, з усієї
процедури побудови класифікатора (включаючи виділення стійких ознак для
розпізнавання) повністю виключається участь людини, що потенційно знижує
ймовірність помилки побудови неправильної моделі зображення особи внаслідок
невірних рішень і помилок розробника.
Зазвичай пошук облич на зображеннях
з допомогою методів, заснованих на побудові математичної моделі зображення
обличчя, полягає в повному переборі всіх прямокутних фрагментів зображення
всіляких розмірів і проведення перевірки кожного з фрагментів на наявність
обличчя. Оскільки схема повного перебору володіє такими безумовними недоліками,
як надмірність і велика обчислювальна складність, авторами застосовуються різні
методи скорочення кількості розглянутих фрагментів.
1.5
Переваги і недоліки методів першої і другої групи
Основа методів першої категорії -
емпірика, є одночасно їх сильною і слабкою стороною. Велика мінливість об'єкта
розпізнавання, залежність вигляду обличчя на зображенні від умов зйомки і
освітлення дозволяють без вагань віднести виявлення особи на зображенні до
завдань високої складності. Застосування емпіричних правил дозволяє побудувати
певну модель зображення обличчя і звести задачу до виконання деякої кількості
відносно простих перевірок. Однак, незважаючи на безумовно розумну посилку -
спробувати використовувати і повторити вже успішно функціонуючий інструмент
розпізнавання - людський зір, методи першої категорії поки далекі по
ефективності від свого прообразу, оскільки дослідники, які вирішили обрати цей
шлях, стикаються з низкою серйозних труднощів. По-перше, процеси, що
відбуваються в мозку під час вирішення задачі розпізнавання зображень вивчені
далеко не повністю, і той набір емпіричних знань про людське обличчя, які
доступні дослідникам на "свідомому рівні", далеко не вичерпує
інструментарій, використовуваний мозком "підсвідомо". По-друге, важко
ефективно перевести неформальний людський досвід і знання в набір формальних
правил, оскільки надто жорсткі рамки правил приведуть до того, що в ряді
випадків особи не будуть виявлені, і навпаки, дуже загальні правила приведуть
до великої кількості випадків помилкового виявлення.
Можна перерахувати такі проблеми,
спільні для методів другої категорії:
1. Залежність від орієнтації і
масштабу обличчя. Більшість класифікаторів не є інваріантними до повороту особи
в площині зображення і зміни його розміру. Тому для успішного виявлення особи,
відмінного за розміром або орієнтації від облич у тренувальному наборі,
потрібна додаткова обробка вхідного зображення (масштабування, поворот).
Проблему зміни масштабу вирішують, зазвичай, шляхом повного перебору всіх
можливих прямокутних фрагментів зображення всіх можливих розмірів. Спроба ж
розглядати ще і всі можливі кути повороту осіб у площині зображення приведе до
того, що час виконання і без того довгої процедури перебору фрагментів
перевищить всі мислимі межі. Якщо говорити про поворот голови поза площиною
зображення, то це є проблемою для багатьох методів з обох категорій, оскільки
при значному повороті обличчя на зображенні змінюється настільки сильно, що
багато ознак і правила (задані розробником або отримані неявно) розпізнавання
фронтального зображення обличчя стають абсолютно непридатними .
2. Неявний спосіб визначення ознак
для розпізнавання особи таїть в собі потенційну небезпеку: класифікатор, що
володіє недостатньо репрезентативним набором зображень облич, теоретично може
виділити вторинні або помилкові ознаки в якості важливих. Один з наслідків -
потенційна залежність від освітлення, яке переважало в тренувальному наборі. У
ряді випадків застосовується додаткова передобробка зображення для компенсації
впливу освітлення.
3.Висока обчислювальна складність.
По-перше, самі класифікатори часто включають в себе велику кількість досить
складних обчислень, по-друге, повний перебір всіх можливих прямокутних
фрагментів зображення сам по собі займає велику кількість часу. Це ускладнює
використання деяких методів у системах реального часу (наприклад - відстеження
переміщення особи в відео потоці). Порівнювати
між собою якість розпізнавання методів різних категорій досить важко, оскільки
в більшості випадків, спиратися можна лише на дані випробувань, що надаються
самими авторами, оскільки провести великомасштабне дослідження щодо реалізації
більшості відомих методів і порівняння їх між собою на єдиному наборі зображень
не представляється можливим унаслідок неймовірною трудомісткості цього
завдання. На основі інформації, наданої авторами методів, також складно
провести коректне порівняння, оскільки перевірка методів часто проводиться на
різних наборах зображень, з різним формулюванням умов успішного і неуспішного
виявлення. До того ж перевірка для багатьох методів першої категорії
проводилася на значно менших наборах зображень.
Помітне розходження між першою і
другою категорією описаних методів полягає ще й у тому, що емпіричні методи
часто досить прості в реалізації (особливо щодо методів другої категорії), і надають
можливість гнучкого налаштування під конкретну задачу шляхом модифікації
інтуїтивно зрозумілих параметрів. Методи, що спираються на інструментарій
розпізнавання образів, вимагають значних зусиль з формування тренувальних
наборів зображень та навчання класифікатора. Проте трудомісткість створення
робочих прототипів методів другої категорії частково компенсується високими
заявленими показниками якості розпізнавання на великих колекціях зображень.
Що
стосується рекомендацій щодо вибору методу для вирішення задачі виявлення осіб,
то можна сказати, що обирати відповідний метод, виходячи з цифрових показників
якості розпізнавання навряд чи доцільно. Скоріше, все залежить від конкретної
задачі і умов в яких повинен функціонувати розроблюваний алгоритм. Побудова
універсального методу, що забезпечує високий рівень розпізнавання при
відсутності обмежень на вихідні зображення в даний час не представляється
можливим, однак для більшості конкретних завдань можна створити методи, що
надають достатній рівень розпізнавання. В
якості умов, що впливають на вибір методу розв'язання задачі, можна
перерахувати такі: Передбачувана
різноманітність осіб: обмежений набір людей, обмеження на можливий тип особи
(раса, присутність волосся на обличчі, окулярів і т.д.), відсутність обмежень;
· Орієнтація осіб на
зображенні: строго вертикальна (або нахил під відомим кутом), в певних межах
поблизу відомого кута нахилу, будь-яка;
· Кольорове або
чорно-біле зображення;
· Масштаб облич і
якість зображення (зашумленість, ступінь стиснення);
· Умови освітлення:
фіксовані відомі, приблизно відомі, будь-які;
· Фон: фіксований,
контрастний однотонний, слабоконтрастних зашумлений, невідомий;
· Що важливіше - не
пропустити ні однієї особи чи мінімізувати кількість випадків помилкового
виявлення?
Розділ
2. Алгоритми для виявлення обличчя
2.1
Виділення областей за кольором шкіри
Наявність інформації про колір
потенційно може покращити процес виявлення обличчя, так як звужує область
пошуку обличчя, а отже, і зменшує кількість хибних позитивних виявлень. Тому
доцільно розвинути метод на основі комбінованого каскаду класифікаторів для
виявлення обличчя на кольорових зображеннях. При цьому у комбінованому каскаді
потрібно сформувати ще один рівень виявлення облич-кандидатів, що передує
каскаду простих класифікаторів, на основі сегментації за кольором шкіри.
Враховуючи, що сегментація за
кольором шкіри може базуватися на пікселях або на регіонах, автором взято за
основу піксельну сегментацію, яка передбачає побудову класифікатора, що
відділяє пікселі шкіри від пікселів фону. При цьому доцільно використати
метод
моделювання з явним визначенням границь кластеру кольору шкіри, так як він є
простим у використанні, швидким і достатньо точним.
Існує декілька кольорових просторів,
які з успіхом застосовано для сегментації за кольором шкіри, наприклад, для RGB
використано наступні явно визначені границі кластеру кольору шкіри (для кожного
з каналів R, G, B):
Модель кольору шкіри при денному
освітленні:>95 and G>40 AND B>20 and max(R,G,B)-min(R,G,B)>15 and
|R-G|>15 and R>G and R>D
Модель кольору шкіри при яскравому
освітленні:>220 and G>210 and B>170 and |R-G|<16 and R>B and
G>B
Досліджено також кольорові простори
TSL, YCbCr та YIQ, для яких, у
свою чергу, встановлено наступні
границі кластеру КШ:: 0,45<=T<=0,65
YCbCr: 85<=Cb<=135
and 135<=Cr<=160
YIQ: 0,02<=I<=0,22 and
-0,08<=Q<=0,12
Експериментальні дослідження методу
виявлення обличчя на кольорових зображеннях з використанням сегментації за
кольором шкіри проведено на тестовому наборі UCD, який містить 58 зображень з
224 вертикальними фронтальними обличчями.
а)
б)
Рисунок 1 - ROC-криві (а) та час
виявлення (б) комбінованого
каскаду класифікаторів на тестовому наборі UCD з використанням різних
кольорових просторів
Як видно з рис. 1а, найвищий рівень
виявлення забезпечує сегментація за кольором шкіри у просторі TSL. Використання
простору TSL у порівнянні з YCbCr, YIQ та RGB забезпечує вищий рівень виявлення
в середньому на 0,4 %, 1,3 % та 2,7 % відповідно. На основі рис. 1б можна
зробити висновок, що найменший час виявлення обличчя досягається при
використанні кольорового простору RGB.
Також досліджено вплив на рівень
виявлення комбінованого каскаду класифікаторів сегментації за кольором шкіри у
двох кольорових просторах, результати сегментації яких поєднано логічним
оператором «І» (рис. 2). На основі результатів, поданих на рис. 2, можна
зробити висновок, що для досягнення високого рівня виявлення доцільно
використати поєднання кольорових просторів TSL+YIQ, тоді як для отримання
високої швидкодії - RGB+TSL. Слід відмітити, що використання просторів RGB+TSL
у порівнянні з TSL+YIQ демонструє нижчий рівень виявлення в середньому лише на
1,3 %.
Рисунок 2 - ROC-криві (а) та час
виявлення (б) комбінованого каскаду класифікаторів на тестовому наборі UCD з
використанням поєднань кольорових просторів.
Порівняння результатів виявлення
обличчя з використанням сегментації за кольором шкіри одного кольорового
простору TSL, а також поєднань просторів TSL+YIQ та RGB+TSL показали (рис. 2),
що доцільно використати саме поєднання двох просторів, так як використання
TSL+YIQ та RGB+TSL дозволило отримати в середньому на 1,7 % та 0,8 % вищий
рівень виявлення та зменшити час виявлення обличчя в тестовому наборі UCD на 6
% та 26 % відповідно.
Подальша обробка сегментованого
зображення може бути здійснена або виділенням сегментів з кольором шкіри та
подачею кожного з них на вхід комбінованого каскаду класифікаторів як окремого
зображення, або обробкою комбінованим каскадом всього вхідного зображення з
накладеною бінарною маскою, в якій одиниці містять пікселі з кольором шкіри, а
нулі - фон. Доцільно використати останній підхід, який потенційно потребує
менше обчислювальних затрат (не потрібно знаходити інтегральне зображення для
кожного сегмента, області сегментів не обробляються повторно, коли більші
сегменти включають менші) та дозволяє виявити більше облич кандидатів
(обробляються краї сегментів, які можуть містити частково сегментовані
обличчя).
У такому випадку з метою уникнення
обробки фонових областей вхідного зображення при виявленні облич-кандидатів
каскад простих класифікаторів обробляє лише ті вікна, наповненість яких нулями
(пікселями фону) на бінарній масці не перевищує 70 %. Вибір такого високого
граничного значення наповненості пояснюється необхідністю обробки країв
сегментів з кольором шкіри, так як часто обличчя сегментуються не повністю.
У результаті експериментальних
досліджень методу виявлення обличчя на кольорових зображеннях з використанням
тестового набору UCD встановлено, що обробка комбінованим каскадом вхідного
зображення з накладеною бінарною маскою виконується на 20 % швидше, ніж обробка
кожного сегмента як окремого зображення. Загалом при використанні сегментації
за кольором шкіри метод виявлення обличчя на основі комбінованого каскаду
класифікаторів демонструє вищий рівень виявлення в середньому на 1,3 % та 2,6 %
(рис. 4), а також потребує на 29 % та 10 % менше часу на обробку вхідних
зображень при застосуванні RGB+TSL та TSL+YIQ відповідно (рис. 5).
2.2
Алгоритм аналізу форми областей зображення
Велика частина існуючих методів виділення
обличчя по кольору стикається з проблемами присутності на зображенні значної
кількості об’єктів, близьких за кольором до шкіри. Причина заклечається в тому,
що об’єднання пікселів кольору шкіри на першому кроці алгоритмів виявлення
обличчя проводиться без врахування форми, розмірів і взаємного розміщення
виділених областей. У подібного підходу є відчутний недолік - методи групування
пікселів шкіри, що не враховують обмеження на форму обличчя. Можна помилково
згрупувати в одну область пікселі, які реально відносяться до різних областей.
В зв’язку з цим тільки однієї інформації про колір недостатньо для стійкого
виділення облич, тому потрібно розширити набір ознак допоміжними властивостями
зображення обличчя.
Серед усіх особливостей обличчя були
вибрані геометричні характеристики. Так, як обличчя близьке за формою до еліпса
з обмеженими пропорціями (відношення довжини до ширини) і кутом нахилу, то,
вираховуючи ці параметри, можна визначити наскільки вони відповідають обличчю.
Для опису еліпса використовується
п’ять параметрів: координати центра еліпса (, ), розміри великої і малої осі
(a, b), а також кут нахилу Θ (рис. 6).
Рисунок 6. Параметри еліпса.
Позначимо за G зв’язану
множину пікселів зображення, wx,y - інтенсивність пікселя з
координатами (x, y). Координати (, ) центра еліпса вираховуються за формулами
(1), (2):
(1)
(2)
Осі еліпса вираховуються відповідно
формулам (3), (4):
(3)
(4)
де Imax та Imin - найбільший і
найменший моменти інерції (5):
(5)
Кут нахилу Θ
визначається
так:
(6)
Тут μ11
- змішаний момент відносно центру еліпса:
(7)
μ20
і μ02
- змішані моменти другого порядку відносно осей x та y:
(8)
Дана модель володіє великою
гнучкістю і дозволяє вбудовувати додаткові умови та обмеження на можливу форму
виділених областей (пропорції, положення, орієнтація еліпса).
2.3
Визначення розривів яскравості
2.3.1
Загальні положення
Три основні види розривів
яскравості, що зустрічаються в на півтонових зображеннях: точки, лінії і
перепади (краї). Найбільш загальним способом пошуку розривів є обробка
зображення за допомогою ковзаючої маски.
Рисунок 7 - ковзаюча маска
Для показаної на рис. 6 маски
розміром 3*3 елемента ця процедура заснована на обчисленні лінійної комбінації
коефіцієнтів маски зі значеннями яскравості елементів зображення, що
покриваються маскою. При використанні цієї маски відгук у кожній точці
зображення задається виразом:
R = w1 * z1 + w2 * z2 + ... + w9 *
z9 (9)
де zi - значення яскравості піксел,
відповідний коеффіціенту wi маски. Як завжди, відгук маски приписується позиції
її центрального елементу.
2.3.2
Визначення точок
Виявлення окремих ізольованих точок
на зображенні не представляє складності.Скористаємося маскою, показаної на рис.
8:
Рисунок 8 - Маска для виявлення
точок
Будемо вважати, що в тому пікселі,
куди потрапляє центр маски, виявлена точка,
якщо:
| R |> = T (10),
де Т - невід'ємних поріг, a R
обчислюється відповідно до (9). У даній формулі вимірюється зважена сума
різниць значень центрального елемента та його сусідів. Інтерес представляють
тільки досить великі відмінності (визначені порогом Т), при яких точка може
вважатися ізольованою. Сума коефіцієнтів маски дорівнює нулю, так що на
областях постійної яскравості вона буде давати нульової відгук.
2.3.3
Визначення ліній
Наступним за рівнем складності є
виявлення ліній. Розглянемо набір масок, показаний на pис. 9,10,11,12:
Рисунок 9 - Маска для виявлення
горизонтальних ліній
Рисунок 10 - Маска для виявлення
ліній під кутом +45
Рисунок 12 - Маска для виявлення
ліній під кутом -45
При ковзанні першої маски по
зображенню, найбільш сильний відгук буде на горизонтальних лініях товщиною в
один піксель, друга маска на pис. 8 дає найбільший відгук на лініях, що
проходять під кутом +45 °, а третя - на вертикальних лініях, четверта на лініях
що проходять під кутом -45 °. Ці напрямки можна виявити і за тією ознакою, що
бажані напрями кожної з масок характеризуються більшими значеннями вагових
коефіцієнтів (10), ніж будь-які інші напрямки. Сума коефіцієнтів кожної маски
дорівнює нулю, так що вони будуть давати нульової відгук на областях постійної
яскравості.
Позначимо через R1, R2, R3 і R4 відгуки масок, показаних на pис. 9, 10, 11,
12, де значення R, обчислюються згідно співвідношенню (9). Зображення
обробляється незалежно за допомогою кожної з цих масок. Якщо в деякій точці
зображення | Ri |> | Rj | для всіх j не дорівнює i, то ця точка, швидше за
все, пов'язана з лінією, орієнтованої вздовж напрямку маски i.
2.3.4
Визначення перепадів
Щоб з упевненістю класифікувати
точку як що знаходиться на перепаді яскравості, зміна яскравості, асоційована з
даною точкою, має бути суттєво більшою, ніж зміна яскравості в точці фону.
Оскільки справа відбувається з локальними обчисленнями, спосіб визначення того,
яке значення є «істотним», а яке ні, полягає у встановленні порогу. Для
кількісного вираження зміни яскравості використовують поняття першої та другої
похідних, рис. 13.
Рисунок 13 - Профіль перепаду
яскравості, перша і друга похідна профілю.
Визначаємо точку зображення як точку
перепаду, якщо її двовимірна похідна першого порядку перевищує деякий заданий
поріг. Зв’язана множина таких точок відповідно до заздалегідь заданим критерієм
зв'язності є перепадом яскравостей. Протяжний перепад яскравостей називають
контуром. Головне завдання при сегментації полягає в тому, щоб зібрати з частин
контуру більш довгі контури.
Якщо спиратися на поведінку другої
похідної, можна дати альтернативне визначення точок перепаду яскравостей як
точок перетину нульового рівня другої похідної зображення. При тому визначення
перепаду яскравостей та контуру залишаються тими ж. Важливо відзначити, що ці
визначення не гарантують успішного відшукання контурів у зображенні.
Похідні першого порядку в зображенні обчислюються за допомогою градієнта. Для
отримання похідних другого порядку застосовується лапласіан.
2.3.5
Оператори градієнта
Обчислення першої похідної цифрового
зображення засноване на різних дискретних наближеннях двовимірного градієнта.
Напрямок вектора градієнта збігається з напрямком максимальної швидкості зміни
функції f в точці (х, у).
Рисунок 14 - Значення яскравостей в
околі деякого елемента зображення
Обчислення градієнта зображення
полягає в отриманні величин приватних похідних Gx = df / dx і Gу = df / dy для
кожної точки. Oдин із способів знаходження перших приватних похідних Gx і Gу в
конкретній точці полягає в застосуванні наступного градієнтного оператора
Собеля:
Gx = (z7 + 2 * z8 + z9) - (z1 + 2 *
z2 + z3) (11)
Gу = (z3 + 2 * z6 + z9) - (z1 + 2 *
z4 + z7) (12).
Для цього оператора Собеля, який
виявляє горизонтальні і вертикальні контури (перепади яскравості), неважко
уявити відповідні маски для згортки з вихідним зображенням. Також можна змінити
наведені формули (11) і (12) таким чином, щоб вони давали максимальний відгук
для контурів, спрямованих діагонально. Додаткові пари масок оператора Собеля,
призначені для виявлення розривів в діагональних напрямках, показані на
рис.15,16:
Рисунок 15 - Маска Собеля для
виявлення точок, що лежать на діагональному перепаді -45 градусів
Рисунок 16 - Маска Собеля для
виявлення точок, що лежать на діагональному перепаді +45 градусів.
У кожної з масок на рис. 15, 16 сума
коефіцієнтів дорівнює нулю, тобто ці оператори будуть давати нульової відгук на
областях постійної яскравості, як і слід було очікувати від диференціального
оператора. Розглянуті маски застосовуються для отримання складових градієнта Gx
і Gy. Для обчислення величини градієнта ці складові необхідно використовувати
спільно. Часто використовується підхід, при якому величина градієнта
обчислюється приблизно через абсолютні значення приватних похідних:
Gradient = | Gx | + | Gy | (13).
Розділ
3. Опис програми
3.1
Структура програми
Спочатку програма аналізує кожен
піксель зображення за кольором і відносить його до кольору шкіри або до фону.
Результати роботи алгоритму виділення кольору шкіри показані на рис. 17,18:
Рисунок 17, Рисунок 18. Виділення
кольору шкіри.
На рис. 17, 18 пікселі, що мають
колір шкіри показані жовтим кольором, а інші пікселі - синім.
Далі програма групує пікселі кольору
шкіри в зв’язані області і аналізує їхню форму як еліпс. Результати роботи
даного алгоритму приведені на рис. 19, 20:
Рисунок 19, Рисунок 20. Аналіз форми
областей зображення.
Після цього визначаються області
розривів яскравості:
Рисунок 21, Рисунок 22. Визначення
областей розривів яскравості.
3.2
Інтерфейс користувача
На формі програми розташовано дві
кнопки. Щоб розпочати програму, потрібно натиснути на кнопку «Завантажити
зображення».
Рисунок 23. Початок роботи.
Після натискання кнопки «Завантажити
зображення» у вікні, що зявиться потрібно вибрати зображення. Після цього в
лівій частині форми з’явиться завантажене зображення.
Рисунок 24. Форма програми після
вибору зображення
Далі потрібно натиснути кнопку
«Знайти обличчя». Після цього в правій частині форми буде відображено результат
роботи програми.
Рисунок 25. Результат роботи
програми.
Висновки
У даній курсовій роботі була
розроблена програма, яка знаходить обличчя на зображеннях. Для програми
створений простий і зрозумілий інтерфейс для користувача. Програма розроблялась
у візуальному середовищі програмування Delphi, яке використовує мову
програмування ObjectPascal і містить у собі великий набір візуальних
інструментів для швидкої та зручної розробки програм.
В ході курсової роботи я ознайомився
з особливостями та проблемами розпізнавання об’єктів, роботи з зображеннями,
роботи з масивами і матрицями великих розмірностей
Список
літератури
1.
Vezhnevets
V., Sazonov V., Andreeva A. A Survey on Pixel-Based Skin Color Detection
Techniques // Proceedings of Graphicon-2003. - Moscow (Russia), 2010. - P.
85-92.
.
Peer
P., Kovac J., Solina F. Human Skin Colour Clustering for Face Detection //
EUROCON 2009 - International Conference on Computer as a Tool. - Ljubljana
(Slovenia), 2003. - Vol. 2. - P. 144-148
.
Paliy
I., Koval V., Kurylyak Y., Sachenko A. Improved Method of Face Detection Using
Color Images / Paliy I., Koval V., Kurylyak Y., Sachenko A. // Proceedings of
the International Conference TCSET’2006. -Lviv-Slavske (Ukraine), 2010 - P.
186-188
.
http://masters.donntu.edu.ua/2007/kita/mikhalets/ind/index.htm
Додатки
Код
програми
unit znahodjennia_oblycca;,
Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,, ExtDlgs,
StdCtrls, ExtCtrls, Jpeg, Math;= class(TForm): TOpenPictureDialog;: TButton;:
TImage;: TButton;: TImage;Button1Click(Sender: TObject);Button2Click(Sender:
TObject);
{ Private declarations }
{ Public declarations };: TForm1;
{$R
*.dfm}boolarr=array[1..1000,1..1000] of
boolean;h=400;w=400;pi=3.1415926535897932384626433832;bmpin,bmpout: TBitmap;,
WW: real;Ellipse(X,Y,A,B: integer; Angle: real);,S,C,H2,K1,K2,R:
real;,X2,Y1,Y2,X3,Y3,X4,Y4,YY:
integer;:=(180-Angle)*PI/180;:=Sin(I);:=Cos(I);:=Sqr(A*S)+Sqr(B*C);H2=0
then:=0;:=0;:=S*C*(Sqr(A)-Sqr(B))/H2;:=A*B/H2;;:=0;Sqr(YY)<=H2
do:=K2*Sqrt(H2-Sqr(YY));:=Round(K1*YY+R);:=Round(K1*YY-R);.Canvas.Pen.Color:=clRed;YY=0
then.Canvas.Pixels[X+X1,Y+YY]:=bmpout.Canvas.Pen.Color;.Canvas.Pixels[X-X1,Y-YY]:=bmpout.Canvas.Pen.Color;.Canvas.MoveTo(X+X1,Y+YY);.Canvas.LineTo(X+X3,Y+YY-1);.Canvas.MoveTo(X+X2,Y+YY);.Canvas.LineTo(X+X4,Y+YY-1);.Canvas.MoveTo(X-X1,Y-YY);.Canvas.LineTo(X-X3,Y-YY+1);.Canvas.MoveTo(X-X2,Y-YY);.Canvas.LineTo(X-X4,Y-YY+1);;:=X1;:=X2;(YY);;:=Int(1.99*(YY-Sqrt(H2)));.Canvas.MoveTo(X+X3,Y+YY-1);.Canvas.LineTo(X+X3-Round(R),Y+YY-Round(H2));.Canvas.LineTo(X+X4,Y+YY-1);.Canvas.MoveTo(X-X3,Y-YY+1);.Canvas.LineTo(X-X3+Round(R),Y-YY+Round(H2));.Canvas.LineTo(X-X4,Y-YY+1);;znah(bmpin,bmpout:Tbitmap;colshkr:boolarr);g:array
[1..1000,1..1000] of
boolean;,j,k,n,r,l,p,q,t,e,w,h,pn,x,y,a,b:integer;,sy,sw:longint;,gg,bb:byte;,u02,u20,teta,imin,imax:real;:TColor;,py:array
[1..30000] of integer;i:=1 to bmpin.Height doj:=1 to bmpin.Width do
g[i,j]:=false;i:=1 to bmpin.Height doj:=1 to bmpin.Width do((colshkr[i,j]) and
(not(g[i,j]))) then:=1;[1]:=j;[1]:=i;[i,j]:=true;:=j;
r:=j;:=r+1;((colshkr[i,r])and(not(g[i,r]))and(r<=bmpin.Width))
do:=pn+1;[pn]:=r;[pn]:=i;[i,r]:=true;:=r+1;;:=r-1;:=i+1;:=0; w:=0;p:=l to r
do((colshkr[t,p]) and (not(g[t,p])))
then:=pn+1;[pn]:=p;[pn]:=t;[t,p]:=true;((colshkr[t,p]) and (e=0) ) then
e:=p;((colshkr[t,p]) and (e<>0)) then w:=p;;:=e; r:=w;l=r then
break;:=l-1;((colshkr[t,p]) and (not(g[t,p])) and (p>=1))
do:=pn+1;[pn]:=p;[pn]:=t;[t,p]:=true;:=p-1;;:=p+1;:=r+1;((colshkr[t,p]) and
(not(g[t,p])) and (p<=bmpin.Width))
do:=pn+1;[pn]:=p;[pn]:=t;[t,p]:=true;:=p+1;;:=p-1;:=t+1;((r=l) or (t>bmpin.Height));:=0;
sy:=0; sw:=0;k:=1 to pn
do:=bmpin.Canvas.Pixels[px[k],py[k]];:=GetRValue(col);:=GetGValue(col);:=GetBValue(col);:=round(0.3*rr+0.59*gg+0.11*bb);:=sw+rr;:=sx+px[k]*rr;:=sy+py[k]*rr;;:=round(sx/sw);:=round(sy/sw);:=0;
u20:=0; u02:=0;k:=1 to pn
do:=bmpin.Canvas.Pixels[px[k],py[k]];:=GetRValue(col);:=GetGValue(col);:=GetBValue(col);:=round(0.3*rr+0.59*gg+0.11*bb);:=u1+(px[k]-x)*(py[k]-y)*rr;:=u02+sqr(px[k]-x)*rr;:=u20+sqr(py[k]-y)*rr;;u20=u02
then teta:=arctan(0)teta:=arctan(2*u1/(u20-u02))/2;:=0; imax:=0;k:=1 to pn
do:=imax+sqrt(abs((px[k]-x)*sin(teta)-(py[k]-y)*cos(teta)));:=imin+sqrt(abs((px[k]-x)*cos(teta)-(py[k]-y)*sin(teta)));;imin=0
then u02:=0 else u02:=power(imax,3)/imin;imax=0 then u20:=0 else
u20:=power(imin,3)/imax;:=round(power((4/pi),1/4)*power(u02,1/8));:=round(power((4/pi),1/4)*power(u20,1/8));(a<4*b)
and (a>3*b) then
ellipse(x,y,a,b,teta);;;min(r:byte;g:byte;b:byte):byte;:=r;b<result then
result:=b;g<result then result:=g;;max(r:byte;g:byte;b:byte):byte;:=r;b>result
then result:=b;g>result then result:=g;;TForm1.Button1Click(Sender:
TObject);openpicturedialog1.Execute
then.Picture.LoadFromFile(openpicturedialog1.filename);:=TBitmap.Create;.assign(image1.Picture.Graphic);.AutoSize
:= true;.AutoSize := false;:= Image1.Height / h;:= Image1.Width / w;(HH >
WW) then.Height := trunc(Image1.Height / HH);.Width := trunc(Image1.Width /
HH);.Stretch := True;.Height := trunc(Image1.Height / WW);.Width :=
trunc(Image1.Width / WW);.Stretch := True;;;;TForm1.Button2Click(Sender: TObject);r,g,b:byte;,gg,t,s,p:real;:Tcolor;,j,k,l,m:integer;:boolarr;:array[1..9]
of byte;,h2,h3,h4,x:real;:
TBitmap;:=TBitmap.Create;.Assign(bmpin);:=TBitmap.Create;.Assign(bmpin);i:=1 to
bmpout.Width doj:=1 to bmpout.Height do:=bmpout.Canvas.Pixels[i,j];:=GetRValue(color);:=GetGValue(color);:=GetBValue(color);((r>95)
and (g>40) and (b>20) and (r>g) and (r>b) and (abs(r-g)>15) and
((max(r,g,b)-min(r,g,b))>15)) or ((r>220)and (g>120) and (b>170)
and (abs(r-g)<=15) and (r>b) and (g>b)) then
colshkr[i,j]:=true else colshkr[i,j]:=false;((r>0)
or (b>0) or (g>0)) then:=r;:=g;:=r; p:=p+g;
p:=p+b;:=rr/p-1/3;:=gg/p-1/3;gg=0 then t:=0;gg>0 then
t:=(arctan(rr/gg))/(2*pi)+1/4;gg<0 then
t:=(arctan(rr/gg))/(2*pi)+3/4;((t>=0.45) and (t<=0.65) and colshkr[i,j])
then colshkr[i,j]:=truecolshkr[i,j]:=false;colshkr[i,j]:=false;;i:=1 to
bmpin.Width doj:=1 to bmpin.Height
do:=bmpin.Canvas.Pixels[i,j];:=GetRValue(color);:=GetGValue(color);:=GetBValue(color);:=round(0.3*r+0.59*g+0.11*b);.Canvas.Pixels[i,j]:=rgb(r,r,r);;i:=2
to (bmpp.Width-1) doj:=2 to (bmpp.Height-1)
do[1]:=getrvalue(bmpp.Canvas.Pixels[i-1,j-1]);[2]:=getrvalue(bmpp.Canvas.Pixels[i,j-1]);[3]:=getrvalue(bmpp.Canvas.Pixels[i+1,j-1]);[4]:=getrvalue(bmpp.Canvas.Pixels[i-1,j]);[5]:=getrvalue(bmpp.Canvas.Pixels[i,j]);[6]:=getrvalue(bmpp.Canvas.Pixels[i+1,j]);[7]:=getrvalue(bmpp.Canvas.Pixels[i-1,j+1]);[8]:=getrvalue(bmpp.Canvas.Pixels[i,j+1]);[9]:=getrvalue(bmpp.Canvas.Pixels[i+1,j+1]);:=abs(z[7]+2*z[8]+z[9]-z[1]-2*z[2]-z[3]);:=abs(z[3]+2*z[6]+z[9]-z[1]-2*z[4]-z[7]);:=abs(z[2]+2*z[3]-z[4]+z[6]-2*z[7]-z[8]);:=abs(2*z[9]+z[8]+z[6]-z[4]-z[2]-2*z[1]);:=50;((h1>x)
or (h2>x) or (h3>x) or (h4>x)) then
bmpp.Canvas.Pixels[i,j]:=clBlackbmpp.Canvas.Pixels[i,j]:=clWhite;;(bmpin,bmpout,colshkr);.Picture.Assign(bmpout);.AutoSize
:= true;.AutoSize := false;:= Image3.Height / h;:= Image3.Width / w;(HH >
WW) then.Height := trunc(Image3.Height / HH);.Width := trunc(Image3.Width /
HH);.Stretch := True;.Height := trunc(Image3.Height / WW);.Width :=
trunc(Image3.Width / WW);.Stretch := True;;;.unit znahodjennia_oblycca;,
Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,, ExtDlgs,
StdCtrls, ExtCtrls, Jpeg, Math;= class(TForm): TOpenPictureDialog;: TButton;:
TImage;: TButton;: TImage;Button1Click(Sender: TObject);Button2Click(Sender:
TObject);
{ Private declarations }
{ Public declarations };: TForm1;
{$R
*.dfm}boolarr=array[1..1000,1..1000] of
boolean;h=400;w=400;pi=3.1415926535897932384626433832;bmpin,bmpout: TBitmap;,
WW: real;Ellipse(X,Y,A,B: integer; Angle: real);,S,C,H2,K1,K2,R: real;,X2,Y1,Y2,X3,Y3,X4,Y4,YY:
integer;:=(180-Angle)*PI/180;:=Sin(I);:=Cos(I);:=Sqr(A*S)+Sqr(B*C);H2=0
then:=0;:=0;:=S*C*(Sqr(A)-Sqr(B))/H2;:=A*B/H2;;:=0;Sqr(YY)<=H2
do:=K2*Sqrt(H2-Sqr(YY));:=Round(K1*YY+R);:=Round(K1*YY-R);.Canvas.Pen.Color:=clRed;YY=0
then.Canvas.Pixels[X+X1,Y+YY]:=bmpout.Canvas.Pen.Color;.Canvas.Pixels[X-X1,Y-YY]:=bmpout.Canvas.Pen.Color;.Canvas.MoveTo(X+X1,Y+YY);.Canvas.LineTo(X+X3,Y+YY-1);.Canvas.MoveTo(X+X2,Y+YY);.Canvas.LineTo(X+X4,Y+YY-1);.Canvas.MoveTo(X-X1,Y-YY);.Canvas.LineTo(X-X3,Y-YY+1);.Canvas.MoveTo(X-X2,Y-YY);.Canvas.LineTo(X-X4,Y-YY+1);;:=X1;:=X2;(YY);;:=Int(1.99*(YY-Sqrt(H2)));.Canvas.MoveTo(X+X3,Y+YY-1);.Canvas.LineTo(X+X3-Round(R),Y+YY-Round(H2));.Canvas.LineTo(X+X4,Y+YY-1);.Canvas.MoveTo(X-X3,Y-YY+1);.Canvas.LineTo(X-X3+Round(R),Y-YY+Round(H2));.Canvas.LineTo(X-X4,Y-YY+1);;znah(bmpin,bmpout:Tbitmap;colshkr:boolarr);g:array
[1..1000,1..1000] of
boolean;,j,k,n,r,l,p,q,t,e,w,h,pn,x,y,a,b:integer;,sy,sw:longint;,gg,bb:byte;,u02,u20,teta,imin,imax:real;:TColor;,py:array
[1..30000] of integer;i:=1 to bmpin.Height doj:=1 to bmpin.Width do
g[i,j]:=false;i:=1 to bmpin.Height doj:=1 to bmpin.Width do((colshkr[i,j]) and
(not(g[i,j]))) then:=1;[1]:=j;[1]:=i;[i,j]:=true;:=j;
r:=j;:=r+1;((colshkr[i,r])and(not(g[i,r]))and(r<=bmpin.Width)) do:=pn+1;[pn]:=r;[pn]:=i;[i,r]:=true;:=r+1;;:=r-1;:=i+1;:=0;
w:=0;p:=l to r do((colshkr[t,p]) and (not(g[t,p])))
then:=pn+1;[pn]:=p;[pn]:=t;[t,p]:=true;((colshkr[t,p]) and (e=0) ) then
e:=p;((colshkr[t,p]) and (e<>0)) then w:=p;;:=e; r:=w;l=r then break;:=l-1;((colshkr[t,p])
and (not(g[t,p])) and (p>=1))
do:=pn+1;[pn]:=p;[pn]:=t;[t,p]:=true;:=p-1;;:=p+1;:=r+1;((colshkr[t,p]) and
(not(g[t,p])) and (p<=bmpin.Width))
do:=pn+1;[pn]:=p;[pn]:=t;[t,p]:=true;:=p+1;;:=p-1;:=t+1;((r=l) or
(t>bmpin.Height));:=0; sy:=0; sw:=0;k:=1 to pn
do:=bmpin.Canvas.Pixels[px[k],py[k]];:=GetRValue(col);:=GetGValue(col);:=GetBValue(col);:=round(0.3*rr+0.59*gg+0.11*bb);:=sw+rr;:=sx+px[k]*rr;:=sy+py[k]*rr;;:=round(sx/sw);:=round(sy/sw);:=0;
u20:=0; u02:=0;k:=1 to pn do:=bmpin.Canvas.Pixels[px[k],py[k]];:=GetRValue(col);:=GetGValue(col);:=GetBValue(col);:=round(0.3*rr+0.59*gg+0.11*bb);:=u1+(px[k]-x)*(py[k]-y)*rr;:=u02+sqr(px[k]-x)*rr;:=u20+sqr(py[k]-y)*rr;;u20=u02
then teta:=arctan(0)teta:=arctan(2*u1/(u20-u02))/2;:=0; imax:=0;k:=1 to pn do:=imax+sqrt(abs((px[k]-x)*sin(teta)-(py[k]-y)*cos(teta)));:=imin+sqrt(abs((px[k]-x)*cos(teta)-(py[k]-y)*sin(teta)));;imin=0
then u02:=0 else u02:=power(imax,3)/imin;imax=0 then u20:=0 else
u20:=power(imin,3)/imax;:=round(power((4/pi),1/4)*power(u02,1/8));:=round(power((4/pi),1/4)*power(u20,1/8));(a<4*b)
and (a>3*b) then
ellipse(x,y,a,b,teta);;;min(r:byte;g:byte;b:byte):byte;:=r;b<result then
result:=b;g<result then
result:=g;;max(r:byte;g:byte;b:byte):byte;:=r;b>result then
result:=b;g>result then result:=g;;TForm1.Button1Click(Sender:
TObject);openpicturedialog1.Execute
then.Picture.LoadFromFile(openpicturedialog1.filename);:=TBitmap.Create;.assign(image1.Picture.Graphic);.AutoSize
:= true;.AutoSize := false;:= Image1.Height / h;:= Image1.Width / w;(HH > WW)
then.Height := trunc(Image1.Height / HH);.Width := trunc(Image1.Width /
HH);.Stretch := True;.Height := trunc(Image1.Height / WW);.Width :=
trunc(Image1.Width / WW);.Stretch := True;;;;TForm1.Button2Click(Sender:
TObject);r,g,b:byte;,gg,t,s,p:real;:Tcolor;,j,k,l,m:integer;:boolarr;:array[1..9]
of byte;,h2,h3,h4,x:real;:
TBitmap;:=TBitmap.Create;.Assign(bmpin);:=TBitmap.Create;.Assign(bmpin);i:=1 to
bmpout.Width doj:=1 to bmpout.Height
do:=bmpout.Canvas.Pixels[i,j];:=GetRValue(color);:=GetGValue(color);:=GetBValue(color);((r>95)
and (g>40) and (b>20) and (r>g) and (r>b) and (abs(r-g)>15) and
((max(r,g,b)-min(r,g,b))>15)) or ((r>220)and (g>120) and (b>170)
and (abs(r-g)<=15) and (r>b) and (g>b)) then[i,j]:=true else colshkr[i,j]:=false;((r>0)
or (b>0) or (g>0)) then:=r;:=g;:=r; p:=p+g;
p:=p+b;:=rr/p-1/3;:=gg/p-1/3;gg=0 then t:=0;gg>0 then
t:=(arctan(rr/gg))/(2*pi)+1/4;gg<0 then
t:=(arctan(rr/gg))/(2*pi)+3/4;((t>=0.45) and (t<=0.65) and colshkr[i,j])
then colshkr[i,j]:=truecolshkr[i,j]:=false;colshkr[i,j]:=false;;i:=1 to
bmpin.Width doj:=1 to bmpin.Height
do:=bmpin.Canvas.Pixels[i,j];:=GetRValue(color);:=GetGValue(color);:=GetBValue(color);:=round(0.3*r+0.59*g+0.11*b);.Canvas.Pixels[i,j]:=rgb(r,r,r);;i:=2
to (bmpp.Width-1) doj:=2 to (bmpp.Height-1) do[1]:=getrvalue(bmpp.Canvas.Pixels[i-1,j-1]);[2]:=getrvalue(bmpp.Canvas.Pixels[i,j-1]);[3]:=getrvalue(bmpp.Canvas.Pixels[i+1,j-1]);[4]:=getrvalue(bmpp.Canvas.Pixels[i-1,j]);[5]:=getrvalue(bmpp.Canvas.Pixels[i,j]);[6]:=getrvalue(bmpp.Canvas.Pixels[i+1,j]);[7]:=getrvalue(bmpp.Canvas.Pixels[i-1,j+1]);[8]:=getrvalue(bmpp.Canvas.Pixels[i,j+1]);[9]:=getrvalue(bmpp.Canvas.Pixels[i+1,j+1]);:=abs(z[7]+2*z[8]+z[9]-z[1]-2*z[2]-z[3]);:=abs(z[3]+2*z[6]+z[9]-z[1]-2*z[4]-z[7]);:=abs(z[2]+2*z[3]-z[4]+z[6]-2*z[7]-z[8]);:=abs(2*z[9]+z[8]+z[6]-z[4]-z[2]-2*z[1]);:=50;((h1>x)
or (h2>x) or(h3>x) or (h4>x)) then
bmpp.Canvas.Pixels[i,j]:=clBlackbmpp.Canvas.Pixels[i,j]:=clWhite;;(bmpin,bmpout,colshkr);.Picture.Assign(bmpout);.AutoSize
:= true;.AutoSize := false;:= Image3.Height / h;:= Image3.Width / w;(HH >
WW) then.Height := trunc(Image3.Height / HH);.Width := trunc(Image3.Width /
HH);.Stretch := True;.Height := trunc(Image3.Height / WW);.Width :=
trunc(Image3.Width / WW);.Stretch := True;;;.unit znahodjennia_oblycca;,
Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,, ExtDlgs,
StdCtrls, ExtCtrls, Jpeg, Math;= class(TForm): TOpenPictureDialog;: TButton;:
TImage;: TButton;: TImage;Button1Click(Sender: TObject);Button2Click(Sender:
TObject);
{ Private declarations }
{ Public declarations };: TForm1;
{$R
*.dfm}boolarr=array[1..1000,1..1000] of boolean;h=400; w=400;
pi=3.1415926535897932384626433832;bmpin,bmpout: TBitmap; , WW: real;
Ellipse(X,Y,A,B: integer; Angle: real);,S,C,H2,K1,K2,R:
real;,X2,Y1,Y2,X3,Y3,X4,Y4,YY: integer;:=(180-Angle)*PI/180;:=Sin(I);:=Cos(I);:=Sqr(A*S)+Sqr(B*C);H2=0
then:=0;:=0;:=S*C*(Sqr(A)-Sqr(B))/H2;:=A*B/H2;;:=0;Sqr(YY)<=H2
do:=K2*Sqrt(H2-Sqr(YY));:=Round(K1*YY+R);:=Round(K1*YY-R);.Canvas.Pen.Color:=clRed;YY=0
then.Canvas.Pixels[X+X1,Y+YY]:=bmpout.Canvas.Pen.Color;.Canvas.Pixels[X-X1,Y-YY]:=bmpout.Canvas.Pen.Color;.Canvas.MoveTo(X+X1,Y+YY);.Canvas.LineTo(X+X3,Y+YY-1);.Canvas.MoveTo(X+X2,Y+YY);.Canvas.LineTo(X+X4,Y+YY-1);.Canvas.MoveTo(X-X1,Y-YY);.Canvas.LineTo(X-X3,Y-YY+1);.Canvas.MoveTo(X-X2,Y-YY);.Canvas.LineTo(X-X4,Y-YY+1);;:=X1;:=X2;(YY);;:=Int(1.99*(YY-Sqrt(H2)));.Canvas.MoveTo(X+X3,Y+YY-1);.Canvas.LineTo(X+X3-Round(R),Y+YY-Round(H2));.Canvas.LineTo(X+X4,Y+YY-1);.Canvas.MoveTo(X-X3,Y-YY+1);.Canvas.LineTo(X-X3+Round(R),Y-YY+Round(H2));.Canvas.LineTo(X-X4,Y-YY+1);;znah(bmpin,bmpout:Tbitmap;colshkr:boolarr);g:array
[1..1000,1..1000] of
boolean;,j,k,n,r,l,p,q,t,e,w,h,pn,x,y,a,b:integer;,sy,sw:longint;,gg,bb:byte;,u02,u20,teta,imin,imax:real;:TColor;,py:array
[1..30000] of integer;i:=1 to bmpin.Height doj:=1 to bmpin.Width do
g[i,j]:=false;i:=1 to bmpin.Height doj:=1 to bmpin.Width do((colshkr[i,j]) and
(not(g[i,j]))) then:=1;[1]:=j;[1]:=i;[i,j]:=true;:=j;
r:=j;:=r+1;((colshkr[i,r])and(not(g[i,r]))and(r<=bmpin.Width))
do:=pn+1;[pn]:=r;[pn]:=i;[i,r]:=true;:=r+1;;:=r-1;:=i+1;:=0; w:=0;p:=l to r
do((colshkr[t,p]) and (not(g[t,p])))
then:=pn+1;[pn]:=p;[pn]:=t;[t,p]:=true;((colshkr[t,p]) and (e=0) ) then
e:=p;((colshkr[t,p]) and (e<>0)) then w:=p;;:=e; r:=w;l=r then
break;:=l-1;((colshkr[t,p]) and (not(g[t,p])) and (p>=1))
do:=pn+1;[pn]:=p;[pn]:=t;[t,p]:=true;:=p-1;;:=p+1;:=r+1;((colshkr[t,p]) and
(not(g[t,p])) and (p<=bmpin.Width))
do:=pn+1;[pn]:=p;[pn]:=t;[t,p]:=true;:=p+1;;:=p-1;:=t+1;((r=l) or
(t>bmpin.Height));:=0; sy:=0; sw:=0;k:=1 to pn do:=bmpin.Canvas.Pixels[px[k],py[k]];:=GetRValue(col);:=GetGValue(col);:=GetBValue(col);:=round(0.3*rr+0.59*gg+0.11*bb);:=sw+rr;:=sx+px[k]*rr;:=sy+py[k]*rr;;:=round(sx/sw);:=round(sy/sw);:=0;
u20:=0; u02:=0;k:=1 to pn
do:=bmpin.Canvas.Pixels[px[k],py[k]];:=GetRValue(col);:=GetGValue(col);:=GetBValue(col);:=round(0.3*rr+0.59*gg+0.11*bb);:=u1+(px[k]-x)*(py[k]-y)*rr;:=u02+sqr(px[k]-x)*rr;:=u20+sqr(py[k]-y)*rr;;u20=u02
then teta:=arctan(0)teta:=arctan(2*u1/(u20-u02))/2;:=0; imax:=0;k:=1 to pn
do:=imax+sqrt(abs((px[k]-x)*sin(teta)-(py[k]-y)*cos(teta)));:=imin+sqrt(abs((px[k]-x)*cos(teta)-(py[k]-y)*sin(teta)));;imin=0
then u02:=0 else u02:=power(imax,3)/imin;imax=0 then u20:=0 else
u20:=power(imin,3)/imax;:=round(power((4/pi),1/4)*power(u02,1/8));:=round(power((4/pi),1/4)*power(u20,1/8));(a<4*b)
and (a>3*b) then
ellipse(x,y,a,b,teta);;;min(r:byte;g:byte;b:byte):byte;:=r;b<result then
result:=b;g<result then
result:=g;;max(r:byte;g:byte;b:byte):byte;:=r;b>result then
result:=b;g>result then result:=g;;TForm1.Button1Click(Sender:
TObject);openpicturedialog1.Execute
then.Picture.LoadFromFile(openpicturedialog1.filename);:=TBitmap.Create;.assign(image1.Picture.Graphic);.AutoSize
:= true;.AutoSize := false;:= Image1.Height / h;:= Image1.Width / w;(HH >
WW) then.Height := trunc(Image1.Height / HH);.Width := trunc(Image1.Width /
HH);.Stretch := True;.Height := trunc(Image1.Height / WW);.Width :=
trunc(Image1.Width / WW);.Stretch := True;;;;TForm1.Button2Click(Sender:
TObject);r,g,b:byte;,gg,t,s,p:real;
:Tcolor;,j,k,l,m:integer;:boolarr;:array[1..9] of byte;,h2,h3,h4,x:real;:
TBitmap;:=TBitmap.Create;.Assign(bmpin);:=TBitmap.Create;.Assign(bmpin);i:=1 to
bmpout.Width doj:=1 to bmpout.Height
do:=bmpout.Canvas.Pixels[i,j];:=GetRValue(color);:=GetGValue(color);:=GetBValue(color);((r>95)
and (g>40) and (b>20) and (r>g) and (r>b) and (abs(r-g)>15) and
((max(r,g,b)-min(r,g,b))>15)) or ((r>220)and (g>120) and (b>170)
and (abs(r-g)<=15) and (r>b) and (g>b)) then[i,j]:=true else
colshkr[i,j]:=false;((r>0) or (b>0) or (g>0)) then:=r;:=g;:=r; p:=p+g;
p:=p+b;:=rr/p-1/3;:=gg/p-1/3;gg=0 then t:=0;gg>0 then
t:=(arctan(rr/gg))/(2*pi)+1/4;gg<0 then
t:=(arctan(rr/gg))/(2*pi)+3/4;((t>=0.45) and (t<=0.65) and colshkr[i,j])
then colshkr[i,j]:=truecolshkr[i,j]:=false;colshkr[i,j]:=false;;i:=1 to
bmpin.Width doj:=1 to bmpin.Height
do:=bmpin.Canvas.Pixels[i,j];:=GetRValue(color);:=GetGValue(color);:=GetBValue(color);:=round(0.3*r+0.59*g+0.11*b);.Canvas.Pixels[i,j]:=rgb(r,r,r);;i:=2
to (bmpp.Width-1) doj:=2 to (bmpp.Height-1)
do[1]:=getrvalue(bmpp.Canvas.Pixels[i-1,j-1]);[2]:=getrvalue(bmpp.Canvas.Pixels[i,j-1]);[3]:=getrvalue(bmpp.Canvas.Pixels[i+1,j-1]);[4]:=getrvalue(bmpp.Canvas.Pixels[i-1,j]);[5]:=getrvalue(bmpp.Canvas.Pixels[i,j]);[6]:=getrvalue(bmpp.Canvas.Pixels[i+1,j]);[7]:=getrvalue(bmpp.Canvas.Pixels[i-1,j+1]);[8]:=getrvalue(bmpp.Canvas.Pixels[i,j+1]);[9]:=getrvalue(bmpp.Canvas.Pixels[i+1,j+1]);:=abs(z[7]+2*z[8]+z[9]-z[1]-2*z[2]-z[3]);:=abs(z[3]+2*z[6]+z[9]-z[1]-2*z[4]-z[7]);:=abs(z[2]+2*z[3]-z[4]+z[6]-2*z[7]-z[8]);:=abs(2*z[9]+z[8]+z[6]-z[4]-z[2]-2*z[1]);:=50;((h1>x)or
(h2>x) or (h3>x) or (h4>x)) then
bmpp.Canvas.Pixels[i,j]:=clBlackbmpp.Canvas.Pixels[i,j]:=clWhite;;(bmpin,bmpout,colshkr);.Picture.Assign(bmpout);.AutoSize
:= true;.AutoSize := false;:= Image3.Height / h;:= Image3.Width / w;(HH >
WW) then.Height := trunc(Image3.Height / HH);.Width := trunc(Image3.Width /
HH);.Stretch := True;.Height := trunc(Image3.Height / WW);.Width :=
trunc(Image3.Width / WW);.Stretch := True;;