def skin_detect(img): """img: in BGR mode""" # initialized all-white mask skinMask = np.zeros(img.shape[0:2], img.dtype) img_LAB = cv2.cvtColor(img, cv2.COLOR_BGR2LAB).astype('float') img_HSV = cv2.cvtColor(img, cv2.COLOR_BGR2HSV).astype('float') # ellipse and HSV_test skinMask[ ellipse_test(img_LAB[...,1], img_LAB[...,2], bound=1.0, prob=0.6) & HSV_threshold(img_HSV[...,0], img_HSV[...,1]) ] \ = 255 # relaxed ellipse test, guarenteed by skin neighborhood skinMask[ (skinMask ==0) & ellipse_test(img_LAB[...,1], img_LAB[...,2] , bound=1.25, prob=0.6) & check_neighbor(skinMask)] = 255 # filling holes:image closing on skinMask # http://stackoverflow.com/a/10317883/2729100 _h,_w = img.shape[0:2] _kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(_h/16,_w/16)) skinMask_closed = cv2.morphologyEx(skinMask,cv2.MORPH_CLOSE,_kernel) # skinMask_closed = skinMask cape_util.display(np.hstack([skinMask, skinMask_closed]), name='skin mask closing before after', mode='gray') # initialization, can't remove, otherwise mask==0 area will be random skin = 255*np.ones(img.shape, img.dtype) skin = cv2.bitwise_and(img, img, mask=skinMask_closed) return skin, (skinMask_closed/255).astype(bool)
def exposure_correction(I_L, I_out, I_out_side_crr, skin_masks, faces_xywh, _eacp_lambda_): I_out_255 = cape_util.mag(I_out, 'float') A = np.ones(I_out_side_crr.shape) I_out_expo_crr = I_out_side_crr.copy() for i in range(len(faces_xywh)): x, y, w, h = faces_xywh[i] face = I_out_side_crr[y:y + h, x:x + w] # each sidelit crted face(L channel) skin_face = cape_util.mask_skin(face, skin_masks[i][1]) # SKIN on that face cumsum = cv2.calcHist([cape_util.mag(skin_face, 'trim')] # cumsumed hist of SKIN , [0], None, [255], [1, 256]).T.ravel().cumsum() # visualize cumsum of hist plt.plot(cumsum) plt.xlim([1, 256]) plt.show() p = np.searchsorted(cumsum, cumsum[-1] * 0.75) if p < 120: print 'face skin is underexposed!' f = (120 + p) / ((2 * p) + 1e-6) A[y:y + h, x:x + w][face > 0] = f # >0 means every pixel *\in S* A_after = EACP(A, I_out_255, lambda_=_eacp_lambda_) # to visualize A before/after EACP cape_util.display(np.hstack([A, A_after]), mode='rainbow') I_out_expo_crr = A_after * I_out_side_crr # to visualize exposure corrected face cape_util.display(cape_util.mag(I_out_expo_crr, 'trim'), name='exposure corrected L', mode='gray') return I_out_expo_crr
def skin_detect(img): """img: in BGR mode""" # initialized all-white mask skinMask = np.zeros(img.shape[0:2], img.dtype) img_LAB = cv2.cvtColor(img, cv2.COLOR_BGR2LAB).astype('float') img_HSV = cv2.cvtColor(img, cv2.COLOR_BGR2HSV).astype('float') # ellipse and HSV_test skinMask[ ellipse_test(img_LAB[...,1], img_LAB[...,2], bound=1.0, prob=0.6) & HSV_threshold(img_HSV[...,0], img_HSV[...,1]) ] \ = 255 # relaxed ellipse test, guarenteed by skin neighborhood skinMask[ (skinMask == 0) & ellipse_test(img_LAB[..., 1], img_LAB[..., 2], bound=1.25, prob=0.6) & check_neighbor(skinMask)] = 255 # filling holes:image closing on skinMask # http://stackoverflow.com/a/10317883/2729100 _h, _w = img.shape[0:2] _kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (_h / 16, _w / 16)) skinMask_closed = cv2.morphologyEx(skinMask, cv2.MORPH_CLOSE, _kernel) # skinMask_closed = skinMask cape_util.display(np.hstack([skinMask, skinMask_closed]), name='skin mask closing before after', mode='gray') # initialization, can't remove, otherwise mask==0 area will be random skin = 255 * np.ones(img.shape, img.dtype) skin = cv2.bitwise_and(img, img, mask=skinMask_closed) return skin, (skinMask_closed / 255).astype(bool)
def face_enhancement(I_origin, _eacp_lambda_=0.2): """ Keyword Arguments: I -- np.uint8, (m,n,3), BGR _eacp_lambda_ -- float, scala """ _I_LAB = cv2.cvtColor(I_origin, cv2.COLOR_BGR2LAB) I = _I_LAB[..., 0] Base, Detail = wls_filter.wlsfilter(I) I_out = Base # float [0,1] I_aindane = aindane.aindane(I_origin) faces_xywh = vj_face.face_detect(I_aindane) faces = [I_origin[y:y + h, x:x + w] for (x, y, w, h) in faces_xywh] skin_masks = [apa_skin.skin_detect(face) for face in faces] _any_skin = False for _mask in skin_masks: _any_skin |= ((_mask[1]).any()) if (faces_xywh == []) or (not _any_skin): # face not detected print 'face or skin not detected!' return I_origin _I_out_faces = [I_out[y:y + h, x:x + w] for (x, y, w, h) in faces_xywh] #float[0,1] S = [ cape_util.mask_skin(_I_out_faces[i], skin_masks[i][1]) \ for i in range(len(_I_out_faces)) ] # float [0,1] # to visualize detected skin and it's (unsmoothed) hist for idx, s in enumerate(S): cape_util.display(cape_util.mag(s), name='detected skin of L channel', mode='gray') # plot original hist(rectangles form, of S). don't include 0(masked) plt.hist(cape_util.mag(s).ravel(), 255, [1, 256]) plt.xlim([1, 256]) plt.show() ## save image data for R silverman analysis import os DATA_DIR = os.path.expanduser('~/Dropbox/dropcode/r/') # save skin pixels (value neq 0.0) np.savetxt(DATA_DIR + str(idx) + '.csv', s[s != 0.0].ravel(), delimiter=',') H = [cape_util.get_smoothed_hist(cape_util.mag(s)) for s in S] # visualize smoothed hist for h in H: plt.plot(h) plt.xlim([1, 256]) plt.show() I_out_side_crr = sidelight_correction(_I_LAB[..., 0], I_out, H, S, faces_xywh, _eacp_lambda_) I_out_expo_crr = exposure_correction(_I_LAB[..., 0], I_out, I_out_side_crr, skin_masks, faces_xywh, _eacp_lambda_) _I_LAB[..., 0] = cape_util.mag((I_out_expo_crr + 255.0 * Detail), 'trim') I_res = cv2.cvtColor(_I_LAB, cv2.COLOR_LAB2BGR) return I_res
def face_enhancement(I_origin, _eacp_lambda_=0.2): """ Keyword Arguments: I -- np.uint8, (m,n,3), BGR _eacp_lambda_ -- float, scala """ _I_LAB = cv2.cvtColor(I_origin, cv2.COLOR_BGR2LAB) I = _I_LAB[..., 0] Base, Detail = wls_filter.wlsfilter(I) I_out = Base # float [0,1] I_aindane = aindane.aindane(I_origin) faces_xywh = vj_face.face_detect(I_aindane) faces = [I_origin[y:y + h, x:x + w] for (x, y, w, h) in faces_xywh] skin_masks = [apa_skin.skin_detect(face) for face in faces] _any_skin = False for _mask in skin_masks: _any_skin |= ((_mask[1]).any()) if (faces_xywh == []) or (not _any_skin): # face not detected print 'face or skin not detected!' return I_origin _I_out_faces = [I_out[y:y + h, x:x + w] for (x, y, w, h) in faces_xywh] #float[0,1] S = [ cape_util.mask_skin(_I_out_faces[i], skin_masks[i][1]) \ for i in range(len(_I_out_faces)) ] # float [0,1] # to visualize detected skin and it's (unsmoothed) hist for idx, s in enumerate(S): cape_util.display(cape_util.mag(s), name='detected skin of L channel', mode='gray') # plot original hist(rectangles form, of S). don't include 0(masked) plt.hist(cape_util.mag(s).ravel(), 255, [1, 256]) plt.xlim([1, 256]) plt.show() ## save image data for R silverman analysis import os DATA_DIR = os.path.expanduser('~/Dropbox/dropcode/r/') # save skin pixels (value neq 0.0) np.savetxt(DATA_DIR+str(idx)+'.csv', s[s!=0.0].ravel(), delimiter=',') H = [cape_util.get_smoothed_hist(cape_util.mag(s)) for s in S] # visualize smoothed hist for h in H: plt.plot(h) plt.xlim([1, 256]) plt.show() I_out_side_crr = sidelight_correction(_I_LAB[..., 0], I_out, H, S, faces_xywh, _eacp_lambda_) I_out_expo_crr = exposure_correction(_I_LAB[..., 0], I_out, I_out_side_crr, skin_masks, faces_xywh, _eacp_lambda_) _I_LAB[..., 0] = cape_util.mag((I_out_expo_crr + 255.0 * Detail), 'trim') I_res = cv2.cvtColor(_I_LAB, cv2.COLOR_LAB2BGR) return I_res
def exposure_correction(I_L, I_out, I_out_side_crr, skin_masks, faces_xywh, _eacp_lambda_): I_out_255 = cape_util.mag(I_out, 'float') A = np.ones(I_out_side_crr.shape) I_out_expo_crr = I_out_side_crr.copy() for i in range(len(faces_xywh)): x, y, w, h = faces_xywh[i] face = I_out_side_crr[y:y + h, x:x + w] # each sidelit crted face(L channel) skin_face = cape_util.mask_skin(face, skin_masks[i][1]) # SKIN on that face cumsum = cv2.calcHist( [cape_util.mag(skin_face, 'trim')] # cumsumed hist of SKIN , [0], None, [255], [1, 256]).T.ravel().cumsum() # visualize cumsum of hist plt.plot(cumsum) plt.xlim([1, 256]) plt.show() p = np.searchsorted(cumsum, cumsum[-1] * 0.75) if p < 120: print 'face skin is underexposed!' f = (120 + p) / ((2 * p) + 1e-6) A[y:y + h, x:x + w][face > 0] = f # >0 means every pixel *\in S* A_after = EACP(A, I_out_255, lambda_=_eacp_lambda_) # to visualize A before/after EACP cape_util.display(np.hstack([A, A_after]), mode='rainbow') I_out_expo_crr = A_after * I_out_side_crr # to visualize exposure corrected face cape_util.display(cape_util.mag(I_out_expo_crr, 'trim'), name='exposure corrected L', mode='gray') return I_out_expo_crr
def sky_enhance(X, P, Sbgr ,I_origin, sky_prob_map): """ ARGs: ----- X: Alpha = x[0]; C = x[1]; S=x[2] P: sky_porb_map Sbgr: np.array([[[Sb, Sg, Sr]]]), mean of the sky color in current image NOTE: computing some color-like array (e.g. beta_old) will actually exceed 255, use 'float' instead of 'uint8' """ Alpha = X[0]; C = X[1]; S=X[2] f_sky_bgr = np.array([[[255,210,160]]], dtype='uint8') f_sky = cv2.cvtColor(f_sky_bgr, cv2.COLOR_BGR2LAB) # preferred color, in CIELab Slab = cv2.cvtColor(Sbgr, cv2.COLOR_BGR2LAB) f_lab = 1.0*f_sky / Slab # (f_l, f_a, f_b), correction ratio print 'f_lab: ', f_lab beta_old = cv2.cvtColor( cape_util.safe_convert(_2to3(S) * Sbgr, np.uint8), cv2.COLOR_BGR2LAB ) kai_old = cv2.cvtColor( cape_util.safe_convert(_2to3(C), np.uint8), cv2.COLOR_BGR2LAB ) W = np.array([[[100, 0, 0]]]) # W = np.array([[[255, 128, 128]]]) # (255,255,255) in RGB P_3 = _2to3(P) beta_new = cv2.add(P_3*(f_lab*beta_old), (1-P_3)*beta_old) kai_new = cv2.add(P_3*((W+kai_old)/2.0), (1-P_3)*kai_old) _fst = _2to3(1-Alpha)*cv2.cvtColor(beta_new.astype('uint8'), cv2.COLOR_LAB2BGR) _lst = _2to3(Alpha)*cv2.cvtColor(kai_new.astype('uint8'), cv2.COLOR_LAB2BGR) res = cv2.add( _fst, _lst ) # use cv2.add() to avoid overflow e.g. 150+125=255, not 20 # visualize _fst, _lst for debugging _first = I_origin.copy(); _last = I_origin.copy() _first[ sky_prob_to_01(sky_prob_map, thresh=0.0) ] = _fst[0] _last[ sky_prob_to_01(sky_prob_map, thresh=0.0) ] = _lst[0] cape_util.display( np.hstack([_first, _last] ) ) return res
def sidelight_correction(I_L, I_out, H, S, faces_xywh, _eacp_lambda_): I_out_255 = cape_util.mag(I_out, 'float') bimodal_Fs, D, M, B = cape_util.detect_bimodal(H) A = np.ones(I_out_255.shape) W = np.zeros(I_out_255.shape) for i in range(len(bimodal_Fs)): if bimodal_Fs[i] == True: b = B[i] d = D[i] m = M[i] f = (b - d) / (m - d) print str(i) + 'th face: d, m, b, f', d, m, b, f x, y, w, h = faces_xywh[i] A[y:y + h, x:x + w][(cape_util.mag(S[i], 'float') < m) & (cape_util.mag(S[i], 'float') > 0)] = f #<m and \in S global W miu = (I_out_255[A == f]).mean() sig = 255 * 3 # manually set, 3*sig = 120 close to 255/2 W = np.exp(-(I_out_255 - miu)**2 / sig**2) # W[A==f] = 1. W[...] = 1 - W[...] # W[A!=f] =1. W[...] = 1. # face_i_crr = EACP(I_out_255[y:y+h,x:x+w]*A, I_out_255[y:y+h,x:x+w], lambda_=_eacp_lambda_) # I_out_255[y:y+h, x:x+w] = face_i_crr else: print '? bimodal not detected on', i, 'th face' # W[...] = 1. cape_util.display(W, mode='rainbow') A_after = A.copy() if (A == 1).all(): print 'A == 1 everywhere!' else: A_after = EACP(A, I_L, W, lambda_=_eacp_lambda_) I_out_side_crr = A_after * I_out_255 # to visualize A before/after EACP cape_util.display(np.hstack([A, A_after]), mode='rainbow') # to visualize sidelight corrected result cape_util.display(cape_util.mag(I_out_side_crr, 'trim'), name='sidelight corrected, L', mode='gray') return I_out_side_crr # float [0.0,255.0]
def sidelight_correction(I_L, I_out, H, S, faces_xywh, _eacp_lambda_): I_out_255 = cape_util.mag(I_out, 'float') bimodal_Fs, D, M, B = cape_util.detect_bimodal(H) A = np.ones(I_out_255.shape) W = np.zeros(I_out_255.shape) for i in range(len(bimodal_Fs)): if bimodal_Fs[i] == True: b = B[i] d = D[i] m = M[i] f = (b - d) / (m - d) print str(i) + 'th face: d, m, b, f', d, m, b, f x, y, w, h = faces_xywh[i] A[y:y + h, x:x + w][(cape_util.mag(S[i], 'float') < m) & (cape_util.mag(S[i], 'float') > 0)] = f #<m and \in S global W miu = (I_out_255[A == f]).mean() sig = 255 * 3 # manually set, 3*sig = 120 close to 255/2 W = np.exp(-(I_out_255 - miu) ** 2 / sig ** 2) # W[A==f] = 1. W[...] = 1 - W[...] # W[A!=f] =1. W[...] = 1. # face_i_crr = EACP(I_out_255[y:y+h,x:x+w]*A, I_out_255[y:y+h,x:x+w], lambda_=_eacp_lambda_) # I_out_255[y:y+h, x:x+w] = face_i_crr else: print '? bimodal not detected on', i, 'th face' # W[...] = 1. cape_util.display(W, mode='rainbow') A_after = A.copy() if (A == 1).all(): print 'A == 1 everywhere!' else: A_after = EACP(A, I_L, W, lambda_=_eacp_lambda_) I_out_side_crr = A_after * I_out_255 # to visualize A before/after EACP cape_util.display(np.hstack([A, A_after]), mode='rainbow') # to visualize sidelight corrected result cape_util.display(cape_util.mag(I_out_side_crr, 'trim'), name='sidelight corrected, L', mode='gray') return I_out_side_crr # float [0.0,255.0]
def main(): I_origin = cv2.imread(IMG_DIR + 'input_teaser.png') lambda_ = 120 I_res = face_enhancement(I_origin, lambda_) cape_util.display(np.hstack([I_origin, I_res])) return 0
def main(): I_origin = cv2.imread(IMG_DIR+'pic23.jpg') res_disp,_ = sky_enhancement(I_origin) cape_util.display(np.hstack([I_origin, res_disp])) return 0
def _test(): I_bgr = cv2.imread(IMG_DIR + 'pic36.jpg') I_res_bgr = ss_enhance(I_bgr) cape_util.display(np.hstack([I_bgr, I_res_bgr])) return
def main(): img_name = 'pic23.jpg' I_org = cv2.imread(IMG_DIR+ img_name) skin_prob_map = apa_skin.skin_prob_map(I_org) lambda_ = 120 res_skin = I_org res_skin = face_enhancement.face_enhancement(I_org, lambda_) cape_util.display( np.hstack([I_org,res_skin]), name='res_skin' ) res_sky, sky_prob_map = sky_enhancement.sky_enhancement(res_skin) cape_util.display( np.hstack([I_org,res_sky]), name='res_sky' ) # res_ge = global_enhace(res_sky, skin_prob_map ,sky_prob_map) res_ge = global_enhace(res_skin, skin_prob_map ,sky_prob_map) cape_util.display( np.hstack([I_org,res_ge]), name='res_ge' ) res_ss = ss_enhance.ss_enhance(res_ge) cape_util.display( np.hstack([I_org,res_ss]), name='res_ss' ) res_de = detail_enhace(res_ss, skin_prob_map, sky_prob_map) cape_util.display( np.hstack([I_org,res_de]), name='res_de' ) # res_de = res_ss cape_util.display( np.hstack([I_org,res_de]), name='lambda_='+str(lambda_) ) DIR = './resources/results/' cv2.imwrite( DIR+str.split(img_name, '.')[0]+'_res.png', np.hstack([I_org, res_de]) ) return 0
def _test(): I_bgr = cv2.imread(IMG_DIR+'pic36.jpg') I_res_bgr = ss_enhance(I_bgr) cape_util.display(np.hstack([I_bgr, I_res_bgr])) return