Exemple #1
0
def process_image_yyy(image, face_data, engine_model, func_name, func_params=None, worker=None):
    """ 对上传图片进行处理(截取人脸部分做替换处理)
    Returns:
        image_output: 处理后的图片数据
    """

    # 处理和替换图片中的人脸部分
    if 'face_image' in face_data:
        _img_np = face_data['face_image']
        x = face_data['x']
        y = face_data['y']
        w = face_data['w']
        h = face_data['h']
        img_hash = face_data['img_hash']

        face_image_orig = image_ndarray_to_pil(_img_np)

        # 如果 face_image 尺寸大于模型标准尺寸,则缩放为标准尺寸再处理
        _img_w, _img_h = w, h
        _h = engine_model['model_size']
        _img = image_ndarray_to_pil(_img_np)
        if _img_h != _h:
            _img = image_resize_default(_img, _h)
            _img_np = image_pil_to_ndarray(_img)

        # 处理图片(返回的已经是 PIL Image)
        _img_out_pil = engine_process_image(engine_model, _img_np, func_name)

        # 将返回图片缩放为原尺寸
        if _img_h != _h:
            if _img_h > _h and ENABLE_ESRGAN:
                #_img_out_pil = esrgan_adapter.process_image(
                #    _img_out_pil, engine_model['esrgan'], _img_w, _img_h)
                # 调用管理进程共享对象接口处理
                ret = exec_esrgan(_img_out_pil, _img_w, _img_h, worker)
                if ret:
                    _img_out_pil = ret
                else:
                    _img_out_pil = image_resize_default(_img_out_pil, _img_h)
            else:
                _img_out_pil = image_resize_default(_img_out_pil, _img_h)

        # 检查是否为主demo,若是则将人脸处理结果保存为图标
        if 'img_hash' in face_data:
            img_hash = face_data['img_hash']
            if img_hash in app_config.IMG_HASH_ICON_DEMO: # 为生成界面图标用的指定图片
                check_if_save_demo_icon(_img_out_pil, SAVE_ICON_DIR, func_name)

        # 将新旧人脸混合后贴回原图
        x = x + int((image.size[0] - app_config.OUTPUT_SIZE_EDITOR[0]) / 2)
        y = y + int((image.size[1] - app_config.OUTPUT_SIZE_EDITOR[1]) / 2)
        edit_area = func_params[1]
        image_output = face_image_blend(image, _img_out_pil,
                                        face_image_orig, x, y, w, h, edit_area, worker)

    return image_output
Exemple #2
0
def process_image_xxx(image, face_data, engine_model, func_name, func_params=None, worker=None):
    """ 对上传图片进行处理(直接处理整张图片)
    Returns:
        image_output: 处理后的图片数据
    """

    # 处理和替换图片中的人脸部分
    # !!直接使用 pil 原图而不是 face_data 中的人脸图做处理
    
    # 如果 image 尺寸不等于模型标准尺寸,则缩放为标准尺寸再处理
    _img_w, _img_h = image.size[0:2]
    _h = engine_model['model_size']
    if _img_h != _h:
        _img_pil = image_resize_default(image, _h)
    else:
        _img_pil = image
    _img_np = image_pil_to_ndarray(_img_pil)

    # 处理图片(返回的已经是 PIL Image)
    _img_out_pil = engine_process_image(engine_model, _img_np, func_name)

    # 将返回图片缩放为原尺寸
    if _img_h != _h:
        if _img_h > _h and ENABLE_ESRGAN:
            #_img_out_pil = esrgan_adapter.process_image(
            #    _img_out_pil, engine_model['esrgan'], _img_w, _img_h)
            # 调用管理进程共享对象接口处理
            ret = exec_esrgan(_img_out_pil, _img_w, _img_h, worker)
            if ret:
                _img_out_pil = ret
            else:
                _img_out_pil = image_resize_default(_img_out_pil, _img_h)
        else:
            _img_out_pil = image_resize_default(_img_out_pil, _img_h)

    # 检查是否为主demo,若是则将人脸处理结果保存为图标
    if 'img_hash' in face_data:
        img_hash = face_data['img_hash']
        if img_hash in app_config.IMG_HASH_ICON_DEMO: # 为生成界面图标用的指定图片
            check_if_save_demo_icon(_img_out_pil, SAVE_ICON_DIR, func_name)

    # 将新旧人脸混合后贴回原图
    x, y = 0, 0
    w, h = image.size[0], image.size[1]
    edit_area = func_params[1]
    _img_out_pil = face_image_blend(_img_out_pil, _img_out_pil,
                                    image, x, y, w, h, edit_area, worker)

    return _img_out_pil
Exemple #3
0
def process_image(image,
                  face_data,
                  engine_model,
                  func_name,
                  func_params=None,
                  worker=None):
    """ 对上传图片进行处理
    Returns:
        image_output: 处理后的图片数据
    """

    # !!直接使用 pil 原图而不是 face_data 中的人脸图做处理

    # 如果 image 尺寸不等于模型标准尺寸,则缩放为标准尺寸再处理
    _img_w, _img_h = image.size[0:2]
    _h = engine_model['model_size']
    if _img_h != _h:
        _img = image_resize_default(image, _h)
    else:
        _img = image

    # 处理图片
    style_name = func_params[0]
    _img_out_pil = engine_process_image(engine_model, _img, style_name)

    # 将返回图片缩放为原尺寸
    if _img_h != _h:
        if _img_h > _h and ENABLE_ESRGAN:
            #_img_out_pil = esrgan_adapter.process_image(
            #    _img_out_pil, engine_model['esrgan'], _img_w, _img_h)
            # 调用管理进程共享对象接口处理
            ret = exec_esrgan(_img_out_pil, _img_w, _img_h, worker)
            if ret:
                _img_out_pil = ret
            else:
                _img_out_pil = image_resize_default(_img_out_pil, _img_h)
        else:
            _img_out_pil = image_resize_default(_img_out_pil, _img_h)

    # 检查是否为主demo,若是则将人脸处理结果保存为图标
    if 'img_hash' in face_data:
        img_hash = face_data['img_hash']
        if img_hash in app_config.IMG_HASH_ICON_DEMO:  # 为生成界面图标用的指定图片
            check_if_save_demo_icon(_img_out_pil, SAVE_ICON_DIR, style_name)

    return _img_out_pil
Exemple #4
0
def process_image(image,
                  face_data,
                  engine_model,
                  func_name,
                  func_params=None,
                  worker=None):
    """ 对上传图片进行处理
    Returns:
        image_output: 处理后的图片数据
    """

    # !!与其他引擎处理方式稍有不同:这里直接使用 pil 原图而不是 face_data 中的人脸图做处理

    # 如果 image 尺寸不等于模型标准尺寸,则缩放为标准尺寸再处理
    _img_w, _img_h = image.size[0:2]
    _h = engine_model['model_size']
    if _img_h != _h:
        _img = image_resize_default(image, _h)
    else:
        _img = image

    # 处理图片
    _img_out_pil = engine_process_image(engine_model, _img, func_name)

    # 将返回图片缩放为原尺寸
    if _img_h != _h:
        if _img_h > _h and ENABLE_ESRGAN:
            #_img_out_pil = esrgan_adapter.process_image(
            #    _img_out_pil, engine_model['esrgan'], _img_w, _img_h)
            # 调用管理进程共享对象接口处理
            ret = exec_esrgan(_img_out_pil, _img_w, _img_h, worker)
            if ret:
                _img_out_pil = ret
            else:
                _img_out_pil = image_resize_default(_img_out_pil, _img_h)
        else:
            _img_out_pil = image_resize_default(_img_out_pil, _img_h)

    return _img_out_pil
Exemple #5
0
def face_image_blend(image_output,
                     face_image_new,
                     face_image_orig,
                     x,
                     y,
                     w,
                     h,
                     edit_area=None,
                     worker=None):
    """替换输出图片中的人脸部分
    将新的人脸图与原人脸图按比例融合,然后平滑替换到输出图中指定位置"""

    logger.info('call face_image_blend. x, y, w, h: {}, {}, {}, {}'.format(
        x, y, w, h))
    #print('--> image_output.size: {}, face_image_new.size: {}, face_image_orig.size: {}'
    #      .format(image_output.size, face_image_new.size, face_image_orig.size))
    #print('--> type(image_output): {}, type(face_image_new): {}'
    #      .format(type(image_output), type(face_image_new)))

    # 将处理后的人脸缩放为检测时的尺寸,然后按照相应坐标替换到原图中
    face_image_new = image_resize_default(face_image_new, h)

    # 将处理后的人脸与原人脸做 alpha 混合,以平滑图像(会降低效果,暂无必要)
    #face_image_new = image_blend(face_image_orig, face_image_new, 0.7)

    # 设置掩模图片
    # 为减少不必要的修改、提高图片质量,可在task参数中设置要编辑的人脸区域
    logger.info('get face mask with area: {}'.format(edit_area))
    mask = None
    if edit_area != None:
        if len(edit_area) == 0:  # 如未指定人脸部分,则使用人像全部
            edit_area = [
                'face', 'l_brow', 'r_brow', 'l_eye', 'r_eye', 'eye_g', 'l_ear',
                'r_ear', 'ear_r', 'nose', 'u_lip', 'l_lip', 'neck', 'neck_l',
                'mouth', 'cloth', 'hat', 'hair'
            ]
        # 解析获取人脸掩模图片
        mask = mm_get_face_mask(face_image_new, edit_area, worker)
    if not mask:
        logger.info('call get_geometric_mask() to make mask')
        mask = get_geometric_mask(face_image_new)  # 默认为椭圆型掩模图片

    # 参考掩模将处理后的人脸替换到图中
    #image_output.save('/app/app/dbg_image_output_1.png')
    image_output.paste(face_image_new, (x, y), mask)
    #image_output.save('/app/app/dbg_image_output_2.png')
    # 含义:使用变量mask对应的模板图像来填充所对应的区域。可以使用模式为“1”、“L”或者“RGBA”的图像作为模板图像。模板图像的尺寸必须与变量image对应的图像尺寸一致。如果变量mask对应图像的值为255,则模板图像的值直接被拷贝过来;如果变量mask对应图像的值为0,则保持当前图像的原始值。变量mask对应图像的其他值,将对两张图像的值进行透明融合。

    return image_output
Exemple #6
0
def process_image(image, engine_model, output_w, output_h):
    # 如果输入尺寸大于等于输出尺寸,则不必做超解析
    in_w, in_h = image.size
    if in_h >= output_h:
        return image

    t1 = time.time()
    image = np.array(image).astype(np.uint8)  # pil to numpy.array

    image = image * 1.0 / 255
    image = torch.from_numpy(np.transpose(image[:, :, [2, 1, 0]],
                                          (2, 0, 1))).float()
    img_LR = image.unsqueeze(0)

    model = engine_model['model']

    if torch.__version__ >= '0.4':
        img_LR = img_LR.to(torch.device('cuda'))
        with torch.no_grad():
            output = model(img_LR).data.squeeze().float().cpu().clamp_(
                0, 1).numpy()
    else:
        from torch.autograd import Variable
        img_LR = Variable(img_LR, volatile=True)
        img_LR = img_LR.cuda()
        output = model(img_LR).data.squeeze().float().cpu().clamp_(0,
                                                                   1).numpy()

    output = np.transpose(output[[2, 1, 0], :, :], (1, 2, 0))
    output = (output * 255.0).round().astype(np.uint8)

    output = transforms.ToPILImage()(output)  # numpy.array to pil
    output = image_resize_default(output, output_h)

    t2 = time.time()
    print('--> esrgan: {}s used'.format(t2 - t1))
    #print('--> type(output): {}'.format(type(output)))
    logger.info(
        'esrgan process image, input size: {} w, {} h, output size: {} w, {} h'
        .format(in_w, in_h, output.size[0], output.size[1]))

    return output
Exemple #7
0
def check_if_save_demo_icon(img_pil, icon_dir, icon_name):
    """将 icon demo 图片的人脸处理结果保存为图标"""
    
    if app_config.DEMO_ICON_ENABLE:
        os.makedirs(icon_dir, exist_ok=True)
        icon_file = os.path.join(icon_dir, '{}.jpg'.format(icon_name))
        
        image_out = img_pil.copy()

        # 对于非人脸检测图,由于会扩展为正方形,处理后图片需要居中截取,否则会有边框,做图标不好看
        img_w, img_h = img_pil.size
        #print('--> img_w: %s, img_h: %s' % (img_w, img_h))
        if img_w >= 380:
            _sz = 380
            x0 = int((img_w - _sz) / 2)
            y0 = int((img_h - _sz) / 2)
            x1 = x0 + _sz
            y1 = y0 + _sz
            image_out = image_out.crop((x0, y0, x1, y1))
        
        icon_img_pil = image_resize_default(image_out, 200) # 缩放为前端所需图标大小
        icon_img_pil.save(icon_file)
        logger.info('icon demo image saved to icon {:s} done!'.format(icon_file))
Exemple #8
0
def process_image(image, face_data, engine_model, func_name, func_params=None, worker=None):
    """ 对上传图片进行处理
    Returns:
        image_output: 处理后的图片数据
    """

    if 'img_hash' not in face_data: # 本引擎只能处理人脸图片
        return None

    # !!直接使用 pil 原图而不是 face_data 中的人脸图做处理
    
    # 如果 image 尺寸不等于模型标准尺寸,则缩放为标准尺寸再处理
    _img_w, _img_h = image.size[0:2]
    _h = engine_model['model_size']
    if _img_h > _h:
        _img_pil = image_resize_default(image, _h)
    else:
        _img_pil = image
    _img_cv2 = image_pil_to_cv2(_img_pil)

    # 开始处理人脸上妆

    # 根据输入参数获取要修改的人脸区域及处理方式
    func_name, func_arg = func_name, func_params[0]
    edit_area = []
    for i in func_params[1]:
        if i == 'skin': # 肤色
            edit_area.extend(['face', 'l_ear', 'r_ear', 'nose', 'l_brow', 'r_brow',
                    'u_lip', 'l_lip', 'neck'])
        elif i == 'lips': # 嘴唇
            edit_area.extend(['u_lip', 'l_lip'])
        else:
            edit_area.append(i)
    logger.info('func_name: {}, func_arg: {}, func_params: {}, edit_area: {}'
                .format(func_name, func_arg, func_params, edit_area))
    
    # 人脸解析器 - 内置 face-parsing.PyTorch:总共 18 个人脸部分(当前使用)
    # 正脸效果较好,侧脸或者小脸不佳
    # 1 'face', 2 'l_brow', 3 'r_brow', 4 'l_eye', 5 'r_eye', 
    # 6 'eye_g', 7 'l_ear', 8 'r_ear', 9 'ear_r', 10 'nose', 
    # 11 'mouth', 12 'u_lip', 13 'l_lip', 14 'neck', 15 'neck_l', 
    # 16 'cloth', 17 'hair', 18 'hat'
    face_area_map = { # 取值从数字 1 开始依次增加;0 为背景部分
        'face': 1,
        'l_brow': 2,
        'r_brow': 3,
        'l_eye': 4,
        'r_eye': 5,
        'eye_g': 6,
        'l_ear': 7,
        'r_ear': 8,
        'ear_r': 9,
        'nose': 10,
        'teeth': 11,
        'u_lip': 12,
        'l_lip': 13,
        'neck': 14,
        'neck_l': 15,
        'cloth': 16,
        'hair': 17,
        'hat': 18
    }
    # 首先得到人脸解析图
    face_areas = list(face_area_map.keys())
    parsing, mask_pil = evaluate(_img_pil, engine_model, face_areas, edit_area)
    parsing = cv2.resize(
        parsing, _img_cv2.shape[0:2], interpolation=cv2.INTER_NEAREST)
    if ENABLE_MASK and mask_pil:
        mask_pil = image_resize_default(mask_pil, _img_cv2.shape[0])
    
    _img_out = _img_cv2
    
    if func_name == 'chg_color': # 着色处理

        parts = [] # 需处理的人脸部分列表
        colors = [] # 各人脸部分相应颜色列表
        # colors 取值数量应与 parts 一致。
        
        # 设定着色参数
        def __set_color(part, color):
            if type(part) is list:
                for i in part:
                    parts.append(face_area_map[i])
                    colors.append(color)
            else:
                parts.append(face_area_map[part])
                colors.append(color)
        
        # 颜色示例 b,g,r:
        # [230, 50, 20] # 蓝
        # [10, 250, 10] # 绿
        # [10, 50, 250] # 红
        # [20, 70, 180] # 唇红
        #print('--> func_params:', func_params)
        for p in edit_area:
          __set_color(p, func_params[2])
        if func_arg in ('avatar', 'hawk', 'red'): # 肤色系列 1
            __set_color(['u_lip', 'l_lip'], [20, 70, 180])
            c1, c2 = 0, 1 # 只修改蓝夜色
        elif func_arg in ('jade', 'golden'): # 肤色系列 2
            __set_color(['u_lip', 'l_lip'], [20, 70, 180])
            c1, c2 = 0, 2 # 修改蓝绿夜色
        else: # 部分着色,如发色
            c1, c2 = 0, 1 # 默认只修改蓝夜色
        
        # 置换指定区域颜色
        for part, color in zip(parts, colors):
            print('--> change color to {} for {}'.format(color, part))
            _img_out = change_color(_img_out, parsing, part, color, c1, c2)

    # 转换输出图从 cv2 到 PIL.Image
    _img_out_pil = image_cv2_to_pil(_img_out)

    if ENABLE_MASK:
        # 使用边缘模糊后的掩模图进行修正
        _img_out_pil.paste(_img_out_pil, (0, 0), mask_pil)

    # 将返回图片缩放为原尺寸
    if _img_h > _h:
        if _img_h > _h and ENABLE_ESRGAN:
            #_img_out_pil = esrgan_adapter.process_image(
            #    _img_out_pil, engine_model['esrgan'], _img_w, _img_h)
            # 调用管理进程共享对象接口处理
            ret = exec_esrgan(_img_out_pil, _img_w, _img_h, worker)
            if ret:
                _img_out_pil = ret
            else:
                _img_out_pil = image_resize_default(_img_out_pil, _img_h)
        else:
            _img_out_pil = image_resize_default(_img_out_pil, _img_h)

    # 检查是否为主demo,若是则将人脸处理结果保存为图标
    if 'img_hash' in face_data:
        img_hash = face_data['img_hash']
        if img_hash in app_config.IMG_HASH_ICON_DEMO: # 为生成界面图标用的指定图片
            check_if_save_demo_icon(_img_out_pil, SAVE_ICON_DIR, func_arg)

    return _img_out_pil
Exemple #9
0
def image_process_wrap(image,
                       face_data=None,
                       entry_process_image=None,
                       engine_model=None,
                       func_class='fc_editor',
                       func_group=None,
                       func_name=None,
                       func_params=None,
                       output_size_w=400,
                       output_size_h=500,
                       worker=None):
    """ 本函数包括两个功能:
      1、face_data 为空时做图片预处理,主要是缩放为标准大小;
      2、face_data 非空时做图片编辑处理,回调函数进行处理。
    输出尺寸比例(output_size_w : output_size_h)应为 4:5,如 400x500 或 720x900。
    """

    if not image:
        raise Exception('image_process_wrap(): input image cannot be None!')

    # 1. 将 png 等图片统一转为 jpg 格式
    image = image_convert_rgb(image)

    # 2. 根据图片尺寸判断是否归一化,并做相应的缩放裁剪
    output_size_w, output_size_h = app_config.OUTPUT_SIZE_EDITOR  # 归一化后的标准尺寸
    img_w, img_h = image.size
    print('func_class: {}; img_w: {}, img_h: {}; output size w: {}, h: {}'.
          format(func_class, img_w, img_h, output_size_w, output_size_h))

    needNormalize = False  # 是否需要进行进行归一化
    if img_w != output_size_w or img_h != output_size_h:
        needNormalize = True

    if needNormalize:
        # 图片裁剪为最大 output_size_w,output_size_h:大图片缩放裁剪、保留短边;小图片保持原尺寸
        if img_w > output_size_w:  # 过宽的,等比缩小为输出宽度 output_size_w
            newWidth = output_size_w
            newHeight = int(float(output_size_w) / img_w * img_h)
            image = image.resize((newWidth, newHeight), Image.ANTIALIAS)
            #image = image.thumbnail((newWidth, newHeight), Image.ANTIALIAS)
        img_w, img_h = image.size
        if img_h > output_size_h:  # 过高的,居中裁剪为输出高度 output_size_h
            x0 = 0
            y0 = int((img_h - output_size_h) / 2)
            x1 = output_size_w
            y1 = y0 + output_size_h
            image = image.crop((x0, y0, x1, y1))
        img_w, img_h = image.size

    # 3. 居中扩展为正方形,宽高都为 output_size_h
    # image_norm = Image.new('RGBA', (output_size_h, output_size_h)) # 带透明信息
    image_norm = Image.new('RGB', (output_size_h, output_size_h),
                           (255, 255, 255))  # 不带透明信息
    x = int((output_size_h - img_w) / 2)
    y = int((output_size_h - img_h) / 2)
    image_norm.paste(image, (x, y))

    image_out = image_norm
    # 4. 将上述正方形图片交给引擎处理
    if entry_process_image and hasattr(entry_process_image, '__call__'):
        #for v in func_params:
        #    print('--> Optional argument (*args): ', v)
        ## 如果输入参数中有 **func_kwargs,则可以如下读取:
        #for k, v in func_kwargs.items():
        #    print('--> Optional argument %s (*kwargs): %s' % (k, v))

        # 调用引擎回调函数对图片进行处理
        #logger.info('call {}, func_name: {}, func_params: {}'.format(entry_process_image, func_name, func_params))
        image_out = entry_process_image(image_norm,
                                        face_data,
                                        engine_model,
                                        func_name,
                                        func_params,
                                        worker=worker)
        if not image_out:
            image_norm.close()
            return None

    # 4. 处理后的图片再去扩展,恢复为步骤 1 后的尺寸(最大output_size_w,output_size_h),保存后返回给客户端
    img_w, img_h = output_size_w, output_size_h  # 使用指定输出尺寸,替代步骤 1 后的尺寸
    x0 = int((output_size_h - img_w) / 2)
    y0 = int((output_size_h - img_h) / 2)
    x1 = x0 + img_w
    y1 = y0 + img_h
    image_out = image_out.crop((x0, y0, x1, y1))
    image_norm.close()

    #logger.info('image wrap process done!')

    # 根据任务类型返回不同大小的输出图片
    if func_class == 'fc_fun':
        _img_w, _img_h = app_config.OUTPUT_SIZE_FUN
        image_out = image_resize_default(image_out, _img_h)

    return image_out
Exemple #10
0
def process_image(image,
                  face_data,
                  engine_model,
                  func_name,
                  func_params=None,
                  worker=None):
    """ 对上传图片进行处理
    Returns:
        image_output: 处理后的图片数据
    """

    # 处理和替换图片中的人脸部分
    if 'face_image' in face_data:
        _img_np = face_data['face_image']
        x = face_data['x']
        y = face_data['y']
        w = face_data['w']
        h = face_data['h']

        face_image_orig = image_ndarray_to_pil(_img_np)

        # 如果 face_image 尺寸大于模型标准尺寸,则缩放为标准尺寸再处理
        _img_w, _img_h = w, h
        _h = engine_model['model_size']
        if _img_h != _h:
            _img = image_resize_default(image_ndarray_to_pil(_img_np), _h)
            _img_np = image_pil_to_ndarray(_img)

        # 使用 face_image 构造测试数据集,包括内容、特征和大小
        logger.info('face_image attr: {}, h {}. model size: {}.'.format(
            face_data['attr'], h, _h))
        _test_dataset = MyTestData(_img_np, face_data['attr'], _h)

        # 处理图片
        # test_atts 为目的特征列表;test_ints 为相应特征处理强度,取值 0~1
        test_atts, test_ints = func_name, func_params[0]
        logger.info('func_params: {}, test_atts: {}, test_ints: {}'.format(
            func_params, test_atts, test_ints))
        _img_out_pil = attgan_multi_process(engine_model, _test_dataset,
                                            test_atts, test_ints)

        # 如果为调试模式,则保存生成的人脸图片做分析用,产品化部署不需要
        #if app_config.DEBUG:
        #    out_file = os.path.join(script_dir, 'new_face.jpg')
        #    _img_out_pil.save(out_file)
        #    print('new image saved to {:s} done!'.format(out_file))

        # 将返回图片缩放为原尺寸
        if _img_h != _h:
            if _img_h > _h and ENABLE_ESRGAN:
                #_img_out_pil = esrgan_adapter.process_image(
                #    _img_out_pil, engine_model['esrgan'], w, h)
                # 调用管理进程共享对象接口处理
                ret = exec_esrgan(_img_out_pil, _img_w, _img_h, worker)
                if ret:
                    _img_out_pil = ret
                else:
                    _img_out_pil = image_resize_default(_img_out_pil, _img_h)
        else:
            _img_out_pil = image_resize_default(_img_out_pil, _img_h)

        # 将新旧人脸混合后贴回原图
        x = x + int((image.size[0] - app_config.OUTPUT_SIZE_EDITOR[0]) / 2)
        y = y + int((image.size[1] - app_config.OUTPUT_SIZE_EDITOR[1]) / 2)
        edit_area = func_params[1]
        image_output = face_image_blend(image, _img_out_pil, face_image_orig,
                                        x, y, w, h, edit_area, worker)

    return image_output
Exemple #11
0
def process_image(image,
                  face_data,
                  engine_model,
                  func_name,
                  func_params=None,
                  worker=None):
    """ 对上传图片进行处理
    Returns:
        image_output: 处理后的图片数据
    注意:对于 facelet_pt 来说,由于引擎是根据 effect 分别在子进程中加载的,所以这里 func_name 没用到
    """

    logger.info(
        'call process_image. func_name: "{}", func_params: "{}"'.format(
            func_name, func_params))

    # 处理和替换图片中的人脸部分
    if 'face_image' in face_data:
        _img_np = face_data['face_image']
        x = face_data['x']
        y = face_data['y']
        w = face_data['w']
        h = face_data['h']

        face_image_orig = image_ndarray_to_pil(_img_np)

        # 由于真实处理过程使用CPU执行太慢,笔记本上运行会导致任务超时,故暂时用 sleep 模拟之
        run_fake = False  # 笔记本上运行设为 True,开发和生产服务器上为 False
        if run_fake:
            time.sleep(3)
            _img_out_pil = image_ndarray_to_pil(_img_np)
        else:
            # 如果 face_image 尺寸大于模型标准尺寸,则缩放为标准尺寸再处理
            _img_w, _img_h = w, h
            _h = engine_model['model_size']
            if _img_h != _h:
                _img = image_resize_default(image_ndarray_to_pil(_img_np), _h)
                _img_np = image_pil_to_ndarray(_img)

            _img_out = engine_process_image(engine_model, _img_np, func_name,
                                            func_params)

            # ndarray/Tensor 转成PIL.Image
            _img_out_pil = image_ndarray_to_pil(_img_out)

            # 如果为调试模式,则保存生成的人脸图片做分析用,产品化部署不需要
            if app_config.DEBUG:
                out_file = os.path.join(script_dir, 'new_face.jpg')
                _img_out_pil.save(out_file)
                print('new image saved to {:s} done!'.format(out_file))

            # 将返回图片缩放为原尺寸
            if _img_h != _h:
                if _img_h > _h and ENABLE_ESRGAN:
                    #_img_out_pil = esrgan_adapter.process_image(
                    #          _img_out_pil, engine_model['esrgan'], w, h)
                    # 调用管理进程共享对象接口处理
                    ret = exec_esrgan(_img_out_pil, _img_w, _img_h, worker)
                    if ret:
                        _img_out_pil = ret
                    else:
                        _img_out_pil = image_resize_default(
                            _img_out_pil, _img_h)
                else:
                    _img_out_pil = image_resize_default(_img_out_pil, _img_h)

        # 将新旧人脸混合后贴回原图
        x = x + int((image.size[0] - app_config.OUTPUT_SIZE_EDITOR[0]) / 2)
        y = y + int((image.size[1] - app_config.OUTPUT_SIZE_EDITOR[1]) / 2)
        edit_area = []
        image_output = face_image_blend(image, _img_out_pil, face_image_orig,
                                        x, y, w, h, edit_area, worker)

    return image_output