Python 从RDD Apache Spark系统保存图像

Python 从RDD Apache Spark系统保存图像,python,apache-spark,pyspark,Python,Apache Spark,Pyspark,我想在映射后检索存储在RDD系统中的图像 我在main.py文件上创建了一个简单的Spark会话,它调用函数preprocess\u Spark,返回名为samples的元组数组。这些元组采用(幻灯片编号,图像)格式。图像是一个np.array,它将在save\u jpeg\u help功能中转换为图像 当我打开Apache Spark WEB UI时,我看到它有一个与以下行对应的作业: rdd.foreach(lambda sample_element: save_nonlabelled_sa

我想在映射后检索存储在RDD系统中的图像

我在
main.py
文件上创建了一个简单的Spark会话,它调用函数preprocess\u Spark,返回名为
samples
的元组数组。这些元组采用
(幻灯片编号,图像)
格式。图像是一个
np.array
,它将在
save\u jpeg\u help
功能中转换为图像

当我打开Apache Spark WEB UI时,我看到它有一个与以下行对应的作业:

rdd.foreach(lambda sample_element: save_nonlabelled_sample_2_jpeg(sample_element, save_dir))
但当它完成时,我的
save\u dir
目录中永远不会保存任何内容

知道我做错了什么吗

问候

main.py

spark = (SparkSession.builder
     .appName("Oncofinder -- Preprocessing")
     .getOrCreate())

samples = preprocess_spark(spark, [1])

if save_jpegs: #SET TO TRUE
    save_rdd_2_jpeg(samples, './data/images')


def save_rdd_2_jpeg(rdd, save_dir):
    rdd.foreach(lambda sample_element: save_nonlabelled_sample_2_jpeg(sample_element, save_dir))


def save_nonlabelled_sample_2_jpeg(sample, save_dir):
    slide_num, img_value = sample
    filename = '{slide_num}_{hash}.jpeg'.format(
        slide_num=slide_num, hash=np.random.randint(1e4))
    filepath = os.path.join(save_dir, filename)
    save_jpeg_help(img_value, filepath)

def save_jpeg_help(img_value, filepath):
    dir = os.path.dirname(filepath)
    os.makedirs(dir, exist_ok=True)
    img = Image.fromarray(img_value.astype(np.uint8), 'RGB')
    img.save(filepath)


def preprocess_spark(spark, slide_nums, folder="data", training=False, tile_size=1024, overlap=0,
               tissue_threshold=0.9, sample_size=256, grayscale=False, normalize_stains=True,
               num_partitions=20000):

    slides = (spark.sparkContext
              .parallelize(slide_nums)
              .filter(lambda slide: open_slide(slide, folder, training) is not None))
    tile_indices = (slides.flatMap(
        lambda slide: process_slide(slide, folder, training, tile_size, overlap)))
    tile_indices = tile_indices.repartition(num_partitions)
    tile_indices.cache()

    tiles = tile_indices.map(lambda tile_index: process_tile_index(tile_index, folder, training))
    filtered_tiles = tiles.filter(lambda tile: keep_tile(tile, tile_size, tissue_threshold))
    samples = filtered_tiles.flatMap(lambda tile: process_tile(tile, sample_size, grayscale))
    if normalize_stains:
        samples = samples.map(lambda sample: normalize_staining(sample))

    return samples
编辑:我正在使用

PYSPARK\u PYTHON=python3 spark提交--masterspark://127.0.1.1:7077 spark_preprocessing.py


运行应用程序。似乎在
foreach
操作之后,没有其他事情发生。有什么原因吗?

如果您在尝试保存样本之前将所有样本收集到驱动程序节点,则可以解决问题。如果重新定义
将rdd\u 2\u jpeg保存为:

def save_rdd_2_jpeg(rdd, save_dir):
    for sample in rdd.collect():
        save_nonlabelled_sample_2_jpeg(sample, save_dir)

然后一切都应该正常。

您是在单个节点上运行还是在多个节点上运行?您使用的是相对路径还是绝对路径?鉴于您在多个节点上运行此操作,您绝对不能只调用
img.save(filepath)
,期望它像在正常Python执行中一样工作。上帝只知道你的图像文件在集群中的实际位置。相反,您必须在驱动程序节点上收集图像数组,然后在这些数组上运行
image.fromarray
img.save
。我尝试了
rdd.collect().foreach(…)
而不是
rdd.foreach(…)
,但我得到的
列表对象没有foreach的属性
将返回标准Python
列表
。然后,您必须迭代该列表的内容,并对每个元素调用图像保存函数。有关更多详细信息,请参见下面的答案。