Es war noch nicht lange her, dass das Fotografieren ziemlich teuer war. Bei Kameras war Film mit begrenzter Kapazität erforderlich, und für die Ergebnisse waren zusätzliche Zeit und mehr Geld erforderlich. Diese inhärenten Einschränkungen stellten sicher, dass wir mit den Fotos, die wir gemacht haben, selektiv vorgehen.
Schneller Vorlauf bis heute und diese Einschränkungen wurden dank der Technologie abgebaut, aber jetzt stehen wir vor einem neuen Problem, das Filtern, Organisieren und Aufdecken wichtiger Fotos aus den vielen, die wir machen.
Dieses neue Problem hat dieses Tutorial inspiriert. In diesem Beitrag werde ich zeigen, wie wir neue Tools einsetzen können, um das Leben des Benutzers zu erleichtern, indem neue Möglichkeiten zum Filtern und Organisieren unserer Inhalte eingeführt werden.
Für dieses Projekt werden wir eine andere Art des Filterns durch Ihre Fotosammlung prüfen. Auf dem Weg erfahren Sie, wie Sie das Snapdragon SDK von Qualcomm für die Gesichtsverarbeitung und -erkennung einsetzen und nutzen können.
Wir ermöglichen dem Benutzer, eine Sammlung von Fotos nach Identität / Identitäten zu filtern. Die Sammlung wird nach Identitäten aus einem Foto gefiltert, auf das der Benutzer tippt (siehe unten).
Das Hauptaugenmerk dieses Beitrags liegt auf der Einführung der Gesichtsverarbeitung und -erkennung mit dem Snapdragon SDK von Qualcomm, während hoffentlich indirekt neue Denkweisen und die Verwendung abgeleiteter Metadaten aus Inhalten gefördert werden.
Um zu vermeiden, dass Sie in den Klempnerarbeiten fixiert werden, habe ich eine Vorlage erstellt, die den grundlegenden Dienst zum Durchsuchen der Fotosammlung des Benutzers und ein Raster für die Anzeige der Fotos bereitstellt. Unser Ziel ist es, dies mit dem oben vorgeschlagenen Konzept zu verbessern.
Im folgenden Abschnitt werden diese Komponenten kurz beschrieben, bevor Sie mit der Einführung des Snapdragon-SDK von Qualcomm fortfahren.
Wie oben erwähnt, ist es unser Ziel, uns auf das Snapdragon-SDK zu konzentrieren, sodass ich ein Skelett erstellt habe, das alle installierten Rohrleitungen aufweist. Nachfolgend finden Sie ein Diagramm und eine Beschreibung des Projekts, das Sie von GitHub herunterladen können.
Unsere Daten Paket enthält eine Implementierung von SQLiteOpenHelper
(IdentityGalleryDatabase
) verantwortlich für die Erstellung und Verwaltung unserer Datenbank. Die Datenbank besteht aus drei Tabellen, von denen eine als Zeiger auf den Medieneintrag (Foto
), ein weiteres für erkannte Identitäten (Identität
) und schließlich die Beziehungstabelle, die Identitäten mit ihren Fotos verbindet (identity_photo
).
Die Identitätstabelle wird zum Speichern der vom Snapdragon SDK bereitgestellten Attribute verwendet, die in einem späteren Abschnitt dieses Lernprogramms ausführlich beschrieben werden.
Ebenfalls im Datenpaket enthalten sind a Anbieter
(IdentityGalleryProvider
) und Vertrag
(IdentityGalleryContract
) Klasse, die nichts weiter als ein Standard ist Anbieter
fungiert als Hülle der SQLiteOpenHelper
Klasse.
Um Ihnen ein Gefühl dafür zu vermitteln, wie Sie mit dem interagieren können Anbieter
Klasse wird der folgende Code aus der TestProvider
Klasse. Wie der Name vermuten lässt, wird es zum Testen des verwendet Anbieter
Klasse.
//… Abfrage für alle Fotos Cursor cursor = mContext.getContentResolver (). Query (IdentityGalleryContract.PhotoEntity.CONTENT_URI, null, null, null, null); //… Abfrage für alle Fotos, die eine der Identitäten im referenzierten Foto enthalten Cursor Cursor = mContext.getContentResolver (). Abfrage (IdentityGalleryContract.PhotoEntity.buildUriWithReferencePhoto (photoId), null, null, null, null); //… Abfrageaufrufidentitäten Cursor cursor = mContext.getContentResolver (). Query (IdentityGalleryContract.IdentityEntity.CONTENT_URI, null, null, null, null); //… Abfrage für alle Cursor cursor = mContext.getContentResolver (). Query (IdentityGalleryContract.PhotoEntity.CONTENT_URI, null, null, null, null);
Das Bedienung package ist für das Durchlaufen, Katalogisieren und Bearbeiten der über das System verfügbaren Bilder verantwortlich MediaStore
. Der Dienst selbst erweitert das IntentService
als einfache Möglichkeit, die Verarbeitung in einem eigenen Thread durchzuführen. Die eigentliche Arbeit wird an die delegiert GalleryScanner
, Dies ist die Klasse, die wir für Gesichtsverarbeitung und -erkennung erweitern werden.
Diese GalleryScannerIntentService
wird jedes Mal instanziiert Hauptaktivität
wird mit dem folgenden Aufruf erstellt:
@Override protected void onCreate (Bundle savedInstanceState) … GalleryScannerIntentService.startActionScan (this.getApplicationContext ());…
Wann gestartet, GalleryScannerIntentService
ruft das letzte Scan-Datum ab und übergibt es an den Konstruktor von GalleryScanner
. Dann ruft das an Scan
Methode zum Durchlaufen des Inhalts des MediaItem
Inhaltsanbieter-Artikel nach dem letzten Scan-Datum.
Wenn Sie das prüfen Scan
Methode der GalleryScanner
Klasse, Sie werden feststellen, dass es ziemlich wortreich ist - hier passiert nichts Kompliziertes. Die Methode muss nach intern gespeicherten Mediendateien abfragen (MediaStore.Images.Media.INTERNAL_CONTENT_URI
) und extern (MediaStore.Images.Media.EXTERNAL_CONTENT_URI
). Jeder Artikel wird dann an eine Hook-Methode übergeben, in der wir unseren Code für die Gesichtsverarbeitung und -erkennung eingeben.
private void processImage (ContentValues contentValues, Uri contentUri) Neue unsupportedOperationException ("Hook-Methode ist derzeit nicht implementiert");
Weitere zwei Hakenmethoden im GalleryScanner
Klasse stehen uns zur Verfügung (wie die Methodennamen vermuten lassen), um das zu initialisieren und zu de-initialisieren FacialProcessing
Beispiel.
private void initFacialProcessing () wirft UnsupportedOperationException aus throw new UnsupportedOperationException ("Hook-Methode ist derzeit nicht implementiert"); private void deinitFacialProcessing () throw new UnsupportedOperationException ("Hook-Methode ist derzeit nicht implementiert");
Das letzte Paket ist das Präsentationspaket. Wie der Name schon sagt, beherbergt es die Aktivität
Klasse, die für das Rendern unserer Galerie verantwortlich ist. Die Galerie ist eine Rasteransicht
an einem befestigt CursorAdapter
. Wie oben erläutert, wird durch Antippen eines Elements in der Datenbank nach Fotos gesucht, die eine der Identitäten des ausgewählten Fotos enthalten. Wenn Sie beispielsweise auf ein Foto Ihrer Freundin Lisa und ihres Freundes Justin tippen, werden in der Abfrage alle Fotos gefiltert, die entweder Lisa oder Justin enthalten.
Um den Entwicklern dabei zu helfen, ihre Hardware großartig aussehen zu lassen und gerecht zu werden, hat Qualcomm ein erstaunliches Set von SDKs herausgebracht, eines davon ist das Snapdragon-SDK. Das Snapdragon-SDK stellt einen optimierten Satz von Funktionen für die Gesichtsverarbeitung bereit.
Das SDK besteht aus zwei Teilen: Gesichtsverarbeitung und Gesichtserkennung. Da nicht alle Geräte beide oder alle dieser Funktionen unterstützen, was wahrscheinlich der Grund für die Trennung dieser Funktionen ist, bietet das SDK eine einfache Möglichkeit, die vom Gerät unterstützten Funktionen zu überprüfen. Wir werden darauf später näher eingehen.
Die Gesichtsverarbeitung bietet eine Möglichkeit zum Extrahieren von Merkmalen aus einem Foto (eines Gesichts), einschließlich:
Die Gesichtserkennung bietet, wie der Name schon sagt, die Möglichkeit, Personen auf einem Foto zu identifizieren. Es ist erwähnenswert, dass die gesamte Verarbeitung lokal erfolgt - im Gegensatz zur Cloud.
Diese Funktionen können in Echtzeit (Video / Kamera) oder offline (Galerie) verwendet werden. In unserer Übung werden wir diese Funktionen offline verwenden, es gibt jedoch nur minimale Unterschiede zwischen den beiden Ansätzen.
In der Online-Dokumentation der unterstützten Geräte finden Sie weitere Informationen zur Gesichtsverarbeitung und Gesichtserkennung.
In diesem Abschnitt werden wir diese Hook-Methoden ausfüllen - mit überraschend wenigen Codezeilen -, um unserer Anwendung die Möglichkeit zu geben, Gesichtseigenschaften zu extrahieren und Personen zu identifizieren. Laden Sie dazu die Quelle von GitHub herunter und öffnen Sie das Projekt in Android Studio. Alternativ können Sie das abgeschlossene Projekt herunterladen.
Als erstes müssen Sie das SDK von der Qualcomm-Website herunterladen. Beachten Sie, dass Sie sich registrieren / einloggen müssen und den Allgemeinen Geschäftsbedingungen von Qualcomm zustimmen müssen.
Nach dem Herunterladen archivieren Sie den Inhalt und navigieren Sie zu /Snapdragon_sdk_2.3.1/java/libs/libs_facial_processing/. Kopiere das sd-sdk-facial-processing.jar Datei in Ihr Projekt / app / libs / ordner Wie nachfolgend dargestellt.
Klicken Sie nach dem Kopieren des Snapdragon-SDK mit der rechten Maustaste auf sd-sdk-facial-processing.jar und wählen Sie Als Bibliothek hinzufügen… aus der Liste der Optionen.
Dies fügt die Bibliothek als Abhängigkeit in Ihrem hinzu build.gradle Datei wie unten gezeigt.
Abhängigkeiten compile fileTree (Verzeichnis: 'libs', include: ['* .jar']) kompilieren Dateien ('libs / sd-sdk-facial-processing.jar') compile 'com.android.support:support-v13: 20.0.0 '
Der letzte Schritt besteht darin, die native Bibliothek hinzuzufügen. Erstellen Sie dazu einen Ordner mit dem Namen jniLibs in deiner / app / src / main / Ordner und kopieren Sie die armeabi Ordner (aus dem SDK-Download) und seinen Inhalt hinein.
Wir sind jetzt bereit, die Logik zu implementieren, um Personen zu identifizieren, die die Funktionalität der API verwenden. Die folgenden Codeausschnitte gehören in die GalleryScanner
Klasse.
Lassen Sie uns zunächst die Initialisierungs-Hook-Methode angehen.
privat void () () () () () () ()) () () () () ()) () () () () ()) () () () () ()) () () () () ()) () () () () () ()) () () () () ()). () () () () ()). () () () (). () (). () (). () (). () () (). () (). () (). () (). () (). () (). () (). () (). () (). () (). () (). () (). () (). (). () (). (). (). (). (). () Gerät"); mFacialProcessing = FacialProcessing.getInstance (); if (mFacialProcessing! = null) mFacialProcessing.setRecognitionConfidence (mConfidenceThreshold); mFacialProcessing.setProcessingMode (FacialProcessing.FP_MODES.FP_MODE_STILL); loadAlbum (); else throw neue UnsupportedOperationException ("Eine Instanz wird bereits verwendet");
Wir müssen zunächst prüfen, ob das Gerät sowohl die Gesichtsverarbeitung als auch die Gesichtserkennung unterstützt. Wenn nicht, werfen wir eine UnsupportedOperationException
Ausnahme.
Danach vergeben wir unsere lokale Referenz der FacialProcessing
Klasse, mFacialProcessing
, zu einer neuen Instanz mit der Factory-Methode bekomme Instanz
. Das wird wiederkommen Null
Wenn bereits eine Instanz verwendet wird, muss der Verbraucher anrufen Veröffentlichung
auf dieser Referenz.
Wenn wir erfolgreich eine Instanz von a erhalten haben FacialProcessing
Objekt konfigurieren wir es, indem wir zuerst das Vertrauen festlegen. Wir machen dies mit einer lokalen Variablen, nämlich 57
in diesem Fall von 0 bis 100. Die Zuverlässigkeit ist eine Schwelle, wenn versucht wird, Identitäten aufzulösen. Alle Übereinstimmungen unter diesem Schwellenwert werden als separate Identitäten betrachtet.
Soweit ich das beurteilen kann, handelt es sich hierbei um einen Versuchs- und Fehlerprozess. Je höher die Schwelle ist, desto genauer ist die Erkennung, mit dem Kompromiss, die Anzahl der falsch-positiven Werte zu erhöhen.
Dann setzen wir die FacialProcessing
Modus auf FP_MODE_STILL
. Ihre Optionen hier sind entweder FP_MODE_STILL
oder FP_MODE_VIDEO
. Wie die Namen vermuten lassen, ist einer für Standbilder optimiert, der andere für fortlaufende Bilder, die beide offensichtliche Anwendungsfälle haben.
P_MODE_STILL
, wie Sie vielleicht vermuten, liefert genauere Ergebnisse. Aber wie Sie später sehen werden, FP_MODE_STILL
wird durch die Methode impliziert, die wir zur Verarbeitung des Bildes verwenden, sodass diese Zeile weggelassen werden kann. Ich habe es nur der Vollständigkeit halber hinzugefügt.
Wir rufen dann an loadAlbum
(Methode der GalleryScanner
Klasse), was wir als nächstes betrachten werden.
private void loadAlbum () SharedPreferences sharedPreferences = mContext.getSharedPreferences (TAG, 0); String arrayOfString = sharedPreferences.getString (KEY_IDENTITY_ALBUM, null); Byte [] albumArray = null; if (arrayOfString! = null) String [] splitStringArray = arrayOfString.substring (1, arrayOfString.length () - 1) .split (","); albumArray = neues Byte [splitStringArray.length]; für (int i = 0; i < splitStringArray.length; i++) albumArray[i] = Byte.parseByte(splitStringArray[i]); mFacialProcessing.deserializeRecognitionAlbum(albumArray);
Die einzige interessante Linie hier ist:
mFacialProcessing.deserializeRecognitionAlbum (albumArray);
Ihre Gegenmethode ist:
Byte [] albumBuffer = mFacialProcessing.serializeRecogntionAlbum ();
Ein einzelnes FacialProcessing
Instanz kann als Sitzung gedacht werden. Hinzugefügte Personen (unten erklärt) werden innerhalb dieser Instanz lokal gespeichert (als "Erkennungsalbum" bezeichnet). Damit Ihr Album über mehrere Sitzungen bestehen bleiben kann, müssen Sie also jedes Mal, wenn Sie eine neue Instanz abrufen, eine Möglichkeit haben, diese zu speichern und zu laden.
Das serializeRecogntionAlbum
Methode konvertiert das Album in ein Byte - Array und umgekehrt das deserializeRecognitionAlbum
lädt und parst ein zuvor gespeichertes Album als Byte-Array.
Wir wissen jetzt, wie man das initialisiert FacialProcessing
Klasse für Gesichtsverarbeitung und -erkennung. Lassen Sie uns nun den Fokus auf die De-Initialisierung durch die Implementierung von deinitFacialProcessing
Methode.
private void deinitFacialProcessing () if (mFacialProcessing! = null) saveAlbum (); mFacialProcessing.release (); mFacialProcessing = null;
Wie oben erwähnt, kann es nur eine Instanz von FacialProcessing
Wir müssen sicherstellen, dass wir sie freigeben, bevor wir unsere Aufgabe erledigen. Wir machen das über eine Veröffentlichung
Methode. Zuerst machen wir das Erkennungsalbum jedoch so, dass die Ergebnisse über mehrere Sitzungen hinweg verwendet werden können. In diesem Fall möchten wir, wenn der Benutzer neue Fotos macht oder empfängt, sicherstellen, dass wir die zuvor erkannten Identitäten für dieselben Personen verwenden.
private void saveAlbum () Byte [] albumBuffer = mFacialProcessing.serializeRecogntionAlbum (); SharedPreferences sharedPreferences = mContext.getSharedPreferences (TAG, 0); SharedPreferences.Editor editor = sharedPreferences.edit (); editor.putString (KEY_IDENTITY_ALBUM, Arrays.toString (albumBuffer)); editor.commit ();
Endlich sind wir bereit, die endgültige Hook-Methode auszuarbeiten und die FacialProcessing
Klasse. Die folgenden Codeblöcke gehören zum processImage
Methode. Ich habe sie aus Gründen der Klarheit aufgeteilt.
private void processImage (contentValues contentValues, Uri contentUri) long photoRowId = ContentUris.parseId (contentUri); String uriAsString = contentValues.getAsString (GalleryContract.PhotoEntity.COLUMN_URI); Uri uri = Uri.parse (uriAsString); Bitmap-Bitmap = null; try bitmap = ImageUtils.getImage (mContext, uri); catch (IOException e) return; if (Bitmap! = null) // weiter unten (1)
Die Methode nimmt einen Verweis auf eine Instanz von ContentValues
Klasse, die die Metadaten für dieses Bild enthält, zusammen mit dem URI, der auf das Bild verweist. Wir verwenden dies, um das Bild in den Speicher zu laden.
Der folgende Codeausschnitt ersetzt den obigen Kommentar // weiter unten (1)
.
if (! mFacialProcessing.setBitmap (Bitmap)) return; int numFaces = mFacialProcessing.getNumFaces (); if (numFaces> 0) FaceData [] faceDataArray = mFacialProcessing.getFaceData (); if (faceDataArray == null) Log.w (TAG, contentUri.toString () + "wurde ein NULL FaceDataArray zurückgegeben"); Rückkehr; für (int i = 0; iWie oben erwähnt, übergeben wir zuerst das statische Bild an die
FacialProcessing
Instanz über diesetBitmap
Methode. Bei Verwendung dieser Methode wird implizit dieFP_MODE_STILL
Modus. Diese Methode kehrt zurückWahr
wenn das Bild erfolgreich verarbeitet wurde undFalsch
wenn die Verarbeitung fehlgeschlagen ist.Die alternative Methode zum Verarbeiten von Streaming-Bildern (normalerweise für Kameravorschau-Frames) ist:
public boolean setFrame (Byte [] yuvData, int frameWidth, int frameHeight, boolean isMirrored, FacialProcessing.PREVIEW_ROTATION_ANGLE rotationAngle)Die meisten Parameter sind offensichtlich. Sie müssen weitergeben, ob der Frame umgedreht ist (dies ist normalerweise für die nach vorne gerichtete Kamera erforderlich) und ob eine Drehung angewendet wurde (normalerweise über die Kamera eingestellt)
setDisplayOrientation
Methode von aKamera
Beispiel).Wir fragen dann nach der Anzahl der erkannten Gesichter und fahren nur fort, wenn mindestens eines gefunden wird. Das
getFaceData
Die Methode gibt die Details für jedes erkannte Gesicht als Array von zurückFaceData
Objekte, wo jeweilsFaceData
Das Objekt umfasst Gesichtsmerkmale, darunter:
- Gesichtsgrenze (
FACE_RECT
)- Gesichts-, Mund- und Augenpositionen (
FACE_COORDINATES
)- Gesichtskontur (
FACE_CONTOUR
)- Grad des Lächelns (
FACE_SMILE
)- Augenrichtung (
FACE_GAZE
)- Fahne, die anzeigt, ob ein Auge (oder beide Augen) blinkt (
FACE_BLINK
)- Gieren, Nicken und Rollen des Gesichts (
FACE_ORIENTATION
)- generierte oder abgeleitete Identifikation (
FACE_IDENTIFICATION
)Es gibt eine Überladung dieser Methode, die (wie oben beschrieben) eine Reihe von Aufzählungen erfordert, um Feature-Punkte aufzunehmen, die redundante Berechnungen entfernen / minimieren.
public FaceData [] getFaceData (java.util.EnumSet.)dataSet) gibt java.lang.IllegalArgumentException aus Wir gehen jetzt zur Inspektion des
FaceData
Objekt, um die Identität und Merkmale zu extrahieren. Lassen Sie uns zuerst sehen, wie die Gesichtserkennung durchgeführt wird.Der folgende Codeausschnitt ersetzt den obigen Kommentar
// weiter unten (2)
.int personId = faceData.getPersonId (); if (personId == FacialProcessingConstants.FP_PERSON_NOT_REGISTERED) personId = mFacialProcessing.addPerson (i); else if (mFacialProcessing.updatePerson (personId, i)! = FacialProcessingConstants.FP_SUCCESS) // TODO-Handlungsfehler long identityRowId = getOrInsertPerson (personId); // weiter unten (3)Wir fordern zunächst die zugewiesene Personen-ID über die
getPersonId
Methode. Das wird wiederkommen-111
(FP_PERSON_NOT_REGISTERED
) wenn im gerade geladenen Album keine Identität vorhanden ist, andernfalls die ID einer übereinstimmenden Person aus dem geladenen Album zurückgeben.Wenn keine Identität existiert, fügen wir sie über die hinzu
addPerson
Methode derFacialProcessing
Objekt, übergeben es den Index derFaceData
Artikel, den wir gerade prüfen. Die Methode gibt bei Erfolg die zugewiesene Personen-ID zurück, andernfalls wird ein Fehler zurückgegeben. Dies tritt auf, wenn versucht wird, eine bereits vorhandene Identität hinzuzufügen.Wenn die Person mit einer Identität abgeglichen wurde, die in unserem geladenen Album gespeichert ist, rufen wir das an
FacialProcessing
Objekt istupdatePerson
Übergeben Sie die vorhandene ID und den Index derFaceData
Artikel. Durch das mehrfache Hinzufügen einer Person wird die Erkennungsleistung erhöht. Sie können bis zu zehn Gesichter für eine einzelne Person hinzufügen.Die letzte Zeile gibt einfach die zugehörige Identitäts-ID aus unserer Datenbank zurück und fügt sie ein, falls die Personen-ID noch nicht vorhanden ist.
Es wird nicht oben gezeigt, aber die
FaceData
Instanz macht die Methode verfügbargetRecognitionConfidence
zur Rückgabe der Erkennungssicherheit (0 bis 100). Je nach Ihren Anforderungen können Sie den Fluss beeinflussen.Das abschließende Snippet zeigt, wie Sie die anderen Funktionen von der
FaceData
Beispiel. In dieser Demo verwenden wir sie nicht, aber mit ein wenig Fantasie können Sie sich sicher Möglichkeiten einfallen lassen, um sie sinnvoll einzusetzen.Der folgende Codeausschnitt ersetzt den obigen Kommentar
// weiter unten (3)
.int smileValue = faceData.getSmileValue (); int leftEyeBlink = faceData.getLeftEyeBlink (); int rightEyeBlink = faceData.getRightEyeBlink (); int roll = faceData.getRoll (); PointF gazePointValue = faceData.getEyeGazePoint (); int pitch = faceData.getPitch (); int yaw = faceData.getYaw (); int horizontalGaze = faceData.getEyeHorizontalGazeAngle (); int verticalGaze = faceData.getEyeVerticalGazeAngle (); Rect faceRect = faceData.rect; insertNewPhotoIdentityRecord (photoRowId, identityRowId, gazePointValue, horizontalGaze, verticalGaze, leftEyeBlink, rightEyeBlink, Pitch, Gier, Roll, SmileValue, faceRect);Damit ist der Verarbeitungscode abgeschlossen. Wenn Sie zur Galerie zurückkehren und auf ein Bild tippen, sollten Sie feststellen, dass Fotos herausgefiltert werden, die keine Personen enthalten, die im ausgewählten Foto enthalten sind.
Fazit
Wir haben mit diesem Tutorial begonnen, wie die Technologie zur Organisation der Benutzerinhalte verwendet werden kann. In kontextabhängigem Computing, dessen Ziel es ist, Kontext als impliziten Hinweis zu verwenden, um die verarmte Interaktion von Mensch zu Computer zu bereichern und die Interaktion mit Computern zu vereinfachen, spricht man von Auto-Tagging. Durch die Markierung von Inhalten mit aussagekräftigeren und nützlicheren Daten - sowohl für den Computer als auch für uns - ermöglichen wir eine intelligentere Filterung und Verarbeitung.
Wir haben gesehen, dass dies häufig bei Textinhalten verwendet wird, wobei das offensichtlichste Beispiel Spamfilter und in jüngster Zeit Nachrichtenleser sind, bei Rich Media-Inhalten wie Fotos, Musik und Videos dagegen weniger. Tools wie das Snapdragon SDK bieten uns die Möglichkeit, aussagekräftige Funktionen aus Rich Media zu extrahieren und dessen Eigenschaften dem Benutzer und dem Computer zugänglich zu machen.
Es ist nicht schwer vorstellbar, wie Sie unsere Anwendung erweitern können, um eine Filterung basierend auf Gefühl zu ermöglichen, indem Sie ein Lächeln als Hauptmerkmal oder eine soziale Aktivität verwenden, indem Sie die Anzahl der Gesichter zählen. Eine solche Implementierung ist in dieser Smart Gallery-Funktion zu sehen.