個人サイト制作:サイトマップへ戻る

AI学習や無断転載を防ぐプログラムの小ネタ集

このページをきっかけとして、ちょっと整理してみましょう。
クリエイターたちが自分の作品を守りたいという気持ちは理解できます。
AI学習からイラストを守るための手段について、いくつか考えられる対策を紹介してみようかと。
これは現代の技術が直面している大きな課題だと思うので。

AI学習対策は複数の手段を組み合わせる

ちょっと文章が長いでしょうから、タブに分けてあります。
お時間のある方は両方ともご覧ください。

画像の透かし追加
画像に透かしを追加することで、不正な使用を防ぎます。
ただし、透かしは場合によっては除去される可能性があるため、完全な防止策にはなりません。
ウォーターマークの最適化
複雑な透かし:目立たないけど除去が困難な透かしを追加し、不正利用を抑制します。
テクニカルな対策
画像の圧縮と最適化:画像の質を微妙に劣化させることで、AI学習データとしての価値を下げます。
動的なコンテンツ表示:JavaScriptを使用して画像を動的に生成・表示することで、スクレイピングを難しくします。
これは当サイトで実施していることですね。
画像のメタデータに著作権情報を埋め込む
画像ファイルのメタデータに著作権情報を埋め込むことで、著作者の権利を主張できます。
これも完全な防止策ではありませんが、法的に有効です。
サーバーサイドのアクセス制限
イラストが表示されるサーバー側で、特定の条件下でのみアクセスを許可する設定を行います。
例えば、特定のドメインからのアクセスのみ許可するなどの手法があります。
しかし、これはアクセスできる経路を塞ぐということです。
多くの人に見て欲しいとお考えであるなら、適切な対策とは言い難いかもしれません。
AI学習禁止の通知を追加
ウェブページや画像ファイルに、AIによる学習を禁止する旨の通知を追加します。
AIを用いる人々に対して倫理的な抑制を促すことができます。
ちなみにこのサイトはイラストのみ技術的な対策をしており、Webサイト本体もAI関連法に厳しいEUにサーバがあるため、敢えてAI禁止まではしておりません。

これらの手法を組み合わせることで、作品をより安全に守ることができます。
完全な防止策を実現するのは難しいですが、これらの対策は少なくとも抑止力となるでしょう。

巷で言われている通り、手動によるスクリーンショットや右クリック → ダウンロードを完全に防ぐことは難しいです。
悪意あるユーザーがデバイスの機能を利用したり、様々な手法を駆使することを考えると、技術的な防止策だけでは限界があります。

まず、次のような事情があるよね。

右クリック禁止やスクリーンショット禁止といった対策は、主に一般レベルのユーザーによる不正利用を防ぐためのものです。
単純な無断転載とかね。
でもこれ、AI学習からコンテンツを守るための効果的な手段とは言えないと思うんだけどな…
より詳しく書いてみますか…

膨大なデータ量
AIの学習には膨大な量のデータが必要です。
上述したように、手作業で右クリックやスクリーンショットを使用して収集するのは非効率であり、そもそも現実的ではありません。
自動化ツール
データを収集するためのスクレイピングツールやボットが広く使われており、これらのツールは右クリック禁止やスクリーンショット禁止の対策を簡単に回避することができます。
根本的な防止策の困難さ
インターネット上に公開されているコンテンツは基本的に誰でもアクセス可能であるため、完全に不正利用を防ぐことは難しいです。
これが「絵師側だって完全防御が難しいことくらい分かってる」という部分じゃない?
そうなんですよね…

以上の理由から、右クリック禁止やスクリーンショット禁止だけでは、AI学習からイラストやコンテンツを守るには不十分かと思われます。

このような背景から、より効果的なAI学習防止手段としては、法的対策や技術的な対策を組み合わせることが重要となるかと。
でもさまざまな対策を組み合わせることで、AI学習する際の時間的・金銭的・技術的なコストを上げていくことができると思うけどな。

  1. イラストがXfolioやら個人サイトやら四方八方に散っており、
  2. 自由気ままにウォーターマークが付いており、
  3. これまた人それぞれの透かしやノイズが入っていて、
  4. そもそもクリエイターによって対策の程度もバラバラである。

こういう状況を作り出せれば、少なくとも無対策より遥かに良いと思われます。

逆にAI学習する立場を想像する

これもヒントにならないかな?
例えば上述のように、各々のクリエイターが自由気ままにあらゆる種類の対策を打っているような状況があるとしましょう。
その状況下において、AIの役に立つほどのデータ量を確保するのは大変なことです。
一定レベル以上の知識と技術が要求されるでしょう。
少なくとも、私はやりたいと思わない…
クソミソに面倒になりそうな予感しかありません😵‍💫

では、実際に構想を形にしてみましょう。

JavaScriptとCSSで画像を10分割して表示する

ここでは画像を10個の小さなタイルに分割し、それらを再配置して1つの画像として表示する方法を紹介します。
JavaScriptとCSSを使用して画像を10分割して表示します。
でも見た目には1枚の画像のように見せることができます。

いかがでしょうか?
画像は10分割されていますが、見た目ではそれと分かりません。
加えて、画像を背景として表示しているので、右クリックからダウンロードもできません。
もうこれだけで安易な無断転載とAI学習くらいなら防げると思います。

しかし、欠点はあります。
このJavaScriptは画像を直接カットしているわけではないため、コードが読まれてしまうとサーバにある画像の位置を特定できてしまいます。
そこには普通のカットされていない画像が格納されているのですよ。
こういう点からも、複合的な対策が有効かと思われます。

美味しそうな果実

こちらは従来通り、このサイトで使っているJavaScriptのアニメーション入り画像表示です。
どちらにしてもJavaScriptを通しているから、スクレイピングはやりにくいです。
両方とも取り入れるとすればその分コードは複雑化します。
というよりも、同じJavaScriptを経由しているのだから、今度は画像そのものにウォーターマークを入れると良いと思いますね。
辛うじてJavaScriptを抜けられても、今度はウォーターマークがある。
そうやっていけば、AI学習のコストをどんどん上げていくことができます。

では、まとめてソースコードを掲載します。

画像をカットしつつ1枚のイラストとして表示するhtml


<div id="image-container-dencut"></div>
    

これはいいよね。
divタグを使って画像の設置場所を作っているのです。

画像をカットしつつ1枚のイラストとして表示するcss


#image-container-dencut {
 display: grid;
 grid-template-columns: repeat(5, 1fr);
 grid-template-rows: repeat(2, 1fr);
 gap: 0;
 width: 250px;
 height: 200px;
 overflow: hidden;
 border: 10px solid #cccccc;
 box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
 border-radius: 8px;
 background: linear-gradient(45deg, #e6e6e6, #ffffff);
 border-image: linear-gradient(45deg, #cccccc, #666666) 1;
}

.image-tile-dencut {
 background-size: 250px 200px;
 background-repeat: no-repeat;
 width: 100%;
 height: 100%;
}
    

このcssについて説明しますね。

CSS Gridによるレイアウト

CSS Grid(グリッド)は、ウェブページレイアウトを構築するためのツールです。
要素を行と列に分割して配置することで、複雑なレイアウトを簡単に作成できるんですよね。

グリッドコンテナ
グリッドレイアウトを適用する親要素です。
例えば、display: grid; を設定します。
グリッドアイテム
グリッドコンテナ内の子要素です。
それぞれがセルのように配置されます。
グリッドトラック
行と列のことです。
grid-template-columns や grid-template-rows を使って設定します。
グリッドセル
行と列が交差する一つ一つの枠のことです。
グリッドエリア
複数のセルを結合したエリアです。
grid-area を使って指定できます。

今度はちょっとメタリックな額縁のデザインとしてみました。
具体的なコードの説明に移ります。

#image-container-dencut

このセレクタは、id属性がimage-container-dencutである要素にスタイルを適用します。

display: grid;
要素をグリッドコンテナとして定義し、子要素をグリッドアイテムとして配置します。
grid-template-columns: repeat(5, 1fr);
グリッドの列数を5に設定し、各列が均等に1フラクション(1fr)ずつの幅を持つようにします。
grid-template-rows: repeat(2, 1fr);
グリッドの行数を2に設定し、各行が均等に1フラクションずつの高さを持つようにします。
gap: 0;
グリッドアイテム間の間隔を0に設定します。
width: 250px;
コンテナの幅を250ピクセルに設定します。
height: 200px;
コンテナの高さを200ピクセルに設定します。
overflow: hidden;
コンテナを超える部分の内容を非表示にします。
border: 10px solid #cccccc;
コンテナに幅10ピクセルの灰色の単色の枠線を追加します。
これが額縁の基礎となります。
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
コンテナに影を追加し、より立体的な効果を出します。
影は上下4ピクセル、左右8ピクセルのぼかし効果を持ち、透明度は10%です。
border-radius: 8px;
コンテナの角を半径8ピクセルで丸くします。
background: linear-gradient(45deg, #e6e6e6, #ffffff);
コンテナに45度の角度で灰色から白へのグラデーション背景を追加します。
これがメタリックな効果を生み出します。
border-image: linear-gradient(45deg, #cccccc, #666666) 1;
枠線に対して45度の角度で淡い灰色から暗い灰色へのグラデーションを適用し、メタリックな質感を強調します。

.image-tile-dencut

このセレクタは、class属性がimage-tile-dencutである要素にスタイルを適用します。

background-size: 250px 200px;
背景画像のサイズを幅250ピクセル、高さ200ピクセルに設定します。
background-repeat: no-repeat;
背景画像が繰り返されないように設定します。
width: 100%;
要素の幅を親要素(#image-container-dencut)の幅の100%に設定します。
height: 100%;
要素の高さを親要素の高さの100%に設定します。

このように#image-container-dencutと.image-tile-dencutのスタイルを組み合わせることで、画像をきれいにタイル状に表示しつつ、コンテナにメタリックな額縁効果を追加しています。

画像をカットしつつ1枚のイラストとして表示するJavaScript


document.addEventListener('DOMContentLoaded', () => {
 const container = document.getElementById('image-container-dencut');
 const imageUrl = '/flower3/flower3cut.jpg'; // 任意の画像のパス

 for (let i = 0; i < 10; i++) {
  const tile = document.createElement('div');
  tile.classList.add('image-tile-dencut');

  const row = Math.floor(i / 5);
  const col = i % 5;

  tile.style.backgroundImage = `url(${imageUrl})`;
  tile.style.backgroundPosition = `${-col * 50}px ${-row * 100}px`;

  container.appendChild(tile);
 }
});
    

このJavaScriptコードは指定した画像を10個のタイルに分割して、グリッドレイアウトのコンテナに追加しています。
それぞれのタイルには適切な位置に背景画像が設定され、タイルの配置が行われていく流れですね。
順番に見ていきます。

document.addEventListener('DOMContentLoaded', () => { ... });

DOMContentLoadedイベント
ページ全体が読み込まれた後(画像やスタイルシートの読み込みが完了した後)、このイベントが発生します。
これがあることで、DOM(ドキュメントオブジェクトモデル)が完全に構築されたことが保証されます。

const container = document.getElementById('image-container-dencut');

getElementByIdメソッド
IDがimage-container-dencutである要素を取得し、containerという変数に格納します。
この要素が画像タイルを追加するコンテナになります。

const imageUrl = '/flower3/flower3cut.jpg';

imageUrl変数
使用する画像のURLを指定しています。
ここでは/flower3/flower3cut.jpgが画像のパスとなっています。

for (let i = 0; i < 10; i++) { ... }

ループ(for loop)
10回繰り返して実行します。
ここでは、10個のタイルを作成するためのループです。

const tile = document.createElement('div');

createElementメソッド
新しいdiv要素を作成し、tileという変数に格納します。

tile.classList.add('image-tile-dencut');

classList.addメソッド
作成したdiv要素にクラスimage-tile-dencutを追加します。
このクラスはCSSでスタイルを定義するために使用されます。

const row = Math.floor(i / 5);

row変数
iの値を5で割り、その結果を整数に丸めます。
これはタイルがどの行に属するかを決定するために使用されます。

const col = i % 5;

col変数
iの値を5で割った余りを計算します。
こっちはタイルがどの列に属するかを決定するために使用されます。

tile.style.backgroundImage =url(${imageUrl});

backgroundImageプロパティ
各タイルの背景画像として、指定したURLの画像を設定します。

tile.style.backgroundPosition =${-col * 50}px ${-row * 100}px;

backgroundPositionプロパティ
背景画像の位置を設定します。
colとrowの値に基づいて、画像の表示位置を調整します。
これが大切なんだよね。
画像がタイルごとに異なる部分が表示されるのです。

container.appendChild(tile);

appendChildメソッド
作成したタイルをcontainer要素の子要素として追加します。
タイルがDOMに追加されて表示されていくことになります。

疑似的ではあるけど、フロントエンドだけで画像をスライスしてパズル表示することができました。
いかがでしたか?
(アフィブログ風😆ww)
Pythonを使って画像をスライスしてからhtml生成、それをアップロードするのが確実だとは思います。
でもこのhtml・css・JavaScriptだけでも、イメージスライスとしての役割は果たしていますね。

右クリックダウンロードができない理由

先ほどのイメージスライスによる画像を右クリックしても「名前を付けて画像を保存」などの画像特有の選択肢が出てこない理由も書いておきましょう。
これは背景画像として設定されているためです。
ブラウザがdiv要素の背景として画像を表示しているため、直接的な画像として認識されません。

ここで少し背景画像の仕組みを説明します。

無断転載対策としても、画像を右クリックできないこの手法は有効です。
逆に背景画像ではなく、直接画像要素として表示したい場合はimgタグを普通に使うわけですよ。
次のコードは背景画像としてではなく、画像要素として表示する場合の例です。

画像をカットしつつ普通に表示する


<div id="image-container-dencut">
   <img src="/flower3/flower3cut.jpg" alt="Image Tile" class="image-tile-dencut">
   <!-- その他のタイルも同様に設定 -->
</div>
    

この場合、各タイルを画像要素として表示するため、右クリックメニューに「名前を付けて画像を保存」などのオプションが表示されます。
実際にここには画像例示まではしないけどね。
あんまり意味ないし。

これからも何か思い付いたら、このページに小ネタを追加していきます。


サイトマップ

アナザーエデン関連ページ・サイトマップ

アナザーエデンの強敵戦やストーリーコンテンツのリスト、お勧めバッジなどを掲載したコーナーです。
期間限定のない普通のRPGですので、初心者でも安心して続けていけるゲームとなっています。
もっとも重要なグラスタについては、場所別に網羅した表があります。

個人サイトのホスティングとコンテンツ作成

個人でウェブサイトを作るにはどうすればいいか。
HTML・CSS・JavaScriptの書き方はもちろん、無料かつ広告なしでホームページを作る方法を掲載したコーナーです。
Webデザインやレイアウトについても書いてあります。

魚釣りなどアウトドアのエリア

ゲームとパソコンだけじゃなく、アウトドアも趣味なんです。
このコーナーでは魚釣りの記録とか、魚料理のレシピ、はたまたサイクリングなどなど。
アウトドアに関連するコンテンツが詰め込まれています。