1. Başlamadan önce
Kodu yazarak kas hafızanızı geliştirebilir ve materyali daha iyi anlayabilirsiniz. Kopyalama ve yapıştırma işlemi zaman kazandırsa da bu uygulamaya yatırım yapmak uzun vadede daha fazla verimlilik ve daha güçlü kodlama becerileri sağlayabilir.
Bu codelab'de, Google'ın TensorFlow Lite için yeni çalışma zamanı olan LiteRT'yi kullanarak canlı kamera feed'inde gerçek zamanlı görüntü segmentasyonu gerçekleştiren bir Android uygulaması oluşturmayı öğreneceksiniz. Başlangıç Android uygulamasını alıp buna görüntü segmentasyonu özellikleri ekleyeceksiniz. Ayrıca ön işleme, çıkarım ve son işleme adımlarını da inceleyeceğiz. Bu kurstan sonra:
- Görüntüleri gerçek zamanlı olarak segmentlere ayıran bir Android uygulaması oluşturun.
- Önceden eğitilmiş bir LiteRT görüntü segmentasyonu modelini entegre edin.
- Giriş resmini model için önceden işleyin.
- CPU ve GPU hızlandırması için LiteRT çalışma zamanını kullanın.
- Segmentasyon maskesini görüntülemek için modelin çıkışını nasıl işleyeceğinizi öğrenin.
- Ön kameraya göre nasıl ayarlama yapacağınızı öğrenin.
Sonunda, aşağıdaki resme benzer bir şey oluşturursunuz:
Ön koşullar
Bu codelab, makine öğrenimi konusunda deneyim kazanmak isteyen deneyimli mobil geliştiriciler için tasarlanmıştır. Aşağıdaki konular hakkında bilgi sahibi olmanız gerekir:
- Kotlin ve Android Studio ile Android geliştirme
- Görüntü işlemenin temel kavramları
Neler öğreneceksiniz?
- LiteRT çalışma zamanını Android uygulamasına entegre etme ve kullanma
- Önceden eğitilmiş bir LiteRT modeli kullanarak görüntü segmentasyonu gerçekleştirme
- Giriş görüntüsünün model için nasıl önceden işleneceği.
- Model için çıkarım çalıştırma
- Sonuçları görselleştirmek için segmentasyon modelinin çıkışını işleme
- Gerçek zamanlı kamera feed'i işleme için CameraX'i kullanma
İhtiyacınız olanlar
- Android Studio'nun son sürümlerinden biri (v2025.1.1'de test edilmiştir).
- Fiziksel bir Android cihaz. En iyi test Galaxy ve Pixel cihazlarda yapılır.
- Örnek kod (GitHub'dan).
- Kotlin ile Android geliştirmeye ilişkin temel bilgiler.
2. Görüntü Segmentasyonu
Görüntü segmentasyonu, bir görüntüyü birden fazla segmente veya bölgeye ayırmayı içeren bir bilgisayar görme görevidir. Nesne algılama, bir nesnenin etrafına sınırlayıcı kutu çizerken görüntü segmentasyonu, görüntüdeki her bir piksele belirli bir sınıf veya etiket atar. Bu sayede, resmin içeriği hakkında çok daha ayrıntılı ve ayrıntılı bir anlayış elde edebilir, her nesnenin tam şeklini ve sınırını öğrenebilirsiniz.
Örneğin, bir kutuda yalnızca "bir kişi" olduğunu bilmek yerine, bu kişiye ait piksellerin hangileri olduğunu tam olarak öğrenebilirsiniz. Bu eğiticide, önceden eğitilmiş bir makine öğrenimi modeli kullanarak Android cihazda gerçek zamanlı görüntü segmentasyonu işleminin nasıl yapılacağı gösterilmektedir.
LiteRT: Cihazda makine öğreniminin sınırlarını zorlama
Mobil cihazlarda gerçek zamanlı ve yüksek doğrulukta segmentasyon sağlayan temel teknolojilerden biri LiteRT'dir. TensorFlow Lite için Google'ın yeni nesil, yüksek performanslı çalışma zamanı olan LiteRT, temel donanımdan mutlak en iyi performansı elde etmek üzere tasarlanmıştır.
Bu, GPU (Grafik İşlem Birimi) ve NPU (Nöral İşlem Birimi) gibi donanım hızlandırıcıların akıllı ve optimize edilmiş kullanımıyla sağlanır. LiteRT, segmentasyon modelinin yoğun hesaplama iş yükünü genel amaçlı CPU'dan bu özel işlemcilere aktararak çıkarım süresini önemli ölçüde kısaltır. Bu hızlandırma, karmaşık modellerin canlı kamera feed'inde sorunsuz bir şekilde çalıştırılmasını mümkün kılar ve makine öğrenimiyle doğrudan telefonunuzda yapabileceklerimizin sınırlarını genişletir. Bu performans seviyesi olmadan, gerçek zamanlı segmentasyon iyi bir kullanıcı deneyimi için çok yavaş ve kesintili olurdu.
3. Hazırlanın
Depoyu klonlama
İlk olarak, LiteRT deposunu klonlayın:
git clone https://github.com/google-ai-edge/LiteRT.git
LiteRT/litert/samples/image_segmentation
, ihtiyacınız olan tüm kaynakların bulunduğu dizindir. Bu codelab için yalnızca kotlin_cpu_gpu/android_starter
projesine ihtiyacınız olacaktır. Takılırsanız bitmiş projeyi inceleyebilirsiniz: kotlin_cpu_gpu/android
Dosya yollarıyla ilgili not
Bu eğitimde, dosya yolları Linux/macOS biçiminde belirtilmiştir. Windows kullanıyorsanız yolları buna göre ayarlamanız gerekir.
Android Studio proje görünümü ile standart dosya sistemi görünümü arasındaki farkı da belirtmek gerekir. Android Studio proje görünümü, projenizin dosyalarının Android geliştirme için düzenlenmiş yapılandırılmış bir gösterimidir. Bu eğitimdeki dosya yolları, Android Studio proje görünümündeki yolları değil, dosya sistemi yollarını ifade eder.
Başlangıç uygulamasını içe aktarma
Başlangıç uygulamasını Android Studio'ya aktararak başlayalım.
- Android Studio'yu açın ve Open'ı (Aç) seçin.
kotlin_cpu_gpu/android_starter
dizinine gidip dizini açın.
Tüm bağımlılıkların uygulamanızda kullanılabilir olduğundan emin olmak için içe aktarma işlemi tamamlandığında projenizi Gradle dosyalarıyla senkronize etmeniz gerekir.
- Android Studio araç çubuğundan Projeyi Gradle Dosyalarıyla Senkronize Et'i seçin.
- Lütfen bu adımı atlamayın. Bu adım işe yaramazsa eğitimin geri kalanı anlaşılmaz.
Başlangıç uygulamasını çalıştırma
Projeyi Android Studio'ya aktardığınıza göre artık uygulamayı ilk kez çalıştırmaya hazırsınız.
Android cihazınızı USB ile bilgisayarınıza bağlayın ve Android Studio araç çubuğunda Çalıştır'ı tıklayın.
Uygulama, cihazınızda başlatılmalıdır. Canlı kamera feed'i görürsünüz ancak henüz segmentasyon yapılmaz. Bu eğitimde yapacağınız tüm dosya düzenlemeleri LiteRT/litert/samples/image_segmentation/kotlin_cpu_gpu/android_starter/app/src/main/java/com/google/aiedge/examples/image_segmentation
dizini altında olacak (Android Studio'nun bu dizini neden yeniden yapılandırdığını artık biliyorsunuz 😃).
Ayrıca TODO
yorumlarını ImageSegmentationHelper.kt
, MainViewModel.kt
ve view/SegmentationOverlay.kt
dosyalarında da görürsünüz. Aşağıdaki adımlarda, bu TODO
'ları doldurarak görüntü segmentasyonu işlevini uygulayacaksınız.
4. Başlangıç uygulamasını anlama
Başlangıç uygulamasında temel bir kullanıcı arayüzü ve kamera işleme mantığı zaten vardır. Aşağıda, önemli dosyalara hızlı bir genel bakış verilmiştir:
app/src/main/java/com/google/aiedge/examples/image_segmentation/MainActivity.kt
: Bu, uygulamanın ana giriş noktasıdır. Jetpack Compose kullanarak kullanıcı arayüzünü oluşturur ve kamera izinlerini yönetir.app/src/main/java/com/google/aiedge/examples/image_segmentation/MainViewModel.kt
: Bu ViewModel, kullanıcı arayüzü durumunu yönetir ve görüntü segmentasyonu sürecini düzenler.app/src/main/java/com/google/aiedge/examples/image_segmentation/ImageSegmentationHelper.kt
: Görüntü segmentasyonu için temel mantığı buraya ekleyeceğiz. Modelin yüklenmesi, kamera karelerinin işlenmesi ve çıkarımın çalıştırılması bu kitaplık tarafından gerçekleştirilir.app/src/main/java/com/google/aiedge/examples/image_segmentation/view/CameraScreen.kt
: Bu Composable işlevi, kamera önizlemesini ve vücudu bölme yer paylaşımını gösterir.app/src/main/assets/selfie_multiclass.tflite
: Bu, kullanacağımız önceden eğitilmiş TensorFlow Lite görüntü segmentasyonu modelidir.
5. LiteRT'yi anlama ve bağımlılık ekleme
Şimdi de başlangıç uygulamasına görüntü segmentasyonu işlevini ekleyelim.
1. LiteRT bağımlılığını ekleme
Öncelikle LiteRT kitaplığını projenize eklemeniz gerekir. Bu, Google'ın optimize edilmiş çalışma zamanı ile cihaz üzerinde makine öğrenimini etkinleştirmenin ilk ve en önemli adımıdır.
app/build.gradle.kts
dosyasını açın ve aşağıdaki satırı dependencies
bloğuna ekleyin:
// LiteRT for on-device ML
implementation(libs.litert)
Bağımlılığı ekledikten sonra Android Studio'nun sağ üst köşesinde görünen Şimdi Senkronize Et düğmesini tıklayarak projenizi Gradle dosyalarıyla senkronize edin.
2. Key LiteRT API'lerini anlama
AçImageSegmentationHelper.kt
Uygulama kodunu yazmadan önce, kullanacağınız LiteRT API'nin temel bileşenlerini anlamanız önemlidir. com.google.ai.edge.litert
paketinden içe aktardığınızdan emin olun ve ImageSegmentationHelper.kt
dosyasının en üstüne aşağıdaki içe aktarma işlemlerini ekleyin:
import com.google.ai.edge.litert.Accelerator
import com.google.ai.edge.litert.CompiledModel
CompiledModel
: Bu, TFLite modelinizle etkileşim kurmak için kullanılan merkezi sınıftır. Belirli bir donanım hızlandırıcı (CPU veya GPU gibi) için önceden derlenmiş ve optimize edilmiş bir modeli temsil eder. Bu ön derleme, LiteRT'nin temel bir özelliğidir ve daha hızlı ve verimli çıkarım yapılmasını sağlar.CompiledModel.Options
:CompiledModel
öğesini yapılandırmak için bu oluşturucu sınıfını kullanırsınız. En önemli ayar, modelinizi çalıştırmak için kullanmak istediğiniz donanım hızlandırıcıyı belirtmektir.Accelerator
: Bu enum, çıkarım için donanım seçmenize olanak tanır. Başlangıç projesi, şu seçenekleri işleyecek şekilde yapılandırılmıştır:Accelerator.CPU
: Modeli cihazın CPU'sunda çalıştırmak için. Bu, en evrensel uyumluluğa sahip seçenektir.Accelerator.GPU
: Modeli cihazın GPU'sunda çalıştırmak için. Bu, genellikle görüntü tabanlı modeller için CPU'dan çok daha hızlıdır.
- Giriş ve Çıkış Arabellekleri (
TensorBuffer
): LiteRT, model girişleri ve çıkışları içinTensorBuffer
kullanır. Bu sayede, bellek üzerinde ayrıntılı kontrol sahibi olabilir ve gereksiz veri kopyalarını önleyebilirsiniz. Bu arabelleklerimodel.createInputBuffers()
vemodel.createOutputBuffers()
kullanarak doğrudanCompiledModel
örneğinizden alırsınız. Ardından giriş verilerinizi bu arabelleklere yazıp sonuçları bu arabelleklerden okursunuz. model.run()
: Bu, çıkarımı yürüten işlevdir. Giriş ve çıkış arabelleklerini LiteRT'ye iletirsiniz. LiteRT, modeli seçilen donanım hızlandırıcıda çalıştırma gibi karmaşık görevleri yönetir.
6. İlk ImageSegmentationHelper uygulamasını tamamlama
Şimdi biraz kod yazma zamanı. ImageSegmentationHelper.kt
'nın ilk uygulamasını tamamlayacaksınız. Bu işlem, LiteRT modelini tutmak için Segmenter
özel sınıfının ayarlanmasını ve düzgün şekilde yayınlamak için cleanup()
işlevinin uygulanmasını içerir.
Segmenter
sınıfını vecleanup()
işlevini tamamlama:ImageSegmentationHelper.kt
dosyasında,Segmenter
adlı özel bir sınıfın vecleanup()
adlı bir işlevin iskeletini bulacaksınız. İlk olarak,Segmenter
sınıfını tamamlayın. Bunun için sınıfın oluşturucusunu modeli tutacak şekilde tanımlayın, giriş/çıkış arabellekleri için özellikler oluşturun ve modeli serbest bırakacak birclose()
yöntemi ekleyin. Ardından, bu yeniclose()
yöntemini çağırmak içincleanup()
işlevini uygulayın. MevcutSegmenter
sınıfını vecleanup()
işlevini aşağıdakilerle değiştirin: (~83. satır)private class Segmenter( // Add this argument private val model: CompiledModel, private val coloredLabels: List<ColoredLabel>, ) { // Add these private vals private val inputBuffers: = model.createInputBuffers() private val outputBuffers: = model.createOutputBuffers() fun cleanup() { // cleanup buffers inputBuffers.forEach { it.close() } outputBuffers.forEach { it.close() } // cleanup model model.close() } }
- toAccelerator yöntemini tanımlayın: Bu yöntem, tanımlanan hızlandırıcı numaralandırmalarını hızlandırıcı menüsünden içe aktarılan LiteRT modüllerine özgü hızlandırıcı numaralandırmalarıyla eşler (~225. satır):
fun toAccelerator(acceleratorEnum: AcceleratorEnum): Accelerator { return when (acceleratorEnum) { AcceleratorEnum.CPU -> Accelerator.CPU AcceleratorEnum.GPU -> Accelerator.GPU } }
CompiledModel
işlevini başlatın: ŞimdiinitSegmenter
işlevini bulun.CompiledModel
örneğini burada oluşturacak ve artık tanımlanmış olanSegmenter
sınıfınızı örneklendirmek için kullanacaksınız. Bu kod, modeli belirtilen hızlandırıcıyla (CPU veya GPU) kurar ve çıkarıma hazırlar.initSegmenter
içindekiTODO
öğesini aşağıdaki uygulamayla değiştirin (Cmd/Ctrl+f "initSegmenter" veya ~62. satır):cleanup() try { withContext(singleThreadDispatcher) { val model = CompiledModel.create( context.assets, "selfie_multiclass.tflite", CompiledModel.Options(toAccelerator(acceleratorEnum)), null, ) segmenter = Segmenter(model, coloredLabels) Log.d(TAG, "Created an image segmenter") } } catch (e: Exception) { Log.i(TAG, "Create LiteRT from selfie_multiclass is failed: ${e.message}") _error.emit(e) }
7. Segmentasyon ve Ön İşleme İşlemini Başlatma
Artık bir modelimiz olduğuna göre, segmentasyon sürecini tetiklememiz ve giriş verilerini model için hazırlamamız gerekiyor.
Tetikleyici Segmentasyonu
Segmentasyon süreci, kameradan kareler alan MainViewModel.kt
içinde başlar.
AçMainViewModel.kt
- Kamera Çerçevelerinden Segmentasyonu Tetikleme:
MainViewModel
içindekisegment
işlevleri, segmentasyon görevimizin giriş noktasıdır. Kameradan yeni bir resim geldiğinde veya galeriden bir resim seçildiğinde çağrılırlar. Bu işlevler daha sonraImageSegmentationHelper
içindekisegment
yöntemini çağırır. Her ikisegment
işlevindekiTODO
'ları aşağıdakiyle değiştirin (satır ~107):// For ImageProxy (from CameraX) fun segment(imageProxy: ImageProxy) { segmentJob = viewModelScope.launch { imageSegmentationHelper.segment(imageProxy.toBitmap(), imageProxy.imageInfo.rotationDegrees) imageProxy.close() } } // For Bitmaps (from gallery) fun segment(bitmap: Bitmap, rotationDegrees: Int) { segmentJob = viewModelScope.launch { val argbBitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true) imageSegmentationHelper.segment(argbBitmap, rotationDegrees) } }
Resmi önceden işleme
Şimdi de resim ön işlemesini yapmak için ImageSegmentationHelper.kt
'ye geri dönelim.
AçImageSegmentationHelper.kt
- Public
segment
işlevini uygulama: Bu işlev,Segmenter
sınıfındaki özelsegment
işlevini çağıran bir sarmalayıcı görevi görür.TODO
yerine şunu ekleyin (~line 95):try { withContext(singleThreadDispatcher) { segmenter?.segment(bitmap, rotationDegrees)?.let { if (isActive) _segmentation.emit(it) } } } catch (e: Exception) { Log.i(TAG, "Image segment error occurred: ${e.message}") _error.emit(e) }
- Ön İşleme Uygulama:
Segmenter
sınıfındaki özelsegment
işlevi, giriş görüntüsünde modeli hazırlamak için gerekli dönüşümleri gerçekleştireceğimiz yerdir. Görüntüyü ölçeklendirme, döndürme ve normalleştirme bu kapsamdadır. Bu işlev daha sonra çıkarım gerçekleştirmek için başka bir özelsegment
işlevini çağırır.segment(bitmap: Bitmap, ...)
işlevindekiTODO
yerine şunu girin (~121. satır):val totalStartTime = SystemClock.uptimeMillis() val rotation = -rotationDegrees / 90 val (h, w) = Pair(256, 256) // Preprocessing val preprocessStartTime = SystemClock.uptimeMillis() var image = bitmap.scale(w, h, true) image = rot90Clockwise(image, rotation) val inputFloatArray = normalize(image, 127.5f, 127.5f) Log.d(TAG, "Preprocessing time: ${SystemClock.uptimeMillis() - preprocessStartTime} ms") // Inference val inferenceStartTime = SystemClock.uptimeMillis() val segmentResult = segment(inputFloatArray) Log.d(TAG, "Inference time: ${SystemClock.uptimeMillis() - inferenceStartTime} ms") Log.d(TAG, "Total segmentation time: ${SystemClock.uptimeMillis() - totalStartTime} ms") return SegmentationResult(segmentResult, SystemClock.uptimeMillis() - inferenceStartTime)
8. LiteRT ile birincil çıkarım
Giriş verileri önceden işlendiğinden artık LiteRT kullanarak temel çıkarımı çalıştırabiliriz.
AçImageSegmentationHelper.kt
- Model Yürütmeyi Uygulama: Özel
segment(inputFloatArray: FloatArray)
işlevi, LiteRTrun()
yöntemiyle doğrudan etkileşim kurduğumuz yerdir. Önceden işlenmiş verilerimizi giriş arabelleğine yazar, modeli çalıştırır ve sonuçları çıkış arabelleğinden okuruz. Bu işlevdekiTODO
yerine şunu yazın (~188. satır):val (h, w, c) = Triple(256, 256, 6) // MODEL EXECUTION PHASE val modelExecStartTime = SystemClock.uptimeMillis() // Write input data - measure time val bufferWriteStartTime = SystemClock.uptimeMillis() inputBuffers[0].writeFloat(inputFloatArray) val bufferWriteTime = SystemClock.uptimeMillis() - bufferWriteStartTime Log.d(TAG, "Buffer write time: $bufferWriteTime ms") // Optional tensor inspection logTensorStats("Input tensor", inputFloatArray) // Run model inference - measure time val modelRunStartTime = SystemClock.uptimeMillis() model.run(inputBuffers, outputBuffers) val modelRunTime = SystemClock.uptimeMillis() - modelRunStartTime Log.d(TAG, "Model.run() time: $modelRunTime ms") // Read output data - measure time val bufferReadStartTime = SystemClock.uptimeMillis() val outputFloatArray = outputBuffers[0].readFloat() val outputBuffer = FloatBuffer.wrap(outputFloatArray) val bufferReadTime = SystemClock.uptimeMillis() - bufferReadStartTime Log.d(TAG, "Buffer read time: $bufferReadTime ms") val modelExecTime = SystemClock.uptimeMillis() - modelExecStartTime Log.d(TAG, "Total model execution time: $modelExecTime ms") // Optional tensor inspection logTensorStats("Output tensor", outputFloatArray) // POSTPROCESSING PHASE val postprocessStartTime = SystemClock.uptimeMillis() // Process mask from model output val inferenceData = InferenceData(width = w, height = h, channels = c, buffer = outputBuffer) val mask = processImage(inferenceData) val postprocessTime = SystemClock.uptimeMillis() - postprocessStartTime Log.d(TAG, "Postprocessing time (mask creation): $postprocessTime ms") return Segmentation( listOf(Mask(mask, inferenceData.width, inferenceData.height)), coloredLabels, )
9. İşleme sonrası ve yer paylaşımını görüntüleme
Çıkarım çalıştırdıktan sonra modelden ham bir çıkış elde ederiz. Görsel segmentasyon maskesi oluşturmak için bu çıkışı işlememiz ve ardından ekranda göstermemiz gerekir.
AçImageSegmentationHelper.kt
- Çıkış İşlemeyi Uygulama:
processImage
işlevi, modelden gelen ham kayan nokta çıkışını, segmentasyon maskesini temsil eden birByteBuffer
değerine dönüştürür. Bunu, her piksel için en yüksek olasılıklı sınıfı bularak yapar.TODO
yerine şunu ekleyin (~line 238):val mask = ByteBuffer.allocateDirect(inferenceData.width * inferenceData.height) for (i in 0 until inferenceData.height) { for (j in 0 until inferenceData.width) { val offset = inferenceData.channels * (i * inferenceData.width + j) var maxIndex = 0 var maxValue = inferenceData.buffer.get(offset) for (index in 1 until inferenceData.channels) { if (inferenceData.buffer.get(offset + index) > maxValue) { maxValue = inferenceData.buffer.get(offset + index) maxIndex = index } } mask.put(i * inferenceData.width + j, maxIndex.toByte()) } } return mask
AçMainViewModel.kt
- Segmentasyon Sonuçlarını Toplama ve İşleme: Şimdi
MainViewModel
'ye geri dönerekImageSegmentationHelper
'den gelen segmentasyon sonuçlarını işliyoruz.segmentationUiShareFlow
,SegmentationResult
toplar, maskeyi renkli birBitmap
haline getirir ve kullanıcı arayüzüne sunar.segmentationUiShareFlow
özelliğindekiTODO
yerine (~63. satır) ifadesini ekleyin. Burada zaten bulunan kodu değiştirmeyin, yalnızca gövdeyi doldurun:viewModelScope.launch { imageSegmentationHelper.segmentation .filter { it.segmentation.masks.isNotEmpty() } .map { val segmentation = it.segmentation val mask = segmentation.masks[0] val maskArray = mask.data val width = mask.width val height = mask.height val pixelSize = width * height val pixels = IntArray(pixelSize) val colorLabels = segmentation.coloredLabels.mapIndexed { index, coloredLabel -> ColorLabel(index, coloredLabel.label, coloredLabel.argb) } // Set color for pixels for (i in 0 until pixelSize) { val colorLabel = colorLabels[maskArray[i].toInt()] val color = colorLabel.getColor() pixels[i] = color } // Get image info val overlayInfo = OverlayInfo(pixels = pixels, width = width, height = height) val inferenceTime = it.inferenceTime Pair(overlayInfo, inferenceTime) } .collect { flow.emit(it) } }
Açview/SegmentationOverlay.kt
Son olarak, kullanıcı ön kameraya geçtiğinde segmentasyon yer paylaşımını doğru şekilde yönlendirmek gerekir. Kamera feed'i, ön kamera için doğal olarak yansıtılır. Bu nedenle, yer paylaşımımızın Bitmap
kamera önizlemesiyle doğru şekilde hizalanmasını sağlamak için aynı yatay çevirme işlemini uygulamamız gerekir.
- Handle Overlay Orientation:
SegmentationOverlay.kt
dosyasındaTODO
ifadesini bulun ve aşağıdaki kodla değiştirin. Bu kod, ön kameranın etkin olup olmadığını kontrol eder. EtkinseCanvas
üzerine çizilmeden önce yer paylaşımlı resmeBitmap
yatay çevirme uygular. (~line 42):val orientedBitmap = if (lensFacing == CameraSelector.LENS_FACING_FRONT) { // Create a matrix for horizontal flipping val matrix = Matrix().apply { preScale(-1f, 1f) } Bitmap.createBitmap(image, 0, 0, image.width, image.height, matrix, false).also { image.recycle() } } else { image }
10. Son Uygulamayı Çalıştırma ve Kullanma
Gerekli tüm kod değişikliklerini tamamladınız. Uygulamayı çalıştırmanın ve çalışmanızı görmenin zamanı geldi.
- Uygulamayı çalıştırma: Android cihazınızı bağlayın ve Android Studio araç çubuğunda Run'ı (Çalıştır) tıklayın.
- Özellikleri Test Etme: Uygulama başlatıldıktan sonra, renkli bir segmentasyon yer paylaşımıyla birlikte canlı kamera feed'ini görmeniz gerekir.
- Kameralar Arasında Geçiş Yapma: Ön ve arka kameralar arasında geçiş yapmak için üst kısımdaki kamera çevirme simgesine dokunun. Yerleşimin nasıl doğru şekilde yönlendirildiğine dikkat edin.
- Hızlandırıcıyı değiştirme: Donanım hızlandırıcıyı değiştirmek için alttaki "CPU" veya "GPU" düğmesine dokunun. Ekranın alt kısmında gösterilen Çıkarım Süresi'ndeki değişikliği gözlemleyin. GPU önemli ölçüde daha hızlı olmalıdır.
- Galeri resmini kullanma: Cihazınızın fotoğraf galerisinden bir resim seçmek için üst kısımdaki "Galeri" sekmesine dokunun. Uygulama, seçilen statik görüntüde segmentasyon gerçekleştirir.
Artık LiteRT tarafından desteklenen, tam işlevli ve gerçek zamanlı bir görüntü segmentasyonu uygulamanız var.
11. Gelişmiş (isteğe bağlı): NPU'yu kullanma
Bu depoda, uygulama sürümünün sinirsel işlem birimleri (NPU'lar) için optimize edilmiş bir versiyonu da bulunur. NPU sürümü, uyumlu NPU'ya sahip cihazlarda önemli bir performans artışı sağlayabilir.
NPU sürümünü denemek için kotlin_npu/android
projesini Android Studio'da açın. Kod, CPU/GPU sürümüne çok benzer ve NPU temsilcisini kullanacak şekilde yapılandırılmıştır.
NPU temsilcisini kullanmak için erken erişim programına kaydolmanız gerekir.
12. Tebrikler!
LiteRT kullanarak gerçek zamanlı görüntü segmentasyonu gerçekleştiren bir Android uygulamasını başarıyla oluşturdunuz. Öğrendikleriniz:
- LiteRT çalışma zamanını bir Android uygulamasına entegre edin.
- Bir TFLite görüntü segmentasyonu modelini yükleyip çalıştırma
- Modelin girişini önceden işleyin.
- Segmentasyon maskesi oluşturmak için modelin çıkışını işleyin.
- Anlık kamera uygulaması için CameraX'i kullanın.
Sonraki Adımlar
- Farklı bir görüntü segmentasyonu modeli deneyin.
- Farklı LiteRT temsilcileriyle (CPU, GPU, NPU) denemeler yapın.