【问题标题】:Can we do image processing with Palantir Foundry?我们可以使用 Palantir Foundry 进行图像处理吗?
【发布时间】:2021-04-16 13:34:41
【问题描述】:

我正在探索 Palantir Foundry 平台,它似乎有大量用于矩形数据或结构化数据的选项。有人有在 Foundry 平台上处理非结构化大数据的经验吗?我们如何使用 Foundry 进行图像分析?

【问题讨论】:

    标签: image-processing computer-vision palantir-foundry


    【解决方案1】:

    虽然大多数示例都是使用表格数据给出的,但实际上很多用例都使用代工厂进行非结构化和半结构化数据处理。 您应该将数据集视为具有用于访问和处理文件的 API 的文件容器。 使用文件级 API,您可以访问数据集中的文件并根据需要处理它们。如果这些文件是图像,您可以从文件中提取信息并随意使用。 一个常见的用例是将 PDF 作为数据集中的文件,从 PDF 中提取信息并将其存储为表格信息,以便您可以对其进行结构化和非结构化搜索。

    这里是提取 PDF 的文件访问示例:

    import com.palantir.transforms.lang.java.api.Compute;
    import com.palantir.transforms.lang.java.api.FoundryInput;
    import com.palantir.transforms.lang.java.api.FoundryOutput;
    import com.palantir.transforms.lang.java.api.Input;
    import com.palantir.transforms.lang.java.api.Output;
    import com.palantir.util.syntacticpath.Paths;
    import com.google.common.collect.AbstractIterator;
    import com.palantir.spark.binarystream.data.PortableFile;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.Iterator;
    import java.util.UUID;
    import org.apache.spark.api.java.function.FlatMapFunction;
    import org.apache.spark.sql.Dataset;
    import org.apache.spark.sql.Encoders;
    import org.apache.spark.sql.Row;
    import org.apache.pdfbox.pdmodel.PDDocument; 
    import org.apache.pdfbox.text.PDFTextStripper;
    
    
    public final class ExtractPDFText {
    
        private static String pdf_source_files_rid = "SOME RID";
        private static String dataProxyPath = "/foundry-data-proxy/api/dataproxy/datasets/";
        private static String datasetViewPath = "/views/master/";
    
        @Compute 
        public void compute(
            @Input("/Base/project_name/treasury_pdf_docs") FoundryInput pdfFiles, 
            @Output("/Base/project_name/clean/pdf_text_extracted") FoundryOutput output) throws IOException {
    
            Dataset<PortableFile> filesDataset = pdfFiles.asFiles().getFileSystem().filesAsDataset(); 
    
            Dataset<String> mappedDataset = filesDataset.flatMap((FlatMapFunction<PortableFile, String>) portableFile -> 
                portableFile.convertToIterator(inputStream -> {
    
                    String pdfFileName = portableFile.getLogicalPath().getFileName().toString();
                    return new PDFIterator(inputStream, pdfFileName);
                }), Encoders.STRING());
    
            Dataset<Row> dataset = filesDataset
                    .sparkSession()
                    .read()
                    .option("inferSchema", "false")
                    .json(mappedDataset);
    
            output.getDataFrameWriter(dataset).write();
        }
    
        private static final class PDFIterator extends AbstractIterator<String> {
            private InputStream inputStream;
            private String pdfFileName;
            private boolean done;
    
            PDFIterator(InputStream inputStream, String pdfFileName) throws IOException {
                this.inputStream = inputStream;
                this.pdfFileName = pdfFileName;
                this.done = false;
            }
    
            @Override
            protected String computeNext() {
                if (done) {
                    return endOfData();
                }
    
                try {
                    String objectId = pdfFileName;
                    String appUrl = dataProxyPath.concat(pdf_source_files_rid).concat(datasetViewPath).concat(pdfFileName);
                    PDDocument document = PDDocument.load(inputStream);
    
                    PDFTextStripper pdfStripper = new PDFTextStripper();
    
                    String text = pdfStripper.getText(document);
                    String strippedText = text.replace("\"", "'").replace("\\", "").replace("“", "'").replace("”", "'").replace("\n", "").replace("\r", "");
    
                    done = true;
                    return "{\"id\": \"" + String.valueOf(UUID.randomUUID()) + "\", \"file_name\": \"" + pdfFileName + "\", \"app_url\": \"" + appUrl + "\", \"object_id\": \"" + objectId + "\", \"text\": \"" + strippedText + "\"}\n";
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    } 
    

    【讨论】:

      【解决方案2】:

      确实,您可以在 Foundry 上进行图像分析,因为您可以访问文件并且可以使用任意库(例如用于 python 的枕头或 skimage)。这可以大规模完成,也可以并行化。

      一个简单的 python sn-p 将两张图片拼接在一起应该可以帮助您入门:

      from transforms.api import transform, Input, Output
      from PIL import Image
      
      
      @transform(
          output=Output("/processed/stitched_images"),
          raw=Input("/raw/images"),
          image_meta=Input("/processed/image_meta")
      )
      def my_compute_function(raw, image_meta, output, ctx):
      
          image_meta = image_meta.dataframe()
      
          def stitch_images(clone):
              left = clone["left_file_name"]
              right = clone["right_file_name"]
              image_name = clone["image_name"]
              with raw.filesystem().open(left, mode="rb") as left_file:
                  with raw.filesystem().open(right, mode="rb") as right_file:
                      with output.filesystem().open(image_name, 'wb') as out_file:
      
                          left_image = Image.open(left_file)
                          right_image = Image.open(right_file)
      
                          (width, height) = left_image.size
      
                          result_width = width * 2
                          result_height = height
                          result = Image.new('RGB', (result_width, result_height))
      
                          result.paste(im=left_image, box=(0, 0))
                          result.paste(im=right_image, box=(height, 0))
      
                          result.save(out_file, format='jpeg', quality=90)
      
          image_meta.rdd.foreach(stitch_images)
      
      

      image_meta 数据集只是一个每行有 2 个文件名的数据集。要从原始文件数据集中提取文件名,您可以使用以下内容:

      @transform(
          output=Output("/processed/image_meta"),
          raw=Input("/raw/images"),
      )
      def my_compute_function(raw, output, ctx):
      
          file_names = [(file_status.path, 1) for file_status in raw.filesystem().ls(glob="*.jpg")]
      
          # create and write spark dataframe based on array
      

      【讨论】:

        【解决方案3】:

        正如其他人所提到的,Palantir-Foundry 的重点是表格数据,目前不提供 GPU 或其他张量处理单元访问。因此,如果不是在最坏的情况下完全不可能,那么做任何像 FFT 变换或深度学习这样激烈的事情都是不明智的。

        话虽如此,您可以将图像文件上传到数据集节点以进行读/写访问。您还可以将它们的二进制信息作为 blob 类型存储到 Dataframe 中,以便将文件存储在给定的记录字段中。鉴于平台上有大量 Python 图像处理相邻和矩阵数学库,并且还可以通过 Code Repo 应用程序手动将库包上传到平台,可以想象有人可以使用简单的操作只要不是过于复杂或占用大量内存,就可以大规模使用。

        【讨论】:

          【解决方案4】:

          请注意,Foundry 目前似乎不支持 GPU,因此如果您正在考虑运行基于深度学习的图像处理,这在 CPU 上会非常慢。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2012-06-29
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-09-03
            • 2021-03-06
            • 1970-01-01
            相关资源
            最近更新 更多