あとがき

https://github.com/kainasubi1230/atogaki.git

Next.js

GitHub

Python

Docker

PostgreSQL

自分の字に自信がなくても、タイピングで「手書き」を届けるシステム

anji

しゃちょー

推しアイデア

このプロダクトの「デジタルの中に消えてしまった "手書きの温もり" を取り戻す」というテーマそのもの!

作った背景

タイピングで自分仕様の「手書き」の文章が出力できたら便利じゃね!?

推し技術

写真1枚から、文字をバラバラにして自動ラベリング。そして、そこからの「文字出力」

プロジェクト詳細

📨 あとがき 〜技術が繋ぐ温もり〜

「タイピングで自分仕様の手書き文章が出力できたら便利じゃね!?」 そんな純粋なワクワクと、デジタルの中に消えてしまった「手書きの温もり」を取り戻したいという想いから始まったプロダクトです。

僕たちは、今回のテーマである「うん」を、否定の接頭辞である「un」と受け取りました。デジタル化によって消えつつある、文字としては書かれていない温かみ、つまり「unwrittenな温もり」を届けるシステム。それがこの『あとがき』です。


📃 参考資料

image 堀川の実際「こんにちは」⬆︎ (「こ」の一画目が下に向いてるのが特徴)

image 堀川の「こんにちは」の出力 ⬆︎


🛠️ 主要機能

① 1枚スキャンで文字登録

自分の字が書いてある写真を1枚アップロードするだけで、OpenCVとPILが走り、文字をバラバラに切り出して自動で『あ・い・う…』とラベリングします。

② 「その人らしさ」を再現するAI学習

事前学習したベースモデルに対し、ユーザーの筆跡だけをLoRAで追加学習させ、独自の書き癖を再現しています。

③ 毎回ちょっと違う字が出る「人間らしいゆらぎ」

既存の手書き風フォントのように同じ文字が綺麗に並ぶ違和感を排除。Chaikinの平滑化アルゴリズムと幾何学的なノイズを加えることで、同じ文字を打っても毎回微妙に形や傾きが変わる「人間らしい自然なゆらぎ」を再現しています。

④ テキストを自由に変形・配置できるキャンバス画面

  • キャンバス操作: 複数選択、移動・回転・リサイズ、図形描画、文字のカスタマイズ(間隔・行間・配色)。
  • 用紙設定:背景スタイル選択(無地・ノート・方眼紙など)、キャンバスの縦向き/横向き切り替え。
  • 出力:PNG/SVG形式でのエクスポートが可能。

⚙️ システムについて

技術スタック

  • フロントエンド:Next.js, React (TypeScript) / Vanilla CSS (カスタムCSS)
  • バックエンド:FastAPI (Python 3.11)
  • AI / 機械学習:PyTorch (LoRAによる個別筆跡追加学習)
  • タスクキュー / 非同期処理:Redis Queue
  • データベース / ストレージ:PostgreSQL / MinIO (S3互換ストレージ)

アーキテクチャ

image

バックエンド

機械学習

1,インターネットからひらがな・カタカナ・常用漢字・英数字の手書き文字を合計約200000文字jsonlファイルに取り込む。 0.0000001単位まで座標化して点の並びにして取り込んでいる。⤴︎ 2,そこから機械学習を回して要素を数値化して抽出する。 3,ユーザーの手書き文字の画像からOpenCVと動的計画法(DP)を用いながら一文字ずつグリッドで切り抜き、それぞれからユーザーの文字の癖を要素化して抽出する。(転移学習)

要素の抽出

・ 文字ごとの領域(BBox) 1文字ずつの大きさや縦横比、全体の傾きを割り出し、文字が収まるサイズを測る。 ・ ストローク軌跡(Trajectory) x, y: 小数点精度の位置座標。 t: 筆記の順序を示すタイムステップ。 pen_state: 筆記中(down)か、次の線へ空中移動中(up)か。 width: 筆圧や線の太さ。 ・ 筆跡のメタデータ 運筆の速度。(点の密度変化) 筆記の曲率。(角の曲がり具合や折れ方の強さ) ベースモデルの基準太さに対するユーザーの線の太さ比率。

フロントエンド

要素の一元管理(データ構造)

キャンバス上のテキスト、手書き文字(SVG)、図形などはすべて、items という1つの配列で管理しています。 最初はただのテキスト(textarea)として表示し、AIの変換が終わったら、取得したSVGのパスデータに解析し直して同じ場所に差し替えることで、スムーズな画面切り替えを実現しています。

直感的なドラッグ・回転操作

要素の移動やサイズ変更、回転といった操作は、useCanvasInteraction.ts という独自のカスタムフックにまとめています。 画面を拡大・縮小(ズーム)しているときでも、マウスの移動量と現在のズーム倍率を計算に掛け合わせることで、「ズームしていてもズレずに、吸い付くように動く操作感」を作りました。


✨ 推しアイデア と 推し技術

・ 推しアイデア

1. プロダクトテーマ  現代のテキストコミュニケーションは便利ですが、文字が持つ「個性」や「温もり」が失われてしまいました。 本プロダクトの、タイピングでありながら自分らしい手書き文字を届けられる——この体験そのものが、僕たちの最大の推しアイデアです。

2. 遊び心と風情ある技術の無駄遣い  AIの追加学習や文字変換には、どうしても 待ち時間 が発生します。僕たちは、そこに "風情あるモーション" や "隠しエフェクト" を仕込みました。  一見すると「なくても困らない機能」かもしれません。でも、デジタルに温もりを宿すプロダクトだからこそ、待ち時間すら心地よい体験に変える。そんな遊び心を僕たちは大切にしました。

・ 推し技術

転移学習(LoRA)の活用  ベースとなる強力な生成モデルに対して「転移学習」を行うことで、大量のデータや膨大な計算リソースを必要とせず、1枚の写真だけで、個人のクセを捉えた手書き風文字の出力を可能にしました。


👥 開発チーム:aplicalm

僕たちは 久留米高専 制御情報工学科の2年生 2人 によるチームです。 「技術で心地よい平穏(Calm)を届ける」をモットーに、アプリケーションを中心として、技術力と執念を詰め込んで開発をしています。

💻 [堀川 海凪 / しゃちょー]

  • 所属: 久留米高専 制御情報工学科 2年
  • 担当: 全体アーキテクチャ設計、バックエンド、AI学習ロジック構築
  • 一言: 「本日寝坊してバスに乗れませんでした。よろしくお願いします!」

🎨 [田中 杏治 / anji]

  • 所属: 久留米高専 制御情報工学科 2年
  • 担当: フロントエンド、UI/UXデザイン、プレゼン準備
  • 一言: 「相方には助けてもらってばっかりですが、お互いカバーし合いながら全力で頑張りたいです。よろしくお願いします!」

☕️ 『あとがき』を作ってみての感想

🪾「ブランチを切ろう!」

今回は2人の役割分担がはっきりしていたため、幸いにもコンフリクトを起こさずに開発を終えることができました。 しかし、1つのブランチにコミットが集中したことで、Gitの履歴が汚くなってしまったのは反省点です。 「動けばいい」で終わらせず、後から見返しても綺麗な、誰にとっても読みやすい開発履歴を残せてこそ一人前の開発者… この反省を生かし、チームのクオリティをもう一段階引き上げていきたいです。

👁️「もっと広い視点」

自分たちだけで画面に向き合っていると、どうしても「この機能をどう実装するか」「バグをどう直すか」という"開発"に集中してしまいがちでした。開発中、多くのメンターさんからアドバイスをいただく機会があり、様々な「面白いプロダクトの広げ方」を頂きました。 これからの開発では、メンターさん方のような広い視点でプロダクトを改良できるようになりたいです。

🎉 最後に

久留米高専の同級生2人で挑んだ今回のハッカソン。 デジタルな文字に温もりを宿す『あとがき』というテーマに向き合い、全力を注いだ2日間でした。 機械学習を使ったプロダクトへの挑戦でしたが、自分たちも作っていてとても楽しかったので、ここで終わりにせずドンドン進化させていきたいと思っています。 アドバイスをくださったメンターの皆様、そしてこのプロダクトに触れてくれた全ての方に、心から感謝を申し上げます。ありがとうございました!m(_ _)m


🍜 おかわりハッカソン

お久しぶりです!Aplicalmの田中です! 進捗が "タブン" 出来ましたので報告させていただきます!

📈 手書き文字生成の精度向上について

① 高精度な文字切り出し

まず最初に行ったのが、手書き文字を一文字ずつ正確に切り出せるようにすることです。 初期段階では、 ・「し」と「す」が一つの文字として結合される。 ・「う」の点だけが別文字として認識される。 ・「に」が隣の「な」の一部を取り込む。 ・列が一つずれてラベリングされる。 など、多くの問題が発生しました。

そこで、 ・Connected Component のマージ条件の見直し ・Y方向の重なり率を利用したマージ判定 ・幅が異常に大きい候補の再分割 ・DP Matching に文字間隔ペナルティを追加 ・EMPTYセルのスキップ抑制 などの改善を行った。

その結果、文字の切り出し精度が向上しました。 (まだ、サンプルによってはうまく行かないことも…)

② 手書き特徴量の抽出

次に、画像から文字の特徴量の抽出精度を上げました。 画像解析を利用し、 ・平均線幅 ・線幅のばらつき ・傾き ・縦横比 ・重心位置 ・ベースライン位置 ・丸み などの特徴量の取得方法を見直しました。

③ フォントではなく"筆跡"を学習する仕組み

最も大きな改善点は、文字を変形する考え方を変更したことです。 元々のやり方では、基本データの影響が強く残り、全体的に綺麗すぎる文字になっていました。

そこで処理を段階化し、 Base Font ↓ Global Style (その人全体の特徴を反映する) ↓ Character Correction (文字ごとの癖を反映する。) ↓ Stroke Correction (一画ごとの特徴を反映する。) ↓ Stroke Shape (各画を一定間隔でサンプリングし、軌跡そのものの違いを学習する。) ↓ Stroke Dynamics (書く速さ、線幅変化、払い、止め などを利用する。) ↓ LoRA (最後にLoRAで細かなクセだけを学習する。)

のように、LoRAが文字全体を変形するのではなく、「最後の仕上げ」を担当する構成に変更した。

④ ベースフォント依存の低減

それでもまだ、生成された文字が既存フォントに非常に似てしまうという問題がありました。 そこで、 ・モーフィング時の補正係数を見直す ・ベースフォントへの引き寄せを弱める ・ユーザー文字の骨格を優先する ように変更しました。 これにより、よりユーザー自身の筆跡に近づけることができました。

💡 今後の課題

今回は、「ひらがな」に大賞を絞り精度を上げてきたので、「カタカナ」「漢字」の精度も上げていきたいです。 また、サンプルによってはうまく出力されないケースも確認しているので、そこも修正していきたいと思っています。

今後も開発を続けて、実用化まで持っていきたいです。 以上 Aplicalm の「あとがき」でした!m(_ _)m

・動画内で使用したサンプル ( 切り出しの改善途中の写真 ) image ・崩し度低め文字 image ・崩し度高め文字 image

anji

@a2a2eaff882feceb