W poprzednich artykułach opisywałem, czym jest HMS od strony programisty. Pokazywałem Wam, jak zacząć swoją przygodę ze środowiskiem Huawei oraz podjąłem się próby pogodzenia zarówno HMS, jak i GMS w jednej aplikacji. Dzisiaj postanowiłem zgłębić nieco temat ML Kit dostarczanego przez Huawei. W ramach tego zestawu producent udostępnia nam kilka różnych możliwości związanych głównie z rozpoznawaniem obrazów.

Czym jest ML Kit? Co oferuje rozpoznawanie obrazów od Huawei?

Wspomniany zestaw ML Kit składa się z następujących funkcjonalności:

  1. Wykrywanie twarzy
  2. Klasyfikacja obrazów
  3. Segmentacja obrazów
  4. Wykrywanie i śledzenie przedmiotów
  5. Wykrywanie elementów krajobrazu
  6. Usługi wykrywania języka oraz tłumaczenia tekstu
  7. Rozpoznawanie dokumentów
  8. Rozpoznawanie kart bankowych

Do celów tego artykułu wykorzystałem gotowy kod dostarczany przez Huawei. Pokusiłem się jedynie o drobne wstawki, które pozwoliły mi na łatwiejsze eksperymenty. Jeśli postanowicie zrobić podobnie, to pamiętajcie, że jedynie część usług może pracować lokalnie. Usługi wykonywane przez chmurę wymagają rejestracji odpowiednio skonfigurowanej aplikacji i konta na stronie producenta, co omówiliśmy w ramach osobnego artykułu dotyczącego rejestracji jako programista HMS.

Rozpoznawanie twarzy to podstawa ML Kit

Pierwszym kitem, na który zwrócę uwagę, jest Face Detection. Jego zadaniem, jak angielska nazwa wskazuje, jest wykrywanie twarzy. API działa na tyle szybko, że możliwe jest śledzenie na bieżąco. Wśród informacji, które otrzymujemy z bibliotek po wykryciu, znajdziemy między innymi: kształt ust czy brwi, kształt oczu, pozycję źrenicy, stopień otwarcia oczu. Mamy więc tutaj dostęp do informacji, które pozwolą nam na wyodrębnienie kluczowych elementów samej twarzy.

Oprócz informacji typowo fizjonomicznych API próbuje także swoich sił na innych polach. Na podstawie powyższych danych może dla nas odczytać emocje takie jak gniew, radość, smutek czy zaskoczenie. Potrzebujemy informacji o płci lub wieku naszego modela? To także znajdziemy za sprawą algorytmów.

Poznaj wiek lub płeć osoby z przetwarzanego obrazu za pomocą ML Kit

Postanowiłem nieco pobawić się właśnie w tej kwestii. Zacząłem losowo sprawdzać, jak API poradzi sobie z naszymi celebrytami i muszę przyznać, że wyniki mnie bardzo zaskoczyły. Płeć była podawana poprawnie w zdecydowanej większości wypadków i jedynie raz udało mi się oszukać ML Kit, podstawiając mu zdjęcie pani Doroty Wellman. Tutaj jednak przyznam szczerze, że wyniki nie są wiążące, ponieważ twarz była ustawiona pod kątem, a dodatkowo pani Dorota miała na twarzy okulary przeciwsłoneczne. Na pozostałych zdjęciach jej płeć podawana była prawidłowo.

Nieco gorzej wyszło już szacowanie wieku. Największą różnicę uzyskałem chyba u Kuby Wojewódzkiego. W zależności od zdjęcia uzyskiwałem rezultaty 30-35 lat. Jest to także przejaskrawiony przypadek z mojej strony. Nie oczekujmy tutaj cudów skoro nikt przy zdrowych zmysłach, patrząc na niego, nie dałby mu 56 lat.

ml kit przetwarzanie obrazu huawei hms

Ocenę wieku pozostawiłbym więc jako miły bajer, a nie coś, czemu można ufać. Postanowiłem nieco rozwinąć temat i pokazałem aplikację rodzinie. Mnie osobiście algorytmy odmłodziły o około 10 lat. Siedmiolatek miał wynik poprawny, ale już jedenastolatka uzyskiwała 20-23 lata. Moja opinia na ten temat jest taka, że o ile wykrywanie konturów elementów twarzy działa wyśmienicie, to szacunki mogą być obarczone błędem. Z tego też względu zamiast wyniku API zwraca nam jedynie prawdopodobieństwo.

Kod wymagany do śledzenia nie jest skomplikowany i jest on na szczęście już podany na tacy przez Huawei:

private fun createFaceAnalyzer() {
    val setting = MLFaceAnalyzerSetting.Factory()
            .setFeatureType(MLFaceAnalyzerSetting.TYPE_FEATURES)
            .setKeyPointType(MLFaceAnalyzerSetting.TYPE_KEYPOINTS)
            .setMinFaceProportion(0.2f)
            .allowTracing()
            .create()
    analyzer = MLAnalyzerFactory.getInstance().getFaceAnalyzer(setting)
    analyzer.setTransactor(FaceAnalyzerTransactor(mOverlay))
}

private fun createLensEngine() {
    mLensEngine = LensEngine.Creator(applicationContext, analyzer)
            .setLensType(lensType)
            .applyDisplayDimension(640, 480)
            .applyFps(25.0f)
            .enableAutomaticFocus(true)
            .create()
}

Jak sprawdzić, co mamy przed sobą?

Jeśli wykrywanie twarzy może nas zaskoczyć możliwościami oraz natłokiem dostarczanych informacji na temat twarzy, to Klasyfikacja Obrazów wydaje się być miła, lekka i przyjemna. W kilku linijkach kodu jesteśmy w stanie odkryć, co takiego znajduje się na naszym obrazie. Przetwarzanie możemy realizować w dwóch trybach: lokalnie lub w chmurze. Różnica? Ogromna. O ile cloud potrafi rozpoznać ponad 12000 różnych kategorii, to przetwarzanie na urządzeniu ograniczy się jedynie do 400 najpopularniejszych. 

Spójrzmy na kod:

val setting = MLLocalClassificationAnalyzerSetting.Factory().setMinAcceptablePossibility(0.8f).create()
val analyzer = MLAnalyzerFactory.getInstance().getLocalImageClassificationAnalyzer(setting)
val frame = MLFrame.fromBitmap(it)
analyzer.asyncAnalyseFrame(frame).addOnSuccessListener { classifications -> // Recognition success.
    displaySuccess(classifications)
}.addOnFailureListener { // Recognition failure.
    displayFailure()
}

Moje eksperymenty na tym polu pokazały, że HMS świetnie radzi sobie z rozpoznawaniem. Oczywiście skoro lista rozpoznawanych obiektów jest ograniczona, to przy pomocy lekkiej dozy wyobraźni znajdziemy przykłady, gdzie rozpoznawanie nie zadziała prawidłowo. Ja próbowałem z kilkunastoma typami zarówno w trybie pracy lokalnej, jak i cloud. Ten pierwszy zwracał często wynik bardzo ogólne, np. „animal” lub „plant”.  Chmura w tych przypadkach zwracała mi zdecydowanie dokładniejsze wyniki takie jak „tiger”, „cat”, „elephant” czy „rose”. Na obecną chwilę rezultaty otrzymujemy w języku angielskim. Nie pojawiły się jeszcze deklaracje, czy pojawi się wsparcie dla naszego dialektu. Bardzo często oprócz pojedynczej kategorii dostajemy ich bardzo wiele, co może pomóc naszym aplikacjom.

ml kit przetwarzanie obrazu huawei hms

Tak jak wspominałem już wcześniej, lista obiektów jest w tej chwili ograniczona. Bohater memów o Polakach, czyli nosacz sundajski, nie jest w tej chwili poprawnie rozpoznawany. Jedynymi rezultatami były np. „animal”, „mammal” lub nazwy innych małp takich jak makaki. Zmierzam niestety do tego, że na chwilę obecną nie można wyszkolić sobie własnych modeli, które pozwolą nam rozpoznać brakujące elementy. To oczywiście może się zmienić w najbliższej przyszłości. Nie zapominajmy, że HMS jest jeszcze bardzo młody i nadal się rozwija. Nie zdziwię się, gdy lista 12000 aktualnie rozpoznawanych obiektów zwiększy się znacznie w najbliższej przyszłości.

Segmentacja obrazów

Dzięki tej usłudze możemy w bardzo łatwy sposób dokonać ekstrakcji interesujących nas elementów obrazów. Od jakiegoś czasu Skype domyślnie rozmazuje tło i zostawia na ekranie jedynie rozmówców. Domyślam się, że chodzi tutaj o zmniejszenie ilości przesyłanych szczegółów obrazu, a przez to zmniejszenie wymagań odnośnie do łącza internetowego i poprawę samej komunikacji. Jeśli zastanawialiście się, w jaki sposób można zastosować podobne techniki w swoich aplikacjach, to właśnie segmentacja może być dobrym wyjściem. Spójrzmy na poniższy przykład:

ml kit przetwarzanie obrazu huawei hms

Jak widać, tło zostało usunięte i pozostała nam jedynie postać pierwszoplanowa. Praca została wykonana bardzo dokładnie.

Jak to zrobić?

val analyzer = MLAnalyzerFactory.getInstance().getImageSegmentationAnalyzer(setting)
val mlFrame = MLFrame.Creator().setBitmap(bitmap).create()
val task = analyzer.asyncAnalyseFrame(mlFrame)
task.addOnSuccessListener { imageSegmentationResult -> // Processing logic for recognition success.
    val foreground = imageSegmentationResult.getForeground()
    if (foreground == null) {
        displayFailure()
    } else {
        displaySuccess(foreground)
    }
}.addOnFailureListener { // Processing logic for recognition failure.
    displayFailure()
}

Pewnie można zarzucić mi, że dokonałem manipulacji. Tło jest w zasadzie szare i usunięcie go nie jest żadnym problemem. Taka była przynajmniej moja pierwsza myśl. Postanowiłem więc przetestować API w nieco trudniejszych warunkach. Moim celem padły plakaty z filmu Jumanji 2. Założyłem, że tła w postaci dżungli będą nieco bardziej wymagające. Dodatkowym testem, który przeprowadziłem, było pojawienie się nie jednej, ale czterech postaci. Huawei wyszło zdecydowanie obronną ręką z tego i poradziło sobie znakomicie.

ml kit przetwarzanie obrazu huawei hms

Zobacz też: Małe smartfony – czy one jeszcze istnieją?

Segmentacja może dotyczyć nie tylko ciała człowieka. Usługa także wspiera np. niebo, psy, rośliny oraz parę innych typów. W wyniku przetwarzania otrzymujecie tablicę współrzędnych wszystkich elementów. Możliwa jest podmiana jedynie jednego z nich, np. psa lub nieba. W następnym odcinku będę eksperymentował z innymi usługami w ramach ML Kit i postaram się je Wam opisać. Jeśli chcielibyście, abym zwrócił na coś szczególną uwagę, to dajcie znać w komentarzach.

Tradycyjnie nie zapominajcie, aby regularnie odwiedzać sekcję programowania Android.com.pl – stale publikujemy ciekawe materiały każdego tygodnia. Pytajcie też śmiało o wsparcie z implementacją HMS na forum dla programistów Android.com.pl. Do usłyszenia!

Źródła grafik wykorzystanych do analizy: Dzień Dobry TVN, GRY-Online

Tomasz Orłowski

Programista Androida z 12-letnim doświadczeniem. Aktualnie współpracuje z Aberit Sp. z o.o. Interactive Agency & Software House