Algorithm & UI/UX
浮世絵風の見た目を作る、暗い領域の抽出と紙の質感の合成
写真の暗い画素を墨色へ置き換え、紙色と粒子を重ねて浮世絵風の見た目を作ります。輪郭だけの線画抽出ではない点と、色・しきい値・紙の模様が出力へどう作用するかを解説します。
このツールの入力から出力まで
現行コードの確認日:
- 入力
- 写真を選び、色や輪郭の加工の強さを調整します。
- 処理
- 写真の暗い領域をしきい値で選び、指定した墨色と紙色を重ねて浮世絵風の静止画を作ります。
- 出力
- 入力は長辺 1500px 以下に縮小し、800×800px の紙面に写真をズーム・移動して JPEG(品質指定 0.85)で保存します。
まず確認する点:新しい絵を生成する処理ではありません。元の構図が残ることと、細かな模様の省略を見比べます。
仕上がりの例
写真を色数を抑えた浮世絵・役者絵風にした例です。
掲載画像はサイトにある既存の公開作例です。保存済みの資料では運営者の愛猫の写真を使用しています。今回の確認日が、この作例を実行した日を表すわけではありません。
保存済み検証記録の条件を見る
資料の種類は「ツールの出力画像を保存した記録」です。公開作例と保存済み記録で素材や色などが異なる場合があるため、下の数値は保存済み検証記録の条件として読んでください。
- 記録の入力画像
- 800×1066px (JPEG)
- 記録の出力画像
- 800×800px (JPEG)
| 画面の項目 | 記録の値 | 現行コードの初期値・範囲 |
|---|---|---|
| 記録で選択されていた項目 | 墨色、単色 | — |
| 線の強さ | 128 | 初期値 128 / 範囲 50〜200 |
| 和紙の濃さ | 30 | 初期値 30 / 範囲 0〜100 |
| 写真のズーム | 100 | 初期値 100 / 範囲 50〜300 |
記録では「これで完成!」から完成表示へ進んでいます。初期値と記録値を比べてから、効果を1項目ずつ変えると作用を確認しやすくなります。
資料ファイルの作成日は実行日として扱っていません。個別端末の処理速度や、ほかの写真に対する検出・加工の精度を測定した資料でもありません。
実装の確認箇所:src/pages/image/ukiyo-e/index.astro。以下のコード抜粋と出力条件は、この本番実装に基づいて説明します。
仕組みを読み進めるときは、Canvas APIと画像処理(画像寸法、drawImage、画素と透明度の扱い)、メモリ管理と画像処理(画素バッファ、縮小と容量予算)が参考になります。
1. 明るさのしきい値による墨色の領域抽出
本ツールでは、CanvasのgetImageDataを使用して各画素のRGBの単純平均を計算し、指定したしきい値に基づいて「墨色にする暗い領域」か「下地」かを判別します。隣り合う画素の差から輪郭を検出する方式ではありません。
選ばれた暗い領域へ「和の色(墨、藍、臙脂)」を割り当てます。髪や服の影のような面も対象になり、しきい値を上げるほど墨色になる範囲が増えます。
暗い画素を墨色にする判定です。隣の画素との差は使わないため、輪郭だけでなく暗い面も選ばれます。
function isInkRegion(r, g, b, threshold = 128) {
return (r + g + b) / 3 < threshold;
} 2. 錦絵の「多色摺り」を模したハイブリッド・レンダリング
フルカラーモードでは、現代的な写真をそのまま表示するのではなく、一度「下絵」として淡く描画した上に、抽出した「主線」を重ねるスタック構造をとっています。
これにより、写真のディテールを活かしつつ、木版を重ねて刷り上げる錦絵(多色摺り)のような質感をシミュレートしています。globalAlphaを調整し、下絵の色をあえて「沈ませる」ことで、デジタルの鮮やかすぎる発色を抑え、日本画特有の落ち着いたトーンを作り出しています。
3. 演算負荷を抑えた「疑似和紙テクスチャ」生成エンジン
和紙の繊維感を表現するために重い画像アセットを読み込むのではなく、実行時にCanvas上で直接ノイズを生成するハックを採用しています。
Math.random()を利用して微細な矩形を15,000 回描画し、生成り色の背景に重ねることで、紙の「ざらつき」と「温かみ」を再現。外部通信を発生させず、矩形の描画で紙のざらつきを表現します。処理時間の実測値を示すものではありません。
出力の仕様と確認する点
輪郭を細い線として検出する処理ではありません。しきい値 50〜200 を上げるほど、影・髪・服などの暗い領域が広く墨色になります。墨色は墨・藍・臙脂などから選びます。
フルカラーでは写真を透明度 0.6 で下地に描いてから暗い領域を重ねます。紙の質感はランダムな小矩形で、再描画のたびに配置が変わります。AI による絵の生成や木版の分版は行いません。
入力は長辺 1500px 以下に縮小し、800×800px の紙面に写真をズーム・移動して JPEG(品質指定 0.85)で保存します。写真を枠外へ動かすと透明領域の RGB が暗い領域として扱われる場合があるため、余白も確認します。
