基于Rokid Glasses的AI助盲应用实践:让科技点亮视障者的世界

基于Rokid Glasses的AI助盲应用实践:让科技点亮视障者的世界

一、项目背景与意义

在人工智能技术快速发展的今天,AI智能眼镜作为AI与现实世界交互的重要载体,正在改变我们的生活方式。对于视障人群而言,如何通过技术手段帮助他们更好地感知和理解周围环境,是一个具有重要社会意义的课题。华为手机推出的"小艺看世界"功能,通过AI图像识别帮助用户了解周围环境,这给了我们很大的启发。然而,小艺看世界是在手机上实现的,对于视障用户来说存在明显的不友好之处,需要拿出手机、打开应用、对准目标、按下拍照按钮,整个过程需要双手操作,对于视障用户来说非常困难。

Rokid Glasses作为AI智能眼镜,天然适合视障辅助应用,眼镜佩戴在头上,无需手持设备,可以在任何场景下使用,而且摄像头位置与眼睛位置一致,拍摄角度更自然,识别更准确。基于这个思路,使用Rokid GlassesRokid CXR-M SDK,开发了一款AI助盲应用"盲导",通过语音指令触发拍照、AI图像识别和TTS语音播报,帮助视障用户识别周围环境、寻找物品、认路导航等,让科技真正服务于特殊人群的需求。

二、技术架构设计

2.1 整体架构

本项目采用手机端+眼镜端协同工作的架构模式:

graph TB subgraph Glasses["Rokid Glasses (眼镜端)"] A1[AI按键] A2[录音功能] A3[拍照功能] A4[TTS播放] A5[显示反馈] end subgraph Phone["Android手机 (手机端)"] B1[UI界面] B2[蓝牙管理] B3[设备绑定管理] B4[AI事件监听] B5[录音管理] B6[ASR和意图识别] B7[场景解析服务] B8[业务逻辑控制] end subgraph Cloud["云端服务"] C1[ASR服务
语音识别] C2[意图识别服务] C3[场景解析服务
AI图像分析] end A1 -->|AI按键事件| B4 B4 -->|onAiKeyDown| B5 B5 -->|开始录音| A2 A2 -->|音频流数据| B5 B4 -->|onAiKeyUp| B5 B5 -->|停止录音| A2 B5 -->|录音数据| B6 B6 -->|发送音频| C1 C1 -->|识别文本| B6 B6 -->|文本| C2 C2 -->|意图类型| B6 B6 -->|意图判断| B8 B8 -->|拍照指令| A3 A3 -->|照片数据| B7 B7 -->|上传照片| C3 C3 -->|场景描述| B7 B7 -->|描述文本| B8 B8 -->|TTS文本| A4 B2 <-->|蓝牙双向通信| A1 B2 <-->|蓝牙双向通信| A2 B2 <-->|蓝牙双向通信| A3 B3 -->|设备绑定信息| B2 style Glasses fill:#e1f5ff style Phone fill:#fff4e1 style Cloud fill:#ffe1f5

2.2 核心模块

手机端提供了Android SDK,基于Android APP的开发方式开发手机端,作为Glasses端与云端AI的中介。

2.2.1 工程整体结构

项目核心类代码如下:

bash 复制代码
app/src/main/java/com/qingkouwei/rokidclient2/
├── MainActivity.kt                    # 主Activity,应用入口
├── MainViewModel.kt                   # 主业务逻辑ViewModel
├── DeviceBindingActivity.kt           # 设备绑定页面
├── DeviceBindingViewModel.kt          # 设备绑定逻辑
│
├── BluetoothHelper.kt                 # 蓝牙扫描和发现
├── RokidConnectionManager.kt          # Rokid SDK连接封装
├── DeviceBindingManager.kt            # 设备绑定信息持久化
│
├── AIEventListenerManager.kt           # AI事件监听管理
├── AudioRecordManager.kt              # 录音管理
├── ASRIntentService.kt                # ASR和意图识别
├── SceneAnalysisService.kt            # 场景解析服务
├── TTSManager.kt                      # TTS语音播报管理
│
├── PhotoCaptureManager.kt            # 拍照功能封装
├── AIImageAnalyzer.kt                 # AI图像分析(可选)
└── RokidSDKStub.kt                    # SDK接口桩(开发环境)
2.2.2 核心模块介绍
2.2.2.1 设备绑定模块

DeviceBindingManager.kt - 设备绑定信息管理

  • 使用SharedPreferences持久化保存设备绑定信息
  • 管理设备名称、地址、socketUuid、macAddress
  • 提供设备绑定状态检查接口

DeviceBindingActivity.kt - 设备绑定UI

  • 扫描周边Rokid设备
  • 显示设备列表供用户选择
  • 处理设备绑定和连接流程

BluetoothHelper.kt - 蓝牙扫描管理

  • 使用UUID 0000be80-0000-1000-8000-00805f9b34fb过滤Rokid设备
  • 支持已配对设备和扫描发现设备
  • 完整的权限管理和蓝牙状态监听
2.2.2.2 连接管理模块

RokidConnectionManager.kt - Rokid SDK连接封装

  • 封装initBluetooth()connectBluetooth()调用
  • 统一连接回调处理
  • 支持自动重连机制
2.2.2.3 AI交互模块

AIEventListenerManager.kt - AI事件监听

  • 设置和取消AI事件监听器
  • 处理onAiKeyDownonAiKeyUponAiExit事件

AudioRecordManager.kt - 录音管理

  • 管理openAudioRecord()closeAudioRecord()调用
  • 通过AudioStreamListener收集音频流数据
  • 返回完整的录音数据
2.2.2.4 业务处理模块

ASRIntentService.kt - ASR和意图识别

  • 处理语音识别(调用云端ASR能力)
  • 识别用户意图(拍照、导航等)
  • 返回识别文本和意图类型

SceneAnalysisService.kt - 场景解析

  • 分析照片场景(调用云端大模型解析图片内容)
  • 生成适合视障用户理解的描述文本

TTSManager.kt - TTS语音播报

  • 使用sendTTSContent()发送文本到眼镜端
  • 处理TTS播放状态回调
  • 管理播放完成和错误处理
2.2.2.5 业务逻辑控制模块

MainViewModel.kt - 主业务逻辑

  • 协调各模块工作
  • 处理设备自动连接
  • 实现完整的AI交互流程:录音 → ASR → 意图识别 → 拍照 → 场景解析 → TTS播报

2.3 完整工作流程

步骤1:应用启动和设备绑定
kotlin 复制代码
// MainActivity.kt
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        val bindingManager = DeviceBindingManager(this)
        
        // 检查设备是否已绑定
        if (!bindingManager.isDeviceBound()) {
            // 未绑定,跳转到绑定页面
            val intent = Intent(this, DeviceBindingActivity::class.java)
            startActivity(intent)
            finish()
            return
        }
        
        // 已绑定,自动连接
        viewModel.autoConnect(bindingManager, bluetoothHelper)
    }
}

绑定流程

  1. 首次安装时,检查设备绑定状态
  2. 未绑定则跳转到设备绑定页面
  3. 扫描周边Rokid设备(使用UUID过滤)
  4. 用户选择设备并绑定
  5. 连接成功后保存设备信息(名称、地址、socketUuid、macAddress)
  6. 跳转到主页面

自动连接流程

  1. 应用启动时检查是否已绑定设备
  2. 从SharedPreferences读取绑定信息
  3. 查找已配对设备或使用保存的连接信息
  4. 调用connectBluetooth()建立连接
  5. 连接成功后设置AI事件监听
步骤2:设置AI事件监听
kotlin 复制代码
// MainViewModel.kt
private fun setupAIEventListener() {
    aiEventListenerManager.setAIEventListener(
        object : AIEventListenerManager.AIEventListenerCallback {
            override fun onAiKeyDown() {
                // AI按键按下,开始录音
                startRecording()
            }

            override fun onAiKeyUp() {
                // AI按键释放,停止录音并处理
                stopRecordingAndProcess()
            }

            override fun onAiExit() {
                // AI场景退出
            }
        },
        set = true
    )
}
步骤3:录音处理
kotlin 复制代码
// MainViewModel.kt
private fun startRecording() {
    audioRecordManager.startRecording(
        object : AudioRecordManager.AudioRecordCallback {
            override fun onRecordingStarted() {
                updateStatus("正在录音...")
            }
        }
    )
}

private fun stopRecordingAndProcess() {
    viewModelScope.launch {
        val audioData = audioRecordManager.stopRecording()
        if (audioData != null && audioData.isNotEmpty()) {
            processRecordedAudio(audioData)
        }
    }
}

//AudioRecordManager.kt
fun startRecording(callback: AudioRecordCallback) {  
    this.callback = callback  
      
    // Set audio stream listener  
    CxrApi.getInstance().setAudioStreamListener(audioStreamListener)  
      
    // Open audio record  
    val status = CxrApi.getInstance().openAudioRecord(CODEC_TYPE_OPUS, STREAM_TYPE)  
    if (status == ValueUtil.CxrStatus.REQUEST_SUCCEED) {  
        Log.d(TAG, "Audio recording started")  
    } else {  
        Log.e(TAG, "Failed to start audio recording: $status")  
        callback.onError("Failed to start recording: $status")  
    }  
}  
  
/**  
 * Stop recording */suspend fun stopRecording(): ByteArray? = withContext(Dispatchers.IO) {  
    if (!isRecording) {  
        Log.w(TAG, "Not recording, cannot stop")  
        // Remove audio stream listener  
        CxrApi.getInstance().setAudioStreamListener(null)  
        return@withContext null  
    }  
  
    // Close audio record  
    val status = CxrApi.getInstance().closeAudioRecord(STREAM_TYPE)  
      
    // Remove audio stream listener  
    CxrApi.getInstance().setAudioStreamListener(null)  
      
    if (status == ValueUtil.CxrStatus.REQUEST_SUCCEED) {  
        isRecording = false  
        // Get recorded audio data  
        val audioData = audioDataBuffer.toByteArray()  
        recordedAudioData = audioData  
        audioDataBuffer.reset()  
          
        Log.d(TAG, "Audio recording stopped, data size: ${audioData.size}")  
        callback?.onRecordingStopped(audioData)  
        return@withContext audioData  
    } else {  
        Log.e(TAG, "Failed to stop audio recording: $status")  
        callback?.onError("Failed to stop recording: $status")  
        return@withContext null  
    }  
}

录音流程

  1. onAiKeyDown事件触发,调用openAudioRecord()
  2. 设置AudioStreamListener接收音频流数据
  3. 持续收集音频数据到Buffer
  4. onAiKeyUp事件触发,调用closeAudioRecord()
  5. 返回完整的录音数据
步骤4:ASR和意图识别
kotlin 复制代码
// MainViewModel.kt
private fun processRecordedAudio(audioData: ByteArray) {
    viewModelScope.launch {
        asrIntentService.processAudio(
            audioData,
            object : ASRIntentService.ASRCallback {
                override fun onSuccess(result: ASRIntentService.ASRResult) {
                    // 发送ASR结果到眼镜端显示
                    CxrApi.getInstance().sendAsrContent(result.text)
                    CxrApi.getInstance().notifyAsrEnd()
                    
                    // 根据意图执行相应操作
                    when (result.intent) {
                        ASRIntentService.IntentType.PHOTO -> {
                            handlePhotoIntent()
                        }
                        ASRIntentService.IntentType.UNKNOWN -> {
                            // 未识别意图
                            CxrApi.getInstance().notifyAsrError()
                        }
                    }
                }
            }
        )
    }
}

ASR和意图识别流程

  1. 将录音数据发送到ASR服务(当前为模拟实现)
  2. 获取识别文本
  3. 将文本发送到意图识别服务
  4. 获取意图类型(拍照、导航等)
  5. 将识别文本发送到眼镜端显示
  6. 根据意图执行相应操作
步骤5:拍照和场景解析
kotlin 复制代码
// MainViewModel.kt
private fun handlePhotoIntent() {
    viewModelScope.launch {
        // 打开相机
        CxrApi.getInstance().openGlassCamera(1920, 1080, 80)
        
        // 拍照
        CxrApi.getInstance().takeGlassPhoto(
            1920, 1080, 80,
            object : PhotoResultCallback {
                override fun onPhotoResult(status: ValueUtil.CxrStatus?, photo: ByteArray?) {
                    if (status == ValueUtil.CxrStatus.RESPONSE_SUCCEED && photo != null) {
                        // 分析场景
                        analyzeSceneAndSpeak(photo)
                    }
                }
            }
        )
    }
}

拍照流程

  1. 调用openGlassCamera()打开眼镜端相机
  2. 调用takeGlassPhoto()触发拍照
  3. 照片以WebP格式通过蓝牙传输
  4. PhotoResultCallback.onPhotoResult()回调接收照片数据
步骤6:场景解析和TTS播报
kotlin 复制代码
// MainViewModel.kt
private fun analyzeSceneAndSpeak(photoData: ByteArray) {
    viewModelScope.launch {
        sceneAnalysisService.analyzeScene(
            photoData,
            object : SceneAnalysisService.AnalysisCallback {
                override fun onSuccess(description: String) {
                    // 发送TTS内容到眼镜端播放
                    CxrApi.getInstance().sendTtsContent(
                        description,
                        object : TTSStatusCallback {
                            override fun onTTSStart() {
                                // TTS开始播放
                            }
                            
                            override fun onTTSEnd() {
                                // TTS播放完成
                            }
                            
                            override fun onTTSError(errorCode: Int) {
                                // TTS播放失败
                            }
                        }
                    )
                }
            }
        )
    }
}

场景解析和TTS流程

  1. 将照片数据发送到场景解析服务(当前为模拟实现)
  2. AI模型分析场景,生成描述文本
  3. 调用sendTtsContent()发送文本到眼镜端
  4. 眼镜端TTS引擎合成语音并播放
  5. 用户听到场景描述

2.4 完整流程时序图

sequenceDiagram participant User as 用户 participant App as 应用 participant Binding as 设备绑定 participant Connect as 连接管理 participant Glasses as Rokid Glasses participant AIEvent as AI事件监听 participant Record as 录音管理 participant ASR as ASR服务 participant AI as 场景解析 participant TTS as TTS播报 Note over App: 应用启动 App->>Binding: 检查设备绑定状态 alt 未绑定 App->>App: 跳转绑定页面 App->>Glasses: 扫描设备 User->>App: 选择设备 App->>Connect: 连接设备 Connect->>Glasses: initBluetooth + connectBluetooth Connect->>Binding: 保存绑定信息 else 已绑定 App->>Connect: 自动连接 Connect->>Glasses: 使用保存信息连接 end Connect->>AIEvent: 设置AI事件监听 AIEvent->>Glasses: setAiEventListener(true) Note over User,TTS: 用户交互流程 User->>Glasses: 按下AI按键 Glasses->>AIEvent: onAiKeyDown AIEvent->>Record: 开始录音 Record->>Glasses: openAudioRecord Glasses->>Record: 音频流数据 User->>Glasses: 释放AI按键 Glasses->>AIEvent: onAiKeyUp AIEvent->>Record: 停止录音 Record->>ASR: 发送录音数据 ASR->>ASR: 语音识别 ASR->>ASR: 意图识别 ASR-->>Record: 返回意图(拍照) Record->>Glasses: openGlassCamera Record->>Glasses: takeGlassPhoto Glasses->>AI: 照片数据 AI->>AI: 场景分析 AI-->>Record: 场景描述 Record->>Glasses: sendTtsContent Glasses->>User: 播放场景描述

三、实际应用场景演示

3.1 场景一:识别道路环境

用户需求:盲人需要了解前方道路情况,判断是否可以安全行走

工作流程

  1. 用户说:"帮我看看前面的路"
  2. 应用触发拍照,获取前方道路图像
  3. AI分析:"前方是一条宽约2米的人行道,路面平整,右侧有盲道,左侧有绿化带,前方约10米处有一个垃圾桶,建议靠右行走"
  4. 通过TTS播放给用户

技术要点

  • 使用Rokid SDK的openGlassCamera()takeGlassPhoto()获取道路图像
  • AI提示词重点强调道路宽度、障碍物、安全提示等信息
  • 描述语言简洁明确,便于盲人理解

3.2 场景二:寻找丢失物品

用户需求:在房间内寻找丢失的钥匙

工作流程

  1. 用户说:"帮我找找钥匙"
  2. 应用拍照识别房间环境
  3. AI分析:"在视野中,我看到一个茶几,茶几上有一串银色的钥匙,位置在茶几中央偏左,距离你约3米"
  4. 用户根据描述找到钥匙

技术要点

  • 多轮对话:先整体描述,再聚焦特定物品
  • 位置描述使用相对位置(前后左右)和距离
  • 物品特征描述(颜色、大小、形状)帮助识别

3.3 场景三:阅读文字信息

用户需求:识别门牌号或路牌

工作流程

  1. 用户说:"帮我看看这个门牌号"
  2. 应用拍照识别
  3. AI分析:"门牌上写着:北京市朝阳区某某路123号"
  4. 清晰朗读给用户

技术要点

  • 使用GPT-4o Vision的强大文字识别能力
  • 按顺序朗读,避免信息混乱
  • 支持中英文混合识别

四、开发心得与总结

4.1 Rokid SDK使用体验

通过本项目的开发实践,我们深刻体验了Rokid CXR-M SDK的强大能力:

1. API设计清晰直观

kotlin 复制代码
// 连接流程清晰,回调机制完善
CxrApi.getInstance().initBluetooth(context, device, callback)
CxrApi.getInstance().connectBluetooth(context, uuid, address, callback)

2. 功能覆盖全面

  • 蓝牙连接:完整的BLE+经典蓝牙双通道支持
  • 拍照功能:AI场景拍照,照片实时传输
  • 设备控制:音量、亮度、电量等全方位控制
  • 状态监听:连接状态、设备状态实时回调
  • 覆盖了主要使用场景

3. 开发体验优秀

  • SDK集成简单,只需添加依赖
  • API调用直观,易于理解和使用
  • 错误处理完善,便于调试

4.2 技术挑战与解决方案

挑战1:Kotlin版本兼容性

  • 问题:Rokid SDK使用Kotlin 2.1.0编译,需要Java 17环境
  • 解决:升级开发环境到Java 17,或使用兼容的Kotlin版本

挑战2:蓝牙连接稳定性

  • 问题:蓝牙连接可能中断,需要保证稳定性
  • 解决:实现完善的错误处理和自动重连机制
  • 代码示例
kotlin 复制代码
override fun onDisconnected() {
    // 连接断开,自动尝试重连
    if (socketUuid != null && macAddress != null) {
        connect(context, socketUuid!!, macAddress!!)
    }
}

挑战3:AI响应时间

  • 问题:AI API调用可能有延迟
  • 解决:使用协程异步处理,显示处理进度,支持本地模型作为备选方案,在处理时进行友好语音提示,让用户感知到进度。

4.3 Rokid SDK能力总结

通过本项目的实践,我们充分验证了Rokid CXR-M SDK在以下方面的能力:

能力类别 SDK功能 应用场景
连接能力 蓝牙双通道连接 手机与眼镜的稳定通信
数据交互 AI场景拍照 获取眼镜端图像数据
设备控制 音量/亮度/电量 优化用户体验
状态管理 连接状态监听 实时反馈设备状态
扩展性 丰富的回调接口 支持复杂业务逻辑

4.4 未来展望

随着AI技术的不断发展和Rokid SDK能力的持续增强,AI助盲应用将能够:

  1. 更精准的环境理解:结合多帧图像进行3D场景重建,读取设备经纬度,识别更细微的环境变化,提供更准确的位置信息
  2. 更自然的交互体验:支持连续对话,理解上下文,个性化学习用户习惯,更智能的提示和建议
  3. 更多实用功能场景:实时导航引导物体跟踪和定位,社交场景识别(识别熟人、表情等)
  4. 更好的性能表现:支持离线AI模型,提升响应速度,降低功耗

五、总结

盲导项目展示了如何利用Rokid Glasses和Rokid CXR-M SDK,结合AI技术开发具有实际社会价值的应用。通过完整的蓝牙连接、拍照传输、AI识别和语音播报流程,为视障人群提供了一个实用的辅助工具。

Rokid SDK的强大能力为开发者提供了坚实的基础,使得我们可以专注于业务逻辑和用户体验的优化。无论是开发纯眼镜端应用,还是手机端配合眼镜的协同应用,Rokid SDK都能提供完整的支持。

相信随着技术的不断进步和Rokid SDK能力的持续增强,AI+AR的应用将在更多领域发挥重要作用,真正让科技服务于每一个人,让智能眼镜成为连接数字世界与现实世界的桥梁。

开发环境介绍 项目名称 :盲导 - AI助盲应用
技术栈 :Kotlin + Jetpack Compose + Rokid CXR-M SDK + OpenAI Vision API
开发平台 :Android
Rokid SDK版本 :1.0.1-20250812.080117-2
致谢:感谢Rokid提供的优秀SDK和开发支持,让AI+AR应用的开发变得更加简单高效。

相关推荐
j***89461 小时前
MySQL数据的增删改查(一)
android·javascript·mysql
小画家~2 小时前
第三十四:golang 原生 pgsql 对应操作
android·开发语言·golang
r***18642 小时前
FlinkCDC实战:将 MySQL 数据同步至 ES
android·mysql·elasticsearch
p***62992 小时前
mysql-connector-java 和 mysql-connector-j的区别
android·java·mysql
海天鹰2 小时前
ACTION_PICK与ACTION_GET_CONTENT的区别
android
i***68322 小时前
图文详述:MySQL的下载、安装、配置、使用
android·mysql·adb
6***v4172 小时前
MySQL 时区参数 time_zone 详解
android·mysql·adb
王能2 小时前
Android三阶贝塞尔曲线应用——根据指定点画出完美的贝塞尔
android·贝塞尔曲线·图表·顶点
c***42102 小时前
MySQL-触发器(TRIGGER)
android·数据库·mysql