Приклад реалізації методів обробки та розпізнавання зображень на Android

Займаючись розробкою додатків під ОС Android виникають цікаві ідеї, які хочеться спробувати, або є якийсь набір теоретичних знань та їх хочеться застосувати на практиці, із сукупності цих факторів і виникла ідея проекту, що описується.

Приклад реалізації представлений у вигляді Android програми, а вихідним зображенням є скріншот тексту, з введеним ключовим словом, для вирішення задачі застосовуються різні алгоритми обробки та розпізнавання зображень.

Допустимо у нас є зображення якогось тексту, це може бути фотографія, скановане зображення або скріншот, і на цьому зображенні необхідно відшукати якусь фразу чи слово в максимально короткий термін, щоб швидко отримати необхідну частину інформації, тут на допомогу нам приходять алгоритми обробки зображень та розпізнавання.

Докладно етапи створення Android програми тут описані не будуть, як і не буде представлено докладний теоретичний опис алгоритмів. При мінімальному тестовому інтерфейсі програми основними цілями нижчеописаного є:

  • Ознайомлення з деякими методами обробки зображень та розпізнавання образів;
  • Ознайомлення з можливостями та складністю реалізації цих методів для Android.

Отримання зображення

Для отримання досліджуваного зображення створюємо Activity, в якій буде лише три елементи:

1. EditText - для введення ключового слова; 2. TextView – для відображення тексту, в якому потрібно знайти це слово; 3. Кнопка створення скріншота та переходу на інший екран.

! Весь код має виключно демонстративний характер і не є правильною інструкцією до дії.

Приблизно так це виглядатиме:

методів

Для пошуку,наприклад, введемо слово "dreams":

обробки

Таким чином ми отримуємо одиночне ключове слово, після якого нижче слідує текст. Варто звернути увагу, що ключове слово і сам текст мають різний розмір шрифту (для ускладнення завдання, скажімо так).

Натискаємо на кнопку та отримуємо скріншот області з ключовим словом та текстом.

Отриманий скріншот відкривається в новій Activity, де в NavigationDrawer зібрані функції послідовних дій. У реальному додатку деякі з операцій можуть бути об'єднані в одну для виключення зайвих проходів зображення.

Попередня обробка отриманого зображення

Для початку потрібно виконати переведення отриманого кольорового зображення на півтонове.

Переклад зображення з кольорового до напівтонового

Для перекладу використовується схема RGB to YUV.

У нашому випадку необхідна лише інтенсивність (яскравість), а отримати її можна за форумом:

Y = 0.299*R + 0.587*G + 0.114*B, де R,G,B червоний, зелений та синій канали відповідно.

Для роботи з квітами, як не дивно, корисний клас Color і, зокрема, його статичні методи red, green і blue, в яких реалізовані операції з зсувами побітів для виділення потрібного колірного каналу з інтового значення кольору пікселя.

Приклад коду для перекладу кольорового пікселя в яскравість:

Виконувати сегментацію на напівтоновому зображенні не набагато легше, ніж на кольоровому, тому наступним кроком необхідно напівтонове зображення перевести в бінарне (значення яскравостей пікселів мають лише два значення 0 і 1).

Бінарізація напівтонового зображення

У цій задачі для бінаризації досить елементарного порогового методу з порогом за умовчанням 128.

Надалі для коригуванняРезультати поріг можна підібрати експериментальним шляхом (у додатку реалізована можливість завдання порога користувачем).

Для отримання бінарного значення яскравості виконується перевірка отриманої напівтонової яскравості:

Де threshold – поріг, Color.WHITE та Color.BLACK – константи для зручності, щоб не плутатися з 0 та 1.

Після виконаного переведення в напівтонову та подальшої бінаризації отримуємо наступний результат:

реалізації

Так як ці два способи обробки зображення є дуже близькими, вони об'єднані в один метод.

Сегментація

Для знаходження ключового слова необхідно після бінаризації виконати кілька етапів сегментації, які полягають у пошуку рядків у тексті, пошуку слів у рядках та віднесення знайдених слів до слів претендентам за кількістю літер (для звуження кола слів для розпізнавання).

Сегментація рядків

Для визначення рядків тексту необхідно знайти частини гістограми з кількістю чорних пікселів більше за нуль, які знаходяться між частинами гістограми з нульовою кількістю пікселів. Для цього складається гістограма кількості чорних пікселів у кожному однопіксельному рядку зображення, після чого вона обробляється для отримання координат рядків по вертикалі (за суттю номера рядків у гістограмі). Знаючи цю координату та загальні розміри зображення, можна виділити область, що містить рядок зі словами.

"Inline" гістограма для наочності (ліворуч) виглядає, наприклад, так:

обробки

Для зручності відображення гістограма нормалізується.

Коли відомо розташування рядків на зображенні, можна переходити до пошуку слів.

Сегментація слів

Для того, щоб зрозуміти, де слова, а де просто сусідні символи, необхідно визначитися, які відстані міжсимволами вважати відстанями між словами, які відстані між символами всередині одного слова. Тут на допомогу приходить метод мод, а точніше адаптований варіант, тому що найчастіше цей метод зустрічається в бінаризації, але його суть можна застосувати і в даній ситуації.

Для початку як і для рядків, аналогічно будуємо гістограму всередині рядка (по суті була вертикальна, тепер горизонтальна), вона необхідна, щоб зрозуміти, де символи, а де білі проміжки.

Приклад отримання такої гістограми нижче і аналогічний попередньому.

Обробляючи цю гістограму можна отримати нову гістограму — проміжків між чорними пікселями, тобто перша градація її буде кількістю «пробілів» шириною 1 піксель, друга градація кількість «пробілів» шириною 2 пікселя і так далі.

Вийде приблизно щось таке:

обробки

Виходячи з логіки методу мод ми знаходимо два яскраво виражені піки (на зображенні вище вони очевидні), і все, що знаходиться біля одного піку - відстані між символами всередині слова, біля другого - відстані між словами.

Маючи таку інформацію про «пробіли» та гістограму рядка, можна виділити ділянки зображення, де знаходяться слова, а також порахувати скільки символів міститься в цих словах.

Повний код даного процесу дивись у вихідниках.

Для візуальної оцінки роботи вищевикладеної сукупності алгоритмів слова в тексті забарвлюються в кольори, що чергуються, а слова претенденти (нагадаю, ті, у яких кількість символів збігається з кількістю символом у ключовому слові) залишаються чорного кольору:

обробки

І так, на даному етапі є шматочки зображень (точніше координати цих шматочків), які містять ключове слово та слова претенденти на основі кількостісимволів можна спробувати знайти серед претендентів ключове слово.

Розпізнавання

Звертаю увагу, що тут під розпізнаванням мається на увазі розпізнавання ключового слова серед претендентів, при цьому про розпізнавання яких саме символів вони не йдуть.

Для розпізнавання підбирається набір інформативних ознак: це може бути кількість кінцевих точок, вузлових точок, а також кількість пікселів з 3, 4 та 5 чорними пікселями-сусідами та інші. Досвідченим шляхом встановлено, що багато ознак втрачає сенс, оскільки вони «перекривають» одне одного.

На даному етапі зупинимося на кількості кінцевих точок, з урахуванням їх розташування (у верхній та нижній частині зображення для кожної частини ознаки вважаються окремо).

До кожного слова виконується підрахунок кількості ознак, після чого відбувається пошук методом найближчих сусідів виходячи з евклидова відстані.

Про всі характерні числа типу A4, A8 і т.д. можна знайти інформацію додатково.

Враховуючи повторюваність слів та похибки, в результаті можна отримати 2-3 найближчих сусіди, серед яких буде знайдено ключове слово (на малюнку виділено червоним).

методів

Також на малюнку видно, що серед червоних слів є слово «dreams».

Для покращення якості розпізнавання можна спробувати підібрати інший поріг бінаризації, а також вибрати інші інформативні ознаки, додавши до них, наприклад, зонди.

Висновок

Поставленої мети вдалося досягти, були випробувані деякі методи обробки та розпізнавання зображень, при цьому їх реалізація під Android не накладає жодних додаткових складнощів, просто потрібно враховувати витрату пам'яті і не зберігати одночасно кілька великих Bitmap.

Сподіваюся, інформація виявиться корисною для початківців свій шлях у вирішенні завдань роботи з зображеннями під Android.

Опис всіх алгоритмів, підрахунок характерних чисел і т.п. можна легко знайти у відкритому доступі як на habrahabr, так і в численних підручниках та онлайн ресурсах.

Цілком проект доступний на GitHub

PS: Наведена реалізація алгоритмів не оптимальна, і вимагає подальшого опрацювання та оптимізації, служить лише мінімально необхідним прикладом для ознайомлення, візуалізації та оцінки роботи вищеописаних методів на Android.

Хардкорна конфа за С++. Ми запрошуємо лише профі.