Chat-GPT API が話題だったので、使ってみたいと思い今回のアプリを作成しました。
概要は OCR で画像から文章を取得し、Chat-GPT API で要約した文章を表示するアプリです。
※今回初めて Flutter を使用し、制作期間も 3 日程度だったのでかなり粗いつくりかもしれませんご了承ください。
構成
- アプリ開発には Flutter を使用、画像の選択、OCR、Chat-GPT API の呼び出しを行っています。
- OCR には Google Firebase の ML Kit を使用しています。
- 検出された文章は Chat-GPT API に渡し、要約した文章を取得し結果を表示します。
環境
- 実行環境
- iPhone13Pro max : iOS 16.0.2
- 開発環境
- macOS Monterey 12.6
- Xcode 14.0.1
- Flutter 3.7.7
Flutter でのアプリの作成
今回アプリを作成するにあたり、Flutter を使用しました。Swift でもよかったのですが今回は Flutter に触れてみたかったと言うこともあり Flutter を選択しました。
動作の流れとしては
- 画像の撮影、選択 + トリミング
- 画像を Google Firebase の ML Kit に渡して OCR で文章を取得
- 取得した文章を Chat-GPT API に渡して要約した文章を取得
- 取得した文章を画面に表示
こんな動作イメージで制作しました。
画面の作成
画面は上記のようなに画面構成で、画面1では画像の選択と言語の選択を行い画面2に読み取った文章と要約結果を表示するようにしています。
個人的にごちゃごちゃしたデザインよりシンプルなデザインが好きなのでこのような最低限のデザインにしました。あと AppBar に色がついているのも嫌だったので透明にしました。
1
2 Widget build(BuildContext context) {
3 SystemChrome.setSystemUIOverlayStyle(
4 const SystemUiOverlayStyle(
5 statusBarBrightness: Brightness.light,
6 )
7 );
8 return Scaffold(
9 appBar: AppBar(
10 automaticallyImplyLeading:true,
11 iconTheme: IconThemeData(color: Colors.black),
12 elevation: 0,
13 backgroundColor: Colors.transparent,
14 ),
AppBar の色を透明にするには上記のように AppBar の backgroundColor を透明にし elevation を 0 し影を消すことで完全に透明にすることができます。 これだけだとステータスバーの色が白で背景に消えてしまうので、SystemChrome.setSystemUIOverlayStyle を使用して statusBarBrightness を Brightness.light にして色を変更しています。
画像の選択、トリミング
今回は画像の選択には image_picker を使用しトリミングには image_cropper を使用しました。
1import 'package:image_cropper/image_cropper.dart';
2import 'package:image_picker/image_picker.dart';
1class Pick{
2 XFile? image;
3 final picker = ImagePicker();
4
5 // 画像をギャラリーから選ぶ関数
6 Future<XFile?> pickImage() async {
7 final image = await ImagePicker().pickImage(source: ImageSource.gallery);
8 // 画像がnullの場合戻る
9 if (image == null) return null;
10
11 final imageTemp = image;
12
13 return imageTemp;
14 }
15 // カメラを使う関数
16 Future<XFile?> pickImageCamera() async {
17 final image = await ImagePicker().pickImage(source: ImageSource.camera);
18 // 画像がnullの場合戻る
19 if (image == null) return null;
20
21 final imageTemp = image;
22
23 return imageTemp;
24 }
25}
image_picker にはもともとカメラとライブラリから画像を選択する関数が用意されているのでそれを使用します。
1Future cropImage(XFile img) async {
2 final croppedFile = await ImageCropper().cropImage(
3 sourcePath: img.path,
4 uiSettings: [
5 AndroidUiSettings(
6 toolbarTitle: 'Cropper',
7 toolbarColor: Colors.deepOrange,
8 toolbarWidgetColor: Colors.white,
9 initAspectRatio: CropAspectRatioPreset.original,
10 lockAspectRatio: false),
11 IOSUiSettings(
12 title: 'Cropper',
13 ),
14 WebUiSettings(
15 context: context,
16 ),
17 ]
18 );
19 if (croppedFile != null) {
20 this.image = XFile(croppedFile.path);
21 }
22}
必要な文字以外は切り抜けるようにトリミングもできるよう image_cropper を使用しました。
OCR
ML Kit を使用には Firebase のプロジェクトを作成し、ML Kit を有効にする必要があります。その際こちらを参考にさせていただきました。
Flutter で ML Kit を使用するには google_mlkit_text_recognition というライブラリを使用します。
1import 'package:google_mlkit_text_recognition/google_mlkit_text_recognition.dart';
画面1で選択した言語と画像を ML Kit に渡し、OCR で文章を取得します。
1Future ocr_ja () async {
2 final InputImage imageFile = InputImage.fromFilePath(image!.path);
3 final textRecognizer =
4 TextRecognizer(script: TextRecognitionScript.japanese);
5 final RecognizedText recognizedText =
6 await textRecognizer.processImage(imageFile);
7 String text = '';
8 for(TextBlock block in recognizedText.blocks)
9 {
10 String temp = block.text;
11 text = text + temp;
12 }
13 setState(() {
14 result = Text(text.replaceAll('\n', ""));
15 });
16 textRecognizer.close();
17}
18
19Future ocr_en () async {
20 final InputImage imageFile = InputImage.fromFilePath(image!.path);
21 final textRecognizer =
22 TextRecognizer(script: TextRecognitionScript.latin);
23 final RecognizedText recognizedText =
24 await textRecognizer.processImage(imageFile);
25 String text = '';
26 for(TextBlock block in recognizedText.blocks)
27 {
28 String temp = block.text;
29 text = text + temp;
30 }
31 setState(() {
32 result = Text(text.replaceAll('\n', ""));
33 });
34 textRecognizer.close();
35}
今回は TextRecognizer の引数に japanese と latin を選択することで日本語と英語バージョンを作成ししました。
- TextRecognizer に画像を渡すには画像を InputImage に変換すしなければいけないので InputImage.fromFilePath(image!.path)で変換
- TextRecognizer に japanese か latin を渡す
- TextRecognizer に InputImage を渡しブロックごとの文章を取得し文字列を結合
- 最後に読み取った文章そのままでは改行が入っているので replaceAll で改行を消す
Chat-GPT に要約してもらう
最後に読み取った文章を Chat-GPT に渡し、文章を生成します。 ChatGPT を Flutter を使用するには以下のライブラリを使用します。
1import 'package:dart_openai/openai.dart';
ChatGPT API を Flutter で使用するにはまず APIKEY を取得する必要があるのでこちらから取得してください。
1Future main() async{
2 await dotenv.load(fileName: '.env');
3 OpenAI.apiKey = dotenv.get('API_KEY');
4 WidgetsFlutterBinding.ensureInitialized();
5 runApp(const MyApp());
6}
取得した APIKEY を OpenAI.apiKey に代入します。今回はソースコードを公開する予定だったので.env ファイルを利用しています。
1Future listenChatGPT(String message) async{
2 answerText = '処理中';
3 final chatCompletion = await OpenAI.instance.chat.create(
4 model: "gpt-3.5-turbo",
5 messages: [
6 OpenAIChatCompletionChoiceMessageModel(
7 content: "あなたはこれから入力される文章を日本語で要約してください",
8 role: "system",
9 ),
10 OpenAIChatCompletionChoiceMessageModel(
11 content: message,
12 role: "user",
13 ),
14 ],
15 );
16 setState(() {
17 answerText = chatCompletion.choices.first.message.toMap()['content'].toString();
18 });
19}
先ほど読み取った文章を引数で渡し、ChatGPT に渡します。 ChatGPT に渡す際 role を指定することができ
- system: AI の設定を記述
- assistant: AI からの発言
- user: ユーザーからの発言
となっています。今回は「あなたはこれから入力される文章を日本語で要約してください」と system に記述することで AI に文章を要約してもらうように指示しています。 user の文章としては先ほど読み取った文章を渡しています。 ChatGPT から返ってきた文章をマップに変換し content の key を指定してあげることで返答だけを得ることができます。
実際に動作させてみる
割といい感じに要約してくれるなって感じですね、今の Chat-GPT だと時間がかかってしまいますが、Chat-GPT4 を使えばもっと早くなるかも(?)って期待してます。
流石に Flutter を初めて 3 日で作ったものなので今後しっかり勉強してもっといいものにできたらいいなと思います。
GitHub にでもソースコード置いておきます