# 使用vision.ToPIL在一定情况下无效

**1. 系统环境**

硬件环境\(Ascend/GPU/CPU\): Ascend/GPU/CPU

软件环境: MindSpore 版本: 2.0.0

执行模式（静态图/动态图）： 不限

Python 版本: 3.9.7

操作系统平台: linux

**2. 报错信息**

2.1 问题描述

定义了一连串的transforms，知道vision.RandomGrayscale要求是PIL作为输入，因此在这个transform前加了vision.ToPIL\(\)，可是为什么会报错提示说输入仍然是个numpy呢？ vision.ToPIL\(\)这个操作好像没有生效。

2.2 报错信息

![](figures/zh-cn_image_0000002135697157.png)

2.3 脚本信息

![](figures/zh-cn_image_0000002100178130.png)

**3. 根因分析**

从源码的角度分析一下，源码其实安装在conda下，在命令行里使用pip show mindspore就可以查看到

![](figures/zh-cn_image_0000002100182478.png)

那么mindspore的源码就位于：/home/xxxx/.conda/envs/ly37/lib/python3.7/site-packages/mindspore

![](figures/zh-cn_image_0000002135783021.png)按照报错提示的python路径，我在dataset里面搜索Compose算子，开始分析源码 mindspore/dataset/transforms/transforms.py

![](figures/zh-cn_image_0000002100023982.png)

如果调用到了\_execute\_py函数，那么util.compose函数是会循环执行transfomrs.Compose中的数据增强算子的，这样vision.ToPIL肯定会返回一个Pillow对象给vision.RandomGrayscale，这样按理说不会出错。但当我在\_execute\_py里面添加一行打印

![](figures/zh-cn_image_0000002135703009.png)

发现其竟然没有打印出来，那么肯定哪里的逻辑有点问题了。

由于是以function call的形式调用transfomrs.Compose，那么一定是触发了他的\_\_call\_\_方法，但是这个类里没有定义，最后在他的父类里找到了方法定义。

mindspore/dataset/transforms/transforms.py

![](figures/zh-cn_image_0000002135783553.png)

发现\_\_call\_\_方法里其实有分支是调用\_execute\_py方法的，但是为什么没走进去呢。如果78行的if条件是False，那么他肯定走了下面的分支导致计算出错，通过添加打印我也确认了这点，发现确实只打印了"go into other branch "

![](figures/zh-cn_image_0000002100024686.png)

那么问题来了，if条件是用来判断什么的呢，导致他条件为False，于是我也把所有的if条件打印了一下，发现and前后两个条件都是False。

![](figures/zh-cn_image_0000002135703621.png)这下就有点不大知道怎么往下看了。不过我也粗略尝试了一下，我想要不直接帮vision.Compose重载一个\_\_call\_\_方法让他直接调用\_execute\_py会怎么样。

![](figures/zh-cn_image_0000002135703781.png)

可以运行成功！

![](figures/zh-cn_image_0000002100025262.png)

**4. 解决方案**

由于RandomGrayscale需要是一个Pillow的输入，那我就构造一个给他呗，把代码改成这样。

![](figures/zh-cn_image_0000002100185462.png)

通过灵活的python lambda表达式，我把输入先用Pillow的函数包装一层，然后再传给vision.RandomGrayscale不就好了，事实证明这么写确实也有效，结果如下：

![](figures/zh-cn_image_0000002135785373.png)

