島根県安来市のフリーランスエンジニア_プログラマー画像1
レシート家計簿アプリの作り方|OCR+AI自動読み取り完全ガイド – Eatransform

レシート家計簿アプリの作り方|OCR+AI自動読み取り完全ガイド

🚧 デモシステム

📱 レシート家計簿

スマホでパシャ!AIが自動で読み取り、家計簿に記録

📸
レシートを撮影 または 画像をアップロード
.jpg, .png 対応
または、サンプルで体験
AI解析中…
✅ レシート読み取り完了
自動で家計簿に記録しました
🏪 店舗名
📅 日付
💰 合計金額
📂 カテゴリ
📝 購入品目
📊 今月の支出内訳
📚 実装ガイド

レシート家計簿アプリの構築手順

OCR + AI でレシート自動読み取り、支出を自動管理

1
開発環境とアーキテクチャ設計

画像認識とデータ管理の技術選定

  • OCR(文字認識): Google Cloud Vision API、Tesseract.js
  • 画像処理: OpenCV、Pillow(Python)
  • バックエンド: Python(FastAPI)、Node.js(Express)
  • データベース: PostgreSQL、MongoDB
  • フロントエンド: React Native(iOS/Android対応)
  • AI分類: OpenAI GPT-4、カスタム機械学習モデル
🛠️ 推奨技術スタック
Google Cloud Vision OpenAI GPT-4 Python + FastAPI React Native PostgreSQL AWS S3
📦 環境構築コマンド
# Python環境の構築
python -m venv venv
source venv/bin/activate

# 必要なライブラリ
pip install fastapi uvicorn
pip install google-cloud-vision
pip install pillow opencv-python
pip install openai sqlalchemy
pip install python-multipart

# React Nativeプロジェクト作成
npx react-native init ReceiptKakeibo
2
OCR(文字認識)の実装

レシート画像から文字を抽出

  • Google Cloud Vision API: 高精度、日本語対応◎、有料
  • AWS Textract: レシート特化、構造化データ抽出
  • Tesseract.js: オープンソース、無料、精度はやや劣る
  • 前処理: 画像の傾き補正、コントラスト調整、ノイズ除去
  • 座標情報: 文字の位置関係から項目を推測
  • 信頼度スコア: 認識精度が低い場合は手動修正を促す
📸 Google Cloud Vision APIでOCR
from google.cloud import vision
import io

class ReceiptOCR:
    def __init__(self):
        self.client = vision.ImageAnnotatorClient()
    
    def extract_text(self, image_path: str):
        # 画像を読み込み
        with io.open(image_path, 'rb') as image_file:
            content = image_file.read()
        
        image = vision.Image(content=content)
        
        # テキスト検出を実行
        response = self.client.document_text_detection(image=image)
        
        if response.error.message:
            raise Exception(f'OCRエラー: {response.error.message}')
        
        # 全文テキスト
        full_text = response.full_text_annotation.text
        
        # 各テキストブロックの詳細情報
        blocks = []
        for page in response.full_text_annotation.pages:
            for block in page.blocks:
                block_text = ''
                for paragraph in block.paragraphs:
                    for word in paragraph.words:
                        word_text = ''.join([
                            symbol.text 
                            for symbol in word.symbols
                        ])
                        block_text += word_text
                
                # テキストの座標
                vertices = [(v.x, v.y) for v in block.bounding_box.vertices]
                
                blocks.append({
                    'text': block_text,
                    'vertices': vertices,
                    'confidence': word.confidence
                })
        
        return {
            'full_text': full_text,
            'blocks': blocks
        }
    
    def preprocess_image(self, image_path: str):
        """画像の前処理"""
        import cv2
        import numpy as np
        
        # 画像を読み込み
        img = cv2.imread(image_path)
        
        # グレースケール化
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        
        # コントラスト調整
        clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
        enhanced = clahe.apply(gray)
        
        # ノイズ除去
        denoised = cv2.fastNlMeansDenoising(enhanced)
        
        # 二値化
        _, binary = cv2.threshold(
            denoised, 
            0, 
            255, 
            cv2.THRESH_BINARY + cv2.THRESH_OTSU
        )
        
        # 前処理済み画像を保存
        preprocessed_path = image_path.replace('.jpg', '_preprocessed.jpg')
        cv2.imwrite(preprocessed_path, binary)
        
        return preprocessed_path

💡 精度向上のコツ: レシートを平らに置き、明るい場所で撮影するようユーザーにガイドを表示。撮影時にグリッド線を表示して傾きを防止すると認識精度が大幅に向上します。

3
AIによるレシート情報の構造化

OCRの生テキストから意味のある情報を抽出

  • 店舗名検出: 上部の大きな文字、「株式会社」などのキーワード
  • 日時検出: 日付・時刻のパターンマッチング
  • 商品行の識別: 「商品名 + 価格」のパターン
  • 合計金額抽出: 「合計」「計」「お預かり」などのキーワード
  • OpenAI GPT-4活用: 複雑なレイアウトも理解可能
  • フォールバック: AIが失敗したら正規表現で補完
🤖 GPT-4でレシート情報を構造化
from openai import OpenAI
import json
import re

class ReceiptParser:
    def __init__(self):
        self.openai = OpenAI(api_key="your-api-key")
    
    async def parse_receipt(self, ocr_text: str):
        prompt = f"""
以下のレシートのOCR結果から、構造化されたデータを抽出してください。

{ocr_text}

以下のJSON形式で返してください:
{{
  "store_name": "店舗名",
  "date": "YYYY-MM-DD",
  "time": "HH:MM",
  "items": [
    {{
      "name": "商品名",
      "price": 金額(数値),
      "quantity": 数量
    }}
  ],
  "subtotal": 小計,
  "tax": 消費税,
  "total": 合計金額
}}

注意:
- 金額は数値のみ(カンマや円記号は除く)
- 商品名は正確に
- 数量が明記されていない場合は1
"""
        
        response = await self.openai.chat.completions.create(
            model="gpt-4",
            messages=[
                {
                    "role": "system",
                    "content": "あなたはレシートデータ抽出の専門家です"
                },
                {
                    "role": "user",
                    "content": prompt
                }
            ],
            temperature=0.1
        )
        
        result_text = response.choices[0].message.content
        
        # JSONを抽出(マークダウンのコードブロックを除去)
        json_match = re.search(r'```json\n(.*?)\n```', result_text, re.DOTALL)
        if json_match:
            result_text = json_match.group(1)
        
        try:
            parsed_data = json.loads(result_text)
            return parsed_data
        except json.JSONDecodeError:
            # フォールバック:正規表現で抽出
            return self.fallback_parse(ocr_text)
    
    def fallback_parse(self, text: str):
        """AIが失敗した時の正規表現パース"""
        lines = text.split('\n')
        
        result = {
            'store_name': '',
            'date': '',
            'time': '',
            'items': [],
            'total': 0
        }
        
        # 日付パターン
        date_pattern = r'(\d{4})[/-](\d{1,2})[/-](\d{1,2})'
        time_pattern = r'(\d{1,2}):(\d{2})'
        
        # 金額パターン(末尾に円がある数字)
        price_pattern = r'(\d{1,3}(?:,\d{3})*|\d+)円?'
        
        for line in lines:
            # 日付検出
            date_match = re.search(date_pattern, line)
            if date_match and not result['date']:
                result['date'] = f"{date_match.group(1)}-{date_match.group(2).zfill(2)}-{date_match.group(3).zfill(2)}"
            
            # 時刻検出
            time_match = re.search(time_pattern, line)
            if time_match and not result['time']:
                result['time'] = f"{time_match.group(1).zfill(2)}:{time_match.group(2)}"
            
            # 合計金額
            if '合計' in line or '計' in line:
                price_match = re.search(price_pattern, line)
                if price_match:
                    result['total'] = int(price_match.group(1).replace(',', ''))
        
        return result

⚠️ API費用: GPT-4は1回あたり5〜20円。月1万枚のレシートで5〜20万円かかります。初期はGPT-3.5-turboで費用を1/10に抑え、精度が足りない場合のみGPT-4を使う戦略も有効です。

4
自動カテゴリ分類エンジン

店舗名・商品名から支出カテゴリを自動判定

  • 店舗ベース分類: コンビニ→食費、ガソリンスタンド→交通費
  • 商品ベース分類: 商品名から詳細カテゴリを推測
  • 機械学習モデル: ユーザーの過去データから学習
  • カテゴリマスター: 大分類・中分類・小分類の階層構造
  • 曖昧さ対応: 確信度が低い場合はユーザーに確認
  • 学習機能: ユーザーの修正を学習して精度向上
🏷️ カテゴリ自動分類
class CategoryClassifier:
    def __init__(self):
        # カテゴリマスター
        self.store_patterns = {
            '食費': [
                'セブンイレブン', 'ファミリーマート', 'ローソン',
                'スーパー', 'イオン', 'イトーヨーカドー',
                'マクドナルド', 'すき家', 'ケンタッキー'
            ],
            '交通費': [
                'JR', '地下鉄', 'バス', 'タクシー',
                'ENEOS', 'シェル', 'コスモ石油'
            ],
            '日用品': [
                'マツモトキヨシ', 'ツルハ', 'スギ薬局',
                'ダイソー', 'セリア', 'ニトリ'
            ],
            '医療費': [
                'クリニック', '病院', '薬局', '歯科'
            ],
            '娯楽': [
                '映画', 'カラオケ', 'ゲームセンター',
                'ボウリング', 'ビリヤード'
            ]
        }
        
        self.item_keywords = {
            '食費': ['おにぎり', 'パン', '弁当', '野菜', '肉', '魚'],
            '日用品': ['シャンプー', '洗剤', 'ティッシュ', 'トイレットペーパー'],
            '交通費': ['ガソリン', '定期券', '切符'],
            '医療費': ['薬', '湿布', '絆創膏', '診察']
        }
    
    def classify(self, store_name: str, items: list):
        # 店舗名から判定
        for category, patterns in self.store_patterns.items():
            for pattern in patterns:
                if pattern in store_name:
                    return {
                        'category': category,
                        'confidence': 0.9,
                        'reason': f'店舗名「{store_name}」から判定'
                    }
        
        # 商品名から判定
        category_scores = {}
        for item in items:
            item_name = item.get('name', '')
            for category, keywords in self.item_keywords.items():
                for keyword in keywords:
                    if keyword in item_name:
                        category_scores[category] = category_scores.get(category, 0) + 1
        
        if category_scores:
            best_category = max(category_scores, key=category_scores.get)
            confidence = category_scores[best_category] / len(items)
            
            return {
                'category': best_category,
                'confidence': confidence,
                'reason': '商品名から判定'
            }
        
        # 判定できない場合
        return {
            'category': 'その他',
            'confidence': 0.5,
            'reason': '自動判定できませんでした'
        }
    
    def learn_from_user(self, user_id: str, store_name: str, 
                        selected_category: str):
        """ユーザーの修正から学習"""
        # データベースに保存
        db.category_learning.create({
            'user_id': user_id,
            'store_name': store_name,
            'category': selected_category,
            'created_at': datetime.now()
        })
        
        # 今後はこのユーザーにとって、
        # この店舗は指定カテゴリに分類される

💡 パーソナライズ: ユーザーごとに分類を学習させると精度が劇的に向上します。例えば「コンビニ=食費」の人もいれば「コンビニ=日用品」の人もいます。

5
データベース設計と家計簿管理

効率的にデータを保存・集計できる設計

  • ユーザーテーブル: 認証情報、プロフィール、設定
  • レシートテーブル: 画像URL、OCR結果、解析データ
  • 支出記録テーブル: 日付、カテゴリ、金額、メモ
  • 予算テーブル: カテゴリ別の月次予算
  • 定期支出テーブル: 家賃、光熱費など固定費
  • インデックス最適化: 日付・カテゴリでの高速検索
🗄️ データベーススキーマ(PostgreSQL)
-- ユーザーテーブル
CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    email VARCHAR(255) UNIQUE NOT NULL,
    password_hash VARCHAR(255) NOT NULL,
    name VARCHAR(100),
    created_at TIMESTAMP DEFAULT NOW(),
    updated_at TIMESTAMP DEFAULT NOW()
);

-- レシートテーブル
CREATE TABLE receipts (
    id SERIAL PRIMARY KEY,
    user_id INTEGER REFERENCES users(id),
    image_url VARCHAR(500) NOT NULL,
    store_name VARCHAR(200),
    receipt_date DATE,
    receipt_time TIME,
    total_amount INTEGER,
    ocr_text TEXT,
    parsed_data JSONB,
    created_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_receipts_user_date 
ON receipts(user_id, receipt_date DESC);

-- 支出記録テーブル
CREATE TABLE expenses (
    id SERIAL PRIMARY KEY,
    user_id INTEGER REFERENCES users(id),
    receipt_id INTEGER REFERENCES receipts(id),
    expense_date DATE NOT NULL,
    category VARCHAR(50) NOT NULL,
    subcategory VARCHAR(50),
    amount INTEGER NOT NULL,
    description TEXT,
    payment_method VARCHAR(20),
    created_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_expenses_user_date 
ON expenses(user_id, expense_date DESC);

CREATE INDEX idx_expenses_category 
ON expenses(user_id, category, expense_date);

-- 予算テーブル
CREATE TABLE budgets (
    id SERIAL PRIMARY KEY,
    user_id INTEGER REFERENCES users(id),
    category VARCHAR(50) NOT NULL,
    year INTEGER NOT NULL,
    month INTEGER NOT NULL,
    budget_amount INTEGER NOT NULL,
    UNIQUE(user_id, category, year, month)
);

-- 定期支出テーブル
CREATE TABLE recurring_expenses (
    id SERIAL PRIMARY KEY,
    user_id INTEGER REFERENCES users(id),
    name VARCHAR(100) NOT NULL,
    category VARCHAR(50) NOT NULL,
    amount INTEGER NOT NULL,
    frequency VARCHAR(20) NOT NULL, -- monthly, yearly
    next_date DATE NOT NULL,
    auto_record BOOLEAN DEFAULT false
);
📊 月次集計クエリ
-- カテゴリ別月次支出
SELECT 
    category,
    SUM(amount) as total_amount,
    COUNT(*) as count
FROM expenses
WHERE user_id = $1
    AND expense_date >= DATE_TRUNC('month', CURRENT_DATE)
    AND expense_date < DATE_TRUNC('month', CURRENT_DATE) + INTERVAL '1 month'
GROUP BY category
ORDER BY total_amount DESC;

-- 予算達成率
SELECT 
    b.category,
    b.budget_amount,
    COALESCE(SUM(e.amount), 0) as spent_amount,
    ROUND(COALESCE(SUM(e.amount), 0) * 100.0 / b.budget_amount, 1) as achievement_rate
FROM budgets b
LEFT JOIN expenses e ON 
    e.user_id = b.user_id 
    AND e.category = b.category
    AND EXTRACT(YEAR FROM e.expense_date) = b.year
    AND EXTRACT(MONTH FROM e.expense_date) = b.month
WHERE b.user_id = $1
    AND b.year = EXTRACT(YEAR FROM CURRENT_DATE)
    AND b.month = EXTRACT(MONTH FROM CURRENT_DATE)
GROUP BY b.category, b.budget_amount;
6
グラフ・分析機能の実装

支出を視覚化して改善につなげる

  • 月次推移グラフ: 過去6ヶ月の支出トレンド
  • カテゴリ別円グラフ: 何にいくら使ったか一目瞭然
  • 日別支出カレンダー: 使いすぎた日がわかる
  • 予算達成率: カテゴリごとの進捗バー
  • 比較分析: 先月比、去年同月比
  • AIレポート: 「外食が先月より20%増えています」
📊 React Nativeでグラフ表示
import React, { useState, useEffect } from 'react';
import { View, Text, StyleSheet, ScrollView } from 'react-native';
import { PieChart, BarChart } from 'react-native-chart-kit';

const ExpenseAnalytics = ({ userId }) => {
  const [monthlyData, setMonthlyData] = useState([]);
  const [categoryData, setCategoryData] = useState([]);

  useEffect(() => {
    fetchAnalytics();
  }, []);

  const fetchAnalytics = async () => {
    const response = await fetch(
      `https://api.example.com/analytics/${userId}`
    );
    const data = await response.json();
    
    setMonthlyData(data.monthly);
    setCategoryData(data.categories);
  };

  // カテゴリ別円グラフデータ
  const pieData = categoryData.map((cat, index) => ({
    name: cat.name,
    amount: cat.amount,
    color: COLORS[index % COLORS.length],
    legendFontColor: '#7F7F7F',
    legendFontSize: 12
  }));

  // 月次推移データ
  const barData = {
    labels: monthlyData.map(m => m.month),
    datasets: [{
      data: monthlyData.map(m => m.total)
    }]
  };

  return (
    
      今月の支出分析
      
      {/* カテゴリ別円グラフ */}
      
        カテゴリ別支出
        
      

      {/* 月次推移グラフ */}
      
        月次推移
        
      

      {/* 予算達成率 */}
      
        予算達成率
        {categoryData.map(cat => (
          
        ))}
      

      {/* AIレポート */}
      
        💡 AIからのアドバイス
        
          外食費が先月より20%増加しています。
          週2回を週1回に減らすと月5,000円節約できます。
        
        
          日用品の支出が予算内に収まっています。
          このペースを維持しましょう!
        
      
    
  );
};

const BudgetProgressBar = ({ category, spent, budget }) => {
  const percentage = Math.min((spent / budget) * 100, 100);
  const isOverBudget = spent > budget;

  return (
    
      
        {category}
        
          ¥{spent.toLocaleString()} / ¥{budget.toLocaleString()}
        
      
      
        
      
    
  );
};

const COLORS = ['#667eea', '#764ba2', '#f093fb', '#4facfe', '#43e97b'];

const chartConfig = {
  backgroundColor: '#ffffff',
  backgroundGradientFrom: '#ffffff',
  backgroundGradientTo: '#ffffff',
  color: (opacity = 1) => `rgba(102, 126, 234, ${opacity})`,
  labelColor: (opacity = 1) => `rgba(0, 0, 0, ${opacity})`,
};

💡 ユーザー定着率UP: 毎月1日に「先月の振り返りレポート」をプッシュ通知すると、アプリを開く頻度が2倍になります。視覚的なグラフで達成感を演出しましょう。

7
予算管理・アラート機能

使いすぎを防ぐ仕組みを提供

  • カテゴリ別予算設定: 食費3万円、交通費1万円など
  • リアルタイムアラート: 予算の80%、100%で通知
  • 週次レポート: 毎週月曜に先週の支出をサマリ
  • 目標貯金額設定: 月5万円貯金など目標管理
  • 支出予測: このペースだと月末いくらになるか予測
  • 比較機能: 同年代の平均支出と比較
🔔 予算アラートシステム
class BudgetAlertSystem:
    def __init__(self):
        self.notification_service = PushNotificationService()
    
    async def check_budget_alerts(self, user_id: int):
        """予算超過チェックとアラート送信"""
        
        # 今月の予算と支出を取得
        budgets = await db.budgets.find({
            'user_id': user_id,
            'year': current_year,
            'month': current_month
        })
        
        for budget in budgets:
            # カテゴリの今月支出を集計
            spent = await db.expenses.aggregate([
                {
                    '$match': {
                        'user_id': user_id,
                        'category': budget.category,
                        'expense_date': {
                            '$gte': start_of_month,
                            '$lte': end_of_month
                        }
                    }
                },
                {
                    '$group': {
                        '_id': None,
                        'total': { '$sum': '$amount' }
                    }
                }
            ])
            
            if not spent:
                continue
            
            spent_amount = spent[0]['total']
            budget_amount = budget.budget_amount
            percentage = (spent_amount / budget_amount) * 100
            
            # 80%達成でアラート
            if percentage >= 80 and percentage < 100:
                if not await self.has_sent_alert(user_id, budget.category, '80%'):
                    await self.send_alert(
                        user_id,
                        f"{budget.category}の予算が80%に達しました",
                        f"予算:¥{budget_amount:,}\n"
                        f"支出:¥{spent_amount:,}\n"
                        f"残り:¥{budget_amount - spent_amount:,}",
                        '80%'
                    )
            
            # 100%超過でアラート
            elif percentage >= 100:
                if not await self.has_sent_alert(user_id, budget.category, '100%'):
                    await self.send_alert(
                        user_id,
                        f"⚠️ {budget.category}の予算を超過しました",
                        f"予算:¥{budget_amount:,}\n"
                        f"支出:¥{spent_amount:,}\n"
                        f"超過:¥{spent_amount - budget_amount:,}",
                        '100%',
                        urgent=True
                    )
    
    async def send_weekly_report(self, user_id: int):
        """週次レポート送信"""
        
        # 先週の支出を集計
        last_week_start = datetime.now() - timedelta(days=7)
        last_week_end = datetime.now()
        
        expenses = await db.expenses.find({
            'user_id': user_id,
            'expense_date': {
                '$gte': last_week_start,
                '$lte': last_week_end
            }
        })
        
        total = sum(e.amount for e in expenses)
        by_category = {}
        
        for expense in expenses:
            cat = expense.category
            by_category[cat] = by_category.get(cat, 0) + expense.amount
        
        # トップ3カテゴリ
        top_categories = sorted(
            by_category.items(), 
            key=lambda x: x[1], 
            reverse=True
        )[:3]
        
        message = f"""
📊 先週の支出レポート

合計:¥{total:,}

トップ3:
"""
        for cat, amount in top_categories:
            message += f"• {cat}: ¥{amount:,}\n"
        
        await self.notification_service.send(user_id, {
            'title': '週次レポート',
            'body': message
        })
    
    async def predict_month_end(self, user_id: int):
        """月末の支出予測"""
        
        # 今月1日からの日数
        today = datetime.now()
        days_passed = today.day
        
        # 月の総日数
        last_day = calendar.monthrange(today.year, today.month)[1]
        
        # 今月の支出合計
        month_spent = await self.get_month_total(user_id)
        
        # 1日あたりの平均支出
        daily_average = month_spent / days_passed
        
        # 月末予測
        predicted_total = daily_average * last_day
        
        return {
            'current_spent': month_spent,
            'predicted_total': int(predicted_total),
            'remaining_days': last_day - days_passed,
            'daily_average': int(daily_average)
        }

⚠️ 通知疲れに注意: アラートが多すぎるとユーザーが通知をオフにします。重要度に応じて通知頻度を調整し、ユーザーが通知設定をカスタマイズできるようにしましょう。

8
本番環境デプロイと運用

安定したサービス提供体制の構築

  • インフラ: AWS(EC2, S3, RDS)、GCP、Heroku
  • 画像ストレージ: S3にレシート画像を保存
  • データベース: RDS PostgreSQL(マネージド)
  • CDN: CloudFrontで画像配信高速化
  • バックアップ: 日次自動バックアップ
  • 監視: CloudWatch、Sentryでエラー監視
🚀 AWS構成例
# インフラ構成

[ユーザー]
    ↓
[CloudFront CDN] ← 画像配信高速化
    ↓
[ALB (Application Load Balancer)]
    ↓
[ECS Fargate] ← コンテナでAPI実行
    ├─ API Server (FastAPI)
    ├─ OCR Worker
    └─ Analytics Worker
    ↓
[RDS PostgreSQL] ← データベース
[ElastiCache Redis] ← キャッシュ・セッション
[S3] ← レシート画像保存

# 月次費用概算(1万ユーザー想定)
- ECS Fargate: ¥5,000〜10,000
- RDS: ¥8,000〜15,000
- S3: ¥2,000〜5,000
- CloudFront: ¥1,000〜3,000
- その他: ¥3,000〜5,000
合計: 約2〜4万円/月
🐳 Dockerfileの例
# Python APIサーバー
FROM python:3.11-slim

WORKDIR /app

# 依存関係のインストール
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# アプリケーションコードをコピー
COPY . .

# 非rootユーザーで実行
RUN adduser --disabled-password --gecos '' appuser
USER appuser

EXPOSE 8000

CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
🛠️ 推奨インフラ構成
AWS ECS Fargate RDS PostgreSQL S3 CloudFront CloudWatch Route 53 Docker

💡 スタート戦略: 最初はHeroku + Supabaseで月5,000円以下でスタート。ユーザーが1,000人を超えたらAWSに移行するのが現実的です。

💰 開発・運用コスト見積もり
初期開発費用(MVP) 120〜180万円
サーバー費用(AWS) 月20,000〜40,000円
Google Cloud Vision API 1,000枚あたり1,500円
OpenAI API(GPT-4) 1回10円×枚数
S3ストレージ 月2,000〜10,000円
プッシュ通知 月3,000〜8,000円
月額運用費(目安) 3〜10万円
本格版開発費用 250〜400万円
💡 収益シミュレーション:
月額480円 × 3,000人(課金率10%) = 月間売上144万円
月額480円 × 10,000人(課金率15%) = 月間売上720万円
→ 初期投資を6ヶ月〜1年で回収可能
✅ 成功させるための重要ポイント
1. OCR精度が命
• 認識精度95%以上を目指す
• 読み取り失敗時の手動修正UIを充実
• ユーザーの修正データを学習に活用
• レシート撮影ガイド(枠線表示)で精度UP

2. 最初は無料で体験させる
• 月20枚まで無料、それ以降は有料
• 「まず使ってもらう」ことを最優先
• 無料期間中に習慣化させる
• 有料の価値を実感してもらう

3. 自動化を徹底
• レシート撮影したら後は全自動
• カテゴリ分類、グラフ作成、全部AI
• 手入力は最小限に(面倒だと離脱)
• 「楽すぎる家計簿」を訴求

4. 視覚化で達成感を
• グラフで支出が減っていく様子を見せる
• 「今月は先月より5,000円節約!」と褒める
• バッジ・ランクシステムでゲーム化
• SNSシェア機能で口コミ拡散

5. 銀行・クレカ連携は後回し
• レシート撮影だけに特化してスタート
• 銀行連携は審査が厳しく時間がかかる
• まずはMVPで市場テスト
• ニーズが確認できたら機能追加
❌ よくある失敗パターン
失敗1: OCR精度が低すぎて使えない
→ 解決策: Google Cloud Vision APIなど実績あるサービスを使う

失敗2: 機能を詰め込みすぎて重い
→ 解決策: 「レシート撮影→自動記録」だけに絞る

失敗3: 課金が高すぎて使われない
→ 解決策: 月額480〜980円、まずは無料体験

失敗4: 継続率が低い
→ 解決策: 週次レポート、予算アラートで定期的に開かせる

失敗5: API費用で赤字
→ 解決策: GPT-4は必要な時だけ、基本はGPT-3.5-turbo使用

完全自動アフィリエイトシステムを作った話【WordPress×楽天API×SNS連携】

データ集計システム – 無料の業務データ管理・分析ツール | Eatransform