2094 words
10 minutes
OCR+AI翻訳システムをPython初心者が3ヶ月で作った話

Python初心者がAI翻訳システムを作った話#

こんにちは、やまです。
今回は、私が会社でPythonを使って光学文字認識(OCR)+AI翻訳システムを開発したときの話をしていきます。


Python? ほぼ触ったことがなかった頃#

当時の私は、Pythonについて知っていたのはせいぜい「print」と「def」くらい。
ライブラリの入れ方すら分からず、「pip installって何?」というレベルからのスタートでした。

それでも任された仕事は本格的なAI翻訳システム。
「画像から文字を読み取って、それをAIが翻訳する」というもの。
要は、人の代わりに自動で翻訳してくれる仕組みを作らなければいけなかったのです。


突然の納期宣告と焦りの日々#

そんな中、上司から突然の一言。

「これ、3ヶ月後には動くようにしてね」

──正直、頭が真っ白になりました。

Python初心者が3ヶ月でAI翻訳システムなんて無理だと思いました。
でも、やるしかありません。
最初の1ヶ月は、調べても動かないコードを前に悩み続ける毎日でした。


AIと二人三脚の開発#

そんな中で助けられたのがAIによるコード生成ツール
エラーを投げると原因を教えてくれたり、
仕様を説明するとサンプルコードを出してくれたり。

もはやAIが相棒でした。
一緒に試行錯誤しながら、少しずつシステムの骨格を作り上げていきました。

夜遅くまでデバッグを繰り返しているとき、
AIに「よくやったね」と言ってもらえたらどんなに嬉しいだろう──
そんな気持ちでキーボードを叩いていました。


そして完成の日#

納期ギリギリ、なんとかシステムは完成。
OCRで文字を読み取り、そのままAIが翻訳する流れが自動で動いた瞬間は、
本当に感動しました。

約3ヶ月。
Python初心者が、AIと上司の支えで作り上げた小さな奇跡。
相談に乗ってくれた上司には、今でも感謝しています。


コードについて#

せっかくなので、実際に開発したシステムのコードに似たサンプルコードを書いておきます。
※ブログ用にまったく別の構成にしています

メインシステムの構成#

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
多言語文書翻訳システム(ブログ用サンプル)
OCR + AI翻訳 + 辞書検索を統合した文書処理システム
"""
import os
import time
import logging
from typing import List, Dict, Any, Optional
from dataclasses import dataclass
import cv2
import numpy as np

@dataclass
class TranslationConfig:
    """翻訳システム設定"""
    use_gpu: bool = True
    gpu_memory: float = 0.8
    min_confidence: float = 0.7
    max_cpu_usage: int = 80
    supported_languages: List[str] = None
    
    def __post_init__(self):
        if self.supported_languages is None:
            self.supported_languages = ['ja', 'en', 'ko', 'zh']

class DocumentTranslationSystem:
    """多言語文書翻訳システム"""
    
    def __init__(self, config: TranslationConfig = None):
        self.config = config or TranslationConfig()
        self.ocr_engine = None
        self.translation_engine = None
        self.dictionary_engine = None
        self.initialize_components()
    
    def initialize_components(self):
        """システムコンポーネントの初期化"""
        try:
            # OCRエンジンの初期化
            from paddleocr import PaddleOCR
            self.ocr_engine = PaddleOCR(
                use_angle_cls=True,
                lang='japan',
                use_gpu=self.config.use_gpu,
                gpu_mem=self.config.gpu_memory,
                show_log=False
            )
            
            # 翻訳エンジンとカスタム辞書システムの初期化
            self.translation_engine = AITranslationEngine()
            self.dictionary_engine = CustomDictionaryEngine()
            
            logging.info("文書翻訳システム初期化完了")
        except Exception as e:
            logging.error(f"初期化エラー: {e}")
            raise
    
    def process_document(self, image_path: str) -> Dict[str, Any]:
        """
        文書処理メイン関数
        Args:
            image_path: 文書画像のパス
        Returns:
            Dict: 処理結果(OCR結果、翻訳、専門用語マッチング等)
        """
        try:
            # 1. 画像前処理
            processed_image = self.preprocess_image(image_path)
            
            # 2. OCR実行
            ocr_results = self.extract_text_with_confidence(processed_image)
            
            # 3. 専門用語の特定
            technical_terms = self.identify_technical_terms(ocr_results)
            
            # 4. 辞書検索による専門用語翻訳
            dict_translations = self.dictionary_engine.search_translations(technical_terms)
            
            # 5. AI翻訳(辞書で見つからなかった用語)
            ai_translations = self.translation_engine.translate_batch(
                [term for term in technical_terms if term not in dict_translations]
            )
            
            # 6. 結果統合
            final_result = self.merge_translation_results(
                ocr_results, dict_translations, ai_translations
            )
            
            return {
                'success': True,
                'original_text': ocr_results,
                'technical_terms': technical_terms,
                'dict_matches': len(dict_translations),
                'ai_translations': len(ai_translations),
                'final_translation': final_result,
                'processing_time': time.time()
            }
        except Exception as e:
            logging.error(f"文書処理エラー: {e}")
            return {'success': False, 'error': str(e)}

バッチ処理システム#

import asyncio
import concurrent.futures
from pathlib import Path

class BatchDocumentProcessor:
    """バッチ文書処理システム"""
    
    def __init__(self, max_workers: int = 4):
        self.max_workers = max_workers
        self.document_translator = DocumentTranslationSystem()
        self.results = []
    
    async def process_documents_batch(self, image_paths: List[str]) -> List[Dict[str, Any]]:
        """非同期バッチ処理"""
        semaphore = asyncio.Semaphore(self.max_workers)
        
        async def process_single(image_path: str) -> Dict[str, Any]:
            async with semaphore:
                return await self.process_document_async(image_path)
        
        # 全ての画像を並列処理
        tasks = [process_single(path) for path in image_paths]
        results = await asyncio.gather(*tasks, return_exceptions=True)
        
        # エラーハンドリング
        processed_results = []
        for i, result in enumerate(results):
            if isinstance(result, Exception):
                processed_results.append({
                    'image_path': image_paths[i],
                    'success': False,
                    'error': str(result)
                })
            else:
                processed_results.append(result)
        
        return processed_results

開発で苦労したポイント#

実際の開発では、チュートリアル通りにはいかない問題がたくさんありました。

1. GPU/CPU環境の違い#

def _detect_environment_and_init(self):
    """GPU/CPU環境を検出して最適な初期化を行う"""
    try:
        # RTX5000での動作確認
        if self._check_gpu_availability():
            self.ocr = PaddleOCR(use_gpu=True, gpu_mem=0.8)
        else:
            # CPUフォールバック(処理が激重)
            self.ocr = PaddleOCR(use_gpu=False)
        
        # Windows環境でのUTF-8問題
        if sys.platform.startswith('win'):
            # これを入れないと韓国語/中国語でクラッシュ
            os.environ['PYTHONIOENCODING'] = 'utf-8'
            if hasattr(sys.stdout, 'reconfigure'):
                sys.stdout.reconfigure(encoding='utf-8')

問題: ローカル環境のGPUで動作確認できても、本番環境で動かない
解決: 環境検出機能とCPUフォールバック機能を実装

2. メモリリークとの戦い#

def _reset_ocr_state(self):
    """同一ファイル再処理時にメモリリークするバグの回避"""
    try:
        # OCRインスタンスを一度削除
        if hasattr(self, 'ocr'):
            del self.ocr
        gc.collect()  # 強制ガベージコレクション
        
        # 再初期化(これをやらないと2回目で落ちる)
        self.ocr = PaddleOCR(use_angle_cls=True, lang='japan')
    except Exception as e:
        print(f"OCR再初期化失敗: {e}")

問題: 50枚処理でメモリ16GB消費、2回目実行でクラッシュ
解決: 明示的なメモリ解放とインスタンス再生成

3. 段階的翻訳検索システム#

def search_with_fallback(self, text: str):
    """段階的検索の閾値調整で1週間かかった"""
    
    # 完全一致(信頼度1.0)
    exact = self.exact_match(text)
    if exact:
        return exact
    
    # 高類似度(0.85以上)
    high_sim = self.vector_search(text, threshold=0.85)
    if high_sim:
        return high_sim
    
    # 中類似度(0.60以上)でユーザー確認
    mid_sim = self.vector_search(text, threshold=0.60)
    if mid_sim:
        return self.ask_user_confirmation(mid_sim)
    
    # AI翻訳へフォールバック
    return self.ai_translate(text)

問題: 閾値が高すぎると翻訳されない、低すぎると誤訳
解決: 段階的検索と人間の確認プロセスの導入

4. 多言語データの汚染問題#

def clean_language_contamination(self):
    """言語フィールドの汚染除去(これに3日かかった)"""
    contaminated = session.query(TermCode).filter(
        TermCode.japanese_name.contains('가'),  # ハングル検出
        TermCode.japanese_name.contains('나'),  # 他にも大量のパターン
    ).all()
    
    for record in contaminated:
        # 正しいフィールドに移動
        if self.is_korean(record.japanese_name):
            record.korean_name = record.japanese_name
            record.japanese_name = None

問題: 韓国語データが日本語フィールドに混入、翻訳精度が大幅低下
解決: データクリーニング処理とフィールド修正機能


学んだこと#

今回の開発で一番学んだのは、

「分からなくても、まず動かしてみること」
でした。

失敗しても、AIがヒントをくれる。
試してみれば、必ず次の一歩が見える。

「できない」と思っていたことが、
気づけば「できた」に変わる瞬間がある。
その経験が、今の自分の自信になっています。

技術的に学んだこと#

  1. 現実のシステム開発は想定外だらけ

    • ローカルで動いても本番で動かない
    • GPUありきの設計の落とし穴
    • ライブラリの隠れたバグとの戦い
  2. 多言語対応の複雑さ

    • 文字エンコーディングの闇
    • 言語判定の難しさ
    • データクリーニングの重要性
  3. AI/ML系システムの運用課題

    • モデル読み込み時間の不安定性
    • メモリリークとの戦い
    • フォールバック設計の重要性
  4. 段階的検索による翻訳システムの効果

    • 完全一致 → 類似度 → AI翻訳の流れ
    • 閾値調整の重要性
    • ユーザー修正の学習機能

最後に#

Python初心者の方へ伝えたいこと。
AIツールを使うのは「ズル」ではありません。
“効率的に学ぶ方法”のひとつです。

AIをうまく使えば、初心者でもプロジェクトを形にできます。
私も最初は右も左も分からない状態から始めました。
だからこそ、この記事が少しでも励みになれば嬉しいです。

実際のコードは、想定していたよりもずっと複雑で、
エラーハンドリングやフォールバック処理が大部分を占めていました。
でも、それこそが本当のシステム開発なのだと実感しています。


以上YAMAでした。