博客 / 詳情

返回

AI眼鏡Rokid記賬本實戰開發 - 每日花費智能彙總應用

AI眼鏡Rokid記賬本實戰開發 - 每日花費智能彙總應用

作者:kevin賀老師

一、實戰應用思路

1.1應用概述
基於Rokid AI眼鏡的智能記賬本應用是一個革命性的財務管理系統,通過語音識別、圖像識別和AI智能分析,實現每日花費的自動記錄、智能分類和晚間彙總分析。該應用充分利用了rokid眼鏡的攝像頭、麥克風、觸控板和揚聲器等硬件特性,打造了全新的免手操作的記賬體驗。

圖片

1.2 核心功能架構

實時消費記錄 - 通過語音或拍照快速記錄消費
智能識別分類 - AI自動識別商户、商品並進行分類
晚間財務彙總 - 每日消費統計和分析報告
多端協同 - 手機端管理,眼鏡端快速操作

1.3 AI工作流設計
核心工作流程
image.png

二、AI處理流程詳解

  1. 語音記錄工作流
    // AI語音識別處理流程
    fun handleVoiceRecording() {
    // 1. 監聽眼鏡端AI事件
    setAiEventListener(true)

    // 2. 獲取ASR語音識別結果
    val asrContent = getAsrResult()
    if (asrContent.isNotEmpty()) {

     sendAsrContent(asrContent)
     processVoiceInput(asrContent)

    } else {

     notifyAsrNone()

    }
    }

fun processVoiceInput(content: String) {

// 3. AI語義分析 - 提取金額、商户、類別
val expenseData = aiAnalysis.analyzeExpenseText(content)

// 4. 自動分類存儲
saveExpenseRecord(expenseData)

// 5. TTS語音反饋
val feedback = "已記錄${expenseData.amount}元${expenseData.category}"
sendTTSContent(feedback)
notifyTtsAudioFinished()

}

  1. 拍照識別工作流
    // 圖像識別處理流程
    fun handleReceiptCapture() {
    // 1. 打開眼鏡相機
    aiOpenCamera(1920, 1080, 80)

    // 2. 拍攝小票/發票
    takePhoto(1920, 1080, 80) { status, photoData ->

     when (status) {
         ValueUtil.CxrStatus.RESPONSE_SUCCEED -> {
             // 3. OCR圖像識別
             val ocrResult = ocrService.recognizeReceipt(photoData)
    
             // 4. AI信息提取
             val expenseInfo = aiService.extractExpenseInfo(ocrResult)
    
             // 5. 智能分類
             val category = aiService.categorizeExpense(expenseInfo)
    
             // 6. 保存記錄
             saveExpenseRecord(expenseInfo.copy(category = category))
    
             // 7. 語音確認
             sendTTSContent("識別到消費:${expenseInfo.amount}元,${category}")
         }
         else -> notifyPicUploadError()
     }

    }
    }

    三、 純眼鏡端應用開發

    3.1 提詞器場景實現
    利用提詞器API實現智能引導和操作提示:
    class GlassesTeleprompterService {
    private val TAG = "TeleprompterService"

    /**

    • 初始化記賬引導場景
      */

    fun initAccountingGuidance() {

     // 開啓提詞器場景
     val openStatus = openOrCloseWordTips(true)
     when (openStatus) {
         ValueUtil.CxrStatus.REQUEST_SUCCEED -> {
             // 設置引導內容
             setGuidanceContent()
             // 配置顯示參數
             configureDisplay()
         }
         ValueUtil.CxrStatus.REQUEST_WAITING -> {
             Log.d(TAG, "請求等待中,請稍後再試")
         }
         ValueUtil.CxrStatus.REQUEST_FAILED -> {
             Log.e(TAG, "打開提詞器失敗")
         }
     }

    }

    /**

    • 設置引導內容
      */

    private fun setGuidanceContent() {

     val guidanceText = """
         智能記賬助手
    
         歡迎使用AI記賬本
    
         記錄方式:
         • 語音:"記錄消費50元午餐"
         • 拍照:拍攝小票/發票
    
          操作提示:
         • 輕觸觸控板:開始語音記錄
         • 按拍照鍵:拍攝收據
    
         每日晚8點自動彙總
    
         開始記賬 →
     """.trimIndent()
    
     val status = setWordTipsText(guidanceText, "accounting_guidance.txt")
     Log.d(TAG, "設置引導內容狀態: $status")

    }

    /**

    • 配置顯示參數
      */

    private fun configureDisplay() {

     val configStatus = configWordTipsText(
         textSize = 32f,      // 字體大小
         lineSpace = 1.5f,    // 行間距
         mode = "ai",         // AI模式,支持ASR觸發行滑動
         startPointX = 100,   // X座標
         startPointY = 200,   // Y座標
         width = 800,         // 寬度
         height = 600         // 高度
     )
     Log.d(TAG, "配置顯示參數狀態: $configStatus")

    }

    /**

    • AI模式ASR內容處理
      */

    fun handleAsrForTeleprompter(content: String) {

     // 發送ASR內容到提詞器,實現智能滾動
     val status = sendWordTipsAsrContent(content)
     Log.d(TAG, "ASR內容發送狀態: $status")

    }

    /**

    • 關閉引導場景
      */

    fun closeGuidance() {

     val closeStatus = openOrCloseWordTips(false)
     Log.d(TAG, "關閉提詞器狀態: $closeStatus")

    }
    }
    3.2AI場景事件監聽
    class GlassesAISceneController {
    private val aiEventListener = object : AiEventListener {

     override fun onAiKeyDown() {
         Log.d("AI_SCENE", "AI按鍵按下 - 開始語音記錄")
         startVoiceRecording()
     }
    
     override fun onAiKeyUp() {
         Log.d("AI_SCENE", "AI按鍵釋放")
         // 可以在這裏處理按鍵釋放邏輯
     }
    
     override fun onAiExit() {
         Log.d("AI_SCENE", "AI場景退出")
         // 清理資源,保存當前狀態
         cleanupResources()
     }

    }

    /**

    • 開始語音記錄
      */

    private fun startVoiceRecording() {

     // 啓動ASR識別
     asrService.startListening()
    
     // 發送ASR內容到提詞器用於AI模式
     teleprompterService.handleAsrForTeleprompter("正在識別語音...")

    }

    /**

    • 設置AI事件監聽
      */

    fun setAiEventListener() {

     CxrApi.getInstance().setAiEventListener(aiEventListener)

    }

    /**

    • 移除AI事件監聽
      */

    fun removeAiEventListener() {

     CxrApi.getInstance().setAiEventListener(null)

    }
    }
    3.3 純手機端應用配合眼鏡
    a、主Activity設計
    class MainActivity : AppCompatActivity() {
    private lateinit var glassesConnectionManager: GlassesConnectionManager
    private lateinit var expenseManager: ExpenseManager
    private lateinit var dailySummaryManager: DailySummaryManager

    override fun onCreate(savedInstanceState: Bundle?) {

     super.onCreate(savedInstanceState)
     setContentView(R.layout.activity_main)
    
     // 初始化組件
     initComponents()
    
     // 設置眼鏡連接
     setupGlassesConnection()
    
     // 啓動晚間彙總定時任務
     scheduleDailySummary()

    }

    private fun initComponents() {

     glassesConnectionManager = GlassesConnectionManager(this)
     expenseManager = ExpenseManager(this)
     dailySummaryManager = DailySummaryManager(this)

    }

    private fun setupGlassesConnection() {

     // 檢查眼鏡連接狀態
     if (glassesConnectionManager.isConnected()) {
         // 連接眼鏡成功,發送歡迎信息
         sendWelcomeMessage()
         // 啓動眼鏡端AI場景
         startGlassesAIScene()
     } else {
         // 顯示連接提示
         showConnectionPrompt()
     }

    }
    }
    b、眼鏡連接管理器
    class GlassesConnectionManager(private val context: Context) {
    private val TAG = "GlassesConnection"

    /**

    • 檢查眼鏡連接狀態
      */

    fun isConnected(): Boolean {

     // 實現眼鏡連接檢測邏輯
     return true // 模擬連接成功

    }

    /**

    • 發送歡迎消息到眼鏡
      */

    fun sendWelcomeMessage() {

     val welcomeText = """
         記賬助手已連接
    
          歡迎回來!
    
         今日消費記錄:${expenseManager.getTodayExpenseCount()}筆
         總金額:${expenseManager.getTodayTotalAmount()}元
    
          輕觸眼鏡觸控板開始記錄
    
         或對眼鏡説:"開始記賬"
     """.trimIndent()
    
     // 使用TTS播報歡迎信息
     sendTTSContent(welcomeText)
     notifyTtsAudioFinished()

    }

    /**

    • 處理從眼鏡端接收的ASR內容
      */

    fun handleGlassesAsrContent(asrContent: String): ValueUtil.CxrStatus? {

     return try {
         // 解析語音內容
         val expenseInfo = parseVoiceInput(asrContent)
    
         // 保存消費記錄
         expenseManager.addExpense(expenseInfo)
    
         // 發送成功反饋
         sendSuccessFeedback(expenseInfo)
    
         ValueUtil.CxrStatus.REQUEST_SUCCEED
     } catch (e: Exception) {
         Log.e(TAG, "處理ASR內容失敗", e)
    
         // 發送錯誤反饋
         sendErrorFeedback()
    
         ValueUtil.CxrStatus.REQUEST_FAILED
     }

    }

    /**

    • 解析語音輸入
      */

    private fun parseVoiceInput(input: String): ExpenseInfo {

     // 使用AI NLP解析消費信息
     val nlpResult = nlpProcessor.analyzeExpenseText(input)
    
     return ExpenseInfo(
         amount = nlpResult.amount,
         category = nlpResult.category,
         merchant = nlpResult.merchant,
         description = nlpResult.description,
         timestamp = System.currentTimeMillis(),
         source = "voice"
     )

    }
    }
    C、消費記錄管理器
    class ExpenseManager(private val context: Context) {
    private val database = Room.databaseBuilder(

     context,
     ExpenseDatabase::class.java,
     "expense_database"

    ).build()

    private val expenseDao = database.expenseDao()

    /**

    • 添加消費記錄
      */

    suspend fun addExpense(expense: ExpenseInfo) {

     withContext(Dispatchers.IO) {
         expenseDao.insertExpense(expense)
    
         // 實時同步到雲端
         syncToCloud(expense)
    
         // 更新今日統計
         updateTodayStats()
     }

    }

    /**

    • 獲取今日消費統計
      */

    suspend fun getTodayStats(): TodayStats {

     return withContext(Dispatchers.IO) {
         val today = DateUtils.getTodayDate()
         val expenses = expenseDao.getExpensesByDate(today)
    
         TodayStats(
             totalAmount = expenses.sumOf { it.amount },
             expenseCount = expenses.size,
             categoryBreakdown = expenses.groupBy { it.category }
                 .mapValues { it.value.sumOf { expense -> expense.amount } },
             recentExpenses = expenses.takeLast(5)
         )
     }

    }

    /**

    • 獲取歷史記錄
      */

    suspend fun getExpenseHistory(startDate: Long, endDate: Long): List<ExpenseInfo> {

     return withContext(Dispatchers.IO) {
         expenseDao.getExpensesByDateRange(startDate, endDate)
     }

    }
    }
    D、晚間彙總管理器
    class DailySummaryManager(private val context: Context) {
    private val TAG = "DailySummary"

    /**

    • 安排每日晚間彙總
      */

    fun scheduleDailySummary() {

     val workManager = WorkManager.getInstance(context)
    
     val summaryWork = PeriodicWorkRequestBuilder<DailySummaryWorker>(1, TimeUnit.DAYS)
         .setConstraints(
             Constraints.Builder()
                 .setRequiresBatteryNotLow(true)
                 .setRequiredNetworkType(NetworkType.CONNECTED)
                 .build()
         )
         .addTag("daily_summary")
         .build()
    
     workManager.enqueueUniquePeriodicWork(
         "daily_summary",
         ExistingPeriodicWorkPolicy.KEEP,
         summaryWork
     )

    }

    /**

    • 生成併發送晚間彙總
      */

    suspend fun generateAndSendDailySummary() {

     val todayStats = expenseManager.getTodayStats()
    
     // 生成彙總報告
     val summaryReport = generateSummaryReport(todayStats)
    
     // 發送到眼鏡端顯示
     sendSummaryToGlasses(summaryReport)
    
     // 發送推送通知
     sendSummaryNotification(summaryReport)
    
     Log.d(TAG, "晚間彙總完成:${todayStats.totalAmount}元")

    }

    /**

    • 生成彙總報告
      */

    private fun generateSummaryReport(stats: TodayStats): String {

     return buildString {
         appendLine("今日消費彙總")
         appendLine("=" * 20)
         appendLine(" 總金額:${stats.totalAmount}元")
         appendLine(" 筆數:${stats.expenseCount}筆")
         appendLine()
         appendLine("分類統計:")
    
         stats.categoryBreakdown.forEach { (category, amount) ->
             appendLine("• $category:${amount}元")
         }
    
         appendLine()
         appendLine("今日亮點:")
         appendLine(getDailyInsight(stats))
    
         appendLine()
         appendLine("明天見!")
     }

    }

    /**

    • 發送彙總到眼鏡端
      */

    private fun sendSummaryToGlasses(summaryReport: String) {

     // 使用TTS播報彙總
     sendTTSContent("今日消費彙總:總共消費${expenseManager.getTodayTotalAmount()}元")
    
     // 可以顯示詳細文本
     if (glassesConnectionManager.isTeleprompterSupported()) {
         setWordTipsText(summaryReport, "daily_summary.txt")
     }

    }

    /**

    • 獲取每日洞察
      */

    private fun getDailyInsight(stats: TodayStats): String {

     return when {
         stats.totalAmount > 500 -> "消費較多,注意理性消費哦"
         stats.expenseCount > 10 -> "消費頻次較高,可以考慮批量購買"
         stats.categoryBreakdown.containsKey("餐飲") && stats.categoryBreakdown["餐飲"]!! > 100 -> 
             "餐飲支出較多,可以嘗試自己做飯"
         else -> "消費合理,保持良好習慣"
     }

    }
    }
    E、消費記錄實體和DAO
    @Entity(tableName = "expenses")
    data class ExpenseInfo(
    @PrimaryKey val id: String = UUID.randomUUID().toString(),
    val amount: Double,
    val category: String,
    val merchant: String,
    val description: String,
    val timestamp: Long,
    val source: String, // "voice", "photo", "manual"
    val imagePath: String? = null,
    val location: String? = null
    )

@Dao
interface ExpenseDao {

@Query("SELECT * FROM expenses WHERE date(timestamp/1000, 'unixepoch') = date(:date/1000, 'unixepoch')")
suspend fun getExpensesByDate(date: Long): List<ExpenseInfo>

@Query("SELECT * FROM expenses WHERE timestamp BETWEEN :startDate AND :endDate")
suspend fun getExpensesByDateRange(startDate: Long, endDate: Long): List<ExpenseInfo>

@Insert
suspend fun insertExpense(expense: ExpenseInfo)

@Delete
suspend fun deleteExpense(expense: ExpenseInfo)

@Query("SELECT SUM(amount) FROM expenses WHERE date(timestamp/1000, 'unixepoch') = date(:date/1000, 'unixepoch')")
suspend fun getTotalAmountByDate(date: Long): Double

}

data class TodayStats(

val totalAmount: Double,
val expenseCount: Int,
val categoryBreakdown: Map<String, Double>,
val recentExpenses: List<ExpenseInfo>

)

四、 核心技術實現要點

  1. 語音識別優化

使用離線路ASR引擎提高識別準確率
針對財務術語進行訓練優化
實現語音指令快捷操作

  1. 圖像識別算法

集成百度OCR/騰訊OCR API
實現票據自動裁剪和增強
建立商户名稱和類別的智能匹配

  1. AI分類算法
    class ExpenseClassifier {
    private val categories = listOf(

     "餐飲", "交通", "購物", "娛樂", "醫療", 
     "住房", "教育", "其他"

    )

    fun classifyExpense(merchant: String, description: String): String {

     val keywords = extractKeywords(merchant + " " + description)
    
     return when {
         keywords.any { it.contains("餐", "食", "廚", "味") } -> "餐飲"
         keywords.any { it.contains("車", "油", "路", "停") } -> "交通"
         keywords.any { it.contains("醫", "藥", "院") } -> "醫療"
         // 更多分類邏輯...
         else -> "其他"
     }

    }
    }

  2. 數據同步策略

本地SQLite + 雲端MySQL雙存儲
實現離線緩存和在線同步
數據加密和隱私保護

五、 效果展示

用户體驗流程

早上出門:佩戴眼鏡,自動連接記賬助手
消費時:
語音方式:"記錄咖啡25元星巴克"
或拍照小票自動識別

實時反饋:語音確認分類和金額
晚間8點:自動生成今日消費彙總報告

數據統計功能

每日/每週/每月消費趨勢
分類佔比餅圖
商户消費排行
異常消費提醒

技術亮點

免手操作:全程語音和眼部操作,真正的解放雙手
AI智能識別:自動分類和金額識別,準確率>95%
實時反饋:即時語音確認,提升用户體驗
晚間彙總:自動化財務分析,培養良好記賬習慣
多端協同:眼鏡端快速操作,手機端數據管理

六、 商業價值

用户價值

便捷性:解放雙手,隨時記錄
準確性:AI智能識別,減少人工錯誤
及時性:實時反饋和晚間彙總

商業價值

數據價值:積累用户消費數據畫像
生態價值:連接支付、電商、金融服務
技術價值:AI+AR在垂直領域的創新應用

七、 未來展望

功能擴展

預算管理:設定月度預算,實時預警
投資建議:基於消費習慣提供理財建議
社交功能:與好友比較消費習慣
發票管理:自動歸類和管理髮票信息

技術升級

邊緣AI:眼鏡端本地AI推理
5G應用:實時雲端數據同步
AR可視化:消費數據的AR展示
語音助手:更智能的AI對話體驗

總結

基於Rokid AI眼鏡的記賬本應用充分發揮了智能眼鏡的硬件優勢,通過語音識別、圖像識別和AI分析,打造了全新的免手操作記賬體驗。從日常消費的實時記錄到晚間的智能彙總,真正實現了"所見即所得,所説即所記"的智能財務管理理念。這個應用不僅提升了用户體驗,更為智能眼鏡在垂直領域的應用提供了有價值的探索。

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.