FLUTTER 快速開發圖像識別應用

更新 發佈閱讀 14 分鐘

前置作業

請確認你已經完成以下安裝:

  1. 安裝 Flutter SDK
  2. 安裝 Android Studio 或 Visual Studio Code(搭配 Flutter plugin)
  3. 設定好 flutter doctor(在終端機執行以下指令):
flutter doctor

確保所有項目都打勾 ✅

建立 Flutter 專案

使用終端機執行以下指令:

​flutter create my_app

你可以將 my_app 換成你想要的專案名稱。

建立後的資料夾結構

建立完成後會看到如下資料夾:

my_app/
├── android/ ← Android 原生專案
├── ios/ ← iOS 原生專案
├── lib/ ← 主要開發目錄,寫 Dart 程式的地方
│ └── main.dart ← App 的進入點
├── test/ ← 測試程式
├── pubspec.yaml ← 套件依賴與資源設定

執行 App

  1. 接上模擬器或手機
  2. 移動到專案目錄
cd my_app
  1. 執行專案
flutter run

影像辨識

由於我們要做的是一個影像辨識APP流程圖如下

系統流程圖

Flutter App
↓ 圖片上傳
Flask API ←→ PyTorch 模型
↓ 傳回結果
顯示結果 + 儲存紀錄 (MySQL)

Flutter撰寫前端邏輯

flutter_cnn\my_app\lib\main.dart

import 'package:flutter/material.dart';

import 'package:image_picker/image_picker.dart';

import 'dart:io';

import 'package:http/http.dart' as http;

import 'dart:convert';



void main() {

  runApp(const MyApp());

}



class MyApp extends StatelessWidget {

  const MyApp({super.key});



  @override

  Widget build(BuildContext context) {

    return MaterialApp(

      title: '影像辨識 App',

      theme: ThemeData(

        primarySwatch: Colors.blue,

      ),

      home: const ImageRecognitionPage(),

    );

  }

}



class ImageRecognitionPage extends StatefulWidget {

  const ImageRecognitionPage({super.key});



  @override

  State<ImageRecognitionPage> createState() => _ImageRecognitionPageState();

}



class _ImageRecognitionPageState extends State<ImageRecognitionPage> {

  File? _image;

  String _result = '';

  bool _loading = false;



  Future<void> _pickImage(ImageSource source) async {

    final picker = ImagePicker();

    final pickedFile = await picker.pickImage(source: source);



    if (pickedFile != null) {

      setState(() {

        _image = File(pickedFile.path);

        _result = '';

      });

      await _uploadImage(_image!);

    }

  }



  Future<void> _uploadImage(File image) async {

    setState(() => _loading = true);



    var request = http.MultipartRequest(

      'POST',

      Uri.parse('http://10.0.2.2:5000/predict'),

    );

    request.files.add(await http.MultipartFile.fromPath('image', image.path));



    var response = await request.send();

    if (response.statusCode == 200) {

      final respStr = await response.stream.bytesToString();

      final data = jsonDecode(respStr);

      setState(() {

        _result = data['result'] ?? '未知結果';

      });

    } else {

      setState(() {

        _result = '辨識失敗,請再試一次';

      });

    }



    setState(() => _loading = false);

  }



  @override

  Widget build(BuildContext context) {

    return Scaffold(

      appBar: AppBar(title: const Text('影像辨識 App')),

      body: Center(

        child: Padding(

          padding: const EdgeInsets.all(16.0),

          child: Column(

            mainAxisAlignment: MainAxisAlignment.center,

            children: [

              _image == null

                  ? const Text('請選擇一張圖片')

                  : Image.file(_image!, height: 200),

              const SizedBox(height: 16),

              _loading

                  ? const CircularProgressIndicator()

                  : Text(_result, style: const TextStyle(fontSize: 18)),

              const SizedBox(height: 16),

              ElevatedButton.icon(

                onPressed: () => _pickImage(ImageSource.camera),

                icon: const Icon(Icons.camera_alt),

                label: const Text('拍照'),

              ),

              const SizedBox(height: 8),

              ElevatedButton.icon(

                onPressed: () => _pickImage(ImageSource.gallery),

                icon: const Icon(Icons.photo),

                label: const Text('從相簿選擇'),

              ),

            ],

          ),

        ),

      ),

    );

  }

}


}

注意

  1. 模擬器的 localhost 不一定指向你的電腦
    • Android 模擬器中,127.0.0.1 指的是模擬器本身,不是你的電腦主機。
    • 你應該用 http://10.0.2.2:5000/predict (Android Emulator 對宿主機的特殊映射IP)。
    • iOS 模擬器的 localhost 通常是指你的電腦本機,可以用 127.0.0.1。
  2. 真實裝置測試
    • 如果你用真機測試,127.0.0.1 指手機自己,不會連到電腦。
    • 這時候你要用電腦的局域網 IP(像是 192.168.x.x),並確保 Flask 伺服器允許外部連線(app.run(host='0.0.0.0'))。

撰寫後端邏輯

flutter_cnn\flask_backend\app.py

from flask import Flask, request, jsonify

from flask_cors import CORS

import torch

from torchvision import models, transforms

from PIL import Image

import io



app = Flask(__name__)

CORS(app)



# 使用 MobileNetV2 作為輕量模型

model = models.mobilenet_v2(pretrained=True)

model.eval()



# 類別名稱(可根據實際情境替換)

with open("imagenet_classes.txt") as f:

    classes = [line.strip() for line in f.readlines()]



# 圖像預處理流程

transform = transforms.Compose([

    transforms.Resize(256),

    transforms.CenterCrop(224),

    transforms.ToTensor(),

    transforms.Normalize(

        mean=[0.485, 0.456, 0.406],

        std=[0.229, 0.224, 0.225]

    )

])



@app.route('/predict', methods=['POST'])

def predict():

    if 'image' not in request.files:

        return jsonify({'error': 'No image provided'}), 400



    image_file = request.files['image']

    image_bytes = image_file.read()

    image = Image.open(io.BytesIO(image_bytes)).convert('RGB')

    input_tensor = transform(image).unsqueeze(0)



    with torch.no_grad():

        outputs = model(input_tensor)

        _, predicted = outputs.max(1)

        predicted_class = classes[predicted.item()]



    return jsonify({'result': predicted_class})



if __name__ == '__main__':

    app.run(host='127.0.0.1', port=5000)

Flutter run

執行

flutter run
flutter run -d <機器名稱> #也可以這樣子
raw-image

Flask RUN

執行

python app.py #你的flask app檔案
raw-image

最終結果

raw-image


留言
avatar-img
于正龍(Ricky)的沙龍
55會員
86內容數
人工智能工作經驗跟研究
你可能也想看
Thumbnail
賽勒布倫尼科夫以流亡處境回望蘇聯電影導演帕拉贊諾夫的舞台作品,以十段寓言式殘篇,重新拼貼記憶、暴力與美學,並將審查、政治犯、戰爭陰影與「形式即政治」的劇場傳統推到台前。本文聚焦於《傳奇:帕拉贊諾夫的十段殘篇》的舞台美術、音樂與多重扮演策略,嘗試解析極權底下不可言說之事,將如何成為可被觀看的公共發聲。
Thumbnail
賽勒布倫尼科夫以流亡處境回望蘇聯電影導演帕拉贊諾夫的舞台作品,以十段寓言式殘篇,重新拼貼記憶、暴力與美學,並將審查、政治犯、戰爭陰影與「形式即政治」的劇場傳統推到台前。本文聚焦於《傳奇:帕拉贊諾夫的十段殘篇》的舞台美術、音樂與多重扮演策略,嘗試解析極權底下不可言說之事,將如何成為可被觀看的公共發聲。
Thumbnail
柏林劇團在 2026 北藝嚴選,再次帶來由布萊希特改編的經典劇目《三便士歌劇》(The Threepenny Opera),導演巴里・柯斯基以舞台結構與舞台調度,重新向「疏離」進行提問。本文將從觀眾慾望作為戲劇內核,藉由沉浸與疏離的辯證,解析此作如何再次照見觀眾自身的位置。
Thumbnail
柏林劇團在 2026 北藝嚴選,再次帶來由布萊希特改編的經典劇目《三便士歌劇》(The Threepenny Opera),導演巴里・柯斯基以舞台結構與舞台調度,重新向「疏離」進行提問。本文將從觀眾慾望作為戲劇內核,藉由沉浸與疏離的辯證,解析此作如何再次照見觀眾自身的位置。
Thumbnail
本文深入解析臺灣劇團「晃晃跨幅町」對易卜生經典劇作《海妲.蓋柏樂》的詮釋,從劇本歷史、聲響與舞臺設計,到演員的主體創作方法,探討此版本如何讓經典劇作在當代劇場語境下煥發新生,滿足現代觀眾的觀看慾望。
Thumbnail
本文深入解析臺灣劇團「晃晃跨幅町」對易卜生經典劇作《海妲.蓋柏樂》的詮釋,從劇本歷史、聲響與舞臺設計,到演員的主體創作方法,探討此版本如何讓經典劇作在當代劇場語境下煥發新生,滿足現代觀眾的觀看慾望。
Thumbnail
《轉轉生》為奈及利亞編舞家庫德斯.奧尼奎庫與 Q 舞團創作的當代舞蹈作品,融合舞蹈、音樂、時尚和視覺藝術,透過身體、服裝與群舞結構,回應殖民歷史、城市經驗與祖靈記憶的交錯。本文將從服裝設計、身體語彙與「輪迴」的「誕生—死亡—重生」結構出發,分析《轉轉生》如何以當代目光,形塑去殖民視角的奈及利亞歷史。
Thumbnail
《轉轉生》為奈及利亞編舞家庫德斯.奧尼奎庫與 Q 舞團創作的當代舞蹈作品,融合舞蹈、音樂、時尚和視覺藝術,透過身體、服裝與群舞結構,回應殖民歷史、城市經驗與祖靈記憶的交錯。本文將從服裝設計、身體語彙與「輪迴」的「誕生—死亡—重生」結構出發,分析《轉轉生》如何以當代目光,形塑去殖民視角的奈及利亞歷史。
Thumbnail
打開 jupyter notebook 寫一段 python 程式,可以完成五花八門的工作,這是玩程式最簡便的方式,其中可以獲得很多快樂,在現今這種資訊發達的時代,幾乎沒有門檻,只要願意,人人可享用。 下一步,希望程式可以隨時待命聽我吩咐,不想每次都要開電腦,啟動開發環境,只為完成一個重複性高
Thumbnail
打開 jupyter notebook 寫一段 python 程式,可以完成五花八門的工作,這是玩程式最簡便的方式,其中可以獲得很多快樂,在現今這種資訊發達的時代,幾乎沒有門檻,只要願意,人人可享用。 下一步,希望程式可以隨時待命聽我吩咐,不想每次都要開電腦,啟動開發環境,只為完成一個重複性高
Thumbnail
# 簡介 身為一位專注於 Vue.js 的前端開發者,這是我第一次嘗試構建 Flutter 網頁應用。讓我們開始吧! ## 第一次嘗試 ### 第一步:創建一個 Flutter 應用 首先,通過運行以下命令來創建一個新的 Flutter 項目: ```sh flutter
Thumbnail
# 簡介 身為一位專注於 Vue.js 的前端開發者,這是我第一次嘗試構建 Flutter 網頁應用。讓我們開始吧! ## 第一次嘗試 ### 第一步:創建一個 Flutter 應用 首先,通過運行以下命令來創建一個新的 Flutter 項目: ```sh flutter
Thumbnail
本篇文章將分享手機App設計教學,並往後介紹使用Flutter開發App的相關知識和技巧。透過這系列的分享,讀者將能夠學習如何利用設計和程式開發技能來製作一個App。文章中也提供了一些靈感來源和教學資源,幫助讀者進行設計和開發的思考和學習。
Thumbnail
本篇文章將分享手機App設計教學,並往後介紹使用Flutter開發App的相關知識和技巧。透過這系列的分享,讀者將能夠學習如何利用設計和程式開發技能來製作一個App。文章中也提供了一些靈感來源和教學資源,幫助讀者進行設計和開發的思考和學習。
Thumbnail
有沒有想過,即使沒有任何編程背景,你的創意也能在六個月內轉化成真實的App?我可以以自身經歷跟你說有了 No-Code Tool (無代碼工具) 和 AI 的幫助,這一切都是可能的!你一行 code 都不需要打,甚至也無須學習任何編程語言!沒有什麼比實踐一個自小認為不可能的任務還振奮人心的事了!
Thumbnail
有沒有想過,即使沒有任何編程背景,你的創意也能在六個月內轉化成真實的App?我可以以自身經歷跟你說有了 No-Code Tool (無代碼工具) 和 AI 的幫助,這一切都是可能的!你一行 code 都不需要打,甚至也無須學習任何編程語言!沒有什麼比實踐一個自小認為不可能的任務還振奮人心的事了!
Thumbnail
本課程學習如何在 Kotlin 程式碼檔案中,設定 ImageView 圖片元件,顯示本地端圖片。
Thumbnail
本課程學習如何在 Kotlin 程式碼檔案中,設定 ImageView 圖片元件,顯示本地端圖片。
Thumbnail
本篇文章將介紹開發 Android 手機應用程式所需的開發軟體,Google 官方的開發工具 Android Studio。這款軟體不僅免費,還提供完整的支援,適合所有 Android 開發者使用。
Thumbnail
本篇文章將介紹開發 Android 手機應用程式所需的開發軟體,Google 官方的開發工具 Android Studio。這款軟體不僅免費,還提供完整的支援,適合所有 Android 開發者使用。
Thumbnail
根據初學者設計了 Kotlin 程式語言的基礎課程,從 Android Studio 到 Android App 開發,提供完整指引。由基礎開始,傳授開發技巧。課程分為三部分:環境安裝、常用元件與界面設計,以及高階技巧如 DataStore、Room 資料儲存與網路處理。
Thumbnail
根據初學者設計了 Kotlin 程式語言的基礎課程,從 Android Studio 到 Android App 開發,提供完整指引。由基礎開始,傳授開發技巧。課程分為三部分:環境安裝、常用元件與界面設計,以及高階技巧如 DataStore、Room 資料儲存與網路處理。
Thumbnail
Kotlin 是 Google 官方推薦的 Android 開發語言,具有簡潔、安全、高效等優點,受到越來越多開發者的青睞。如果你也想學習 Kotlin,卻不知道從哪裡開始,那麼這本【Kotlin 入門指南】就是你的最佳選擇。
Thumbnail
Kotlin 是 Google 官方推薦的 Android 開發語言,具有簡潔、安全、高效等優點,受到越來越多開發者的青睞。如果你也想學習 Kotlin,卻不知道從哪裡開始,那麼這本【Kotlin 入門指南】就是你的最佳選擇。
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News