Bring grayscale circuit from vimz
Piotr Mikołajczyk piomiko41@gmail.com
Thu, 26 Sep 2024 17:12:44 +0200
4 files changed,
289 insertions(+),
0 deletions(-)
A
circuit/grayscale_step.circom
@@ -0,0 +1,97 @@
+pragma circom 2.0.0; + +include "utils/row_hasher.circom"; +include "utils/pixels.circom"; +include "node_modules/circomlib/circuits/bitify.circom"; + + +template GrayscaleChecker(n) { + signal input orig[n][3]; + signal input gray[n]; + + signal output n_check; + + component lt[n][2]; + + for (var i = 0; i < n; i++) { + var inter = 299 * orig[i][0] + 587 * orig[i][1] + 114 * orig[i][2]; + + lt[i][0] = LessEqThan(18); + lt[i][1] = LessEqThan(18); + + lt[i][0].in[1] <== 1000; + lt[i][0].in[0] <== inter - 1000 * gray[i]; + lt[i][0].out === 1; + + lt[i][1].in[1] <== 1000; + lt[i][1].in[0] <== 1000 * gray[i] - inter; + lt[i][1].out === 1; + } + n_check <== n; +} + +template GrayScale(width){ + + signal input original[width]; + signal input transformed[width]; + + component decompressor[width]; + component decompressor_grey[width]; + component greychecker[width]; + + for (var j=0; j<width; j++) { + decompressor[j] = Decompressor(); + decompressor[j].in <== original[j]; + + decompressor_grey[j] = DecompressorGrey(); + decompressor_grey[j].in <== transformed[j]; + + greychecker[j] = GrayscaleChecker(10); + greychecker[j].orig <== decompressor[j].out; + greychecker[j].gray <== decompressor_grey[j].out; + } + +} + +template GrayScaleHash(width){ + signal input ivc_input[2]; + // signal input prev_orig_hash; + // signal input prev_gray_hash; + signal output ivc_output[2]; + // signal output next_orig_hash; + // signal output next_gray_hash; + + // Private inputs + signal input external_inputs [2 * width]; + + signal row_orig [width]; + signal row_tran [width]; + + for (var i = 0; i < width; i++) { + row_orig[i] <== external_inputs[i]; + row_tran[i] <== external_inputs[i + width]; + } + + component orig_row_hasher = RowHasher(width); + component gray_row_hasher = RowHasher(width); + component orig_hasher = Hasher(2); + component gray_hasher = Hasher(2); + + orig_row_hasher.img <== row_orig; + orig_hasher.values[0] <== ivc_input[0]; // prev_orig_hash + orig_hasher.values[1] <== orig_row_hasher.hash; + ivc_output[0] <== orig_hasher.hash; // next_orig_hash + + gray_row_hasher.img <== row_tran; + gray_hasher.values[0] <== ivc_input[1]; // prev_gray_hash + gray_hasher.values[1] <== gray_row_hasher.hash; + ivc_output[1] <== gray_hasher.hash; // next_grey_hash + + // grayscale code here ... + component checker = GrayScale(width); + checker.original <== row_orig; + checker.transformed <== row_tran; + +} + +component main { public [ivc_input] } = GrayScaleHash(128);
A
circuit/package.json
@@ -0,0 +1,9 @@
+{ + "name": "circom", + "version": "1.0.0", + "main": "index.js", + "license": "MIT", + "dependencies": { + "circomlib": "^2.0.5" + } +}
A
circuit/utils/pixels.circom
@@ -0,0 +1,153 @@
+pragma circom 2.0.0; +include "../node_modules/circomlib/circuits/bitify.circom"; +include "../node_modules/circomlib/circuits/mux1.circom"; +include "../node_modules/circomlib/circuits/comparators.circom"; + +template Decompressor(){ + signal input in; + signal output out[10][3]; + + component toBits = Num2Bits(240); + component toNum[10][3]; + + toBits.in <== in; + + for (var i=0; i<10; i++) { + for (var j=0; j<3; j++) { + toNum[i][j] = Bits2Num(8); + toNum[i][j].in[0] <== toBits.out[i*24+j*8]; + toNum[i][j].in[1] <== toBits.out[i*24+j*8+1]; + toNum[i][j].in[2] <== toBits.out[i*24+j*8+2]; + toNum[i][j].in[3] <== toBits.out[i*24+j*8+3]; + toNum[i][j].in[4] <== toBits.out[i*24+j*8+4]; + toNum[i][j].in[5] <== toBits.out[i*24+j*8+5]; + toNum[i][j].in[6] <== toBits.out[i*24+j*8+6]; + toNum[i][j].in[7] <== toBits.out[i*24+j*8+7]; + out[i][j] <== toNum[i][j].out; + } + } +} + +template DecompressorKernel(kernel_size){ + signal input in; + signal output out[kernel_size][kernel_size]; + + component toBits = Num2Bits(kernel_size*kernel_size*9); // 8-bit value, 1-bit sign + component toNum[kernel_size][kernel_size]; + component selector[kernel_size][kernel_size]; + + toBits.in <== in; + + for (var i=0; i<kernel_size; i++) { + for (var j=0; j<kernel_size; j++) { + toNum[i][j] = Bits2Num(8); + toNum[i][j].in[0] <== toBits.out[i*kernel_size*9+j*9]; + toNum[i][j].in[1] <== toBits.out[i*kernel_size*9+j*9+1]; + toNum[i][j].in[2] <== toBits.out[i*kernel_size*9+j*9+2]; + toNum[i][j].in[3] <== toBits.out[i*kernel_size*9+j*9+3]; + toNum[i][j].in[4] <== toBits.out[i*kernel_size*9+j*9+4]; + toNum[i][j].in[5] <== toBits.out[i*kernel_size*9+j*9+5]; + toNum[i][j].in[6] <== toBits.out[i*kernel_size*9+j*9+6]; + toNum[i][j].in[7] <== toBits.out[i*kernel_size*9+j*9+7]; + + var value = toNum[i][j].out; // value + var sign = toBits.out[i*kernel_size*9+j*9+8]; // sign + + selector[i][j] = Mux1(); + selector[i][j].c[0] <== value; + selector[i][j].c[1] <== 0 - value; + selector[i][j].s <== sign; + + out[i][j] <== selector[i][j].out; + } + } +} + + +template DecompressorGrey(){ + signal input in; + signal output out[10]; + + component toBits = Num2Bits(240); + component toNum[10]; + + toBits.in <== in; + + for (var i=0; i<10; i++) { + var j=0; + toNum[i] = Bits2Num(8); + toNum[i].in[0] <== toBits.out[i*24]; + toNum[i].in[1] <== toBits.out[i*24+1]; + toNum[i].in[2] <== toBits.out[i*24+2]; + toNum[i].in[3] <== toBits.out[i*24+3]; + toNum[i].in[4] <== toBits.out[i*24+4]; + toNum[i].in[5] <== toBits.out[i*24+5]; + toNum[i].in[6] <== toBits.out[i*24+6]; + toNum[i].in[7] <== toBits.out[i*24+7]; + out[i] <== toNum[i].out; + } +} + + +template CompressorCrop(){ + signal input in[10]; + signal output out; + + component toNum = Bits2Num(240); + component toBits[10]; + + for (var i=0; i<10; i++) { + toBits[i] = Num2Bits(24); + toBits[i].in <== in[i]; + for (var j=0; j<24; j++) { + toNum.in[i*24+j] <== toBits[i].out[j]; + } + } + out <== toNum.out; +} + +template DecompressorCrop(){ + signal input in; + signal output out[10]; + + component decomp = DecompressorGrey(); + + decomp.in <== in; + out <== decomp.out; +} + +template CropInfoDecompressor(){ + + signal input in; + signal output row_index; + signal output x; + signal output y; + + component toBits = Num2Bits(36); + component toNumX = Bits2Num(12); + component toNumY = Bits2Num(12); + component toNumIndex = Bits2Num(12); + + toBits.in <== in; + for (var i=0; i<12; i++) { + toNumX.in[i] <== toBits.out[i]; + toNumY.in[i] <== toBits.out[i+12]; + toNumIndex.in[i] <== toBits.out[i+24]; + } + + x <== toNumX.out; + y <== toNumY.out; + row_index <== toNumIndex.out; +} + + +template Test () { + signal input sig1; + signal input sig2; + + component decom = Decompressor(); + decom.in <== sig1; + sig2 === decom.out[2][2]; +} + +// component main = Test();
A
circuit/utils/row_hasher.circom
@@ -0,0 +1,30 @@
+pragma circom 2.0.0; +include "../node_modules/circomlib/circuits/poseidon.circom"; + +template Hasher(inputSize) { + signal input values[inputSize]; + signal output hash; + + component hasher = Poseidon(inputSize); + for (var i = 0; i < inputSize; i++) { + hasher.inputs[i] <== values[i]; + } + hash <== hasher.out; +} + + +template RowHasher (width) { + signal input img[width]; + signal output hash; + + component hasher[width-1]; + + for(var i=0; i < width-1; i++) { + hasher[i] = Hasher(2); + hasher[i].values[0] <== i == 0 ? img[0] : hasher[i-1].hash; + hasher[i].values[1] <== img[i+1]; + } + + hash <== hasher[width-2].hash; + +}