mirror of
https://github.com/deepinsight/insightface.git
synced 2025-12-30 16:12:27 +00:00
refine repo structure
This commit is contained in:
@@ -18,11 +18,11 @@ try:
|
||||
except ImportError:
|
||||
raise ImportError(
|
||||
"Unable to import dependency mxnet. "
|
||||
"A quick tip is to install via `pip install mxnet-mkl/mxnet-cu90mkl --pre`. ")
|
||||
"A quick tip is to install via `pip install mxnet-mkl/mxnet-cu90mkl --pre`. "
|
||||
)
|
||||
|
||||
__version__ = '0.1.5'
|
||||
|
||||
from . import model_zoo
|
||||
from . import utils
|
||||
from . import app
|
||||
|
||||
|
||||
@@ -7,16 +7,21 @@ import mxnet.ndarray as nd
|
||||
from ..model_zoo import model_zoo
|
||||
from ..utils import face_align
|
||||
|
||||
__all__ = ['FaceAnalysis',
|
||||
'Face']
|
||||
__all__ = ['FaceAnalysis', 'Face']
|
||||
|
||||
Face = collections.namedtuple('Face', [
|
||||
'bbox', 'landmark', 'det_score', 'embedding', 'gender', 'age', 'embedding_norm', 'normed_embedding'])
|
||||
'bbox', 'landmark', 'det_score', 'embedding', 'gender', 'age',
|
||||
'embedding_norm', 'normed_embedding'
|
||||
])
|
||||
|
||||
Face.__new__.__defaults__ = (None, ) * len(Face._fields)
|
||||
|
||||
Face.__new__.__defaults__ = (None,) * len(Face._fields)
|
||||
|
||||
class FaceAnalysis:
|
||||
def __init__(self, det_name='retinaface_r50_v1', rec_name='arcface_r100_v1', ga_name='genderage_v1'):
|
||||
def __init__(self,
|
||||
det_name='retinaface_r50_v1',
|
||||
rec_name='arcface_r100_v1',
|
||||
ga_name='genderage_v1'):
|
||||
assert det_name is not None
|
||||
self.det_model = model_zoo.get_model(det_name)
|
||||
if rec_name is not None:
|
||||
@@ -35,26 +40,33 @@ class FaceAnalysis:
|
||||
if self.ga_model is not None:
|
||||
self.ga_model.prepare(ctx_id)
|
||||
|
||||
def get(self, img, det_thresh = 0.8, det_scale = 1.0, max_num = 0):
|
||||
bboxes, landmarks = self.det_model.detect(img, threshold=det_thresh, scale = det_scale)
|
||||
if bboxes.shape[0]==0:
|
||||
def get(self, img, det_thresh=0.8, det_scale=1.0, max_num=0):
|
||||
bboxes, landmarks = self.det_model.detect(img,
|
||||
threshold=det_thresh,
|
||||
scale=det_scale)
|
||||
if bboxes.shape[0] == 0:
|
||||
return []
|
||||
if max_num>0 and bboxes.shape[0]>max_num:
|
||||
area = (bboxes[:,2]-bboxes[:,0])*(bboxes[:,3]-bboxes[:,1])
|
||||
img_center = img.shape[0]//2, img.shape[1]//2
|
||||
offsets = np.vstack([ (bboxes[:,0]+bboxes[:,2])/2-img_center[1], (bboxes[:,1]+bboxes[:,3])/2-img_center[0] ])
|
||||
offset_dist_squared = np.sum(np.power(offsets,2.0),0)
|
||||
values = area-offset_dist_squared*2.0 # some extra weight on the centering
|
||||
bindex = np.argsort(values)[::-1] # some extra weight on the centering
|
||||
if max_num > 0 and bboxes.shape[0] > max_num:
|
||||
area = (bboxes[:, 2] - bboxes[:, 0]) * (bboxes[:, 3] -
|
||||
bboxes[:, 1])
|
||||
img_center = img.shape[0] // 2, img.shape[1] // 2
|
||||
offsets = np.vstack([
|
||||
(bboxes[:, 0] + bboxes[:, 2]) / 2 - img_center[1],
|
||||
(bboxes[:, 1] + bboxes[:, 3]) / 2 - img_center[0]
|
||||
])
|
||||
offset_dist_squared = np.sum(np.power(offsets, 2.0), 0)
|
||||
values = area - offset_dist_squared * 2.0 # some extra weight on the centering
|
||||
bindex = np.argsort(
|
||||
values)[::-1] # some extra weight on the centering
|
||||
bindex = bindex[0:max_num]
|
||||
bboxes = bboxes[bindex, :]
|
||||
landmarks = landmarks[bindex, :]
|
||||
ret = []
|
||||
for i in range(bboxes.shape[0]):
|
||||
bbox = bboxes[i, 0:4]
|
||||
det_score = bboxes[i,4]
|
||||
det_score = bboxes[i, 4]
|
||||
landmark = landmarks[i]
|
||||
_img = face_align.norm_crop(img, landmark = landmark)
|
||||
_img = face_align.norm_crop(img, landmark=landmark)
|
||||
embedding = None
|
||||
embedding_norm = None
|
||||
normed_embedding = None
|
||||
@@ -66,8 +78,13 @@ class FaceAnalysis:
|
||||
normed_embedding = embedding / embedding_norm
|
||||
if self.ga_model is not None:
|
||||
gender, age = self.ga_model.get(_img)
|
||||
face = Face(bbox = bbox, landmark = landmark, det_score = det_score, embedding = embedding, gender = gender, age = age
|
||||
, normed_embedding=normed_embedding, embedding_norm = embedding_norm)
|
||||
face = Face(bbox=bbox,
|
||||
landmark=landmark,
|
||||
det_score=det_score,
|
||||
embedding=embedding,
|
||||
gender=gender,
|
||||
age=age,
|
||||
normed_embedding=normed_embedding,
|
||||
embedding_norm=embedding_norm)
|
||||
ret.append(face)
|
||||
return ret
|
||||
|
||||
|
||||
@@ -4,11 +4,11 @@ import numpy as np
|
||||
import mxnet.ndarray as nd
|
||||
import cv2
|
||||
|
||||
__all__ = ['FaceDetector',
|
||||
'retinaface_r50_v1',
|
||||
'retinaface_mnet025_v1',
|
||||
'retinaface_mnet025_v2',
|
||||
'get_retinaface']
|
||||
__all__ = [
|
||||
'FaceDetector', 'retinaface_r50_v1', 'retinaface_mnet025_v1',
|
||||
'retinaface_mnet025_v2', 'get_retinaface'
|
||||
]
|
||||
|
||||
|
||||
def _whctrs(anchor):
|
||||
"""
|
||||
@@ -30,12 +30,11 @@ def _mkanchors(ws, hs, x_ctr, y_ctr):
|
||||
|
||||
ws = ws[:, np.newaxis]
|
||||
hs = hs[:, np.newaxis]
|
||||
anchors = np.hstack((x_ctr - 0.5 * (ws - 1),
|
||||
y_ctr - 0.5 * (hs - 1),
|
||||
x_ctr + 0.5 * (ws - 1),
|
||||
y_ctr + 0.5 * (hs - 1)))
|
||||
anchors = np.hstack((x_ctr - 0.5 * (ws - 1), y_ctr - 0.5 * (hs - 1),
|
||||
x_ctr + 0.5 * (ws - 1), y_ctr + 0.5 * (hs - 1)))
|
||||
return anchors
|
||||
|
||||
|
||||
def _ratio_enum(anchor, ratios):
|
||||
"""
|
||||
Enumerate a set of anchors for each aspect ratio wrt an anchor.
|
||||
@@ -61,6 +60,7 @@ def _scale_enum(anchor, scales):
|
||||
anchors = _mkanchors(ws, hs, x_ctr, y_ctr)
|
||||
return anchors
|
||||
|
||||
|
||||
def anchors_plane(height, width, stride, base_anchors):
|
||||
"""
|
||||
Parameters
|
||||
@@ -86,8 +86,11 @@ def anchors_plane(height, width, stride, base_anchors):
|
||||
all_anchors[ih, iw, k, 3] = base_anchors[k, 3] + sh
|
||||
return all_anchors
|
||||
|
||||
def generate_anchors(base_size=16, ratios=[0.5, 1, 2],
|
||||
scales=2 ** np.arange(3, 6), stride=16):
|
||||
|
||||
def generate_anchors(base_size=16,
|
||||
ratios=[0.5, 1, 2],
|
||||
scales=2**np.arange(3, 6),
|
||||
stride=16):
|
||||
"""
|
||||
Generate anchor (reference) windows by enumerating aspect ratios X
|
||||
scales wrt a reference (0, 0, 15, 15) window.
|
||||
@@ -95,10 +98,13 @@ def generate_anchors(base_size=16, ratios=[0.5, 1, 2],
|
||||
|
||||
base_anchor = np.array([1, 1, base_size, base_size]) - 1
|
||||
ratio_anchors = _ratio_enum(base_anchor, ratios)
|
||||
anchors = np.vstack([_scale_enum(ratio_anchors[i, :], scales)
|
||||
for i in range(ratio_anchors.shape[0])])
|
||||
anchors = np.vstack([
|
||||
_scale_enum(ratio_anchors[i, :], scales)
|
||||
for i in range(ratio_anchors.shape[0])
|
||||
])
|
||||
return anchors
|
||||
|
||||
|
||||
def generate_anchors_fpn(cfg):
|
||||
"""
|
||||
Generate anchor (reference) windows by enumerating aspect ratios X
|
||||
@@ -106,22 +112,23 @@ def generate_anchors_fpn(cfg):
|
||||
"""
|
||||
RPN_FEAT_STRIDE = []
|
||||
for k in cfg:
|
||||
RPN_FEAT_STRIDE.append( int(k) )
|
||||
RPN_FEAT_STRIDE.append(int(k))
|
||||
RPN_FEAT_STRIDE = sorted(RPN_FEAT_STRIDE, reverse=True)
|
||||
anchors = []
|
||||
for k in RPN_FEAT_STRIDE:
|
||||
v = cfg[str(k)]
|
||||
bs = v['BASE_SIZE']
|
||||
__ratios = np.array(v['RATIOS'])
|
||||
__scales = np.array(v['SCALES'])
|
||||
stride = int(k)
|
||||
#print('anchors_fpn', bs, __ratios, __scales, file=sys.stderr)
|
||||
r = generate_anchors(bs, __ratios, __scales, stride)
|
||||
#print('anchors_fpn', r.shape, file=sys.stderr)
|
||||
anchors.append(r)
|
||||
v = cfg[str(k)]
|
||||
bs = v['BASE_SIZE']
|
||||
__ratios = np.array(v['RATIOS'])
|
||||
__scales = np.array(v['SCALES'])
|
||||
stride = int(k)
|
||||
#print('anchors_fpn', bs, __ratios, __scales, file=sys.stderr)
|
||||
r = generate_anchors(bs, __ratios, __scales, stride)
|
||||
#print('anchors_fpn', r.shape, file=sys.stderr)
|
||||
anchors.append(r)
|
||||
|
||||
return anchors
|
||||
|
||||
|
||||
def clip_pad(tensor, pad_shape):
|
||||
"""
|
||||
Clip boxes of the pad area.
|
||||
@@ -133,10 +140,11 @@ def clip_pad(tensor, pad_shape):
|
||||
h, w = pad_shape
|
||||
|
||||
if h < H or w < W:
|
||||
tensor = tensor[:, :, :h, :w].copy()
|
||||
tensor = tensor[:, :, :h, :w].copy()
|
||||
|
||||
return tensor
|
||||
|
||||
|
||||
def bbox_pred(boxes, box_deltas):
|
||||
"""
|
||||
Transform the set of class-agnostic boxes into class-specific boxes
|
||||
@@ -174,11 +182,12 @@ def bbox_pred(boxes, box_deltas):
|
||||
# y2
|
||||
pred_boxes[:, 3:4] = pred_ctr_y + 0.5 * (pred_h - 1.0)
|
||||
|
||||
if box_deltas.shape[1]>4:
|
||||
pred_boxes[:,4:] = box_deltas[:,4:]
|
||||
if box_deltas.shape[1] > 4:
|
||||
pred_boxes[:, 4:] = box_deltas[:, 4:]
|
||||
|
||||
return pred_boxes
|
||||
|
||||
|
||||
def landmark_pred(boxes, landmark_deltas):
|
||||
if boxes.shape[0] == 0:
|
||||
return np.zeros((0, landmark_deltas.shape[1]))
|
||||
@@ -189,10 +198,11 @@ def landmark_pred(boxes, landmark_deltas):
|
||||
ctr_y = boxes[:, 1] + 0.5 * (heights - 1.0)
|
||||
pred = landmark_deltas.copy()
|
||||
for i in range(5):
|
||||
pred[:,i,0] = landmark_deltas[:,i,0]*widths + ctr_x
|
||||
pred[:,i,1] = landmark_deltas[:,i,1]*heights + ctr_y
|
||||
pred[:, i, 0] = landmark_deltas[:, i, 0] * widths + ctr_x
|
||||
pred[:, i, 1] = landmark_deltas[:, i, 1] * heights + ctr_y
|
||||
return pred
|
||||
|
||||
|
||||
class FaceDetector:
|
||||
def __init__(self, param_file, rac):
|
||||
self.param_file = param_file
|
||||
@@ -203,55 +213,74 @@ class FaceDetector:
|
||||
pos = self.param_file.rfind('-')
|
||||
prefix = self.param_file[0:pos]
|
||||
pos2 = self.param_file.rfind('.')
|
||||
epoch = int(self.param_file[pos+1:pos2])
|
||||
epoch = int(self.param_file[pos + 1:pos2])
|
||||
sym, arg_params, aux_params = mx.model.load_checkpoint(prefix, epoch)
|
||||
if ctx_id>=0:
|
||||
if ctx_id >= 0:
|
||||
ctx = mx.gpu(ctx_id)
|
||||
else:
|
||||
ctx = mx.cpu()
|
||||
model = mx.mod.Module(symbol=sym, context=ctx, label_names = None)
|
||||
model = mx.mod.Module(symbol=sym, context=ctx, label_names=None)
|
||||
if fix_image_size is not None:
|
||||
data_shape = (1,3)+fix_image_size
|
||||
data_shape = (1, 3) + fix_image_size
|
||||
else:
|
||||
data_shape = (1,3)+self.default_image_size
|
||||
data_shape = (1, 3) + self.default_image_size
|
||||
model.bind(data_shapes=[('data', data_shape)])
|
||||
model.set_params(arg_params, aux_params)
|
||||
#warmup
|
||||
data = mx.nd.zeros(shape=data_shape)
|
||||
db = mx.io.DataBatch(data=(data,))
|
||||
db = mx.io.DataBatch(data=(data, ))
|
||||
model.forward(db, is_train=False)
|
||||
out = model.get_outputs()[0].asnumpy()
|
||||
self.model = model
|
||||
self.nms_threshold = nms
|
||||
|
||||
self.landmark_std = 1.0
|
||||
_ratio = (1.,)
|
||||
_ratio = (1., )
|
||||
fmc = 3
|
||||
if self.rac=='net3':
|
||||
_ratio = (1.,)
|
||||
elif self.rac=='net3l':
|
||||
_ratio = (1.,)
|
||||
if self.rac == 'net3':
|
||||
_ratio = (1., )
|
||||
elif self.rac == 'net3l':
|
||||
_ratio = (1., )
|
||||
self.landmark_std = 0.2
|
||||
elif network=='net5': #retinaface
|
||||
elif network == 'net5': #retinaface
|
||||
fmc = 5
|
||||
else:
|
||||
assert False, 'rac setting error %s'%self.rac
|
||||
assert False, 'rac setting error %s' % self.rac
|
||||
|
||||
if fmc==3:
|
||||
if fmc == 3:
|
||||
self._feat_stride_fpn = [32, 16, 8]
|
||||
self.anchor_cfg = {
|
||||
'32': {'SCALES': (32,16), 'BASE_SIZE': 16, 'RATIOS': _ratio, 'ALLOWED_BORDER': 9999},
|
||||
'16': {'SCALES': (8,4), 'BASE_SIZE': 16, 'RATIOS': _ratio, 'ALLOWED_BORDER': 9999},
|
||||
'8': {'SCALES': (2,1), 'BASE_SIZE': 16, 'RATIOS': _ratio, 'ALLOWED_BORDER': 9999},
|
||||
}
|
||||
elif fmc==5:
|
||||
'32': {
|
||||
'SCALES': (32, 16),
|
||||
'BASE_SIZE': 16,
|
||||
'RATIOS': _ratio,
|
||||
'ALLOWED_BORDER': 9999
|
||||
},
|
||||
'16': {
|
||||
'SCALES': (8, 4),
|
||||
'BASE_SIZE': 16,
|
||||
'RATIOS': _ratio,
|
||||
'ALLOWED_BORDER': 9999
|
||||
},
|
||||
'8': {
|
||||
'SCALES': (2, 1),
|
||||
'BASE_SIZE': 16,
|
||||
'RATIOS': _ratio,
|
||||
'ALLOWED_BORDER': 9999
|
||||
},
|
||||
}
|
||||
elif fmc == 5:
|
||||
self._feat_stride_fpn = [64, 32, 16, 8, 4]
|
||||
self.anchor_cfg = {}
|
||||
_ass = 2.0**(1.0/3)
|
||||
_ass = 2.0**(1.0 / 3)
|
||||
_basescale = 1.0
|
||||
for _stride in [4, 8, 16, 32, 64]:
|
||||
key = str(_stride)
|
||||
value = {'BASE_SIZE': 16, 'RATIOS': _ratio, 'ALLOWED_BORDER': 9999}
|
||||
value = {
|
||||
'BASE_SIZE': 16,
|
||||
'RATIOS': _ratio,
|
||||
'ALLOWED_BORDER': 9999
|
||||
}
|
||||
scales = []
|
||||
for _ in range(3):
|
||||
scales.append(_basescale)
|
||||
@@ -261,61 +290,70 @@ class FaceDetector:
|
||||
|
||||
print(self._feat_stride_fpn, self.anchor_cfg)
|
||||
self.use_landmarks = False
|
||||
if len(sym)//len(self._feat_stride_fpn)==3:
|
||||
if len(sym) // len(self._feat_stride_fpn) == 3:
|
||||
self.use_landmarks = True
|
||||
print('use_landmarks', self.use_landmarks)
|
||||
self.fpn_keys = []
|
||||
|
||||
for s in self._feat_stride_fpn:
|
||||
self.fpn_keys.append('stride%s'%s)
|
||||
self.fpn_keys.append('stride%s' % s)
|
||||
|
||||
self._anchors_fpn = dict(zip(self.fpn_keys, generate_anchors_fpn(cfg=self.anchor_cfg)))
|
||||
self._anchors_fpn = dict(
|
||||
zip(self.fpn_keys, generate_anchors_fpn(cfg=self.anchor_cfg)))
|
||||
for k in self._anchors_fpn:
|
||||
v = self._anchors_fpn[k].astype(np.float32)
|
||||
self._anchors_fpn[k] = v
|
||||
self.anchor_plane_cache = {}
|
||||
|
||||
self._num_anchors = dict(zip(self.fpn_keys, [anchors.shape[0] for anchors in self._anchors_fpn.values()]))
|
||||
self._num_anchors = dict(
|
||||
zip(self.fpn_keys,
|
||||
[anchors.shape[0] for anchors in self._anchors_fpn.values()]))
|
||||
|
||||
def detect(self, img, threshold=0.5, scale=1.0):
|
||||
proposals_list = []
|
||||
scores_list = []
|
||||
landmarks_list = []
|
||||
if scale==1.0:
|
||||
if scale == 1.0:
|
||||
im = img
|
||||
else:
|
||||
im = cv2.resize(img, None, None, fx=scale, fy=scale, interpolation=cv2.INTER_LINEAR)
|
||||
im = cv2.resize(img,
|
||||
None,
|
||||
None,
|
||||
fx=scale,
|
||||
fy=scale,
|
||||
interpolation=cv2.INTER_LINEAR)
|
||||
im_info = [im.shape[0], im.shape[1]]
|
||||
im_tensor = np.zeros((1, 3, im.shape[0], im.shape[1]))
|
||||
for i in range(3):
|
||||
im_tensor[0, i, :, :] = im[:, :, 2 - i]
|
||||
data = nd.array(im_tensor)
|
||||
db = mx.io.DataBatch(data=(data,), provide_data=[('data', data.shape)])
|
||||
db = mx.io.DataBatch(data=(data, ),
|
||||
provide_data=[('data', data.shape)])
|
||||
self.model.forward(db, is_train=False)
|
||||
net_out = self.model.get_outputs()
|
||||
for _idx,s in enumerate(self._feat_stride_fpn):
|
||||
_key = 'stride%s'%s
|
||||
for _idx, s in enumerate(self._feat_stride_fpn):
|
||||
_key = 'stride%s' % s
|
||||
stride = int(s)
|
||||
if self.use_landmarks:
|
||||
idx = _idx*3
|
||||
idx = _idx * 3
|
||||
else:
|
||||
idx = _idx*2
|
||||
idx = _idx * 2
|
||||
scores = net_out[idx].asnumpy()
|
||||
scores = scores[:, self._num_anchors['stride%s'%s]:, :, :]
|
||||
idx+=1
|
||||
scores = scores[:, self._num_anchors['stride%s' % s]:, :, :]
|
||||
idx += 1
|
||||
bbox_deltas = net_out[idx].asnumpy()
|
||||
|
||||
height, width = bbox_deltas.shape[2], bbox_deltas.shape[3]
|
||||
A = self._num_anchors['stride%s'%s]
|
||||
A = self._num_anchors['stride%s' % s]
|
||||
K = height * width
|
||||
key = (height, width, stride)
|
||||
if key in self.anchor_plane_cache:
|
||||
anchors = self.anchor_plane_cache[key]
|
||||
else:
|
||||
anchors_fpn = self._anchors_fpn['stride%s'%s]
|
||||
anchors_fpn = self._anchors_fpn['stride%s' % s]
|
||||
anchors = anchors_plane(height, width, stride, anchors_fpn)
|
||||
anchors = anchors.reshape((K * A, 4))
|
||||
if len(self.anchor_plane_cache)<100:
|
||||
if len(self.anchor_plane_cache) < 100:
|
||||
self.anchor_plane_cache[key] = anchors
|
||||
|
||||
scores = clip_pad(scores, (height, width))
|
||||
@@ -323,43 +361,43 @@ class FaceDetector:
|
||||
|
||||
bbox_deltas = clip_pad(bbox_deltas, (height, width))
|
||||
bbox_deltas = bbox_deltas.transpose((0, 2, 3, 1))
|
||||
bbox_pred_len = bbox_deltas.shape[3]//A
|
||||
bbox_pred_len = bbox_deltas.shape[3] // A
|
||||
bbox_deltas = bbox_deltas.reshape((-1, bbox_pred_len))
|
||||
|
||||
proposals = bbox_pred(anchors, bbox_deltas)
|
||||
#proposals = clip_boxes(proposals, im_info[:2])
|
||||
|
||||
|
||||
scores_ravel = scores.ravel()
|
||||
order = np.where(scores_ravel>=threshold)[0]
|
||||
order = np.where(scores_ravel >= threshold)[0]
|
||||
proposals = proposals[order, :]
|
||||
scores = scores[order]
|
||||
|
||||
proposals[:,0:4] /= scale
|
||||
proposals[:, 0:4] /= scale
|
||||
|
||||
proposals_list.append(proposals)
|
||||
scores_list.append(scores)
|
||||
|
||||
if self.use_landmarks:
|
||||
idx+=1
|
||||
idx += 1
|
||||
landmark_deltas = net_out[idx].asnumpy()
|
||||
landmark_deltas = clip_pad(landmark_deltas, (height, width))
|
||||
landmark_pred_len = landmark_deltas.shape[1]//A
|
||||
landmark_deltas = landmark_deltas.transpose((0, 2, 3, 1)).reshape((-1, 5, landmark_pred_len//5))
|
||||
landmark_pred_len = landmark_deltas.shape[1] // A
|
||||
landmark_deltas = landmark_deltas.transpose(
|
||||
(0, 2, 3, 1)).reshape((-1, 5, landmark_pred_len // 5))
|
||||
landmark_deltas *= self.landmark_std
|
||||
#print(landmark_deltas.shape, landmark_deltas)
|
||||
landmarks = landmark_pred(anchors, landmark_deltas)
|
||||
landmarks = landmarks[order, :]
|
||||
|
||||
landmarks[:,:,0:2] /= scale
|
||||
landmarks[:, :, 0:2] /= scale
|
||||
landmarks_list.append(landmarks)
|
||||
|
||||
proposals = np.vstack(proposals_list)
|
||||
landmarks = None
|
||||
if proposals.shape[0]==0:
|
||||
if proposals.shape[0] == 0:
|
||||
if self.use_landmarks:
|
||||
landmarks = np.zeros( (0,5,2) )
|
||||
return np.zeros( (0,5) ), landmarks
|
||||
landmarks = np.zeros((0, 5, 2))
|
||||
return np.zeros((0, 5)), landmarks
|
||||
scores = np.vstack(scores_list)
|
||||
scores_ravel = scores.ravel()
|
||||
order = scores_ravel.argsort()[::-1]
|
||||
@@ -369,9 +407,10 @@ class FaceDetector:
|
||||
landmarks = np.vstack(landmarks_list)
|
||||
landmarks = landmarks[order].astype(np.float32, copy=False)
|
||||
|
||||
pre_det = np.hstack((proposals[:,0:4], scores)).astype(np.float32, copy=False)
|
||||
pre_det = np.hstack((proposals[:, 0:4], scores)).astype(np.float32,
|
||||
copy=False)
|
||||
keep = self.nms(pre_det)
|
||||
det = np.hstack( (pre_det, proposals[:,4:]) )
|
||||
det = np.hstack((pre_det, proposals[:, 4:]))
|
||||
det = det[keep, :]
|
||||
if self.use_landmarks:
|
||||
landmarks = landmarks[keep]
|
||||
@@ -409,18 +448,19 @@ class FaceDetector:
|
||||
return keep
|
||||
|
||||
|
||||
def get_retinaface(name, rac='net3',
|
||||
root='~/.insightface/models', **kwargs):
|
||||
def get_retinaface(name, rac='net3', root='~/.insightface/models', **kwargs):
|
||||
from .model_store import get_model_file
|
||||
_file = get_model_file("retinaface_%s"%name, root=root)
|
||||
_file = get_model_file("retinaface_%s" % name, root=root)
|
||||
return FaceDetector(_file, rac)
|
||||
|
||||
|
||||
def retinaface_r50_v1(**kwargs):
|
||||
return get_retinaface("r50_v1", rac='net3', **kwargs)
|
||||
|
||||
|
||||
def retinaface_mnet025_v1(**kwargs):
|
||||
return get_retinaface("mnet025_v1", rac='net3', **kwargs)
|
||||
|
||||
|
||||
def retinaface_mnet025_v2(**kwargs):
|
||||
return get_retinaface("mnet025_v2", rac='net3l', **kwargs)
|
||||
|
||||
|
||||
@@ -3,9 +3,7 @@ import mxnet as mx
|
||||
import numpy as np
|
||||
import cv2
|
||||
|
||||
__all__ = ['FaceGenderage',
|
||||
'genderage_v1',
|
||||
'get_genderage']
|
||||
__all__ = ['FaceGenderage', 'genderage_v1', 'get_genderage']
|
||||
|
||||
|
||||
class FaceGenderage:
|
||||
@@ -22,21 +20,22 @@ class FaceGenderage:
|
||||
pos = self.param_file.rfind('-')
|
||||
prefix = self.param_file[0:pos]
|
||||
pos2 = self.param_file.rfind('.')
|
||||
epoch = int(self.param_file[pos+1:pos2])
|
||||
sym, arg_params, aux_params = mx.model.load_checkpoint(prefix, epoch)
|
||||
epoch = int(self.param_file[pos + 1:pos2])
|
||||
sym, arg_params, aux_params = mx.model.load_checkpoint(
|
||||
prefix, epoch)
|
||||
all_layers = sym.get_internals()
|
||||
sym = all_layers['fc1_output']
|
||||
if ctx_id>=0:
|
||||
if ctx_id >= 0:
|
||||
ctx = mx.gpu(ctx_id)
|
||||
else:
|
||||
ctx = mx.cpu()
|
||||
model = mx.mod.Module(symbol=sym, context=ctx, label_names = None)
|
||||
data_shape = (1,3)+self.image_size
|
||||
model = mx.mod.Module(symbol=sym, context=ctx, label_names=None)
|
||||
data_shape = (1, 3) + self.image_size
|
||||
model.bind(data_shapes=[('data', data_shape)])
|
||||
model.set_params(arg_params, aux_params)
|
||||
#warmup
|
||||
data = mx.nd.zeros(shape=data_shape)
|
||||
db = mx.io.DataBatch(data=(data,))
|
||||
db = mx.io.DataBatch(data=(data, ))
|
||||
model.forward(db, is_train=False)
|
||||
embedding = model.get_outputs()[0].asnumpy()
|
||||
self.model = model
|
||||
@@ -45,33 +44,30 @@ class FaceGenderage:
|
||||
|
||||
def get(self, img):
|
||||
assert self.param_file and self.model
|
||||
assert img.shape[2]==3 and img.shape[0:2]==self.image_size
|
||||
assert img.shape[2] == 3 and img.shape[0:2] == self.image_size
|
||||
data = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
|
||||
data = np.transpose(data, (2,0,1))
|
||||
data = np.transpose(data, (2, 0, 1))
|
||||
data = np.expand_dims(data, axis=0)
|
||||
data = mx.nd.array(data)
|
||||
db = mx.io.DataBatch(data=(data,))
|
||||
db = mx.io.DataBatch(data=(data, ))
|
||||
self.model.forward(db, is_train=False)
|
||||
ret = self.model.get_outputs()[0].asnumpy()
|
||||
g = ret[:,0:2].flatten()
|
||||
g = ret[:, 0:2].flatten()
|
||||
gender = np.argmax(g)
|
||||
a = ret[:,2:202].reshape( (100,2) )
|
||||
a = ret[:, 2:202].reshape((100, 2))
|
||||
a = np.argmax(a, axis=1)
|
||||
age = int(sum(a))
|
||||
return gender, age
|
||||
|
||||
def get_genderage(name, download=True,
|
||||
root='~/.insightface/models', **kwargs):
|
||||
|
||||
def get_genderage(name, download=True, root='~/.insightface/models', **kwargs):
|
||||
if not download:
|
||||
return FaceGenderage(name, False, None)
|
||||
else:
|
||||
from .model_store import get_model_file
|
||||
_file = get_model_file("genderage_%s"%name, root=root)
|
||||
_file = get_model_file("genderage_%s" % name, root=root)
|
||||
return FaceGenderage(name, True, _file)
|
||||
|
||||
|
||||
def genderage_v1(**kwargs):
|
||||
return get_genderage("v1", download=True, **kwargs)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -3,9 +3,10 @@ import mxnet as mx
|
||||
import numpy as np
|
||||
import cv2
|
||||
|
||||
__all__ = ['FaceRecognition',
|
||||
'arcface_r100_v1', 'arcface_outofreach_v1', 'arcface_mfn_v1',
|
||||
'get_arcface']
|
||||
__all__ = [
|
||||
'FaceRecognition', 'arcface_r100_v1', 'arcface_outofreach_v1',
|
||||
'arcface_mfn_v1', 'get_arcface'
|
||||
]
|
||||
|
||||
|
||||
class FaceRecognition:
|
||||
@@ -22,21 +23,22 @@ class FaceRecognition:
|
||||
pos = self.param_file.rfind('-')
|
||||
prefix = self.param_file[0:pos]
|
||||
pos2 = self.param_file.rfind('.')
|
||||
epoch = int(self.param_file[pos+1:pos2])
|
||||
sym, arg_params, aux_params = mx.model.load_checkpoint(prefix, epoch)
|
||||
epoch = int(self.param_file[pos + 1:pos2])
|
||||
sym, arg_params, aux_params = mx.model.load_checkpoint(
|
||||
prefix, epoch)
|
||||
all_layers = sym.get_internals()
|
||||
sym = all_layers['fc1_output']
|
||||
if ctx_id>=0:
|
||||
if ctx_id >= 0:
|
||||
ctx = mx.gpu(ctx_id)
|
||||
else:
|
||||
ctx = mx.cpu()
|
||||
model = mx.mod.Module(symbol=sym, context=ctx, label_names = None)
|
||||
data_shape = (1,3)+self.image_size
|
||||
model = mx.mod.Module(symbol=sym, context=ctx, label_names=None)
|
||||
data_shape = (1, 3) + self.image_size
|
||||
model.bind(data_shapes=[('data', data_shape)])
|
||||
model.set_params(arg_params, aux_params)
|
||||
#warmup
|
||||
data = mx.nd.zeros(shape=data_shape)
|
||||
db = mx.io.DataBatch(data=(data,))
|
||||
db = mx.io.DataBatch(data=(data, ))
|
||||
model.forward(db, is_train=False)
|
||||
embedding = model.get_outputs()[0].asnumpy()
|
||||
self.model = model
|
||||
@@ -45,12 +47,12 @@ class FaceRecognition:
|
||||
|
||||
def get_embedding(self, img):
|
||||
assert self.param_file and self.model
|
||||
assert img.shape[2]==3 and img.shape[0:2]==self.image_size
|
||||
assert img.shape[2] == 3 and img.shape[0:2] == self.image_size
|
||||
data = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
|
||||
data = np.transpose(data, (2,0,1))
|
||||
data = np.transpose(data, (2, 0, 1))
|
||||
data = np.expand_dims(data, axis=0)
|
||||
data = mx.nd.array(data)
|
||||
db = mx.io.DataBatch(data=(data,))
|
||||
db = mx.io.DataBatch(data=(data, ))
|
||||
self.model.forward(db, is_train=False)
|
||||
embedding = self.model.get_outputs()[0].asnumpy()
|
||||
return embedding
|
||||
@@ -59,18 +61,19 @@ class FaceRecognition:
|
||||
emb1 = self.get_embedding(img1).flatten()
|
||||
emb2 = self.get_embedding(img2).flatten()
|
||||
from numpy.linalg import norm
|
||||
sim = np.dot(emb1, emb2)/(norm(emb1)*norm(emb2))
|
||||
sim = np.dot(emb1, emb2) / (norm(emb1) * norm(emb2))
|
||||
return sim
|
||||
|
||||
def get_arcface(name, download=True,
|
||||
root='~/.insightface/models', **kwargs):
|
||||
|
||||
def get_arcface(name, download=True, root='~/.insightface/models', **kwargs):
|
||||
if not download:
|
||||
return FaceRecognition(name, False, None)
|
||||
else:
|
||||
from .model_store import get_model_file
|
||||
_file = get_model_file("arcface_%s"%name, root=root)
|
||||
_file = get_model_file("arcface_%s" % name, root=root)
|
||||
return FaceRecognition(name, True, _file)
|
||||
|
||||
|
||||
def arcface_r100_v1(**kwargs):
|
||||
return get_arcface("r100_v1", download=True, **kwargs)
|
||||
|
||||
@@ -78,6 +81,6 @@ def arcface_r100_v1(**kwargs):
|
||||
def arcface_mfn_v1(**kwargs):
|
||||
return get_arcface("mfn_v1", download=True, **kwargs)
|
||||
|
||||
|
||||
def arcface_outofreach_v1(**kwargs):
|
||||
return get_arcface("outofreach_v1", download=False, **kwargs)
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
"""
|
||||
This code file mainly comes from https://github.com/dmlc/gluon-cv/blob/master/gluoncv/model_zoo/model_store.py
|
||||
"""
|
||||
@@ -11,14 +10,17 @@ import glob
|
||||
|
||||
from ..utils import download, check_sha1
|
||||
|
||||
_model_sha1 = {name: checksum for checksum, name in [
|
||||
('95be21b58e29e9c1237f229dae534bd854009ce0', 'arcface_r100_v1'),
|
||||
('', 'arcface_mfn_v1'),
|
||||
('39fd1e087a2a2ed70a154ac01fecaa86c315d01b', 'retinaface_r50_v1'),
|
||||
('2c9de8116d1f448fd1d4661f90308faae34c990a', 'retinaface_mnet025_v1'),
|
||||
('0db1d07921d005e6c9a5b38e059452fc5645e5a4', 'retinaface_mnet025_v2'),
|
||||
('7dd8111652b7aac2490c5dcddeb268e53ac643e6', 'genderage_v1'),
|
||||
]}
|
||||
_model_sha1 = {
|
||||
name: checksum
|
||||
for checksum, name in [
|
||||
('95be21b58e29e9c1237f229dae534bd854009ce0', 'arcface_r100_v1'),
|
||||
('', 'arcface_mfn_v1'),
|
||||
('39fd1e087a2a2ed70a154ac01fecaa86c315d01b', 'retinaface_r50_v1'),
|
||||
('2c9de8116d1f448fd1d4661f90308faae34c990a', 'retinaface_mnet025_v1'),
|
||||
('0db1d07921d005e6c9a5b38e059452fc5645e5a4', 'retinaface_mnet025_v2'),
|
||||
('7dd8111652b7aac2490c5dcddeb268e53ac643e6', 'genderage_v1'),
|
||||
]
|
||||
}
|
||||
|
||||
base_repo_url = 'http://insightface.ai/files/'
|
||||
_url_format = '{repo_url}models/{file_name}.zip'
|
||||
@@ -26,19 +28,21 @@ _url_format = '{repo_url}models/{file_name}.zip'
|
||||
|
||||
def short_hash(name):
|
||||
if name not in _model_sha1:
|
||||
raise ValueError('Pretrained model for {name} is not available.'.format(name=name))
|
||||
raise ValueError(
|
||||
'Pretrained model for {name} is not available.'.format(name=name))
|
||||
return _model_sha1[name][:8]
|
||||
|
||||
|
||||
def find_params_file(dir_path):
|
||||
if not os.path.exists(dir_path):
|
||||
return None
|
||||
paths = glob.glob("%s/*.params"%dir_path)
|
||||
if len(paths)==0:
|
||||
paths = glob.glob("%s/*.params" % dir_path)
|
||||
if len(paths) == 0:
|
||||
return None
|
||||
paths = sorted(paths)
|
||||
return paths[-1]
|
||||
|
||||
|
||||
def get_model_file(name, root=os.path.join('~', '.insightface', 'models')):
|
||||
r"""Return location for the pretrained on local file system.
|
||||
|
||||
@@ -68,7 +72,9 @@ def get_model_file(name, root=os.path.join('~', '.insightface', 'models')):
|
||||
if check_sha1(file_path, sha1_hash):
|
||||
return file_path
|
||||
else:
|
||||
print('Mismatch in the content of model file detected. Downloading again.')
|
||||
print(
|
||||
'Mismatch in the content of model file detected. Downloading again.'
|
||||
)
|
||||
else:
|
||||
print('Model file is not found. Downloading.')
|
||||
|
||||
@@ -92,6 +98,5 @@ def get_model_file(name, root=os.path.join('~', '.insightface', 'models')):
|
||||
if check_sha1(file_path, sha1_hash):
|
||||
return file_path
|
||||
else:
|
||||
raise ValueError('Downloaded file has different hash. Please try again.')
|
||||
|
||||
|
||||
raise ValueError(
|
||||
'Downloaded file has different hash. Please try again.')
|
||||
|
||||
@@ -54,4 +54,3 @@ def get_model_list():
|
||||
|
||||
"""
|
||||
return sorted(_models.keys())
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import hashlib
|
||||
import requests
|
||||
from tqdm import tqdm
|
||||
|
||||
|
||||
def check_sha1(filename, sha1_hash):
|
||||
"""Check whether the sha1 hash of the file content matches the expected hash.
|
||||
Parameters
|
||||
@@ -31,6 +32,7 @@ def check_sha1(filename, sha1_hash):
|
||||
l = min(len(sha1_file), len(sha1_hash))
|
||||
return sha1.hexdigest()[0:l] == sha1_hash[0:l]
|
||||
|
||||
|
||||
def download(url, path=None, overwrite=False, sha1_hash=None):
|
||||
"""Download an given URL
|
||||
Parameters
|
||||
@@ -59,26 +61,29 @@ def download(url, path=None, overwrite=False, sha1_hash=None):
|
||||
else:
|
||||
fname = path
|
||||
|
||||
if overwrite or not os.path.exists(fname) or (sha1_hash and not check_sha1(fname, sha1_hash)):
|
||||
if overwrite or not os.path.exists(fname) or (
|
||||
sha1_hash and not check_sha1(fname, sha1_hash)):
|
||||
dirname = os.path.dirname(os.path.abspath(os.path.expanduser(fname)))
|
||||
if not os.path.exists(dirname):
|
||||
os.makedirs(dirname)
|
||||
|
||||
print('Downloading %s from %s...'%(fname, url))
|
||||
print('Downloading %s from %s...' % (fname, url))
|
||||
r = requests.get(url, stream=True)
|
||||
if r.status_code != 200:
|
||||
raise RuntimeError("Failed downloading url %s"%url)
|
||||
raise RuntimeError("Failed downloading url %s" % url)
|
||||
total_length = r.headers.get('content-length')
|
||||
with open(fname, 'wb') as f:
|
||||
if total_length is None: # no content length header
|
||||
if total_length is None: # no content length header
|
||||
for chunk in r.iter_content(chunk_size=1024):
|
||||
if chunk: # filter out keep-alive new chunks
|
||||
if chunk: # filter out keep-alive new chunks
|
||||
f.write(chunk)
|
||||
else:
|
||||
total_length = int(total_length)
|
||||
for chunk in tqdm(r.iter_content(chunk_size=1024),
|
||||
total=int(total_length / 1024. + 0.5),
|
||||
unit='KB', unit_scale=False, dynamic_ncols=True):
|
||||
unit='KB',
|
||||
unit_scale=False,
|
||||
dynamic_ncols=True):
|
||||
f.write(chunk)
|
||||
|
||||
if sha1_hash and not check_sha1(fname, sha1_hash):
|
||||
|
||||
@@ -1,88 +1,71 @@
|
||||
|
||||
import cv2
|
||||
import numpy as np
|
||||
from skimage import transform as trans
|
||||
|
||||
src1 = np.array([
|
||||
[51.642,50.115],
|
||||
[57.617,49.990],
|
||||
[35.740,69.007],
|
||||
[51.157,89.050],
|
||||
[57.025,89.702]], dtype=np.float32)
|
||||
#<--left
|
||||
src2 = np.array([
|
||||
[45.031,50.118],
|
||||
[65.568,50.872],
|
||||
[39.677,68.111],
|
||||
[45.177,86.190],
|
||||
[64.246,86.758]], dtype=np.float32)
|
||||
src1 = np.array([[51.642, 50.115], [57.617, 49.990], [35.740, 69.007],
|
||||
[51.157, 89.050], [57.025, 89.702]],
|
||||
dtype=np.float32)
|
||||
#<--left
|
||||
src2 = np.array([[45.031, 50.118], [65.568, 50.872], [39.677, 68.111],
|
||||
[45.177, 86.190], [64.246, 86.758]],
|
||||
dtype=np.float32)
|
||||
|
||||
#---frontal
|
||||
src3 = np.array([
|
||||
[39.730,51.138],
|
||||
[72.270,51.138],
|
||||
[56.000,68.493],
|
||||
[42.463,87.010],
|
||||
[69.537,87.010]], dtype=np.float32)
|
||||
src3 = np.array([[39.730, 51.138], [72.270, 51.138], [56.000, 68.493],
|
||||
[42.463, 87.010], [69.537, 87.010]],
|
||||
dtype=np.float32)
|
||||
|
||||
#-->right
|
||||
src4 = np.array([
|
||||
[46.845,50.872],
|
||||
[67.382,50.118],
|
||||
[72.737,68.111],
|
||||
[48.167,86.758],
|
||||
[67.236,86.190]], dtype=np.float32)
|
||||
src4 = np.array([[46.845, 50.872], [67.382, 50.118], [72.737, 68.111],
|
||||
[48.167, 86.758], [67.236, 86.190]],
|
||||
dtype=np.float32)
|
||||
|
||||
#-->right profile
|
||||
src5 = np.array([
|
||||
[54.796,49.990],
|
||||
[60.771,50.115],
|
||||
[76.673,69.007],
|
||||
[55.388,89.702],
|
||||
[61.257,89.050]], dtype=np.float32)
|
||||
src5 = np.array([[54.796, 49.990], [60.771, 50.115], [76.673, 69.007],
|
||||
[55.388, 89.702], [61.257, 89.050]],
|
||||
dtype=np.float32)
|
||||
|
||||
src = np.array([src1,src2,src3,src4,src5])
|
||||
src_map = {112 : src, 224 : src*2}
|
||||
src = np.array([src1, src2, src3, src4, src5])
|
||||
src_map = {112: src, 224: src * 2}
|
||||
|
||||
arcface_src = np.array([
|
||||
[38.2946, 51.6963],
|
||||
[73.5318, 51.5014],
|
||||
[56.0252, 71.7366],
|
||||
[41.5493, 92.3655],
|
||||
[70.7299, 92.2041] ], dtype=np.float32 )
|
||||
arcface_src = np.array(
|
||||
[[38.2946, 51.6963], [73.5318, 51.5014], [56.0252, 71.7366],
|
||||
[41.5493, 92.3655], [70.7299, 92.2041]],
|
||||
dtype=np.float32)
|
||||
|
||||
arcface_src = np.expand_dims(arcface_src, axis=0)
|
||||
|
||||
# In[66]:
|
||||
|
||||
|
||||
# lmk is prediction; src is template
|
||||
def estimate_norm(lmk, image_size = 112, mode='arcface'):
|
||||
assert lmk.shape==(5,2)
|
||||
tform = trans.SimilarityTransform()
|
||||
lmk_tran = np.insert(lmk, 2, values=np.ones(5), axis=1)
|
||||
min_M = []
|
||||
min_index = []
|
||||
min_error = float('inf')
|
||||
if mode=='arcface':
|
||||
assert image_size==112
|
||||
src = arcface_src
|
||||
else:
|
||||
src = src_map[image_size]
|
||||
for i in np.arange(src.shape[0]):
|
||||
tform.estimate(lmk, src[i])
|
||||
M = tform.params[0:2,:]
|
||||
results = np.dot(M, lmk_tran.T)
|
||||
results = results.T
|
||||
error = np.sum(np.sqrt(np.sum((results - src[i]) ** 2,axis=1)))
|
||||
# print(error)
|
||||
if error< min_error:
|
||||
min_error = error
|
||||
min_M = M
|
||||
min_index = i
|
||||
return min_M, min_index
|
||||
def estimate_norm(lmk, image_size=112, mode='arcface'):
|
||||
assert lmk.shape == (5, 2)
|
||||
tform = trans.SimilarityTransform()
|
||||
lmk_tran = np.insert(lmk, 2, values=np.ones(5), axis=1)
|
||||
min_M = []
|
||||
min_index = []
|
||||
min_error = float('inf')
|
||||
if mode == 'arcface':
|
||||
assert image_size == 112
|
||||
src = arcface_src
|
||||
else:
|
||||
src = src_map[image_size]
|
||||
for i in np.arange(src.shape[0]):
|
||||
tform.estimate(lmk, src[i])
|
||||
M = tform.params[0:2, :]
|
||||
results = np.dot(M, lmk_tran.T)
|
||||
results = results.T
|
||||
error = np.sum(np.sqrt(np.sum((results - src[i])**2, axis=1)))
|
||||
# print(error)
|
||||
if error < min_error:
|
||||
min_error = error
|
||||
min_M = M
|
||||
min_index = i
|
||||
return min_M, min_index
|
||||
|
||||
|
||||
def norm_crop(img, landmark, image_size=112, mode='arcface'):
|
||||
M, pose_index = estimate_norm(landmark, image_size, mode)
|
||||
warped = cv2.warpAffine(img,M, (image_size, image_size), borderValue = 0.0)
|
||||
return warped
|
||||
|
||||
M, pose_index = estimate_norm(landmark, image_size, mode)
|
||||
warped = cv2.warpAffine(img, M, (image_size, image_size), borderValue=0.0)
|
||||
return warped
|
||||
|
||||
@@ -4,6 +4,7 @@ This code file mainly comes from https://github.com/dmlc/gluon-cv/blob/master/gl
|
||||
import os
|
||||
import errno
|
||||
|
||||
|
||||
def makedirs(path):
|
||||
"""Create directory recursively if not exists.
|
||||
Similar to `makedir -p`, you can skip checking existence before this function.
|
||||
@@ -19,6 +20,7 @@ def makedirs(path):
|
||||
if exc.errno != errno.EEXIST:
|
||||
raise
|
||||
|
||||
|
||||
def try_import(package, message=None):
|
||||
"""Try import specified package, with custom message support.
|
||||
|
||||
@@ -42,6 +44,7 @@ def try_import(package, message=None):
|
||||
raise e
|
||||
raise ImportError(message)
|
||||
|
||||
|
||||
def try_import_cv2():
|
||||
"""Try import cv2 at runtime.
|
||||
|
||||
@@ -52,8 +55,10 @@ def try_import_cv2():
|
||||
"""
|
||||
msg = "cv2 is required, you can install by package manager, e.g. 'apt-get', \
|
||||
or `pip install opencv-python --user` (note that this is unofficial PYPI package)."
|
||||
|
||||
return try_import('cv2', msg)
|
||||
|
||||
|
||||
def try_import_mmcv():
|
||||
"""Try import mmcv at runtime.
|
||||
|
||||
@@ -64,8 +69,10 @@ def try_import_mmcv():
|
||||
"""
|
||||
msg = "mmcv is required, you can install by first `pip install Cython --user` \
|
||||
and then `pip install mmcv --user` (note that this is unofficial PYPI package)."
|
||||
|
||||
return try_import('mmcv', msg)
|
||||
|
||||
|
||||
def try_import_rarfile():
|
||||
"""Try import rarfile at runtime.
|
||||
|
||||
@@ -76,8 +83,10 @@ def try_import_rarfile():
|
||||
"""
|
||||
msg = "rarfile is required, you can install by first `sudo apt-get install unrar` \
|
||||
and then `pip install rarfile --user` (note that this is unofficial PYPI package)."
|
||||
|
||||
return try_import('rarfile', msg)
|
||||
|
||||
|
||||
def import_try_install(package, extern_url=None):
|
||||
"""Try import the specified package.
|
||||
If the package not installed, try use pip to install and import if success.
|
||||
@@ -108,7 +117,8 @@ def import_try_install(package, extern_url=None):
|
||||
|
||||
# trying to install package
|
||||
url = package if extern_url is None else extern_url
|
||||
pipmain(['install', '--user', url]) # will raise SystemExit Error if fails
|
||||
pipmain(['install', '--user',
|
||||
url]) # will raise SystemExit Error if fails
|
||||
|
||||
# trying to load again
|
||||
try:
|
||||
@@ -122,6 +132,7 @@ def import_try_install(package, extern_url=None):
|
||||
return __import__(package)
|
||||
return __import__(package)
|
||||
|
||||
|
||||
def try_import_dali():
|
||||
"""Try import NVIDIA DALI at runtime.
|
||||
"""
|
||||
@@ -129,9 +140,12 @@ def try_import_dali():
|
||||
dali = __import__('nvidia.dali', fromlist=['pipeline', 'ops', 'types'])
|
||||
dali.Pipeline = dali.pipeline.Pipeline
|
||||
except ImportError:
|
||||
|
||||
class dali:
|
||||
class Pipeline:
|
||||
def __init__(self):
|
||||
raise NotImplementedError(
|
||||
"DALI not found, please check if you installed it correctly.")
|
||||
"DALI not found, please check if you installed it correctly."
|
||||
)
|
||||
|
||||
return dali
|
||||
|
||||
@@ -6,11 +6,10 @@ import shutil
|
||||
import sys
|
||||
from setuptools import setup, find_packages
|
||||
|
||||
|
||||
def read(*names, **kwargs):
|
||||
with io.open(
|
||||
os.path.join(os.path.dirname(__file__), *names),
|
||||
encoding=kwargs.get("encoding", "utf8")
|
||||
) as fp:
|
||||
with io.open(os.path.join(os.path.dirname(__file__), *names),
|
||||
encoding=kwargs.get("encoding", "utf8")) as fp:
|
||||
return fp.read()
|
||||
|
||||
|
||||
@@ -22,10 +21,11 @@ def find_version(*file_paths):
|
||||
return version_match.group(1)
|
||||
raise RuntimeError("Unable to find version string.")
|
||||
|
||||
|
||||
try:
|
||||
import pypandoc
|
||||
long_description = pypandoc.convert('README.md', 'rst')
|
||||
except(IOError, ImportError):
|
||||
except (IOError, ImportError):
|
||||
long_description = open('README.md').read()
|
||||
|
||||
VERSION = find_version('insightface', '__init__.py')
|
||||
@@ -58,4 +58,3 @@ setup(
|
||||
include_package_data=True,
|
||||
install_requires=requirements,
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user