LoginSignup
20
4

More than 1 year has passed since last update.

UnityでTextureに目で見えないウォーターマークを埋め込んでみる

Posted at

はじめに

こんにちは、QualiArts Advent Calendar 2022、12日目の記事になります。
本日はUnityの環境において、Textureに目で見えないウォーターマークを埋め込む実験について書きます。
実装例は https://github.com/thammin/unity-texture-watermark に上げています。

環境:
Unity 2021.3.0f1

ウォーターマーク(電子透かし)

主に、画像ファイルの著作権の保護などの目的に使われています。
今回はQRコードを埋め込んだらどうなるかを試していきます。

picture1

実現の方法は様々ですが、その中に元画像のピクセルにデータを埋め込む手法があります。
処理後の画像は、jpeg変換などによって発生するデータロスもある程度回復できるように、今回はウェーブレット変換離散コサイン変換を利用して埋め込みます。

アルゴリズムのフローは下記を参考しました。
https://github.com/mchall/HiddenWatermark
https://github.com/ShieldMnt/invisible-watermark
https://github.com/accord-net/framework

ウェーブレット変換の概要

Jpeg2000_2-level_wavelet_transform-lichtenstein.png

ウェーブレット変換は、画像の色を隣接した値の差分と和を求めて、再帰的に行うと上記の画像1のようになります。

DWT 2 interations

LL = 横 Low 周波数 + 縦 Low 周波数
LH = 横 Low 周波数 + 縦 High 周波数
HL = 横 High 周波数 + 縦 Low 周波数
HH = 横 High 周波数 + 縦 High 周波数

左上の画像は横と縦の低い周波数で構成されています。
今回はウェーブレット変換を2回行った、LL2のところにデータを埋め込みます。

離散コサイン変換

DCT

離散コサイン変換は、上記の画像2のように離散信号を周波数領域へ変換する方法の一つであります。
特徴として、パーワーのほとんどが左上の低い周波数領域に集中します。
今回はウェーブレット変換した画像をさらにブロックを分割して、離散コサイン変換された後の真ん中にデータを埋め込みます。

全体的な処理順

前提:
・対象画像(1024x1024)
・ウェーターマーク画像(64x64)
・作業用の色配列(1024x1024)

エンコード順:

  1. 作業用の色配列をYuvに変換
  2. 作業用の色配列をウェーブレット変換を2回行なって、LL2の領域を抽出する
  3. ウェーターマーク画像のピクセル毎に、LL2の領域からさらにブロック(4x4)を切り出して、離散コサイン変換を行う
  4. ブロックの中間領域にウェーターマークのピクセルを埋め込む
    埋め込み方法:白ならデータを正方面に増幅、黒ならデータを負方面に増幅
  5. 逆離散コサイン変換を行う
  6. 逆ウェーブレット変換を2回行う
  7. 作業用の色配列をRgbに変換
  8. 対象画像に作業用のRgbに変換されたデータを加算する

デコード順:

  1. 対象画像をYuvに変換
  2. 対象画像をウェーブレット変換を2回行って、LL2の領域を抽出する
  3. LL2の領域から順番にブロック(4x4)を切り出して、離散コサイン変換を行う
  4. ブロック中間領域からデータを判定する
    判定方法:データが0以上なら白、以下なら黒
  5. 判定したデータを画像として書き出す

上記の実装はこちらで確認できます。
https://github.com/thammin/unity-texture-watermark/blob/master/Assets/Watermark.cs

Unity上の実行例

Unity
INPUT = 元画像
OUTPUT = 埋め込んだ後の画像
WATERMARK = 埋め込みたいQRコード画像
EMBED WATERMARK = INPUTに加算するデータ(可視化のためにグレースケール調整入っています)
RECOVERED WATERMARK = 埋め込んだ後の画像から抽出したQRコード画像

実際に実行したら、肉眼でOUTPUT画像から大きいの変更がない事を確認できて、
QRコードも無事に抽出できました。

試しにOUTPUTをJPEG変換して、抽出できるかも確認しましょう

outputTexture.EncodeToJPG(jpegQuality);

Screen Shot 2022-12-12 at 19.33.12.png

Quality 15まで落とすと、ノイズが増えてきたのも確認できました。

結論

なんで画像にQRコードを見えないように埋め込むのはさておき、
ウェーブレット変換と離散コサイン変換を利用することで、
ある程度の画質が落とされても復帰できる事を確認できました。

以上、12日目の記事でした。引き続き今後のカレンダー投稿を宜しくお願いします。

  1. By Alessio Damato - Own work, CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=2118889

  2. Alessio Damato - I made it by myself, CC 表示-継承 3.0, https://commons.wikimedia.org/w/index.php?curid=781346による

20
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
4