在MacBookPro M1上使用AI无损放大图片

​ 最近,我发现了一个名为 upscayl 的开源图像放大软件,它的使用效果令人印象深刻。出于好奇,我在 GitHub Repo 上探究了其源码实现,结果发现底层模型采用的是 Real-ESRGAN 技术。为了验证这一点,我尝试运行了 Real-ESRGAN 提供的 colab demo,其整体效果与 upscayl 极为相似。这促使我尝试将其部署到我的 Apple Silicon 电脑上,探索在这个平台上的表现。这个过程非常有趣,因此我决定记录下来,与大家分享。

项目安装

​ 在运行这个Real-ESRGAN之前,先假设电脑已经安装好了miniconda/conda (强烈推荐使用虚拟环境来隔离,避免安装各种项目依赖导致冲突已经不好清理)

创建Python虚拟环境

conda create -n Real-ESRGAN python=3.10
conda activate Real-ESRGAN

接着Clone项目和依赖:

git clone https://github.com/xinntao/Real-ESRGAN.git
cd Real-ESRGAN
# Install basicsr - https://github.com/xinntao/BasicSR
# We use BasicSR for both training and inference
pip install basicsr
# facexlib and gfpgan are for face enhancement
pip install facexlib
pip install gfpgan
pip install -r requirements.txt
python setup.py develop

到这一步基本上和官方仓库的一致。

接下来运行的时候就是有区别的部分了,截止到2023年6月21号master分支的最新版本,里面的代码并没有支持Apple Silicon的mps backend,所以我们需要改动一下源码

找到realesrgan/utils.py, 再找到初始化设备部分:

原先的代码如下:

# initialize model
if gpu_id:
    self.device = torch.device(
        f'cuda:{gpu_id}' if torch.cuda.is_available() else 'cpu') if device is None else device
else:
    self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') if device is None else device

if isinstance(model_path, list):
    # dni
    assert len(model_path) == len(dni_weight), 'model_path and dni_weight should have the save length.'
    loadnet = self.dni(model_path[0], model_path[1], dni_weight)
else:
    # if the model_path starts with https, it will first download models to the folder: weights
    if model_path.startswith('https://'):
        model_path = load_file_from_url(
            url=model_path, model_dir=os.path.join(ROOT_DIR, 'weights'), progress=True, file_name=None)
    loadnet = torch.load(model_path, map_location=torch.device('cpu'))

我们偷懒一点直接把里面的cpu都改成mps, 整个改动就完成了。

# initialize model
if gpu_id:
    self.device = torch.device(
        f'cuda:{gpu_id}' if torch.cuda.is_available() else 'cpu') if device is None else device
else:
    self.device = torch.device('cuda' if torch.cuda.is_available() else 'mps') if device is None else device

if isinstance(model_path, list):
    # dni
    assert len(model_path) == len(dni_weight), 'model_path and dni_weight should have the save length.'
    loadnet = self.dni(model_path[0], model_path[1], dni_weight)
else:
    # if the model_path starts with https, it will first download models to the folder: weights
    if model_path.startswith('https://'):
        model_path = load_file_from_url(
            url=model_path, model_dir=os.path.join(ROOT_DIR, 'weights'), progress=True, file_name=None)
    loadnet = torch.load(model_path, map_location=torch.device('mps'))

如果不改的话是没办法运行的,会提示Error "slow_conv2d_cpu" not implemented for 'Half 的错误,我本来还打算去修复这个错误的,结果只需要把pytorch backend换成mps就完美解决了。

执行主程序放大图片

动漫版本

python inference_realesrgan.py -i ./doraemon.jpg  -o ./image-results -s 10

00017-3455420656

girl-ai-01girl-ai-01_out

人物版本

注意得增加一个参数来增强脸部的特写

python inference_realesrgan.py -i ./00017-3455420656.png  -o ./doraemon-results -s 10 --face_enhance

00017-3455420656 00017-3455420656_out

总结

AI放大这块的效果,已经超过了我的预期。目前AI已经能够通过它训练过的事物来进行对放大后的失真进行补全。

现在Stable Diffusion 结合 Real-ESRGAN组合,生成图片和放大图片的工作流配合的天衣无缝。本文中的原图也是AI绘制出来的,以后写文章什么的,就不用担心没有可以商用的图片啦🎉。