├── res-4.png ├── res-5.jpg ├── res-py.png ├── af-feature.png ├── README.md ├── demo.py ├── sparsify_segments.py ├── affinity_matrix_to_laplacian.py ├── sparse_test.py ├── semantic_soft_segmentation.py ├── preprocess_features.py ├── spectral_matting.py ├── soft_segments_from_eigs.py └── imguidedfilter.py /res-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lebronyxm/SSS-semantic-soft-segmentation/HEAD/res-4.png -------------------------------------------------------------------------------- /res-5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lebronyxm/SSS-semantic-soft-segmentation/HEAD/res-5.jpg -------------------------------------------------------------------------------- /res-py.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lebronyxm/SSS-semantic-soft-segmentation/HEAD/res-py.png -------------------------------------------------------------------------------- /af-feature.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lebronyxm/SSS-semantic-soft-segmentation/HEAD/af-feature.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # semantic_soft_segmentation 2 | python implementation of Semantic Soft Segmentation fork 3 | 4 | forked from qwymierne/semantic_soft_segmentation 5 | 6 | i find some errors in the original repo, so i fork it and pull some req. 7 | -------------------------------------------------------------------------------- /demo.py: -------------------------------------------------------------------------------- 1 | from scipy.misc import imread 2 | from semantic_soft_segmentation import semantic_soft_segmentation 3 | 4 | if __name__ == '__main__': 5 | #img = imread('COCO_train2014_000000362884.jpg', mode='RGB') 6 | image = imread('../af.png',mode='RGB') 7 | features = imread('../af-feature.png',mode='RGB') 8 | 9 | #features = img[:, img.shape[1] // 2 + 1:, :] 10 | #image = img[:, :img.shape[1] // 2, :] 11 | 12 | sss = semantic_soft_segmentation(image, features) 13 | -------------------------------------------------------------------------------- /sparsify_segments.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | 4 | def sparsify_segments(soft_segments, laplacian, image_grad=None): 5 | 6 | sigmaS = 1 # sparsity 7 | sigmaF = 1 # fidelity 8 | delta = 100 # constraint 9 | h, w, comp_cnt = soft_segments.shape 10 | N = h * w * comp_cnt 11 | 12 | if image_grad is None: 13 | sp_pow = 0.9 14 | else: 15 | image_grad[image_grad > 0.1] = 0.1 16 | image_grad = image_grad + 0.9 17 | sp_pow = np.matlib.repmat(image_grad, comp_cnt, 1) 18 | -------------------------------------------------------------------------------- /affinity_matrix_to_laplacian.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import scipy 3 | 4 | 5 | def affinity_matrix_to_laplacian(aff, normalize=False): 6 | N = aff.shape[0] 7 | if normalize: 8 | aa = np.sum(aff, axis=1) 9 | D = scipy.sparse.spdiags(aa, 0, N, N) 10 | aa = np.sqrt(1 / aa) 11 | D12 = scipy.sparse.spdiags(aa, 0, N, N) 12 | lap = np.matmul(np.matmul(D12, (D - aff)), D12) 13 | else: 14 | lap = scipy.sparse.spdiags(np.sum(aff, axis=1).reshape([-1]), 0, N, N) - aff 15 | 16 | return lap 17 | -------------------------------------------------------------------------------- /sparse_test.py: -------------------------------------------------------------------------------- 1 | from scipy import sparse 2 | from scipy.stats import uniform 3 | import numpy as np 4 | from datetime import datetime 5 | 6 | import random 7 | 8 | SIZE = 640 * 480 9 | # SIZE = 15 10 | 11 | 12 | def create_coo(): 13 | # non_zeros = random.randint(np.floor(np.sqrt(SIZE) - np.log(SIZE)), np.floor(np.sqrt(SIZE) + np.log(SIZE))) 14 | non_zeros = random.randint(np.floor(SIZE ** 1.2 - np.log(SIZE)), np.floor(SIZE ** 1.2 + np.log(SIZE))) 15 | print(datetime.now(), non_zeros) 16 | rows = np.array(random.choices(range(SIZE), k=non_zeros)) 17 | print(datetime.now()) 18 | cols = np.array(random.choices(range(SIZE), k=non_zeros)) 19 | print(datetime.now()) 20 | fill = [np.random.randn() for _ in range(non_zeros)] 21 | print(datetime.now()) 22 | return sparse.coo_matrix((fill, (rows, cols)), shape=(SIZE, SIZE)) 23 | 24 | 25 | if __name__ == '__main__': 26 | print(datetime.now()) 27 | print(create_coo().multiply(create_coo())) 28 | print(datetime.now()) 29 | -------------------------------------------------------------------------------- /semantic_soft_segmentation.py: -------------------------------------------------------------------------------- 1 | from preprocess_features import preprocess_features 2 | from spectral_matting import matting_affinity 3 | from affinity_matrix_to_laplacian import affinity_matrix_to_laplacian 4 | from soft_segments_from_eigs import soft_segments_from_eigs 5 | 6 | import scipy 7 | from scipy.misc import imread 8 | import numpy as np 9 | 10 | 11 | def semantic_soft_segmentation(img, features): 12 | # img = imread(image_path, mode='RGB') 13 | if features.shape[2] > 3: 14 | features = preprocess_features(features, img) 15 | # else: 16 | # features = imread(features) 17 | 18 | # superpixels = Superpixels(img) 19 | h, w, _ = img.shape 20 | affinities = list() 21 | affinities.append(matting_affinity(img)) 22 | # affinities[1] = superpixels.neighbor_affinities(features) 23 | # affinities[2] = superpixels.nearby_affinities(img) 24 | laplacian = affinity_matrix_to_laplacian(affinities[0] 25 | # + 0.01 * affinities[1] 26 | # + 0.01 * affinities[2] 27 | ) 28 | 29 | eig_cnt = 100 30 | eigen_values, eigen_vectors = scipy.sparse.linalg.eigs(laplacian, k=eig_cnt, which='LM') 31 | # idx = eigen_values.argsort() 32 | # eigen_values = eigen_values[idx][:eig_cnt] 33 | # eigen_vectors = eigen_vectors[:, idx][:eig_cnt] 34 | 35 | initial_segm_cnt = 40 36 | sparsity_param = 0.8 37 | iter_cnt = 40 38 | init_soft_segments = soft_segments_from_eigs(eigen_vectors, laplacian, h, w, eigen_values, features, 39 | initial_segm_cnt, iter_cnt, sparsity_param) 40 | # grouped_segments = group_segments(init_soft_segments, features) 41 | # soft_segments = sparsify_segments(grouped_segments, laplacian, image_gradient(img, False, 6)) 42 | 43 | return ( 44 | # soft_segments, 45 | init_soft_segments, 46 | laplacian, 47 | affinities, 48 | features, 49 | # superpixels, 50 | eigen_vectors, 51 | eigen_values 52 | ) 53 | -------------------------------------------------------------------------------- /preprocess_features.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from imguidedfilter import imguidedfilter 3 | from scipy.io import loadmat 4 | from scipy import misc 5 | import cv2 6 | 7 | def feature_PCA(features, dim): 8 | features = features.astype(float) 9 | h, w, d = features.shape 10 | features = features.reshape((-1, d)) 11 | #print(features.shape) 12 | featmean = np.mean(features, axis=0).reshape((1,-1)) #not 0 13 | #featmean = np.mean(features, axis=0) #not 0 14 | #print(featmean.shape) 15 | #temp = np.matmul(np.ones((h * w)), featmean) 16 | features = features - np.dot(np.ones((h * w)).reshape((h * w,1)), featmean)#(dim 0) != (dim 0) 17 | #features = features - np.matmul(np.ones((h * w)), featmean) #(dim 1) != 1 (dim 0) 18 | covar = np.matmul(features.T, features) 19 | eigen_values, eigen_vectors = np.linalg.eig(covar) 20 | idx = eigen_values.argsort() 21 | eigen_vectors = eigen_vectors[:, idx[:-dim-1:-1]] 22 | #eigen_vectors = eigen_vectors[:, idx][:dim] 23 | print(features.shape) 24 | print(eigen_vectors.shape) 25 | pcafeat = np.matmul(features, eigen_vectors) 26 | pcafeat = pcafeat.reshape((h, w, dim)) 27 | 28 | return pcafeat 29 | 30 | def rgb2gray(rgb): 31 | return np.dot(rgb[...,:3], [0.299, 0.587, 0.114]) 32 | 33 | def preprocess_features(features, img=None): 34 | features[features < -5] = -5 35 | features[features > 5] = 5 36 | 37 | if img is not None: 38 | fd = features.shape[2] 39 | #fd = features.shape[3] 40 | maxfd = fd - fd % 3 41 | for i in range(0, maxfd, 3): 42 | # features(:, :, i : i+2) = imguidedfilter(features(:, :, i : i+2), image, 'NeighborhoodSize', 10); 43 | features[:, :, i : i + 3] = imguidedfilter(features[:, :, i : i + 3], img, (10, 10), 0.01) 44 | for i in range(maxfd, fd): 45 | # features(:, :, i) = imguidedfilter(features(:, :, i), image, 'NeighborhoodSize', 10); 46 | features[:, :, i] = imguidedfilter(features[:, :, i], img, (10, 10), 0.01) 47 | 48 | simp = feature_PCA(features, 3) 49 | for i in range(0, 3): 50 | # simp(:,:,i) = simp(:,:,i) - min(min(simp(:,:,i))); 51 | simp[:, :, i] = simp[:, :, i] - simp[:, :, i].min() 52 | # simp(:,:,i) = simp(:,:,i) / max(max(simp(:,:,i))); 53 | simp[:, :, i] = simp[:, :, i] / simp[:, :, i].max() 54 | 55 | return simp 56 | 57 | ori=loadmat('/Users/yangxuemeng/mygithub/SemanticSoftSegmentation/af.mat') 58 | feat = ori['embedmap'] 59 | img = misc.imread('../af.png',mode='RGB') 60 | simp = preprocess_features(feat,img) 61 | misc.imsave('./res-9.jpg',simp) 62 | -------------------------------------------------------------------------------- /spectral_matting.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import numpy.matlib 3 | import skimage 4 | import scipy.ndimage 5 | from scipy.misc import imread 6 | import matplotlib.pyplot as plt 7 | 8 | 9 | def local_RGB_normal_distributions(img, window_radius=1, epsilon=1e-8): 10 | h, w, c = img.shape 11 | N = h * w 12 | window_size = 2 * window_radius + 1 13 | 14 | img_mean = scipy.ndimage.generic_filter(img, np.mean, size=(window_size, window_size, 1)) 15 | cov_mat = np.zeros((3, 3, N)) 16 | # cov_mat = (np.transpose(img - img_mean, (1, 2, 0)).reshape(-1, 2)).apply(np.cov) 17 | for r in range(c): 18 | for s in range(r, c): 19 | temp = scipy.ndimage.generic_filter(img[:, :, r] * img[:, :, s], np.mean, size=(window_size, window_size)) \ 20 | - img_mean[:, :, r] * img_mean[:, :, s] 21 | cov_mat[r, s] = temp.reshape((-1)) 22 | 23 | for i in range(c): 24 | cov_mat[i, i] += epsilon 25 | 26 | for r in range(1, c): 27 | for s in range(r): 28 | cov_mat[r, s] = cov_mat[s, r] 29 | 30 | return img_mean, cov_mat 31 | 32 | 33 | def matting_affinity(img, in_map=None, window_radius=1, epsilon=1e-7): 34 | window_size = 2 * window_radius + 1 35 | neigh_size = window_size ** 2 36 | h, w, c = img.shape 37 | if in_map is None: 38 | in_map = np.full((h, w), True) 39 | N = h * w 40 | epsilon = epsilon / neigh_size 41 | 42 | img_mean, cov_mat = local_RGB_normal_distributions(img, window_radius, epsilon) 43 | 44 | indices = np.array(range(h * w)).reshape(h, w) 45 | neigh_ind = skimage.util.view_as_windows(indices, window_size) 46 | in_map = in_map[window_radius:-window_radius, window_radius:-window_radius] 47 | neigh_ind = neigh_ind[in_map].reshape(-1, neigh_size) 48 | in_ind = neigh_ind[:, neigh_size // 2] 49 | pix_cnt = in_ind.shape[0] 50 | 51 | # Prepare in & out data 52 | img = img.transpose((2, 0, 1)).reshape(-1, 3) 53 | img_mean = img_mean.transpose((2, 0, 1)).reshape(-1, 3) 54 | flow_rows = np.zeros((neigh_size, neigh_size, pix_cnt)) 55 | flow_cols = np.zeros((neigh_size, neigh_size, pix_cnt)) 56 | flows = np.zeros((neigh_size, neigh_size, pix_cnt)) 57 | 58 | # Compute matting affinity 59 | for i in range(pix_cnt): 60 | neighs = neigh_ind[i] 61 | shifted_win_colors = img[neighs] - np.matlib.repmat(img_mean[in_ind[i]], neighs.shape[0], 1) 62 | flows[:, :, i] = np.matmul(shifted_win_colors, np.linalg.solve(cov_mat[:, :, in_ind[i]], shifted_win_colors.T)) 63 | neighs = np.matlib.repmat(neighs, neighs.shape[0], 1) 64 | flow_rows[:, :, i] = neighs 65 | flow_cols[:, :, i] = neighs.T 66 | 67 | flows = (flows + 1) / neigh_size 68 | 69 | W = scipy.sparse.coo_matrix((flows.reshape(-1), (flow_rows.reshape(-1), flow_cols.reshape(-1))), shape=[N, N]) 70 | W = (W + W.T) / 2 71 | 72 | print(W.shape) 73 | return W 74 | 75 | 76 | if __name__ == '__main__': 77 | matting_affinity('COCO_train2014_000000362884.jpg') 78 | -------------------------------------------------------------------------------- /soft_segments_from_eigs.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from sklearn.cluster import KMeans 3 | import math 4 | 5 | 6 | def soft_segments_from_eigs(eig_vecs, laplacian, h, w, eig_vals=None, features=None, comp_cnt=10, max_iter=20, 7 | sparsity_param=0.9, image_grad=None, initial_segments=None): 8 | 9 | eig_val_cnt = eig_vecs.shape[1] 10 | if eig_vals is None: 11 | eig_vals = 1e-5 * np.identity(eig_val_cnt) 12 | 13 | if initial_segments is None: 14 | if features is not None: 15 | features = features.reshape(-1, features.shape[2]) # TODO check 16 | initial_segments = KMeans(n_clusters=comp_cnt, max_iter=100, n_jobs=-1).fit_predict(features) 17 | else: 18 | eig_vals = abs(eig_vals) 19 | init_eigs_cnt = 20 20 | init_eigs_weights = np.diag(1 / np.sqrt(np.diag(eig_vecs[1:init_eigs_cnt + 1, 1:init_eigs_cnt + 1]))) 21 | init_eig_vecs = eig_vecs[:, 1:init_eigs_cnt + 1] * init_eigs_weights # TODO test 22 | initial_segments = KMeans(n_clusters=comp_cnt, max_iter=100, n_jobs=-1).fit_predict(features) 23 | 24 | soft_segments = np.zeros((len(initial_segments), comp_cnt)) 25 | for i in range(comp_cnt): 26 | soft_segments[:, i] = (initial_segments == i).astype(float) 27 | 28 | print(soft_segments) 29 | print(soft_segments.shape) 30 | 31 | if image_grad is None: 32 | sp_mat = sparsity_param 33 | else: 34 | image_grad[image_grad > 0.2] = 0.2 35 | image_grad = image_grad + 0.8 36 | sp_mat = np.matlib.repmat(image_grad, comp_cnt, 1) 37 | 38 | thr_e = 1e-10 39 | w1 = 0.3 40 | w0 = 0.3 41 | e1 = w1 ** sparsity_param * np.power(np.maximum(abs(soft_segments), thr_e), (sp_mat - 2)) 42 | print(e1) 43 | e0 = w0 ** sparsity_param * np.power(np.maximum(abs(soft_segments + 1), thr_e), (sp_mat - 2)) 44 | 45 | scld = 1 46 | eig_vectors = eig_vecs[:, :eig_val_cnt] 47 | eig_values = eig_vals[:eig_val_cnt] 48 | 49 | remove_iter = math.ceil(max_iter / 4) 50 | remove_iter_cycle = math.ceil(max_iter / 4) 51 | 52 | for iter in range(max_iter): 53 | tA = np.zeros(((comp_cnt - 1) * eig_val_cnt,(comp_cnt - 1) * eig_val_cnt)) 54 | tb = np.zeros(((comp_cnt - 1) * eig_val_cnt, 1)) 55 | for k in range(comp_cnt - 1): 56 | weighted_eigs = np.matlib.repmat(e1[:, k] + e0[:, k], 1, eig_val_cnt) * eig_vectors # czemu nie działa 57 | tA[k * eig_val_cnt:(k + 1) * eig_val_cnt, k * eig_val_cnt:(k + 1) * eig_val_cnt] = \ 58 | np.matmul(eig_vectors.T, weighted_eigs) + scld * eig_values 59 | tb[k * eig_val_cnt:(k + 1) * eig_val_cnt] = np.matmul(eig_vectors.T, e1[:,k]) 60 | k = comp_cnt 61 | weighted_eigs = np.matlib.repmat(e1[:, k] + e0[:, k], 1, eig_val_cnt) * eig_vectors 62 | ttA = np.matmul(eig_vectors.T, weighted_eigs + scld * eig_values) 63 | ttb = np.matmul(eig_vectors.T, e0[:, k]) + scld * np.sum(np.matmul(eig_vectors.T, laplacian), axis=1) 64 | 65 | tA = tA + np.matlib.repmat(ttA, comp_cnt - 1, comp_cnt - 1) 66 | tb = tb + np.matlib.repmat(ttb, comp_cnt - 1, 1) 67 | 68 | y = np.linalg.solve(tA, tb).reshape(eig_val_cnt, comp_cnt - 1) 69 | soft_segments = np.matmul(eig_vecs[:, :eig_val_cnt], y) 70 | soft_segments[:, comp_cnt - 1] = 1 - np.sum(soft_segments[:, :comp_cnt - 1], axis=1) 71 | 72 | if iter > remove_iter: 73 | nzii = filter((lambda x: x > 0.1), max(abs(soft_segments)) > 0.1) 74 | comp_cnt = len(nzii) 75 | soft_segments = soft_segments[:, nzii] 76 | remove_iter += remove_iter_cycle 77 | 78 | if len(sp_mat) == 1: 79 | e1 = w1 ** sparsity_param * np.power(np.maximum(abs(soft_segments), thr_e), (sp_mat - 2)) 80 | e0 = w0 ** sparsity_param * np.power(np.maximum(abs(soft_segments + 1), thr_e), (sp_mat - 2)) 81 | else: 82 | e1 = w1 ** sparsity_param * np.power(np.maximum(abs(soft_segments), thr_e), (sp_mat[:, :soft_segments.shape[1]] - 2)) 83 | e0 = w0 ** sparsity_param * np.power(np.maximum(abs(soft_segments + 1), thr_e), (sp_mat[:, :soft_segments.shape[1]] - 2)) 84 | soft_segments = soft_segments.reshape((h, w, soft_segments.shape[1])) 85 | return soft_segments 86 | -------------------------------------------------------------------------------- /imguidedfilter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding:utf-8 -*- 3 | 4 | # from https://github.com/BlueCocoa/imguidedfilter-opencv 5 | 6 | 7 | import cv2 8 | import numpy as np 9 | 10 | 11 | def imguidedfilter(A, G, filtSize, inversionEpsilon): 12 | """images.internal.algimguidedfilter @ matlab R2018a 13 | A: numpy ndaary image float [0, 1], [h,w,c] 14 | G: numpy ndaary image float [0, 1], [h,w,c] 15 | filtSize: 2-element tuple (h, w) 16 | """ 17 | sizeA = A.shape 18 | if len(sizeA) == 2: 19 | sizeA = (sizeA[0], sizeA[1], 1) 20 | sizeG = G.shape 21 | if len(sizeG) == 2: 22 | sizeG = (sizeG[0], sizeG[1], 1) 23 | 24 | doMultiChannelCovProcessing = sizeG[2] > sizeA[2] 25 | isGuidanceChannelReuseNeeded = sizeG[2] < sizeA[2] 26 | 27 | approximateGuidedFilter = False 28 | subsampleFactor = 1 29 | useIntergralFiltering = False 30 | # NotImplemented for nargin >= 5 31 | 32 | originalClassA = A.dtype 33 | A = A.astype(np.double) 34 | G = G.astype(np.double) 35 | 36 | B = np.zeros(A.shape, dtype=A.dtype) 37 | 38 | if not doMultiChannelCovProcessing: 39 | # Iprime = I[0:subsampleFactor:-1, 0:subsampleFactor:-1] 40 | # since we did not implement subsampleFactor 41 | I = G[:, :, 1] 42 | 43 | for k in range(0, sizeA[2]): 44 | # P = A[0:subsampleFactor:-1, 0:subsampleFactor:-1,k] 45 | # since we did not implement subsampleFactor 46 | P = A[:, :, k] 47 | 48 | if not isGuidanceChannelReuseNeeded: 49 | I = G[:, :, k] 50 | Iprime = I 51 | 52 | meanI = cv2.boxFilter(Iprime, -1, filtSize) 53 | meanP = cv2.boxFilter(P, -1, filtSize) 54 | corrI = cv2.boxFilter(Iprime * Iprime, -1, filtSize) 55 | corrIP = cv2.boxFilter(Iprime * P, -1, filtSize) 56 | 57 | varI = corrI - meanI * meanI 58 | covIP = corrIP - meanI * meanP 59 | 60 | a = covIP / (varI + inversionEpsilon) 61 | b = meanP - a * meanI 62 | 63 | meana = cv2.boxFilter(a, -1, filtSize) 64 | meanb = cv2.boxFilter(b, -1, filtSize) 65 | 66 | B[:, :, k] = meana * I + meanb 67 | else: 68 | # Iprime = G[0:subsampleFactor:-1, 0:subsampleFactor:-1, :] 69 | # since we did not implement subsampleFactor 70 | Iprime = G 71 | meanIrgb = cv2.boxFilter(Iprime, -1, filtSize) 72 | 73 | meanIr = meanIrgb[:, :, 0] 74 | meanIg = meanIrgb[:, :, 1] 75 | meanIb = meanIrgb[:, :, 2] 76 | 77 | # P = A[0:subsampleFactor:-1, 0:subsampleFactor:-1,:] 78 | # since we did not implement subsampleFactor 79 | P = A 80 | 81 | meanP = cv2.boxFilter(P, -1, filtSize) 82 | 83 | IP = Iprime * P.reshape((sizeA[0], sizeA[1], 1)) 84 | corrIrP = cv2.boxFilter(IP[:, :, 0], -1, filtSize) 85 | corrIgP = cv2.boxFilter(IP[:, :, 1], -1, filtSize) 86 | corrIbP = cv2.boxFilter(IP[:, :, 2], -1, filtSize) 87 | 88 | varIrr = cv2.boxFilter(Iprime[:, :, 0] * Iprime[:, :, 0], -1, filtSize) - meanIr * meanIr + inversionEpsilon 89 | varIrg = cv2.boxFilter(Iprime[:, :, 0] * Iprime[:, :, 1], -1, filtSize) - meanIr * meanIg 90 | varIrb = cv2.boxFilter(Iprime[:, :, 0] * Iprime[:, :, 2], -1, filtSize) - meanIr * meanIb 91 | varIgg = cv2.boxFilter(Iprime[:, :, 1] * Iprime[:, :, 1], -1, filtSize) - meanIg * meanIg + inversionEpsilon 92 | varIgb = cv2.boxFilter(Iprime[:, :, 1] * Iprime[:, :, 2], -1, filtSize) - meanIg * meanIb 93 | varIbb = cv2.boxFilter(Iprime[:, :, 2] * Iprime[:, :, 2], -1, filtSize) - meanIb * meanIb + inversionEpsilon 94 | 95 | covIrP = corrIrP - meanIr * meanP 96 | covIgP = corrIgP - meanIg * meanP 97 | covIbP = corrIbP - meanIb * meanP 98 | 99 | invMatEntry11 = varIgg * varIbb - varIgb * varIgb 100 | invMatEntry12 = varIgb * varIrb - varIrg * varIbb 101 | invMatEntry13 = varIrg * varIgb - varIgg * varIrb 102 | 103 | covDet = (invMatEntry11 * varIrr) + (invMatEntry12 * varIrg) + (invMatEntry13 * varIrb) 104 | 105 | a = np.zeros(sizeG, dtype=P.dtype) 106 | 107 | a[:, :, 0] = ((invMatEntry11 * covIrP) + \ 108 | ((varIrb * varIgb - varIrg * varIbb) * covIgP) + \ 109 | ((varIrg * varIgb - varIrb * varIgg) * covIbP)) / covDet 110 | 111 | a[:, :, 1] = ((invMatEntry12 * covIrP) + \ 112 | ((varIrr * varIbb - varIrb * varIrb) * covIgP) + \ 113 | ((varIrb * varIrg - varIrr * varIgb) * covIbP)) / covDet 114 | 115 | a[:, :, 2] = ((invMatEntry13 * covIrP) + \ 116 | ((varIrg * varIrb - varIrr * varIgb) * covIgP) + \ 117 | ((varIrr * varIgg - varIrg * varIrg) * covIbP)) / covDet 118 | 119 | b = meanP - (a[:, :, 0] * meanIr) - (a[:, :, 1] * meanIg) - (a[:, :, 2] * meanIb) 120 | 121 | a = cv2.boxFilter(a, -1, filtSize) 122 | b = cv2.boxFilter(b, -1, filtSize) 123 | 124 | B = np.sum(a * G, axis=2) + b 125 | return B 126 | --------------------------------------------------------------------------------