はじめに
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値化はプログラム内でやってもいいと思いますが、念の為、手作業で。
これを下記プログラムに通します。
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種類出力されます。
これは、1ピクセル単位で、なかなか扱いが不便なこともあるので、
エッジをぼかさずに4倍して出力し直します。
(Qiitaの仕組み上、この記事の画像ではボケてるかもしれません)
この2画像を重ねると(プログラム上ではBLEND ADD)元画像が見えてきます。
レーザー彫刻
使用機材は、
xTool D1Pro 10W
素材はダイソーの黒い名刺ケース。
画像を読み込んで、レーザーでアルミの黒塗装をはがしてくれる。
名刺サイズで30~40分。遅!
【設定】
「out1x4.png」は白黒反転させずに、デフォルトのまま。
画像の黒部分が、レーザー発振して、アルミ塗装がはがれるので、
結果的に、データの黒がシルバーに、データの白がブラックになります。
・幅を910mmに。
・素材をMetal Cardにした。
・ビットマップモードをSierraに変更。
・彫刻密度はMaxの260に変更。
ビットマップモードについてはよくわかりませんが、設定後にシミュレーション画像が出て、一番マシに感じました。色勾配のある部分では、自動的にレーザーの線が入るようなのですが、これを無効にできませんでした&調べる時間がありませんでした。
※印刷が途中で止まりました。原因不明です。もしかしたら、このような模様(空間周波数が高い)は、想定外で、エッジのトレースとかで、メモリがパンクしているのかもしれません。
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
岩本・渡邉研究室の解説ページ
マウス操作で体験できる
入力画像から、音声の周波数分析結果が元の画像になるような音声生成が面白い。