diff --git a/app/app.py b/app/app.py new file mode 100644 index 0000000..49796f9 --- /dev/null +++ b/app/app.py @@ -0,0 +1,63 @@ +import threading + +import fawkes.protection + +from tkinter import Tk, BOTH, StringVar +from tkinter.ttk import Frame, Label, Style, Button +from tkinter.filedialog import askdirectory, askopenfilenames + + +class UI(Frame): + def __init__(self): + super().__init__() + self.my_fawkes = fawkes.protection.Fawkes("high_extract", '0', 1) + self.var = StringVar() + self.var.set('Initial') + self.img_paths = './imgs' + self.initUI() + + def initUI(self): + self.master.title("This is a Window") + self.pack(fill=BOTH, expand=1) + + btn_Open = Button(self, + text='open img directory', + width=30, + command=self.select_path) + btn_Open.pack() + + btn_Run = Button(self, + text='run the code', + width=3, + command=lambda: thread_it(self.my_fawkes.run_protection, self.img_paths)) + btn_Run.pack() + + Label_Show = Label(self, + textvariable=self.var, + font=('Arial', 13), width=50) + Label_Show.pack() + + def select_path(self): + self.img_paths = askopenfilenames(filetypes=[('image', "*.gif *.jpg *.png")]) + self.var.set('the paths have been set') + + +root = Tk() +root.title('window') +root.geometry('600x500') +app = UI() + + +def main(): + root.mainloop() + + +def thread_it(func, *args): + app.var.set('cloak in process') + t = threading.Thread(target=func, args=args) + t.setDaemon(True) + t.start() + + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/fawkes/__init__.py b/fawkes/__init__.py index ffc8269..df6aac8 100644 --- a/fawkes/__init__.py +++ b/fawkes/__init__.py @@ -8,7 +8,7 @@ __version__ = '0.0.6' from .detect_faces import create_mtcnn, run_detect_face from .differentiator import FawkesMaskGeneration -from .protection import main +from .protection import main, Fawkes from .utils import load_extractor, init_gpu, select_target_label, dump_image, reverse_process_cloaked, Faces, get_file __all__ = ( @@ -16,5 +16,5 @@ __all__ = ( 'FawkesMaskGeneration', 'load_extractor', 'init_gpu', 'select_target_label', 'dump_image', 'reverse_process_cloaked', - 'Faces', 'get_file', 'main', + 'Faces', 'get_file', 'main', 'Fawkes' ) diff --git a/fawkes/differentiator.py b/fawkes/differentiator.py index 29a9a02..162dfff 100644 --- a/fawkes/differentiator.py +++ b/fawkes/differentiator.py @@ -405,9 +405,9 @@ class FawkesMaskGeneration: if all_clear: break - # if iteration != 0 and iteration % (self.MAX_ITERATIONS // 2) == 0: - # LR = LR / 2 - # print("Learning Rate: ", LR) + if iteration != 0 and iteration % (self.MAX_ITERATIONS // 2) == 0: + LR = LR * 0.8 + print("Learning Rate: ", LR) if iteration % (self.MAX_ITERATIONS // 5) == 0: if self.verbose == 1: diff --git a/fawkes/protection.py b/fawkes/protection.py index 68f5b70..7313f1a 100644 --- a/fawkes/protection.py +++ b/fawkes/protection.py @@ -18,7 +18,7 @@ import numpy as np from fawkes.differentiator import FawkesMaskGeneration from fawkes.utils import load_extractor, init_gpu, select_target_label, dump_image, reverse_process_cloaked, \ Faces - +from fawkes.align_face import aligner random.seed(12243) np.random.seed(122412) @@ -54,10 +54,14 @@ def check_imgs(imgs): class Fawkes(object): def __init__(self, feature_extractor, gpu, batch_size): + global graph + graph = tf.get_default_graph() + self.feature_extractor = feature_extractor self.gpu = gpu self.batch_size = batch_size self.sess = init_gpu(gpu) + self.aligner = aligner(self.sess) self.fs_names = [feature_extractor] if isinstance(feature_extractor, list): self.fs_names = feature_extractor @@ -67,23 +71,23 @@ class Fawkes(object): def mode2param(self, mode): if mode == 'low': th = 0.003 - max_step = 20 + max_step = 50 lr = 20 elif mode == 'mid': th = 0.005 - max_step = 50 - lr = 15 + max_step = 100 + lr = 30 elif mode == 'high': th = 0.008 - max_step = 500 - lr = 15 + max_step = 200 + lr = 20 elif mode == 'ultra': if not tf.test.is_gpu_available(): print("Please enable GPU for ultra setting...") sys.exit(1) th = 0.01 - max_step = 2000 - lr = 8 + max_step = 200 + lr = 20 else: raise Exception("mode must be one of 'low', 'mid', 'high', 'ultra', 'custom'") return th, max_step, lr @@ -99,38 +103,38 @@ class Fawkes(object): if not image_paths: raise Exception("No images in the directory") + with graph.as_default(): + faces = Faces(image_paths, self.aligner, verbose=1) - faces = Faces(image_paths, self.sess, verbose=1) + original_images = faces.cropped_faces + original_images = np.array(original_images) - original_images = faces.cropped_faces - original_images = np.array(original_images) + if separate_target: + target_embedding = [] + for org_img in original_images: + org_img = org_img.reshape([1] + list(org_img.shape)) + tar_emb = select_target_label(org_img, self.feature_extractors_ls, self.fs_names) + target_embedding.append(tar_emb) + target_embedding = np.concatenate(target_embedding) + else: + target_embedding = select_target_label(original_images, self.feature_extractors_ls, self.fs_names) - if separate_target: - target_embedding = [] - for org_img in original_images: - org_img = org_img.reshape([1] + list(org_img.shape)) - tar_emb = select_target_label(org_img, self.feature_extractors_ls, self.fs_names) - target_embedding.append(tar_emb) - target_embedding = np.concatenate(target_embedding) - else: - target_embedding = select_target_label(original_images, self.feature_extractors_ls, self.fs_names) + protected_images = generate_cloak_images(self.sess, self.feature_extractors_ls, original_images, + target_emb=target_embedding, th=th, faces=faces, sd=sd, + lr=lr, max_step=max_step, batch_size=batch_size) - protected_images = generate_cloak_images(self.sess, self.feature_extractors_ls, original_images, - target_emb=target_embedding, th=th, faces=faces, sd=sd, - lr=lr, max_step=max_step, batch_size=batch_size) + faces.cloaked_cropped_faces = protected_images - faces.cloaked_cropped_faces = protected_images + cloak_perturbation = reverse_process_cloaked(protected_images) - reverse_process_cloaked(original_images) + final_images = faces.merge_faces(cloak_perturbation) - cloak_perturbation = reverse_process_cloaked(protected_images) - reverse_process_cloaked(original_images) - final_images = faces.merge_faces(cloak_perturbation) + for p_img, cloaked_img, path in zip(final_images, protected_images, image_paths): + file_name = "{}_{}_cloaked.{}".format(".".join(path.split(".")[:-1]), mode, format) + dump_image(p_img, file_name, format=format) - for p_img, cloaked_img, path in zip(final_images, protected_images, image_paths): - file_name = "{}_{}_cloaked.{}".format(".".join(path.split(".")[:-1]), mode, format) - dump_image(p_img, file_name, format=format) - - elapsed_time = time.time() - start_time - print('attack cost %f s' % elapsed_time) - print("Done!") + elapsed_time = time.time() - start_time + print('attack cost %f s' % elapsed_time) + print("Done!") def main(*argv): diff --git a/fawkes/utils.py b/fawkes/utils.py index 6fae615..5557702 100644 --- a/fawkes/utils.py +++ b/fawkes/utils.py @@ -86,7 +86,7 @@ def load_image(path): class Faces(object): - def __init__(self, image_paths, sess, verbose=1): + def __init__(self, image_paths, aligner, verbose=1): model_dir = os.path.join(os.path.expanduser('~'), '.fawkes') if not os.path.exists(os.path.join(model_dir, "mtcnn.p.gz")): os.makedirs(model_dir, exist_ok=True) @@ -94,7 +94,7 @@ class Faces(object): cache_subdir='') self.verbose = verbose - self.aligner = aligner(sess) + self.aligner = aligner self.org_faces = [] self.cropped_faces = [] self.cropped_faces_shape = [] diff --git a/fawkes_dev/azure.py b/fawkes_dev/azure_add_images.py similarity index 99% rename from fawkes_dev/azure.py rename to fawkes_dev/azure_add_images.py index 2aee371..7bc95fd 100644 --- a/fawkes_dev/azure.py +++ b/fawkes_dev/azure_add_images.py @@ -14,10 +14,102 @@ data = f.read().split("\n") subscription_key = data[0] uri_base = data[1] -cloak_image_base = 'http://sandlab.cs.uchicago.edu/fawkes/files/cloak/{}_ultra_cloaked.png' +cloak_image_base = 'http://sandlab.cs.uchicago.edu/fawkes/files/cloak/{}_high_cloaked.png' original_image_base = 'http://sandlab.cs.uchicago.edu/fawkes/files/cloak/{}.png' +def test_cloak(): + NUM_TRAIN = 5 + total_idx = range(0, 82) + TRAIN_RANGE = random.sample(total_idx, NUM_TRAIN) + + TEST_RANGE = random.sample([i for i in total_idx if i not in TRAIN_RANGE], 20) + + personGroupId = 'all' + + # delete_personGroup(personGroupId) + # create_personGroupId(personGroupId, personGroupId) + + with open("protect_personId.txt", 'r') as f: + protect_personId = f.read() + print(protect_personId) + delete_personGroupPerson(personGroupId, protect_personId) + + protect_personId = create_personId(personGroupId, 'Emily') + with open("protect_personId.txt", 'w') as f: + f.write(protect_personId) + + print("Created protect personId: {}".format(protect_personId)) + for idx in TRAIN_RANGE: + image_url = cloak_image_base.format(idx) + r = add_persistedFaceId(personGroupId, protect_personId, image_url) + if r is not None: + print("Added {}".format(idx)) + else: + print("Unable to add {}-th image of protect person".format(idx)) + + # add other people + # for idx_person in range(5000, 15000): + # personId = create_personId(personGroupId, str(idx_person)) + # print("Created personId: {}".format(idx_person)) + # for idx_image in range(10): + # image_url = "http://sandlab.cs.uchicago.edu/fawkes/files/target_data/{}/{}.jpg".format( + # idx_person, idx_image) + # r = add_persistedFaceId(personGroupId, personId, image_url) + # if r is not None: + # print("Added {}".format(idx_image)) + # else: + # print("Unable to add {}-th image".format(idx_image)) + + # train model based on personGroup + + train_personGroup(personGroupId) + + while json.loads(get_trainStatus(personGroupId))['status'] != 'succeeded': + time.sleep(2) + + # list_personGroupPerson(personGroupId) + + # test original image + idx_range = TEST_RANGE + acc = 0. + tot = 0. + for idx in idx_range: + original_image_url = original_image_base.format(idx) + faceId = detect_face(original_image_url) + if faceId is None: + print("{} does not exist".format(idx)) + continue + original_faceIds = [faceId] + + # verify + res = eval(original_faceIds, personGroupId, protect_personId) + if res: + acc += 1. + tot += 1. + + acc /= tot + print(acc) # 1.0 + + +def list_personGroups(): + headers = { + 'Ocp-Apim-Subscription-Key': subscription_key, + } + + params = urllib.parse.urlencode({ + }) + + body = json.dumps({}) + + conn = http.client.HTTPSConnection(uri_base) + conn.request("GET", "/face/v1.0/persongroups?%s" % params, body, headers) + response = conn.getresponse() + data = response.read() + print(data) + conn.close() + + def detect_face(image_url): r = requests.get(image_url) if r.status_code != 200: @@ -274,98 +366,6 @@ def get_trainStatus(personGroupId): return data -def test_cloak(): - NUM_TRAIN = 10 - total_idx = range(0, 82) - TRAIN_RANGE = random.sample(total_idx, NUM_TRAIN) - - TEST_RANGE = random.sample([i for i in total_idx if i not in TRAIN_RANGE], 20) - - personGroupId = 'all' - - # delete_personGroup(personGroupId) - # create_personGroupId(personGroupId, personGroupId) - - with open("protect_personId.txt", 'r') as f: - protect_personId = f.read() - print(protect_personId) - delete_personGroupPerson(personGroupId, protect_personId) - - protect_personId = create_personId(personGroupId, 'Emily') - with open("protect_personId.txt", 'w') as f: - f.write(protect_personId) - - print("Created protect personId: {}".format(protect_personId)) - for idx in TRAIN_RANGE: - image_url = cloak_image_base.format(idx) - r = add_persistedFaceId(personGroupId, protect_personId, image_url) - if r is not None: - print("Added {}".format(idx)) - else: - print("Unable to add {}-th image of protect person".format(idx)) - - # add other people - # for idx_person in range(1300, 5000): - # personId = create_personId(personGroupId, str(idx_person)) - # print("Created personId: {}".format(idx_person)) - # for idx_image in range(10): - # image_url = "http://sandlab.cs.uchicago.edu/fawkes/files/target_data/{}/{}.jpg".format( - # idx_person, idx_image) - # r = add_persistedFaceId(personGroupId, personId, image_url) - # if r is not None: - # print("Added {}".format(idx_image)) - # else: - # print("Unable to add {}-th image".format(idx_image)) - - # train model based on personGroup - - train_personGroup(personGroupId) - - while json.loads(get_trainStatus(personGroupId))['status'] != 'succeeded': - time.sleep(2) - - # list_personGroupPerson(personGroupId) - - # test original image - idx_range = TEST_RANGE - acc = 0. - tot = 0. - for idx in idx_range: - original_image_url = original_image_base.format(idx) - faceId = detect_face(original_image_url) - if faceId is None: - print("{} does not exist".format(idx)) - continue - original_faceIds = [faceId] - - # verify - res = eval(original_faceIds, personGroupId, protect_personId) - if res: - acc += 1. - tot += 1. - - acc /= tot - print(acc) # 1.0 - - -def list_personGroups(): - headers = { - 'Ocp-Apim-Subscription-Key': subscription_key, - } - - params = urllib.parse.urlencode({ - }) - - body = json.dumps({}) - - conn = http.client.HTTPSConnection(uri_base) - conn.request("GET", "/face/v1.0/persongroups?%s" % params, body, headers) - response = conn.getresponse() - data = response.read() - print(data) - conn.close() - - def delete_personGroup(personGroupId): headers = { 'Ocp-Apim-Subscription-Key': subscription_key, diff --git a/setup.py b/setup.py index 3fb4385..40941ee 100644 --- a/setup.py +++ b/setup.py @@ -82,7 +82,6 @@ install_requires = [ 'keras==2.2.5', 'scikit-image', 'pillow>=7.0.0', - 'opencv-python>=4.2.0.34' ] setup(