├── .idea ├── .gitignore ├── encodings.xml ├── misc.xml ├── modules.xml ├── untitled1.iml └── vcs.xml ├── ColoredImageEnh.py ├── ImageEnh.py ├── README.md ├── Results ├── cells.PNG ├── cells2x2x2.png ├── cells2x2x4.png ├── island.PNG ├── island2x2x2.png ├── island2x2x4.png ├── miss.PNG ├── miss1x1x1.png ├── miss2x2x2.png ├── miss2x2x4.png ├── road.PNG ├── road2x2x2.png ├── skeleton.PNG └── skeleton2x2x2.png ├── main.py ├── test_images └── cells.PNG └── utils.py /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/untitled1.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 11 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /ColoredImageEnh.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from scipy.interpolate import interp1d 3 | from utils import utils 4 | 5 | epsilon = 0.000001 6 | utils = utils() 7 | 8 | class ColoredImageEnh: 9 | def __init__(self, image, n, m, gamma): 10 | """ 11 | Initializing the model and it's variables 12 | :param image: image to be enhanced 13 | :param n: number of windows in width 14 | :param m: number of windows in height 15 | :param gamma: fuzzification coffecient 16 | """ 17 | self.image = image 18 | self.n = n 19 | self.m = m 20 | self.gamma = gamma 21 | 22 | # Membership matrix of pixels to each window 23 | self.pixelMemberships = np.full((n, m, image.shape[0], image.shape[1]), -1000, dtype=np.float) 24 | # Mean of each window 25 | self.windowsMean = np.full((n, m), -1000, dtype=np.float) 26 | # Cardinality of each window 27 | self.windowsCard = np.full((n, m), -1000, dtype=np.float) 28 | self.pijMat = np.full((n, m, image.shape[0], image.shape[1]), -1000, dtype=np.float) 29 | # Variance of each window 30 | self.windowsVariance = np.full((n, m), -1000, dtype=np.float) 31 | 32 | self.image = self.convertImgDown(self.image) 33 | self.epsilon = 0.00001 34 | # Luminosity matrix of colored image 35 | self.lum = np.full((image.shape[0] , image.shape[1]) , -1000 , dtype=np.float) 36 | 37 | def convertImgDown(self, image): 38 | """ 39 | Mapping pixel values from interval [0 , 255] to [-1 , 1] 40 | :param image: image needed to be converted 41 | :return: image after mapping it to interval [-1 , 1] 42 | """ 43 | mapping = interp1d([0, 255], [-1, 1]) 44 | image = mapping(image) 45 | return image 46 | 47 | def convertImgUp(self, img): 48 | """ 49 | Mapping pixel values from interval [-1 , 1] to interval [0 , 255] 50 | :param img: image needed to be converted 51 | :return: image after mapping 52 | """ 53 | mapping = interp1d([np.min(img), np.max(img)], [0, 255]) 54 | img = mapping(img) 55 | return img 56 | 57 | def imageLuminosity(self,i,j): 58 | """ 59 | Calculating the Luminosity of colored image at index i , j 60 | :param i: row index 61 | :param j: column index 62 | :return: The luminosity value at index [i j] 63 | """ 64 | if self.lum[i][j] == -1000: 65 | for x in range(self.image.shape[0]): 66 | for y in range(self.image.shape[1]): 67 | temp = utils.add(self.image[x][y][2] , self.image[x][y][1]) 68 | temp = utils.add(temp , self.image[x][y][0]) 69 | self.lum[x][y] = utils.mult(1/3 , temp) 70 | return self.lum[i][j] 71 | 72 | 73 | def qxi(self, i, x): 74 | """ 75 | Calculating formula: 76 | :param i: 77 | :param x: 78 | :return: 79 | """ 80 | x0 = 0 81 | x1 = self.image.shape[0] 82 | nCi = utils.comb(self.n, i) 83 | nom = ((x - x0) ** i) * ((x1 - x) ** (self.n - i)) 84 | denom = (x1 - x0) ** self.n 85 | ans = nCi * nom / denom 86 | return ans 87 | 88 | def qyj(self, j, y): 89 | y0 = 0 90 | y1 = self.image.shape[1] 91 | nCi = utils.comb(self.m, j) 92 | nom = (np.power((y - y0), j)) * (np.power((y1 - y), (self.m - j))) 93 | denom = (y1 - y0) ** self.m 94 | ans = nCi * nom / denom 95 | return ans 96 | 97 | def pij(self, i, j, x, y): 98 | if self.pijMat[i][j][x][y] == -1000: 99 | ans = self.qxi(i, x) * self.qyj(j, y) 100 | self.pijMat[i][j][x][y] = ans 101 | return self.pijMat[i][j][x][y] 102 | 103 | def membership(self, i, j, x, y): 104 | """ 105 | Calculating the membership of pixel [x][y] to a window i,j 106 | :param i: window row index 107 | :param j: window column index 108 | :param x: pixel row index 109 | :param y: pixel column index 110 | :return: Membership value 111 | """ 112 | if self.pixelMemberships[i][j][x][y] == -1000: 113 | nom = self.pij(i, j, x, y) ** self.gamma 114 | denom = 0 115 | for idx1 in range(self.n): 116 | for idx2 in range(self.m): 117 | denom += np.power(self.pij(idx1, idx2, x, y), self.gamma) 118 | ans = nom / (denom + epsilon) 119 | self.pixelMemberships[i][j][x][y] = ans 120 | return self.pixelMemberships[i][j][x][y] 121 | 122 | def windowCard(self, i, j): 123 | """ 124 | Calculating the cardinality of window i,j 125 | :param i: 126 | :param j: 127 | :return: window card value 128 | """ 129 | if self.windowsCard[i][j] == -1000: 130 | card = 0.0 131 | for x in range(self.image.shape[0]): 132 | for y in range(self.image.shape[1]): 133 | card += self.membership(i, j, x, y) 134 | self.windowsCard[i][j] = card 135 | return self.windowsCard[i][j] 136 | 137 | def windowMean(self, i, j): 138 | """ 139 | Calculating the mean of window i,j 140 | :param i: 141 | :param j: 142 | :return: Mean value 143 | """ 144 | if self.windowsMean[i][j] == -1000: 145 | card = self.windowCard(i, j) 146 | mean = 0.0 147 | for x in range(self.image.shape[0]): 148 | for y in range(self.image.shape[1]): 149 | mean = utils.add(mean, utils.mult(self.membership(i, j, x, y) / card, self.imageLuminosity(x,y))) 150 | self.windowsMean[i][j] = mean 151 | return self.windowsMean[i][j] 152 | 153 | def windowVar(self, i, j): 154 | """ 155 | Calculating the squared Variance of a window 156 | :param i: 157 | :param j: 158 | :return: Squared variance value 159 | """ 160 | if self.windowsVariance[i][j] == -1000: 161 | var = 0.0 162 | card = self.windowCard(i, j) 163 | mean = self.windowMean(i, j) 164 | for x in range(self.image.shape[0]): 165 | for y in range(self.image.shape[1]): 166 | memship = self.membership(i, j, x, y) 167 | nom = memship * (utils.norm(utils.subtract(self.imageLuminosity(x,y), mean)) ** 2) 168 | denom = card 169 | var += nom / denom 170 | self.windowsVariance[i][j] = var 171 | return self.windowsVariance[i][j] 172 | 173 | def imageEnhance(self): 174 | """ 175 | Iterating over the channels , pixel and windows and calculate the new image after enhancing 176 | :return: Enhanced image after converting it to interval[0,255] 177 | """ 178 | final_img = np.zeros((self.image.shape[0] , self.image.shape[1] , 3) , dtype=np.float) 179 | sigma = np.sqrt(1/3) 180 | for chn in range(3): 181 | for i in range(self.n): 182 | for j in range(self.m): 183 | var = np.sqrt(self.windowVar(i,j)) 184 | mean = self.windowMean(i,j) 185 | for x in range(self.image.shape[0]): 186 | for y in range(self.image.shape[1]): 187 | memship = self.membership(i, j, x, y) 188 | final_img[x][y][chn] += utils.mult((memship*sigma/var) , utils.subtract(self.image[x][y][chn] , mean)) 189 | 190 | final_img = self.convertImgUp(final_img) 191 | 192 | return final_img 193 | 194 | 195 | 196 | 197 | 198 | 199 | -------------------------------------------------------------------------------- /ImageEnh.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from scipy.interpolate import interp1d 3 | import math 4 | from utils import utils 5 | 6 | epsilon = 0.00001 7 | utils = utils() 8 | class ImageEnh: 9 | def __init__(self, image, n, m, gamma): 10 | self.image = image 11 | self.n = n 12 | self.m = m 13 | self.gamma = gamma 14 | self.pixelMemberships = np.full((n, m, image.shape[0], image.shape[1]), -1000 , dtype=np.float) 15 | self.windowsMean = np.full((n, m), -1000 ,dtype=np.float) 16 | self.windowsCard = np.full((n, m), -1000 , dtype=np.float) 17 | self.pijMat = np.full((n, m, image.shape[0], image.shape[1]), -1000,dtype=np.float) 18 | self.windowsVariance = np.full((n, m), -1000,dtype=np.float) 19 | self.image = self.convertImgDown(self.image) 20 | self.epsilon = 0.00001 21 | 22 | 23 | def convertImgDown(self, image): 24 | mapping = interp1d([0, 255], [-1, 1]) 25 | image = mapping(image) 26 | # for x in range(self.image.shape[0]): 27 | # for y in range(self.image.shape[1]): 28 | # self.image[x][y] = (((self.image[x][y]) * (2)) / (255)) - 1 29 | return image 30 | 31 | def convertImgUp(self, img): 32 | num1 = np.abs(np.min(img)) 33 | num2 = np.abs(np.max(img)) 34 | mapping = interp1d([-1*max(num1,num2), max(num1,num2)], [0, 255]) 35 | img = mapping(img) 36 | # new_img = np.zeros((self.image.shape[0] , self.image.shape[1])) 37 | # for x in range(self.image.shape[0]): 38 | # for y in range(self.image.shape[1]): 39 | # new_img[x][y] = (((img[x][y] + 1) * (255)) / (2)) 40 | return img 41 | 42 | def qxi(self, i, x): 43 | x0 = 0 44 | x1 = self.image.shape[0] 45 | nCi = utils.comb(self.n, i) 46 | nom = ((x - x0) ** i) * ((x1 - x) ** (self.n - i)) 47 | denom = (x1 - x0) ** self.n 48 | ans = nCi * nom / denom 49 | # if ans > 1 or ans < 0: 50 | # print('Error in qxi : ', ans) 51 | return ans 52 | 53 | def qyj(self, j, y): 54 | y0 = 0 55 | y1 = self.image.shape[1] 56 | nCi = utils.comb(self.m, j) 57 | nom = (np.power((y - y0),j)) * (np.power((y1 - y) , (self.m - j))) 58 | denom = (y1 - y0) ** self.m 59 | ans = nCi * nom / denom 60 | # if ans > 1 or ans < 0: 61 | # print('Error in qyj : ', ans) 62 | return ans 63 | 64 | def pij(self, i, j, x, y): 65 | if self.pijMat[i][j][x][y] == -1000: 66 | ans = self.qxi(i, x) * self.qyj(j, y) 67 | # if ans > 1 or ans < 0: 68 | # print('Error in pij : ', i, j, ans) 69 | self.pijMat[i][j][x][y] = ans 70 | return self.pijMat[i][j][x][y] 71 | 72 | def membership(self, i, j, x, y): 73 | if self.pixelMemberships[i][j][x][y] == -1000: 74 | nom = self.pij(i, j, x, y) ** self.gamma 75 | denom = 0 76 | for idx1 in range(self.n): 77 | for idx2 in range(self.m): 78 | denom += np.power(self.pij(idx1, idx2, x, y), self.gamma) 79 | ans = nom / (denom + epsilon) 80 | if ans > 1 or ans < 0 or math.isnan(ans): 81 | print('Error in membership : ', denom) 82 | self.pixelMemberships[i][j][x][y] = ans 83 | return self.pixelMemberships[i][j][x][y] 84 | 85 | def windowCard(self, i, j): 86 | if self.windowsCard[i][j] == -1000: 87 | card = 0.0 88 | for x in range(self.image.shape[0]): 89 | for y in range(self.image.shape[1]): 90 | card += self.membership(i, j, x, y) 91 | self.windowsCard[i][j] = card 92 | return self.windowsCard[i][j] 93 | 94 | def windowMean(self, i, j): 95 | if self.windowsMean[i][j] == -1000: 96 | card = self.windowCard(i, j) 97 | mean = 0.0 98 | for x in range(self.image.shape[0]): 99 | for y in range(self.image.shape[1]): 100 | mean = utils.add(mean, utils.mult(self.membership(i, j, x, y) / card, self.image[x][y])) 101 | self.windowsMean[i][j] = mean 102 | return self.windowsMean[i][j] 103 | 104 | def windowVar(self, i, j): 105 | if self.windowsVariance[i][j] == -1000: 106 | var = 0.0 107 | card = self.windowCard(i, j) 108 | mean = self.windowMean(i, j) 109 | for x in range(self.image.shape[0]): 110 | for y in range(self.image.shape[1]): 111 | memship = self.membership(i, j, x, y) 112 | nom = memship * (utils.norm(utils.subtract(self.image[x][y], mean)) ** 2) 113 | denom = card 114 | var += nom / denom 115 | self.windowsVariance[i][j] = var 116 | return self.windowsVariance[i][j] 117 | 118 | def enhanceImage(self): 119 | image_copy = np.zeros((self.image.shape[0], self.image.shape[1])) 120 | sigma = np.sqrt(1/3) 121 | for i in range(self.n): 122 | for j in range(self.m): 123 | mean = self.windowMean(i, j) 124 | variance = np.sqrt(self.windowVar(i, j)) 125 | for x in range(self.image.shape[0]): 126 | for y in range(self.image.shape[1]): 127 | left = sigma / variance 128 | psi = utils.mult(left, utils.subtract(self.image[x][y], mean)) 129 | memship = self.membership(i, j, x, y) 130 | image_copy[x][y] += utils.mult(memship, psi) 131 | image_copy = self.convertImgUp(image_copy) 132 | return image_copy -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Color Image Enhancement Using the Support Fuzzification in the Framework of the Logarithmic Model 2 | 3 | This is an implementation of [Color Image Enhancement Using the Support Fuzzification in the Framework of the Logarithmic Model](https://www.researchgate.net/publication/237202014_Color_Image_Enhancement_Using_the_Support_Fuzzification_in_the_Framework_of_the_Logarithmic_Model) 4 | 5 | 6 | ### Prerequisites 7 | - cv2 8 | - numpy 9 | - scipy 10 | 11 | 12 | ### Running code 13 | main.py contains all what you need 14 | 15 | assign the global variable n,m and gamma as you wish 16 | 17 | assign the img_name variable with the image file name(without extension) you want to enahance (by default it should bee a PNG file but you can change the code in the functions: colored_enhancing() , gray_enhancing()) 18 | 19 | finally, calling the function: 20 | 21 | colored_enhancing() for enhancing colored images (obviously) 22 | 23 | gray_enhancing() for enhancing gray images 24 | 25 | 26 | ### Note 27 | all image files must be located at .\project_folder\test_images 28 | 29 | 30 | ### Results 31 | Test 1 32 | 33 | 34 | ![](https://github.com/ivan-abboud/Image_enhancement_with_fuzzy_logic/blob/master/Results/cells.PNG) 35 | ![n=2 ,m=2 ,gamma=2](https://github.com/ivan-abboud/Image_enhancement_with_fuzzy_logic/blob/master/Results/cells2x2x2.png) 36 | ![n=2 ,m=2 ,gamma=2](https://github.com/ivan-abboud/Image_enhancement_with_fuzzy_logic/blob/master/Results/cells2x2x4.png) 37 | 38 | 39 | Test 2 40 | 41 | 42 | ![](https://github.com/ivan-abboud/Image_enhancement_with_fuzzy_logic/blob/master/Results/miss.PNG) 43 | ![](https://github.com/ivan-abboud/Image_enhancement_with_fuzzy_logic/blob/master/Results/miss1x1x1.png) 44 | ![n=2 ,m=2 ,gamma=2](https://github.com/ivan-abboud/Image_enhancement_with_fuzzy_logic/blob/master/Results/miss2x2x2.png) 45 | ![n=2 ,m=2 ,gamma=2](https://github.com/ivan-abboud/Image_enhancement_with_fuzzy_logic/blob/master/Results/miss2x2x4.png) 46 | 47 | 48 | Test 3 49 | 50 | 51 | ![](https://github.com/ivan-abboud/Image_enhancement_with_fuzzy_logic/blob/master/Results/road.PNG) 52 | ![n=2 ,m=2 ,gamma=2](https://github.com/ivan-abboud/Image_enhancement_with_fuzzy_logic/blob/master/Results/road2x2x2.png) 53 | 54 | 55 | further tests can be seen in Results folder 56 | 57 | 58 | ## Acknowledgments 59 | 60 | Damascus University 61 | Department of Artifcial Intelligence 62 | -------------------------------------------------------------------------------- /Results/cells.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivan-abboud/Image_enhancement_using_fuzzy_logic/d229dcbfdc95146eba43a2596414fc3add2ba6b1/Results/cells.PNG -------------------------------------------------------------------------------- /Results/cells2x2x2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivan-abboud/Image_enhancement_using_fuzzy_logic/d229dcbfdc95146eba43a2596414fc3add2ba6b1/Results/cells2x2x2.png -------------------------------------------------------------------------------- /Results/cells2x2x4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivan-abboud/Image_enhancement_using_fuzzy_logic/d229dcbfdc95146eba43a2596414fc3add2ba6b1/Results/cells2x2x4.png -------------------------------------------------------------------------------- /Results/island.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivan-abboud/Image_enhancement_using_fuzzy_logic/d229dcbfdc95146eba43a2596414fc3add2ba6b1/Results/island.PNG -------------------------------------------------------------------------------- /Results/island2x2x2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivan-abboud/Image_enhancement_using_fuzzy_logic/d229dcbfdc95146eba43a2596414fc3add2ba6b1/Results/island2x2x2.png -------------------------------------------------------------------------------- /Results/island2x2x4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivan-abboud/Image_enhancement_using_fuzzy_logic/d229dcbfdc95146eba43a2596414fc3add2ba6b1/Results/island2x2x4.png -------------------------------------------------------------------------------- /Results/miss.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivan-abboud/Image_enhancement_using_fuzzy_logic/d229dcbfdc95146eba43a2596414fc3add2ba6b1/Results/miss.PNG -------------------------------------------------------------------------------- /Results/miss1x1x1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivan-abboud/Image_enhancement_using_fuzzy_logic/d229dcbfdc95146eba43a2596414fc3add2ba6b1/Results/miss1x1x1.png -------------------------------------------------------------------------------- /Results/miss2x2x2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivan-abboud/Image_enhancement_using_fuzzy_logic/d229dcbfdc95146eba43a2596414fc3add2ba6b1/Results/miss2x2x2.png -------------------------------------------------------------------------------- /Results/miss2x2x4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivan-abboud/Image_enhancement_using_fuzzy_logic/d229dcbfdc95146eba43a2596414fc3add2ba6b1/Results/miss2x2x4.png -------------------------------------------------------------------------------- /Results/road.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivan-abboud/Image_enhancement_using_fuzzy_logic/d229dcbfdc95146eba43a2596414fc3add2ba6b1/Results/road.PNG -------------------------------------------------------------------------------- /Results/road2x2x2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivan-abboud/Image_enhancement_using_fuzzy_logic/d229dcbfdc95146eba43a2596414fc3add2ba6b1/Results/road2x2x2.png -------------------------------------------------------------------------------- /Results/skeleton.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivan-abboud/Image_enhancement_using_fuzzy_logic/d229dcbfdc95146eba43a2596414fc3add2ba6b1/Results/skeleton.PNG -------------------------------------------------------------------------------- /Results/skeleton2x2x2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivan-abboud/Image_enhancement_using_fuzzy_logic/d229dcbfdc95146eba43a2596414fc3add2ba6b1/Results/skeleton2x2x2.png -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import ImageEnh 3 | import numpy as np 4 | import ColoredImageEnh 5 | 6 | 7 | n=2 8 | m=2 9 | gamma=4 10 | img_name = 'cells' 11 | test_folder = 'test_images' 12 | 13 | def colored_enhancing(): 14 | img = cv2.imread(test_folder + '\\' + img_name + '.png') 15 | print(img.shape) 16 | imgEnh = ColoredImageEnh.ColoredImageEnh(img, n, m, gamma) 17 | final_image = imgEnh.imageEnhance() 18 | final_image = np.array(final_image, dtype=np.uint8) 19 | cv2.imshow('before converting', img) 20 | cv2.imshow('final', final_image) 21 | cv2.imwrite(img_name + str(n) + 'x' + str(m) + 'x' + str(gamma) + '.png', final_image) 22 | print(final_image) 23 | cv2.waitKey(0) 24 | cv2.destroyAllWindows() 25 | 26 | def gray_enhancing(): 27 | img = cv2.imread(img_name + '.png') 28 | print(img.shape) 29 | img = cv2.cvtColor(img , cv2.COLOR_BGR2GRAY) 30 | imgEnh = ImageEnh.ImageEnh(img ,n,m,gamma) 31 | final_image = imgEnh.enhanceImage() 32 | final_image = np.array(final_image , dtype = np.uint8) 33 | cv2.imshow('before converting' , img) 34 | cv2.imshow('final' , final_image) 35 | cv2.imwrite(img_name+str(n)+'x'+str(m)+'x'+str(gamma)+'.png' , final_image) 36 | cv2.waitKey(0) 37 | cv2.destroyAllWindows() 38 | 39 | colored_enhancing() -------------------------------------------------------------------------------- /test_images/cells.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivan-abboud/Image_enhancement_using_fuzzy_logic/d229dcbfdc95146eba43a2596414fc3add2ba6b1/test_images/cells.PNG -------------------------------------------------------------------------------- /utils.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import operator as op 3 | from functools import reduce 4 | 5 | epsilon = 0.000001 6 | class utils: 7 | def __init__(self): 8 | self.epsilon = epsilon 9 | 10 | def add(self , x1, x2): 11 | return (x1 + x2) / (1 + (x1 * x2) + epsilon) 12 | 13 | def subtract(self ,x1, x2): 14 | return (x1 - x2) / (1 - (x1 * x2) + epsilon) 15 | 16 | def mult(self ,lamda, x): 17 | nom = ((1 + x) ** lamda) - ((1 - x) ** lamda) 18 | denom = ((1 + x) ** lamda) + ((1 - x) ** lamda) 19 | return nom / (denom+epsilon ) 20 | 21 | def fai(self ,x): 22 | return 0.5 * np.log((1 + x) / (1 - x + epsilon) ) 23 | 24 | def norm(self ,x): 25 | return np.abs(utils.fai(self,x)) 26 | 27 | def comb(self ,n, r): 28 | r = min(r, n - r) 29 | numer = reduce(op.mul, range(n, n - r, -1), 1) 30 | denom = reduce(op.mul, range(1, r + 1), 1) 31 | return numer / denom 32 | 33 | def colorAdd(self , q1,q2): 34 | res = [] 35 | res.append(self.add(q1[0] , q2[0])) 36 | res.append(self.add(q1[1] , q2[1])) 37 | res.append(self.add(q1[2] , q2[2])) 38 | return res 39 | 40 | 41 | def colorSub(self , q1,q2): 42 | res = [] 43 | res.append(self.subtract(q1[0] , q2[0])) 44 | res.append(self.subtract(q1[1] , q2[1])) 45 | res.append(self.subtract(q1[2] , q2[2])) 46 | return res 47 | 48 | def colorMult(self,lamda,q): 49 | res = [] 50 | res.append(self.mult(lamda, q[0])) 51 | res.append(self.mult(lamda, q[1])) 52 | res.append(self.mult(lamda, q[2])) 53 | return res 54 | 55 | def colorNorm(self,q): 56 | res = 0 57 | res += self.fai(q[0])**2 58 | res += self.fai(q[1])**2 59 | res += self.fai(q[2])**2 60 | return np.sqrt(res) --------------------------------------------------------------------------------