Skip to content

Commit a0762ac

Browse files
authored
Merge pull request #44 from wfus/decode
Decode
2 parents ed74236 + 5bdd1f9 commit a0762ac

17 files changed

+886
-625
lines changed

CMakeLists.txt

+5
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,8 @@ target_link_libraries(decode_server seal ${OpenCV_LIBS})
5050
# Image testing, debugging only
5151
add_executable(image_test homo/image_test.cpp ${LIBRARY_SOURCES})
5252
target_link_libraries(image_test seal ${OpenCV_LIBS})
53+
54+
55+
# Image testing, debugging only
56+
add_executable(test_decode tests/test_decode.cpp ${LIBRARY_SOURCES})
57+
target_link_libraries(test_decode seal ${OpenCV_LIBS})

README.md

+16
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,22 @@
11
# Fast Homomorphic Image Processing
22
These days neural networks and fully homomorphic encryption are a meme. For example, Microsoft demonstrated with Cryptonets of a neural network generating predictions fully homomorphically on the MNIST dataset. However, it would be useful to have a way to preprocess images homomorphically. Consider the use case where an edge device sends a homomorphically encrypted image to a server that runs a prediction algorithm with two neural networks that take in different sized features, as is common. It would be prohibitive to make the edge device homomorphically encrypt two copies of the images, since that would be prohibitively expensive. Therefore, having proprocessing and feature extraction computed homomorphically will provide much more flexibility for homomorphic neural nets.
33

4+
## Homomorphic Image Decompression
5+
6+
We will show how to homomorphically compute something simpler than JPEG decompression, run length decoding. The idea is the same: we would like to expand out a [run length encoding](https://en.wikipedia.org/wiki/Run-length_encoding) (which is used after DCT step of the JPEG standard)
7+
This is difficult to do because converting the run length decoding into a boolean circuit is completely unfeasable due to the number of gates needed. Without resorting to evaluating a boolean circuit, the following operations are not possible with homomorphic encryption
8+
9+
* Dividing by a ciphertext
10+
* Conditionals (if, else)
11+
* No looping on variables
12+
* Cannot prematurely exit program
13+
14+
Since the boolean circuit approach is not feasable by __many multiple orders of magnitude__, we use an approximation approach. For each run length tuple, we approximate a "step" function defined by 1 if between b1 and b2 and 0 otherwise using a discrete Fourier series. We also taylor expand the cosine and sine function. Note that it is difficult to use a sigmoid type function for approximating, because we cannot use division. A sample approximation of the step-like function with a discrete fourier series is shown in the following graph.
15+
16+
![approximategraph](docs/approxstep.png)
17+
18+
19+
420
### Homomorphic Image Resizing
521
There are two common types of interpolation used when images are scaled: [bilinear interpolation](https://en.wikipedia.org/wiki/Bilinear_interpolation) and [bicubic interpolation](https://en.wikipedia.org/wiki/Bicubic_interpolation). Bilinear interpolation requires a 2 by 2 square around the point to be interpolated, and involves linear interpolation in one direction and then in the other in a two dimensional space. Bicubic interpolation is similar except cubic rather than linear interpolation is used, and it requires a 4 by 4 square around a point to be interpolated.
622

benchmark/benchmark.py

+16-12
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,24 @@
11
from subprocess import call
2+
import os
23

34
CWD = "../"
45
IMAGE_NAMES = [("image/boazbarak.jpg", 'boaz')]
56
POLY_N = [2048, 4096, 8192, 16384]
67
PLAIN_MOD = [11, 31, 101, 307, 1009, 3001, 10007, 30011, 100003]
8+
DBC = [16, 32, 60]
79
WIDTH_HEIGHT_PAIRS = [(17, 17)]
810
LOG_DIR = "../logs"
911

10-
def log_resize(imname, inter, width, height, poly_n, plain_mod):
11-
return "{}/resize_{}_{}_{}_{}_{}_{}.txt".format(LOG_DIR, imname, inter, width, height, poly_n, plain_mod)
12+
def log_resize(imname, inter, width, height, poly_n, plain_mod, dbc):
13+
return "{}/resize_{}_{}_{}_{}_{}_{}_{}.txt".format(LOG_DIR, imname, inter, width, height, poly_n, plain_mod, dbc)
1214

1315
def log_jpeg(imname, poly_n, plain_mod):
1416
return "{}/jpg_{}_{}_{}.txt".format(LOG_DIR, imname, poly_n, plain_mod)
1517

16-
def call_resize(image, logname, outname, inter, width, height, poly_n, plain_mod):
18+
def call_resize(image, logname, outname, inter, width, height, poly_n, plain_mod, dbc):
1719
f = open(logname, 'w')
1820
print("Resize Client (Sending)")
19-
call(['./bin/client_resize', '--width', str(width), '--height', str(height), '--send', '-f', image, '--cmod', str(poly_n), '--pmod', str(plain_mod)],
21+
call(['./bin/client_resize', '--width', str(width), '--height', str(height), '--send', '-f', image, '--cmod', str(poly_n), '--pmod', str(plain_mod), '--dbc', str(dbc)],
2022
cwd=CWD, stdout=f)
2123
print("Resize Server")
2224
call(['./bin/server_resize', '--width', str(width), '--height', str(height), inter, '--cmod', str(poly_n), '--pmod', str(plain_mod)],
@@ -38,17 +40,19 @@ def call_jpeg(image, logname, outname, poly_n, plain_mod):
3840
cwd=CWD, stdout=f)
3941

4042
if __name__ == '__main__':
43+
os.system('mkdir -p ../logs')
4144
for image_name, short_name in IMAGE_NAMES:
4245
for poly_n in POLY_N:
4346
for plain_mod in PLAIN_MOD:
4447
for width, height in WIDTH_HEIGHT_PAIRS:
45-
for inter in ['bilinear', 'bicubic']:
46-
logname = log_resize(short_name, inter, width, height, poly_n, plain_mod)
47-
outname = "logs/{}_{}_{}_{}_{}_{}.png".format(short_name, inter, width, height, poly_n, plain_mod)
48-
inter_param = '' if inter == 'bilinear' else '--bicubic'
49-
call_resize(image_name, logname, outname, inter_param, width, height, poly_n, plain_mod)
48+
for dbc in DBC:
49+
for inter in ['bicubic']:
50+
logname = log_resize(short_name, inter, width, height, poly_n, plain_mod, dbc)
51+
outname = "logs/{}_{}_{}_{}_{}_{}_{}.png".format(short_name, inter, width, height, poly_n, plain_mod, dbc)
52+
inter_param = '' if inter == 'bilinear' else '--bicubic'
53+
call_resize(image_name, logname, outname, inter_param, width, height, poly_n, plain_mod, dbc)
5054

51-
logname = log_jpeg(short_name, poly_n, plain_mod)
52-
outname = "logs/new_{}_{}_{}.jpg".format(short_name, poly_n, plain_mod)
53-
call_jpeg(image_name, logname, outname, poly_n, plain_mod)
55+
# logname = log_jpeg(short_name, poly_n, plain_mod)
56+
# outname = "logs/new_{}_{}_{}.jpg".format(short_name, poly_n, plain_mod)
57+
# call_jpeg(image_name, logname, outname, poly_n, plain_mod)
5458

docs/approxstep.png

47.3 KB
Loading

0 commit comments

Comments
 (0)