1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

VSS (Visual Secret Sharing)の実装と出力(OHP&レーザー彫刻)

Posted at

はじめに

2 out of 2 VSSのプログラム例と出力例(OHP&レーザー彫刻)について紹介します。
VSSはVisual Secret Sharingの略で、日本語にすれば視覚秘密分散です。
2 out of 2は2枚のノイズに見える画像を重ねることで、1つの意味ある画像が見えることを意味します。
他に、3枚の画像のうち全部揃わないと見えないとか、2枚揃えば見えるとか、複数のバリエーションがあります。

環境

Processing 4
xtools Creative Space
レーザープリンタ
A4 OHPシート

手順

まず、適当に画像を用意します。
ここでは、
・サイズ:100x20ピクセル
・白地に黒文字
・2値化画像
を用意しました。
2値化はプログラム内でやってもいいと思いますが、念の為、手作業で。
Hextomino.png

これを下記プログラムに通します。

Processing
void setup() {
  size(800, 600);
  background(0);

  PImage in = loadImage("Hextomino.png");// 入力画像

  int blockSize = 2; //各ピクセルを 2x2 に拡大してパターンを埋め込む
  PImage[] out = generateVSSout(in, blockSize);

  //2画像の保存
  out[0].save("out1.png");
  out[1].save("out2.png");

  // 表示(4倍に拡大)
  scale(4, 4);
  noSmooth();
  image(out[0], 0, 0);
  image(out[1], 0, 50);

  image(out[0], 0, 100);
  blendMode(ADD);
  image(out[1], 0, 100);
  
  // 保存(4倍に拡大)
  PImage i = get(0, 0, in.width * 2 * 4, in.height * 2 * 4);
  PImage j = get(0, 50*4, in.width * 2 * 4, in.height * 2 * 4);
  PImage k = get(0, 100*4, in.width * 2 * 4, in.height * 2 * 4);
  i.save("out1x4.png");
  j.save("out2x4.png");
  k.save("blend_x4.png");
}

/**
 * 2値の視覚秘密分散(2-out-of-2)を行う関数。
 * 入力画像in(白背景に黒文字)を読み取り、2つのシェア(PImage)を返す。
 * blockSizeは1画素を何倍に拡大してパターンを割り当てるかの指定。
 */
PImage[] generateVSSout(PImage img, int blockSize) {

  // 元画像の幅・高さ
  int w = img.width;
  int h = img.height;

  img.loadPixels();

  // シェア画像は (w * blockSize, h * blockSize) サイズ
  PImage s1 = createImage(w * blockSize, h * blockSize, RGB);
  PImage s2 = createImage(w * blockSize, h * blockSize, RGB);
  s1.loadPixels();
  s2.loadPixels();

  // 2x2パターン用の座標定義(例)
  //   黒画素のとき: 同パターン(A,A or B,B) → 重なると真っ黒
  //   白画素のとき: 異なるパターン(A,B) → 重なりがずれて白っぽく見える
  int[][] patternA = { {0, 0}, {1, 1} };
  int[][] patternB = { {0, 1}, {1, 0} };

  // 全ピクセルを白にする
  for (int i = 0; i < s1.pixels.length; i++) {
    s1.pixels[i] = color(255);
    s2.pixels[i] = color(255);
  }

  for (int y = 0; y < h; y++) {
    for (int x = 0; x < w; x++) {
      // in 画像の (x, y) のピクセルの赤成分を取得
      float r = red(img.pixels[y * w + x]);

      // r < 128 を「黒画素」とみなす(適宜調整)
      boolean isBlack = (r < 128);

      int[][] p1, p2;
      if (isBlack) {
        // 黒画素 → 同じパターンを両方のシェアに
        if (random(1) < 0.5) {
          p1 = patternA;
          p2 = patternA;
        } else {
          p1 = patternB;
          p2 = patternB;
        }
      } else {
        // 白画素 → 異なるパターンをシェアに
        if (random(1) < 0.5) {
          p1 = patternA;
          p2 = patternB;
        } else {
          p1 = patternB;
          p2 = patternA;
        }
      }

      // out画像に書き込む先頭ブロック座標
      int bx = x * blockSize;
      int by = y * blockSize;

      // s1 にパターン p1 を書き込み
      for (int[] coord : p1) {
        int dx = coord[0];
        int dy = coord[1];
        int index = (by + dy) * s1.width + (bx + dx);
        s1.pixels[index] = color(0); // 黒
      }
      // s2 にパターン p2 を書き込み
      for (int[] coord : p2) {
        int dx = coord[0];
        int dy = coord[1];
        int index = (by + dy) * s2.width + (bx + dx);
        s2.pixels[index] = color(0); // 黒
      }
    }
  }


  s1.updatePixels();
  s2.updatePixels();

  return new PImage[] { s1, s2 };
}

出力結果

乱数要素があるので、あくまで例です。
実行すると、まず、入力画像の縦横2倍(200x40)の画像が2種類出力されます。
out1.png
out2.png

これは、1ピクセル単位で、なかなか扱いが不便なこともあるので、
エッジをぼかさずに4倍して出力し直します。
(Qiitaの仕組み上、この記事の画像ではボケてるかもしれません)
out1x4.png
out2x4.png

この2画像を重ねると(プログラム上ではBLEND ADD)元画像が見えてきます。
blend_x4.png

レーザー彫刻

使用機材は、
xTool D1Pro 10W
素材はダイソーの黒い名刺ケース。
画像を読み込んで、レーザーでアルミの黒塗装をはがしてくれる。
名刺サイズで30~40分。遅!

【設定】
「out1x4.png」は白黒反転させずに、デフォルトのまま。
画像の黒部分が、レーザー発振して、アルミ塗装がはがれるので、
結果的に、データの黒がシルバーに、データの白がブラックになります。
・幅を910mmに。
・素材をMetal Cardにした。
・ビットマップモードをSierraに変更。
・彫刻密度はMaxの260に変更。

ビットマップモードについてはよくわかりませんが、設定後にシミュレーション画像が出て、一番マシに感じました。色勾配のある部分では、自動的にレーザーの線が入るようなのですが、これを無効にできませんでした&調べる時間がありませんでした。

※印刷が途中で止まりました。原因不明です。もしかしたら、このような模様(空間周波数が高い)は、想定外で、エッジのトレースとかで、メモリがパンクしているのかもしれません。

image.png

image.png

OHP印刷

「out2x4.png」を幅を910mmでOHPに印刷します。
白は、透明になり、
黒は、黒になります。

理論的には、これでうまくいくはずですが、OHPシートがレーザープリンタの熱で、若干、伸縮します。
なので、91.1mmとか、若干伸ばしたほうが、いいかもしれません。

結果

やってみないと、わからないですが、2枚をピッタリ重ねるのは難しいです。
コンピュータなら楽ですが、
物理的に重ねる場合、回転も合わせる必要があるので、想像以上にシビアです。
合わせ方が悪いのか、印刷の大きさが悪いのか、ある程度、試行錯誤が必要です。
OHPシートもったいないので、スケール違いを複数並べて、いっぺんに印刷して、合成がいい感じのものだけを選抜したほうが、楽です。

OHPとOHPなら、伸縮率同じだから、もう少し楽でしょう。

用語

日本語 英語
視覚暗号 Visual Cryptography VC
視覚暗号法 Visual Cryptography Scheme VCS
(カラー白黒VSC) Colored Black and White VCS CBW-VCS
(視覚秘密分散) Visual Secret Sharing VSS
- Progressive Visual Secret Sharing PVSS
視覚復号型秘密分散法 Visual Secret Sharing Scheme VSSS

日本語ではVSSSがHitしますが、英語文献ではVSSが一般的と思います。

参考サイト

Youtube「視覚復号型秘密分散」を使って、色んなネタを作ってみた

Contrast-Enhanced Color Visual Cryptography for (k, n) Threshold Schemes

岩本・渡邉研究室の解説ページ

マウス操作で体験できる

入力画像から、音声の周波数分析結果が元の画像になるような音声生成が面白い。

1
0
1

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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?