Roman
commited on
Commit
•
1974e22
1
Parent(s):
2a040cc
chore: include reshape in FHE execution
Browse files- app.py +1 -1
- client_server_interface.py +4 -7
- filters.py +16 -22
- filters/black and white/deployment/client.zip +2 -2
- filters/black and white/deployment/server.zip +2 -2
- filters/blur/deployment/client.zip +1 -1
- filters/blur/deployment/server.zip +2 -2
- filters/identity/deployment/client.zip +2 -2
- filters/identity/deployment/server.zip +2 -2
- filters/inverted/deployment/client.zip +2 -2
- filters/inverted/deployment/server.zip +2 -2
- filters/ridge detection/deployment/client.zip +2 -2
- filters/ridge detection/deployment/server.zip +2 -2
- filters/rotate/deployment/client.zip +2 -2
- filters/rotate/deployment/server.zip +2 -2
- filters/sharpen/deployment/client.zip +1 -1
- filters/sharpen/deployment/server.zip +2 -2
app.py
CHANGED
@@ -187,7 +187,7 @@ def encrypt(user_id, input_image, filter_name):
|
|
187 |
client = get_client(user_id, filter_name)
|
188 |
|
189 |
# Pre-process, encrypt and serialize the image
|
190 |
-
encrypted_image = client.
|
191 |
|
192 |
# Compute the input's size in Megabytes
|
193 |
encrypted_input_size = len(encrypted_image) / 1000000
|
|
|
187 |
client = get_client(user_id, filter_name)
|
188 |
|
189 |
# Pre-process, encrypt and serialize the image
|
190 |
+
encrypted_image = client.encrypt_serialize(input_image)
|
191 |
|
192 |
# Compute the input's size in Megabytes
|
193 |
encrypted_input_size = len(encrypted_image) / 1000000
|
client_server_interface.py
CHANGED
@@ -118,20 +118,17 @@ class FHEClient:
|
|
118 |
"""
|
119 |
return self.client.evaluation_keys.serialize()
|
120 |
|
121 |
-
def
|
122 |
-
"""
|
123 |
|
124 |
Args:
|
125 |
-
input_image (numpy.ndarray): The image to
|
126 |
|
127 |
Returns:
|
128 |
bytes: The pre-processed, encrypted and serialized image.
|
129 |
"""
|
130 |
-
# Pre-process the image
|
131 |
-
preprocessed_image = self.filter.pre_processing(input_image)
|
132 |
-
|
133 |
# Encrypt the image
|
134 |
-
encrypted_image = self.client.encrypt(
|
135 |
|
136 |
# Serialize the encrypted image to be sent to the server
|
137 |
serialized_encrypted_image = self.client.specs.serialize_public_args(encrypted_image)
|
|
|
118 |
"""
|
119 |
return self.client.evaluation_keys.serialize()
|
120 |
|
121 |
+
def encrypt_serialize(self, input_image):
|
122 |
+
"""Encrypt and serialize the input image in the clear.
|
123 |
|
124 |
Args:
|
125 |
+
input_image (numpy.ndarray): The image to encrypt and serialize.
|
126 |
|
127 |
Returns:
|
128 |
bytes: The pre-processed, encrypted and serialized image.
|
129 |
"""
|
|
|
|
|
|
|
130 |
# Encrypt the image
|
131 |
+
encrypted_image = self.client.encrypt(input_image)
|
132 |
|
133 |
# Serialize the encrypted image to be sent to the server
|
134 |
serialized_encrypted_image = self.client.specs.serialize_public_args(encrypted_image)
|
filters.py
CHANGED
@@ -52,7 +52,7 @@ class TorchRotate(nn.Module):
|
|
52 |
Returns:
|
53 |
torch.Tensor: The rotated image.
|
54 |
"""
|
55 |
-
return x.transpose(
|
56 |
|
57 |
|
58 |
class TorchConv(nn.Module):
|
@@ -102,15 +102,26 @@ class TorchConv(nn.Module):
|
|
102 |
kernel_shape[0],
|
103 |
kernel_shape[1],
|
104 |
)
|
|
|
|
|
105 |
else:
|
106 |
raise ValueError(
|
107 |
"Wrong kernel shape, only 1D or 2D kernels are accepted. Got kernel of shape "
|
108 |
f"{kernel_shape}"
|
109 |
)
|
110 |
|
|
|
|
|
|
|
|
|
|
|
|
|
111 |
# Apply the convolution
|
112 |
x = nn.functional.conv2d(x, kernel, stride=stride, groups=self.groups)
|
113 |
|
|
|
|
|
|
|
114 |
# Subtract a given threshold if given
|
115 |
if self.threshold is not None:
|
116 |
x -= self.threshold
|
@@ -212,8 +223,11 @@ class Filter:
|
|
212 |
# This version's compiler only handles tuples of 1-batch array as inputset, meaning we need
|
213 |
# to define the inputset as a Tuple[np.ndarray[shape=(1, 3, H, W)]]
|
214 |
np.random.seed(42)
|
|
|
|
|
|
|
215 |
inputset = tuple(
|
216 |
-
np.random.randint(0, 256, size=((
|
217 |
)
|
218 |
|
219 |
# Convert the Torch module to a Numpy module
|
@@ -239,22 +253,6 @@ class Filter:
|
|
239 |
|
240 |
return self.fhe_circuit
|
241 |
|
242 |
-
def pre_processing(self, input_image):
|
243 |
-
"""Apply pre-processing to the encrypted input images.
|
244 |
-
|
245 |
-
Args:
|
246 |
-
input_image (np.ndarray): The image to pre-process.
|
247 |
-
|
248 |
-
Returns:
|
249 |
-
input_image (np.ndarray): The pre-processed image.
|
250 |
-
"""
|
251 |
-
# Reshape the inputs found in inputset. This is done because Torch and Numpy don't follow
|
252 |
-
# the same shape conventions.
|
253 |
-
# Additionally, make sure the input images are made of integers only
|
254 |
-
input_image = np.expand_dims(input_image.transpose(2, 0, 1), axis=0).astype(np.int64)
|
255 |
-
|
256 |
-
return input_image
|
257 |
-
|
258 |
def post_processing(self, output_image):
|
259 |
"""Apply post-processing to the encrypted output images.
|
260 |
|
@@ -271,10 +269,6 @@ class Filter:
|
|
271 |
# Clip the image's values to proper RGB standards as filters don't handle such constraints
|
272 |
output_image = output_image.clip(0, 255)
|
273 |
|
274 |
-
# Reshape the inputs found in inputset. This is done because Torch and Numpy don't follow
|
275 |
-
# the same shape conventions.
|
276 |
-
output_image = output_image.transpose(0, 2, 3, 1).squeeze(0)
|
277 |
-
|
278 |
# Gradio requires all images to follow a RGB format
|
279 |
if self.repeat_out_channels:
|
280 |
output_image = output_image.repeat(3, axis=2)
|
|
|
52 |
Returns:
|
53 |
torch.Tensor: The rotated image.
|
54 |
"""
|
55 |
+
return x.transpose(0, 1)
|
56 |
|
57 |
|
58 |
class TorchConv(nn.Module):
|
|
|
102 |
kernel_shape[0],
|
103 |
kernel_shape[1],
|
104 |
)
|
105 |
+
|
106 |
+
|
107 |
else:
|
108 |
raise ValueError(
|
109 |
"Wrong kernel shape, only 1D or 2D kernels are accepted. Got kernel of shape "
|
110 |
f"{kernel_shape}"
|
111 |
)
|
112 |
|
113 |
+
# Reshape the image. This is done because Torch convolutions and Numpy arrays (for PIL
|
114 |
+
# display) don't follow the same shape conventions. More precisely, x is of shape
|
115 |
+
# (Width, Height, Channels) while the conv2d operator requires an input of shape
|
116 |
+
# (Batch, Channels, Height, Width)
|
117 |
+
x = x.transpose(2, 0).unsqueeze(axis=0)
|
118 |
+
|
119 |
# Apply the convolution
|
120 |
x = nn.functional.conv2d(x, kernel, stride=stride, groups=self.groups)
|
121 |
|
122 |
+
# Reshape the output back to the original shape (Width, Height, Channels)
|
123 |
+
x = x.transpose(1, 3).reshape((x.shape[2], x.shape[3], self.n_out_channels))
|
124 |
+
|
125 |
# Subtract a given threshold if given
|
126 |
if self.threshold is not None:
|
127 |
x -= self.threshold
|
|
|
223 |
# This version's compiler only handles tuples of 1-batch array as inputset, meaning we need
|
224 |
# to define the inputset as a Tuple[np.ndarray[shape=(1, 3, H, W)]]
|
225 |
np.random.seed(42)
|
226 |
+
# inputset = tuple(
|
227 |
+
# np.random.randint(0, 256, size=((1, 3) + INPUT_SHAPE), dtype=np.int64) for _ in range(100)
|
228 |
+
# )
|
229 |
inputset = tuple(
|
230 |
+
np.random.randint(0, 256, size=(INPUT_SHAPE + (3, )), dtype=np.int64) for _ in range(100)
|
231 |
)
|
232 |
|
233 |
# Convert the Torch module to a Numpy module
|
|
|
253 |
|
254 |
return self.fhe_circuit
|
255 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
256 |
def post_processing(self, output_image):
|
257 |
"""Apply post-processing to the encrypted output images.
|
258 |
|
|
|
269 |
# Clip the image's values to proper RGB standards as filters don't handle such constraints
|
270 |
output_image = output_image.clip(0, 255)
|
271 |
|
|
|
|
|
|
|
|
|
272 |
# Gradio requires all images to follow a RGB format
|
273 |
if self.repeat_out_channels:
|
274 |
output_image = output_image.repeat(3, axis=2)
|
filters/black and white/deployment/client.zip
CHANGED
@@ -1,3 +1,3 @@
|
|
1 |
version https://git-lfs.github.com/spec/v1
|
2 |
-
oid sha256:
|
3 |
-
size
|
|
|
1 |
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:d29a4e9e982ee241d8add504f07bcf97f4d8a0e9ac829beadca47a776071b529
|
3 |
+
size 385
|
filters/black and white/deployment/server.zip
CHANGED
@@ -1,3 +1,3 @@
|
|
1 |
version https://git-lfs.github.com/spec/v1
|
2 |
-
oid sha256:
|
3 |
-
size
|
|
|
1 |
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:a5c5140caae2aa8da37b2cde5f5fa4d91ad4eab377e026e64f8d85824c615eb7
|
3 |
+
size 5740
|
filters/blur/deployment/client.zip
CHANGED
@@ -1,3 +1,3 @@
|
|
1 |
version https://git-lfs.github.com/spec/v1
|
2 |
-
oid sha256:
|
3 |
size 391
|
|
|
1 |
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:4ae0e376e218678bda97cc74d9ec982f3bc2d6481de0f1d7ce9fe1aa86bb949f
|
3 |
size 391
|
filters/blur/deployment/server.zip
CHANGED
@@ -1,3 +1,3 @@
|
|
1 |
version https://git-lfs.github.com/spec/v1
|
2 |
-
oid sha256:
|
3 |
-
size
|
|
|
1 |
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:9743554d7f410d98e8cb2a42419805ee2474f7a7a72d53a0af6878d5ac57ae83
|
3 |
+
size 8716
|
filters/identity/deployment/client.zip
CHANGED
@@ -1,3 +1,3 @@
|
|
1 |
version https://git-lfs.github.com/spec/v1
|
2 |
-
oid sha256:
|
3 |
-
size
|
|
|
1 |
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:1e6069504c9bdbee4a7512503f0e0f14540dda5e81f07b8c06945e2fd130e816
|
3 |
+
size 376
|
filters/identity/deployment/server.zip
CHANGED
@@ -1,3 +1,3 @@
|
|
1 |
version https://git-lfs.github.com/spec/v1
|
2 |
-
oid sha256:
|
3 |
-
size
|
|
|
1 |
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:0977f6308e0545c9f46a4a1558e7ac9d8b9768d4a975e6a7b300c87c7aa31eb5
|
3 |
+
size 2537
|
filters/inverted/deployment/client.zip
CHANGED
@@ -1,3 +1,3 @@
|
|
1 |
version https://git-lfs.github.com/spec/v1
|
2 |
-
oid sha256:
|
3 |
-
size
|
|
|
1 |
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:1e6069504c9bdbee4a7512503f0e0f14540dda5e81f07b8c06945e2fd130e816
|
3 |
+
size 376
|
filters/inverted/deployment/server.zip
CHANGED
@@ -1,3 +1,3 @@
|
|
1 |
version https://git-lfs.github.com/spec/v1
|
2 |
-
oid sha256:
|
3 |
-
size
|
|
|
1 |
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:0c896a6ba50a4bdc05f6c2d7681d5bb2bb73455badad095eb89afff81371d851
|
3 |
+
size 4152
|
filters/ridge detection/deployment/client.zip
CHANGED
@@ -1,3 +1,3 @@
|
|
1 |
version https://git-lfs.github.com/spec/v1
|
2 |
-
oid sha256:
|
3 |
-
size
|
|
|
1 |
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:284b77b3d44bde414f4d5024ed82d3661bb458d5161d4295d95fc093e1d43255
|
3 |
+
size 395
|
filters/ridge detection/deployment/server.zip
CHANGED
@@ -1,3 +1,3 @@
|
|
1 |
version https://git-lfs.github.com/spec/v1
|
2 |
-
oid sha256:
|
3 |
-
size
|
|
|
1 |
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:7ff23c15ac778614572e8133436479cad9386ae0ad4a73198ed265e9faee4677
|
3 |
+
size 6440
|
filters/rotate/deployment/client.zip
CHANGED
@@ -1,3 +1,3 @@
|
|
1 |
version https://git-lfs.github.com/spec/v1
|
2 |
-
oid sha256:
|
3 |
-
size
|
|
|
1 |
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:1e6069504c9bdbee4a7512503f0e0f14540dda5e81f07b8c06945e2fd130e816
|
3 |
+
size 376
|
filters/rotate/deployment/server.zip
CHANGED
@@ -1,3 +1,3 @@
|
|
1 |
version https://git-lfs.github.com/spec/v1
|
2 |
-
oid sha256:
|
3 |
-
size
|
|
|
1 |
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:a4ff1894d64c954ef5030cc7f09edd1e33502b4a90879c7e1f98e3b00041a458
|
3 |
+
size 4387
|
filters/sharpen/deployment/client.zip
CHANGED
@@ -1,3 +1,3 @@
|
|
1 |
version https://git-lfs.github.com/spec/v1
|
2 |
-
oid sha256:
|
3 |
size 396
|
|
|
1 |
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:3b724ed4b2985d5bafe983054848abc35479add2fa265f8337336604908a1e62
|
3 |
size 396
|
filters/sharpen/deployment/server.zip
CHANGED
@@ -1,3 +1,3 @@
|
|
1 |
version https://git-lfs.github.com/spec/v1
|
2 |
-
oid sha256:
|
3 |
-
size
|
|
|
1 |
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:c19c95cdcea6a43e45a06370f67bd770f55e41757d0c85ca6815b56d704c2a92
|
3 |
+
size 8735
|