Реалізація AI-сегментації відеопотоку в реальному часі у мобільному застосунку

TRUETECH займається розробкою, підтримкою та обслуговуванням мобільних додатків iOS, Android, PWA. Маємо великий досвід та експертизу для публікації мобільних додатків до популярних маркетів Google Play, App Store, Amazon, AppGallery та інші.

Розробка та підтримка будь-яких видів мобільних додатків:

Інформаційні та розважальні мобільні програми
Новинки, ігри, довідники, онлайн-каталоги, погодні, фітнес та здоров'я, туристичні, освітні, соціальні мережі та месенджери, квіз, блоги та подкасти, форуми, агрегатори
Мобільні програми електронної комерції
Інтернет-магазини, B2B-додатки, маркетплейси, онлайн-обмінники, кешбек-сервіси, біржі, дропшиппінг-платформи, програми лояльності, доставка їжі та товарів, платіжні системи
Мобільні програми для управління бізнес-процесами
CRM-системи, ERP-системи, управління проектами, інструменти для команди продажів, облік фінансів, управління виробництвом, логістика та доставка, управління персоналом, системи моніторингу даних
Мобільні програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, платформи надання електронних послуг, платформи кешбеку, відеохостинги, тематичні портали, платформи онлайн-бронювання та запису, платформи онлайн-торгівлі

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

Послуги, які ми пропонуємо
Показано 1 з 1Усі 1735 послуг
Реалізація AI-сегментації відеопотоку в реальному часі у мобільному застосунку
Складний
~2-4 тижні
Часті запитання

Наші компетенції:

Етапи розробки

Останні роботи

  • image_mobile-applications_feedme_467_0.webp
    Розробка мобільного додатка для компанії FEEDME
    792
  • image_mobile-applications_xoomer_471_0.webp
    Розробка мобільного додатку для компанії XOOMER
    671
  • image_mobile-applications_rhl_428_0.webp
    Розробка мобільного додатку для компанії RHL
    1097
  • image_mobile-applications_zippy_411_0.webp
    Розробка мобільного додатку для компанії ZIPPY
    969
  • image_mobile-applications_affhome_429_0.webp
    Розробка мобільного додатку для компанії Affhome
    914
  • image_mobile-applications_flavors_409_0.webp
    Розробка мобільного додатку для компанії FLAVORS
    495

Сегментація відео в реальному часі через AI у мобільних додатках

Сегментація відео в реальному часі на мобільних — коли додаток розуміє все у кадрі: людину, фон, машину, дорогу — і робить це на кожному кадрі з частотою 15–30 FPS. Зробити так, щоб «працює в демо» — просто. Зробити так, щоб «не гріється, не лагає, працює на iPhone XR» — потребує серйозної роботи з оптимізацією.

Типи сегментації та їхні застосування

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

Instance сегментація — окрема маска для кожного об'єкту одного класу (три машини — три маски). Застосування: підрахунок об'єктів, трекинг.

Panoptic — комбінація обох. Більш обчислювально витратна; рідко використовується на мобільних.

Вибір моделі для роботи в реальному часі

Швидкість критична. Ось дійсні цифри на iPhone 14 Pro (Neural Engine):

Модель Дозвіл FPS (CoreML) Якість
MobileNetV3-DeepLabV3 513×513 22–28 Середня
EfficientPS-lite 640×360 18–24 Хороша
YOLOv8n-seg 640×640 20–30 Хороша
Segment Anything (SAM-mobile) 1024×1024 3–5 Відмінна

SAM для інтерактивної сегментації (тап на об'єкт → маска). Для роботи в реальному часі без введення користувача рекомендуються YOLOv8n-seg або DeepLabV3+.

iOS: CoreML конвеєр для роботи в реальному часі

class RealtimeSegmentationProcessor {

    private let model: VNCoreMLModel
    private let processQueue = DispatchQueue(label: "segmentation.process", qos: .userInteractive)

    // Пропуск кадрів: обробляємо кожен N-й кадр
    private var frameCounter = 0
    private let processEveryNFrames = 2  // 30fps камера → 15fps обробка

    func captureOutput(_ output: AVCaptureOutput,
                       didOutput sampleBuffer: CMSampleBuffer,
                       from connection: AVCaptureConnection) {
        frameCounter += 1
        guard frameCounter % processEveryNFrames == 0 else { return }
        guard let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else { return }

        processQueue.async { [weak self] in
            self?.runSegmentation(on: pixelBuffer)
        }
    }

    private func runSegmentation(on pixelBuffer: CVPixelBuffer) {
        let request = VNCoreMLRequest(model: model) { [weak self] req, _ in
            guard let observation = req.results?.first as? VNCoreMLFeatureValueObservation,
                  let maskArray = observation.featureValue.multiArrayValue else { return }

            let mask = self?.processMask(maskArray)
            DispatchQueue.main.async {
                self?.delegate?.didUpdateSegmentationMask(mask)
            }
        }

        // Важливо: pixelBuffer повинен бути у правильному форматі
        request.imageCropAndScaleOption = .scaleFill
        let handler = VNImageRequestHandler(cvPixelBuffer: pixelBuffer,
                                           orientation: .right)  // альбомна орієнтація
        try? handler.perform([request])
    }

    private func processMask(_ array: MLMultiArray) -> SegmentationMask {
        // Конвертація MLMultiArray → CVPixelBuffer для рендерингу
        // Форма: [numClasses, height, width]
        let numClasses = array.shape[0].intValue
        let height = array.shape[1].intValue
        let width = array.shape[2].intValue

        // Argmax по класам для кожного пікселя → карта мітки
        var labelMap = [UInt8](repeating: 0, count: height * width)
        for y in 0..<height {
            for x in 0..<width {
                var maxClass = 0
                var maxVal: Float = -Float.infinity
                for c in 0..<numClasses {
                    let val = array[[c, y, x] as [NSNumber]].floatValue
                    if val > maxVal { maxVal = val; maxClass = c }
                }
                labelMap[y * width + x] = UInt8(maxClass)
            }
        }
        return SegmentationMask(labels: labelMap, width: width, height: height,
                                classColors: Self.classColorMap)
    }
}

Рендеринг маски над відеопотоком

Наївний підхід рисування маски у циклі CPU дає 3–5 FPS. Правильний підхід використовує Metal / OpenGL ES:

// Metal шейдер для накладення маски на відео
// Входи: videoTexture (YCbCr), maskTexture (карта мітки), colorLUT (клас→колір)
fragment float4 segmentationOverlay(
    VertexOut in [[stage_in]],
    texture2d<float> videoTexture [[texture(0)]],
    texture2d<uint> maskTexture [[texture(1)]],
    texture1d<float> colorLUT [[texture(2)]],
    constant OverlayParams& params [[buffer(0)]]
) {
    float2 uv = in.texCoords;
    float4 videoColor = videoTexture.sample(sampler, uv);
    uint classLabel = maskTexture.sample(nearestSampler, uv).r;

    if (classLabel == 0) { return videoColor; }  // фон—без змін

    float4 maskColor = colorLUT.sample(sampler, float(classLabel) / float(params.numClasses));
    return mix(videoColor, maskColor, params.overlayAlpha);  // змішування
}

Цей конвеєр Metal рендерить маску на GPU без участі CPU—стабільні 30 FPS навіть на iPhone 11.

Заміна фону — окремий випадок

Для відеозвонків популярна бінарна сегментація (людина / фон). MediaPipe Selfie Segmentation — готове рішення, оптимізоване для цього:

// Android: MediaPipe Selfie Segmentation
val options = ImageSegmenterOptions.builder()
    .setBaseOptions(BaseOptions.builder()
        .setModelAssetPath("selfie_segmentation.tflite")
        .setDelegate(Delegate.GPU)
        .build())
    .setRunningMode(RunningMode.LIVE_STREAM)
    .setResultListener { result, _ ->
        val confidenceMask = result.confidenceMasks?.get(0)
        updateBackground(confidenceMask)
    }
    .build()

val segmenter = ImageSegmenter.createFromOptions(context, options)

Delegate.GPU критична: той самий MediaPipe на CPU дає 8–12 FPS; на GPU—25–30 FPS.

Кошторис за часом

Базова сегментація одного класу (наприклад, людина) з готовою моделлю та простим рендерингом займає 1 тиждень. Багатокласова сегментація з Metal/GPU рендерингом, користувацькою моделлю для конкретної задачі, оптимізацією продуктивності та підтримкою iOS + Android вимагає 2–4 тижнів.