diff --git a/CLAUDE.md b/CLAUDE.md index 945c208..fdf20ff 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -79,6 +79,8 @@ - 定量撮影モード要求仕様(SmTIAS-LightSim 側からの外部要求): docs/05_TECH/TECH_01_定量撮影モード要求仕様.md - MiniTIAS 引き継ぎ手順(SmTIAS-LightSim 側からのハンドオフ手順): docs/05_TECH/TECH_02_MiniTIAS引き継ぎ手順.md +- 定量モード実装報告と SHADING_MODE 相談(MiniTIAS → SmTIAS-LightSim): docs/05_TECH/TECH_03_定量モード実装報告とSHADING_MODE相談.md +- 上記への回答(SmTIAS-LightSim → MiniTIAS): docs/05_TECH/TECH_04_MiniTIASへの回答.md ### 06_TEST(テスト・実機検証) diff --git a/README.md b/README.md index ba79556..292a1a7 100644 --- a/README.md +++ b/README.md @@ -1,29 +1,36 @@ # MiniTIAS 千葉大学フロンティア医工学センターの舌画像撮影・解析システム(TIAS)のスマートフォン版。 -既存の積分球装置による撮影と画質を比較するため、まずは撮影・保存に特化したアプリとして開発。 +PC 側のシミュレーション(SmTIAS-LightSim)と実機撮影を定量比較するため、Camera2 API の +完全マニュアル制御で RAW(DNG)を撮影・保存することに特化したアプリ。 ## 主な機能 -- フロントカメラによる舌画像の撮影(PNG 無圧縮保存) -- 3 秒カウントダウンタイマー -- 画面輝度調整スライダー(LED 光源の補助) -- 撮影画像の一覧表示・拡大閲覧・削除 -- 端末を逆さに装着する専用アタッチメントに対応した UI 回転 +- **定量モード撮影(DNG)**: フロントカメラを Camera2 API でフルマニュアル制御(AE/AWB/AF/NR/EDGE OFF・線形トーンマップ・露光 1/120s・ISO 40 固定)し、10-bit BGGR Bayer の RAW を `.dng`(約 16 MB)で保存 +- **メタデータ JSON**: 撮影設定・実適用値・センサ特性・LSC マップ・画素統計・Hot pixel map を `.meta.json` に保存 +- **プレビュー JPEG**: シャッター瞬間のライブプレビュー(自動 ISP 処理)スナップショットを `.preview.jpg` として保存し、アプリ内で撮れ具合を確認 +- **一覧・閲覧・削除**: 撮影画像のサムネイル一覧、拡大表示、関連 3 ファイル連動削除 +- **カメラ診断**: 実機 Camera2 能力(HW Level・対応モード・出力サイズ等)を JSON 出力(インフラのみ・UI 非表示) +- 端末を逆さに装着する専用アタッチメントに対応した 180° 回転 UI、画面輝度調整、シャッター音 ON/OFF + +> 旧通常モードの非圧縮 PNG 撮影パス(`captureFullResolutionPng`)はフォールバック用にコードを温存。 ## 対象デバイス -- AQUOS sense3(フロントカメラ + LED ライト付きアタッチメント) +- AQUOS sense3(SH-02M)/ フロントカメラ + LED ライト付きアタッチメント +- 診断結果: HW Level 3 + RAW + MANUAL_SENSOR + MANUAL_POST_PROCESSING 対応 ## 技術スタック | 項目 | 技術 | |------|------| -| フレームワーク | Flutter 3.11 / Dart | +| フレームワーク | Flutter(stable)/ Dart | | 状態管理 | Provider | -| カメラ | camera パッケージ(Camera2 API) | -| 画像処理 | image パッケージ(YUV→PNG 変換) | +| カメラ(プレビュー) | camera パッケージ(ライブプレビュー用) | +| カメラ(撮影・変換) | Android ネイティブ Kotlin(Camera2 API / `DngCreator` / YUV→JPEG・PNG エンコード) | | 権限管理 | permission_handler | +| 設定保存 | shared_preferences(シャッター音 ON/OFF 等) | +| 画面輝度 | screen_brightness | 詳細は [docs/02_ENV/ENV_01_技術スタック.md](docs/02_ENV/ENV_01_技術スタック.md) を参照。 @@ -54,22 +61,30 @@ flutter run # ビルド&実行 ``` +撮影データ(`.dng` / `.meta.json` / `.preview.jpg`)は端末の `Pictures/MiniTIAS/` に保存される。 +PC への転送は **adb pull** を推奨(大容量 DNG では MTP に不整合リスクあり)。 + ## プロジェクト構成 ``` lib/ -├── screens/ # 画面(撮影・一覧) -├── providers/ # 状態管理(カメラ・ギャラリー) -├── services/ # ビジネスロジック(ファイル保存・権限・RAW 変換) +├── screens/ # 画面(ホーム・撮影・一覧) +├── providers/ # 状態管理(カメラ・ギャラリー・診断) +├── services/ # ビジネスロジック(ファイル保存・権限・RAW 撮影・サウンド) ├── widgets/ # 共通ウィジェット(プレビュー・シャッターボタン・グリッド) ├── app.dart # アプリ設定 └── main.dart # エントリポイント +android/app/src/main/kotlin/com/example/mini_tias/ +└── RawCapturePlugin.kt # Camera2 撮影・DNG/PNG/JPEG 変換・診断のネイティブ実装 + docs/ ├── 01_GUIDE/ # 開発規約・ルール ├── 02_ENV/ # 環境構築 ├── 03_PLAN/ # 要件定義・開発ステップ -└── 04_SPEC/ # 画面機能仕様 +├── 04_SPEC/ # 画面機能仕様 +├── 05_TECH/ # 技術設計・SmTIAS-LightSim 側との外部要求/合意 +└── 06_TEST/ # 実機検証結果(カメラ診断など) ``` ## 開発ガイド @@ -88,6 +103,10 @@ - [要件定義書](docs/03_PLAN/PLAN_01_要件定義書.md) - [開発ステップ](docs/03_PLAN/PLAN_02_開発ステップ.md) - [画面機能仕様書](docs/04_SPEC/SPEC_01_画面機能仕様書.md) +- [定量撮影モード要求仕様(外部要求)](docs/05_TECH/TECH_01_定量撮影モード要求仕様.md) +- [開発進捗ログ](docs/PROGRESS.md) - [Git 運用ルール](docs/01_GUIDE/GUIDE_04_Git運用ルール.md) - [コーディング規約](docs/01_GUIDE/GUIDE_06_コーディング規約.md) - [テスト方針](docs/01_GUIDE/GUIDE_07_テスト方針.md) + + diff --git "a/docs/02_ENV/ENV_01_\346\212\200\350\241\223\343\202\271\343\202\277\343\203\203\343\202\257.md" "b/docs/02_ENV/ENV_01_\346\212\200\350\241\223\343\202\271\343\202\277\343\203\203\343\202\257.md" index 73163b7..1a3e80a 100644 --- "a/docs/02_ENV/ENV_01_\346\212\200\350\241\223\343\202\271\343\202\277\343\203\203\343\202\257.md" +++ "b/docs/02_ENV/ENV_01_\346\212\200\350\241\223\343\202\271\343\202\277\343\203\203\343\202\257.md" @@ -26,21 +26,30 @@ | パッケージ | 用途 | 備考 | | --- | --- | --- | -| `camera` | インカメラのライブプレビュー・撮影 | Flutter 公式プラグイン | -| `image` | 撮影画像の PNG エンコード | YUV → RGB → PNG 変換に使用 | -| `path_provider` | アプリ内ファイルパスの取得 | 保存先ディレクトリの参照に使用 | +| `camera` | インカメラのライブプレビュー | フレーミング用.撮影本体は Camera2 ネイティブ実装 | | `permission_handler` | カメラ・ストレージの権限管理 | Android の実行時権限リクエスト | | `provider` | 状態管理 | Flutter 公式推奨.シンプルかつ拡張しやすい | | `screen_brightness` | 画面の輝度制御 | アタッチメント装着時の明るさ調整に使用 | +| `shared_preferences` | 設定の永続化 | シャッター音 ON/OFF などの保存に使用 | ※ パッケージバージョンは環境構築時に最新 stable を採用し,`pubspec.yaml` で管理する. +### ネイティブ実装(Android / Kotlin) + +撮影・画像変換・カメラ診断は Dart パッケージではなく Android ネイティブで実装する(`RawCapturePlugin.kt`,MethodChannel 経由). + +| 処理 | 実装 | +| --- | --- | +| 定量モード撮影(RAW) | Camera2 API フルマニュアル制御 + `DngCreator` で DNG 出力 | +| 画像変換 | YUV→JPEG(プレビュー保存),YUV→非圧縮 PNG(旧通常モード) | +| 画素統計・Hot pixel map | RAW から Kotlin で算出し meta.json に格納 | +| カメラ診断 | `CameraCharacteristics` を読み出して JSON 化 | + +> 当初は `image` パッケージで PNG エンコードしていたが,速度の問題からネイティブへ移行した(経緯は [docs/PROGRESS.md](../PROGRESS.md) を参照). + ### 共有ストレージ保存 (Shared Storage) -画像の保存先は `Pictures/MiniTIAS/`(Android 共有ストレージ)とする.Android 10 以降の Scoped Storage 制約により,`path_provider` では共有ストレージに直接書き込めない.保存方法は以下のいずれかを環境構築時に検証・確定する. - -- `saver_gallery` 等の既存パッケージを利用 -- Platform Channels で Android の MediaStore API を直接呼び出し +画像の保存先は `Pictures/MiniTIAS/`(Android 共有ストレージ)とする.DNG をネイティブ側で直接書き込み(`FileOutputStream`),保存後に `MediaScannerConnection.scanFile`(MethodChannel `scanFile`)で MediaStore に登録する方式を採用した.大容量 DNG の MethodChannel 転送を避けるため,ファイル書き込みは Kotlin 側で完結させ,Dart へはパスのみ返す. ### 状態管理 (State Management) @@ -55,8 +64,8 @@ | 処理 | 実行場所 | 備考 | | --- | --- | --- | | 撮影・ライブプレビュー | スマホ(Flutter アプリ) | インカメラ使用 | -| 画像保存(PNG) | スマホ(Flutter アプリ) | 共有ストレージに保存 | -| データ転送 | USB 接続 | PC からフォルダを直接参照 | +| 画像保存(DNG + meta.json + preview.jpg) | スマホ(ネイティブ Camera2) | 共有ストレージに保存 | +| データ転送 | USB 接続(adb pull 推奨) | 大容量 DNG は MTP で不整合リスクあり | | キャリブレーション | PC | カラーバーを用いた色補正 | | 色変換・解析 | PC | L\*a\*b\* 変換,色差計算等 | diff --git "a/docs/04_SPEC/SPEC_01_\347\224\273\351\235\242\346\251\237\350\203\275\344\273\225\346\247\230\346\233\270.md" "b/docs/04_SPEC/SPEC_01_\347\224\273\351\235\242\346\251\237\350\203\275\344\273\225\346\247\230\346\233\270.md" index edaa6a8..1ec3ae5 100644 --- "a/docs/04_SPEC/SPEC_01_\347\224\273\351\235\242\346\251\237\350\203\275\344\273\225\346\247\230\346\233\270.md" +++ "b/docs/04_SPEC/SPEC_01_\347\224\273\351\235\242\346\251\237\350\203\275\344\273\225\346\247\230\346\233\270.md" @@ -331,28 +331,37 @@ | --- | --- | | `CameraProvider` | カメラの初期化・プレビュー制御・撮影実行・ライフサイクル管理 | | `GalleryProvider` | 画像一覧の取得・キャッシュ・削除操作 | +| `DiagnosticsProvider` | カメラ診断の実行・結果保存(インフラのみ・UI 非表示) | ### ディレクトリ構成 ```text lib/ -├── main.dart # アプリエントリポイント,Provider 登録 -├── app.dart # MaterialApp 定義,テーマ設定 +├── main.dart # アプリエントリポイント,Provider 登録 +├── app.dart # MaterialApp 定義,テーマ設定,180° 回転 ├── providers/ -│ ├── camera_provider.dart # カメラ制御の状態管理 -│ └── gallery_provider.dart # 画像一覧の状態管理 +│ ├── camera_provider.dart # カメラ制御の状態管理 +│ ├── gallery_provider.dart # 画像一覧の状態管理 +│ └── diagnostics_provider.dart # カメラ診断(インフラのみ) ├── screens/ -│ ├── capture_screen.dart # 撮影画面 (S-01) -│ └── gallery_screen.dart # 一覧画面 (S-02) +│ ├── home_screen.dart # BottomNavigationBar による画面切替 +│ ├── capture_screen.dart # 撮影画面 (S-01) +│ └── gallery_screen.dart # 一覧画面 (S-02) ├── widgets/ -│ ├── camera_preview.dart # カメラプレビューウィジェット -│ ├── shutter_button.dart # シャッターボタン -│ └── image_grid.dart # サムネイルグリッド +│ ├── camera_preview.dart # カメラプレビューウィジェット +│ ├── shutter_button.dart # シャッターボタン +│ └── image_grid.dart # サムネイルグリッド └── services/ - ├── file_service.dart # ファイル保存・命名・削除 - └── permission_service.dart # パーミッション管理 + ├── file_service.dart # ファイル保存・命名・削除 + ├── permission_service.dart # パーミッション管理 + ├── raw_capture_service.dart # ネイティブ撮影(DNG/PNG)・診断の MethodChannel + └── sound_service.dart # シャッター音・保存完了音の制御 ``` +※ 撮影・画像変換・診断の実処理は Android ネイティブ +`android/.../RawCapturePlugin.kt`(Camera2 / `DngCreator`)が担い, +`raw_capture_service.dart` が MethodChannel で橋渡しする。 + ### レイヤー構成 ```text @@ -388,7 +397,7 @@ ### データ保全 - 撮影データは端末ローカルにのみ保存する(クラウド同期なし) -- PNG(非圧縮)形式で保存し,画質劣化を防ぐ +- 定量モードは RAW(DNG,10-bit BGGR Bayer)で保存し,ISP 処理による情報欠落を防ぐ(旧通常モードは非圧縮 PNG) ### 対応端末