Spaces:
Sleeping
Sleeping
| import torch | |
| import requests | |
| from PIL import Image | |
| from torchvision import transforms | |
| import gradio as gr | |
| import io | |
| import requests | |
| import torch | |
| import numpy as np | |
| from torch.autograd import Variable | |
| import torchvision.models as models | |
| import torchvision.transforms as transforms | |
| import math | |
| import uuid | |
| import numpy as np | |
| import PIL.Image | |
| import PIL.ImageDraw | |
| import cv2 | |
| model = torch.hub.load('pytorch/vision:v0.6.0', 'vgg16', pretrained=True).eval() | |
| device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") | |
| model = model.to(device) | |
| # Download human-readable labels for ImageNet. | |
| response = requests.get("https://git.io/JJkYN") | |
| labels = response.text.split("\n") | |
| import itertools | |
| #compare two binary strings, check where there is one difference | |
| def compBinary(s1,s2): | |
| count = 0 | |
| pos = 0 | |
| for i in range(len(s1)): | |
| if s1[i] != s2[i]: | |
| count+=1 | |
| pos = i | |
| if count == 1: | |
| return True, pos | |
| else: | |
| return False, None | |
| #compare if the number is same as implicant term | |
| #s1 should be the term | |
| def compBinarySame(term,number): | |
| for i in range(len(term)): | |
| if term[i] != '-': | |
| if term[i] != number[i]: | |
| return False | |
| return True | |
| #combine pairs and make new group | |
| def combinePairs(group, unchecked): | |
| #define length | |
| l = len(group) -1 | |
| #check list | |
| check_list = [] | |
| #create next group | |
| next_group = [[] for x in range(l)] | |
| #go through the groups | |
| for i in range(l): | |
| #first selected group | |
| for elem1 in group[i]: | |
| #next selected group | |
| for elem2 in group[i+1]: | |
| b, pos = compBinary(elem1, elem2) | |
| if b == True: | |
| #append the ones used in check list | |
| check_list.append(elem1) | |
| check_list.append(elem2) | |
| #replace the different bit with '-' | |
| new_elem = list(elem1) | |
| new_elem[pos] = '-' | |
| new_elem = "".join(new_elem) | |
| next_group[i].append(new_elem) | |
| for i in group: | |
| for j in i: | |
| if j not in check_list: | |
| unchecked.append(j) | |
| return next_group, unchecked | |
| #remove redundant lists in 2d list | |
| def remove_redundant(group): | |
| new_group = [] | |
| for j in group: | |
| new=[] | |
| for i in j: | |
| if i not in new: | |
| new.append(i) | |
| new_group.append(new) | |
| return new_group | |
| #remove redundant in 1d list | |
| def remove_redundant_list(list): | |
| new_list = [] | |
| for i in list: | |
| if i not in new_list: | |
| new_list.append(i) | |
| return new_list | |
| #return True if empty | |
| def check_empty(group): | |
| if len(group) == 0: | |
| return True | |
| else: | |
| count = 0 | |
| for i in group: | |
| if i: | |
| count+=1 | |
| if count == 0: | |
| return True | |
| return False | |
| #find essential prime implicants ( col num of ones = 1) | |
| def find_prime(Chart): | |
| prime = [] | |
| for col in range(len(Chart[0])): | |
| count = 0 | |
| pos = 0 | |
| for row in range(len(Chart)): | |
| #find essential | |
| if Chart[row][col] == 1: | |
| count += 1 | |
| pos = row | |
| if count == 1: | |
| prime.append(pos) | |
| return prime | |
| def check_all_zero(Chart): | |
| for i in Chart: | |
| for j in i: | |
| if j != 0: | |
| return False | |
| return True | |
| #find max value in list | |
| def find_max(l): | |
| max = -1 | |
| index = 0 | |
| for i in range(len(l)): | |
| if l[i] > max: | |
| max = l[i] | |
| index = i | |
| return index | |
| #multiply two terms (ex. (p1 + p2)(p1+p4+p5) )..it returns the product | |
| def multiplication(list1, list2): | |
| list_result = [] | |
| #if empty | |
| if len(list1) == 0 and len(list2)== 0: | |
| return list_result | |
| #if one is empty | |
| elif len(list1)==0: | |
| return list2 | |
| #if another is empty | |
| elif len(list2)==0: | |
| return list1 | |
| #both not empty | |
| else: | |
| for i in list1: | |
| for j in list2: | |
| #if two term same | |
| if i == j: | |
| #list_result.append(sorted(i)) | |
| list_result.append(i) | |
| else: | |
| #list_result.append(sorted(list(set(i+j)))) | |
| list_result.append(list(set(i+j))) | |
| #sort and remove redundant lists and return this list | |
| list_result.sort() | |
| return list(list_result for list_result,_ in itertools.groupby(list_result)) | |
| #petrick's method | |
| def petrick_method(Chart): | |
| #initial P | |
| P = [] | |
| for col in range(len(Chart[0])): | |
| p =[] | |
| for row in range(len(Chart)): | |
| if Chart[row][col] == 1: | |
| p.append([row]) | |
| P.append(p) | |
| #do multiplication | |
| for l in range(len(P)-1): | |
| P[l+1] = multiplication(P[l],P[l+1]) | |
| P = sorted(P[len(P)-1],key=len) | |
| final = [] | |
| #find the terms with min length = this is the one with lowest cost (optimized result) | |
| min=len(P[0]) | |
| for i in P: | |
| if len(i) == min: | |
| final.append(i) | |
| else: | |
| break | |
| #final is the result of petrick's method | |
| return final | |
| #chart = n*n list | |
| def find_minimum_cost(Chart, unchecked): | |
| P_final = [] | |
| #essential_prime = list with terms with only one 1 (Essential Prime Implicants) | |
| essential_prime = find_prime(Chart) | |
| essential_prime = remove_redundant_list(essential_prime) | |
| #print out the essential primes | |
| if len(essential_prime)>0: | |
| s = "\nEssential Prime Implicants :\n" | |
| for i in range(len(unchecked)): | |
| for j in essential_prime: | |
| if j == i: | |
| s= s+binary_to_letter(unchecked[i])+' , ' | |
| #print(s[:(len(s)-3)]) | |
| #modifiy the chart to exclude the covered terms | |
| for i in range(len(essential_prime)): | |
| for col in range(len(Chart[0])): | |
| if Chart[essential_prime[i]][col] == 1: | |
| for row in range(len(Chart)): | |
| Chart[row][col] = 0 | |
| #if all zero, no need for petrick method | |
| if check_all_zero(Chart) == True: | |
| P_final = [essential_prime] | |
| else: | |
| #petrick's method | |
| P = petrick_method(Chart) | |
| #find the one with minimum cost | |
| #see "Introduction to Logic Design" - Alan B.Marcovitz Example 4.6 pg 213 | |
| ''' | |
| Although Petrick's method gives the minimum terms that cover all, | |
| it does not mean that it is the solution for minimum cost! | |
| ''' | |
| P_cost = [] | |
| for prime in P: | |
| count = 0 | |
| for i in range(len(unchecked)): | |
| for j in prime: | |
| if j == i: | |
| count = count+ cal_efficient(unchecked[i]) | |
| P_cost.append(count) | |
| for i in range(len(P_cost)): | |
| if P_cost[i] == min(P_cost): | |
| P_final.append(P[i]) | |
| #append prime implicants to the solution of Petrick's method | |
| for i in P_final: | |
| for j in essential_prime: | |
| if j not in i: | |
| i.append(j) | |
| return P_final | |
| #calculate the number of literals | |
| def cal_efficient(s): | |
| count = 0 | |
| for i in range(len(s)): | |
| if s[i] != '-': | |
| count+=1 | |
| return count | |
| #print the binary code to letter | |
| def binary_to_letter(s): | |
| out = '' | |
| c = 'a' | |
| more = False | |
| n = 0 | |
| for i in range(len(s)): | |
| #if it is a range a-zA-Z | |
| if more == False: | |
| if s[i] == '1': | |
| out = out + c | |
| elif s[i] == '0': | |
| out = out + c+'\'' | |
| if more == True: | |
| if s[i] == '1': | |
| out = out + c + str(n) | |
| elif s[i] == '0': | |
| out = out + c + str(n) + '\'' | |
| n+=1 | |
| #conditions for next operations | |
| if c=='z' and more == False: | |
| c = 'A' | |
| elif c=='Z': | |
| c = 'a' | |
| more = True | |
| elif more == False: | |
| c = chr(ord(c)+1) | |
| return out | |
| def binary_to_letter_final(s, dictionary): | |
| out = '' | |
| c = 'a' | |
| more = False | |
| n = 0 | |
| for i in range(len(s)): | |
| #if it is a range a-zA-Z | |
| if more == False: | |
| if s[i] == '1': | |
| out = out + c | |
| elif s[i] == '0': | |
| out = out + c+'\'' | |
| if more == True: | |
| if s[i] == '1': | |
| out = out + c + str(n) | |
| elif s[i] == '0': | |
| out = out + c + str(n) + '\'' | |
| n+=1 | |
| #conditions for next operations | |
| if c=='z' and more == False: | |
| c = 'A' | |
| elif c=='Z': | |
| c = 'a' | |
| more = True | |
| elif more == False: | |
| c = chr(ord(c)+1) | |
| return_string = '' | |
| for char in out: | |
| if char == "'": | |
| return_string += "'" | |
| else: | |
| return_string+='('+dictionary[char]+')' | |
| return return_string | |
| #main function | |
| def quin_macluskey(n_var,minterms, dictionary): | |
| a = minterms | |
| #make a group list | |
| group = [[] for x in range(n_var+1)] | |
| for i in range(len(a)): | |
| #convert to binary | |
| a[i] = bin(a[i])[2:] | |
| if len(a[i]) < n_var: | |
| #add zeros to fill the n-bits | |
| for j in range(n_var - len(a[i])): | |
| a[i] = '0'+ a[i] | |
| #if incorrect input | |
| elif len(a[i]) > n_var: | |
| print('\nError : Choose the correct number of variables(bits)\n') | |
| return | |
| #count the num of 1 | |
| index = a[i].count('1') | |
| #group by num of 1 separately | |
| group[index].append(a[i]) | |
| all_group=[] | |
| unchecked = [] | |
| #combine the pairs in series until nothing new can be combined | |
| while check_empty(group) == False: | |
| all_group.append(group) | |
| next_group, unchecked = combinePairs(group,unchecked) | |
| group = remove_redundant(next_group) | |
| s = "\nPrime Implicants :\n" | |
| for i in unchecked: | |
| s= s + binary_to_letter(i) + " , " | |
| #print(s[:(len(s)-3)]) | |
| #make the prime implicant chart | |
| Chart = [[0 for x in range(len(a))] for x in range(len(unchecked))] | |
| for i in range(len(a)): | |
| for j in range (len(unchecked)): | |
| #term is same as number | |
| if compBinarySame(unchecked[j], a[i]): | |
| Chart[j][i] = 1 | |
| #prime contains the index of the prime implicant terms | |
| #prime = remove_redundant_list(find_minimum_cost(Chart)) | |
| primes = find_minimum_cost(Chart, unchecked) | |
| primes = remove_redundant(primes) | |
| print("\n-- Answers --\n") | |
| result = '' | |
| for prime in primes: | |
| s='' | |
| for i in range(len(unchecked)): | |
| for j in prime: | |
| if j == i: | |
| s= s+binary_to_letter_final(unchecked[i], dictionary)+' + ' | |
| result += s[:(len(s)-3)] | |
| #print(result) | |
| return result | |
| #This part shortens boolean formulas even more than the last step, applicable only in the context of image prediction boolean formulas | |
| def pre_image(res_image,model): | |
| model.eval() | |
| res_image = res_image[:,:,::-1] | |
| img = Image.fromarray(res_image) | |
| normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406], | |
| std=[0.229, 0.224, 0.225]) | |
| transform_pipeline = transforms.Compose([ | |
| transforms.Resize(256), | |
| transforms.CenterCrop(224), | |
| transforms.ToTensor(), | |
| normalize, | |
| ]) | |
| img = transform_pipeline(img) | |
| # PyTorch pretrained models expect the Tensor dims to be (num input imgs, num color channels, height, width). | |
| # Currently however, we have (num color channels, height, width); let's fix this by inserting a new axis. | |
| img = img.unsqueeze(0) # Insert the new axis at index 0 i.e. in front of the other axes/dims. | |
| # Now that we have preprocessed our img, we need to convert it into a | |
| # Variable; PyTorch models expect inputs to be Variables. A PyTorch Variable is a | |
| # wrapper around a PyTorch Tensor. | |
| img = Variable(img) | |
| img = img.to(device) | |
| output = model(img) # Returns a Tensor of shape (batch, num class labels) | |
| _, preds = torch.max(output, 1) | |
| preds = preds.detach().cpu().numpy() | |
| return preds[0] | |
| def pre_image2(img,model): | |
| model.eval() | |
| #img = Image.open(img) | |
| normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406], | |
| std=[0.229, 0.224, 0.225]) | |
| transform_pipeline = transforms.Compose([ | |
| transforms.Resize(256), | |
| transforms.CenterCrop(224), | |
| transforms.ToTensor(), | |
| normalize, | |
| ]) | |
| img = transform_pipeline(img) | |
| # PyTorch pretrained models expect the Tensor dims to be (num input imgs, num color channels, height, width). | |
| # Currently however, we have (num color channels, height, width); let's fix this by inserting a new axis. | |
| img = img.unsqueeze(0) # Insert the new axis at index 0 i.e. in front of the other axes/dims. | |
| # Now that we have preprocessed our img, we need to convert it into a | |
| # Variable; PyTorch models expect inputs to be Variables. A PyTorch Variable is a | |
| # wrapper around a PyTorch Tensor. | |
| img = Variable(img) | |
| img = img.to(device) | |
| output = model(img) # Returns a Tensor of shape (batch, num class labels) | |
| _, preds = torch.max(output, 1) | |
| preds = preds.detach().cpu().numpy() | |
| return preds[0] | |
| def findsubsets(s, n): | |
| return list(itertools.combinations(s, n)) | |
| def find_all_subsets(s): | |
| res = [] | |
| for i in range(1,len(s)+1): | |
| res+= findsubsets(s,i) | |
| return res+[()] | |
| def bitwise_general_or(comb,elt_mask_list): | |
| res_mask = elt_mask_list[comb[0]] | |
| for i in range(1,len(comb)): | |
| new_mask = elt_mask_list[comb[i]] | |
| res_mask = cv2.bitwise_and(res_mask,new_mask) | |
| return res_mask | |
| def overlap(res_mask,main_img): | |
| res_mask = np.mean(res_mask,axis=2) | |
| bw_mask = np.array(res_mask,dtype=np.uint8) | |
| img = np.array(main_img) | |
| rows,cols,channels = img.shape | |
| roi = img[0:rows,0:cols] | |
| img1_bg = cv2.bitwise_and(roi,roi,mask=bw_mask) | |
| return img1_bg | |
| def mask_generation(main_img,painted_img): | |
| img1 = cv2.imread(main_img) | |
| img2 = cv2.imread(painted_img) | |
| k,l,m = img1.shape | |
| mat_3 = np.full((k,l,m),255) | |
| mat_3[(img1[:,:,0]!=img2[:,:,0]) | (img1[:,:,1]!=img2[:,:,1]) | (img1[:,:,2]!=img2[:,:,2])]=0 | |
| return mat_3 | |
| def calculate_weight(a_list): | |
| running_sum = 0 | |
| for e in a_list: | |
| running_sum+=2**e | |
| return running_sum | |
| def shape_to_mask( | |
| img_shape, points, shape_type=None, line_width=10, point_size=5 | |
| ): | |
| mask = np.zeros(img_shape[:2], dtype=np.uint8) | |
| mask = PIL.Image.fromarray(mask) | |
| draw = PIL.ImageDraw.Draw(mask) | |
| xy = [tuple(point) for point in points] | |
| if shape_type == "circle": | |
| assert len(xy) == 2, "Shape of shape_type=circle must have 2 points" | |
| (cx, cy), (px, py) = xy | |
| d = math.sqrt((cx - px) ** 2 + (cy - py) ** 2) | |
| draw.ellipse([cx - d, cy - d, cx + d, cy + d], outline=1, fill=1) | |
| elif shape_type == "rectangle": | |
| assert len(xy) == 2, "Shape of shape_type=rectangle must have 2 points" | |
| draw.rectangle(xy, outline=1, fill=1) | |
| elif shape_type == "line": | |
| assert len(xy) == 2, "Shape of shape_type=line must have 2 points" | |
| draw.line(xy=xy, fill=1, width=line_width) | |
| elif shape_type == "linestrip": | |
| draw.line(xy=xy, fill=1, width=line_width) | |
| elif shape_type == "point": | |
| assert len(xy) == 1, "Shape of shape_type=point must have 1 points" | |
| cx, cy = xy[0] | |
| r = point_size | |
| draw.ellipse([cx - r, cy - r, cx + r, cy + r], outline=1, fill=1) | |
| else: | |
| assert len(xy) > 2, "Polygon must have points more than 2" | |
| draw.polygon(xy=xy, outline=1, fill=1) | |
| mask = np.array(mask, dtype=bool) | |
| return mask | |
| def combine_similar_masks(dj,shape): | |
| j = 0 | |
| for i in range(len(dj['shapes'])): | |
| if dj['shapes'][i]["label"]==shape: | |
| j+=1 | |
| curr_mask = shape_to_mask((dj['imageHeight'],dj['imageWidth']), dj['shapes'][i]['points'], shape_type=None,line_width=1, point_size=1) | |
| mask_img = curr_mask.astype(np.int)#boolean to 0,Convert to 1 | |
| mask_img = 255*mask_img | |
| mask_img = np.stack((mask_img, mask_img, mask_img), axis=2) | |
| mask_img = 255 - mask_img | |
| if j==1: | |
| result_mask= mask_img | |
| else: | |
| result_mask = cv2.bitwise_and(mask_img, result_mask) | |
| return result_mask | |
| def combine_all_masks(dj): | |
| j = 0 | |
| for i in range(len(dj['shapes'])): | |
| j+=1 | |
| curr_mask = shape_to_mask((dj['imageHeight'],dj['imageWidth']), dj['shapes'][i]['points'], shape_type=None,line_width=1, point_size=1) | |
| mask_img = curr_mask.astype(np.int)#boolean to 0,Convert to 1 | |
| mask_img = 255*mask_img | |
| mask_img = np.stack((mask_img, mask_img, mask_img), axis=2) | |
| mask_img = 255 - mask_img | |
| if j==1: | |
| result_mask= mask_img | |
| else: | |
| result_mask = cv2.bitwise_and(mask_img, result_mask) | |
| return result_mask | |
| def get_key(my_dict,val): | |
| for key, value in my_dict.items(): | |
| if val == value: | |
| return key | |
| import json | |
| import tempfile | |
| #TODO: Add a region for bg, so add a shape in unique_shape_set, write a function forcombiningall masks and doing the not to found the | |
| #bg mask and then the rest is the same | |
| def generate_predictions(path, main_img): | |
| print(main_img) | |
| #generate all elemantary masks | |
| #if flag=True then combine similar label masks, else no | |
| #with open(path, "r",encoding="utf-8") as f: | |
| path[0].seek(0) | |
| my_bytes = path[0].read() | |
| string_data = my_bytes.decode('utf8') | |
| dj = json.loads(string_data) | |
| bit_assignment = {} | |
| elt_mask_dict = {} | |
| unique_shape_set = set() | |
| for elt in dj["shapes"]: | |
| unique_shape_set.add(elt["label"]) | |
| #unique_shape_set.add('bg') | |
| l = len(unique_shape_set) | |
| i = l-1 | |
| for shape in unique_shape_set: | |
| if shape=='bg': | |
| intermed_mask = combine_all_masks(dj) | |
| mask_img = 255 - intermed_mask | |
| bit_assignment[shape]=i | |
| elt_mask_dict[i] = mask_img | |
| i = i-1 | |
| else: | |
| mask_img = combine_similar_masks(dj,shape) | |
| bit_assignment[shape]= i | |
| elt_mask_dict[i]= mask_img | |
| i=i-1 | |
| true_prediction = pre_image2(main_img, model) | |
| all_file_comb_list = find_all_subsets(elt_mask_dict) | |
| minterms = [] | |
| bit_list = list(elt_mask_dict.keys()) | |
| print(len(all_file_comb_list)) | |
| for comb in all_file_comb_list: | |
| print('ho') | |
| if comb == (): | |
| res_image = np.array(main_img) | |
| prediction = true_prediction | |
| else: | |
| res_mask = bitwise_general_or(comb,elt_mask_dict) | |
| res_image = overlap(res_mask,main_img) | |
| prediction = pre_image(res_image,model) | |
| if prediction==true_prediction: | |
| region_present = [e for e in bit_list if not e in list(comb)] | |
| minterms.append(calculate_weight(region_present)) | |
| dictionary = {} | |
| ch = 'a' | |
| for i in range(l): | |
| dictionary[chr(ord(ch) -i+l-1)]=get_key(bit_assignment, i) | |
| #print(dictionary) | |
| print('no') | |
| result = quin_macluskey(l,minterms, dictionary) | |
| print(result) | |
| return result | |
| gr.Interface(fn=generate_predictions, | |
| inputs=["files", "pil"], | |
| outputs="text").launch(share= True, debug= True) | |