您好我有很多图像(数百万以下)需要进行分类。我正在使用Spark并设法将(filename1, content1), (filename2, content2) ...
格式的所有图像读入一个大的RDD。
images = sc.wholeTextFiles("hdfs:///user/myuser/images/image/00*")
然而,我真的很困惑如何处理图像的unicode表示。
以下是一个图像/文件的示例:
(u'hdfs://NameService/user/myuser/images/image/00product.jpg', u'\ufffd\ufffd\ufffd\ufffd\x00\x10JFIF\x00\x01\x01\x01\x00`\x00`\x00\x00\ufffd\ufffd\x01\x1eExif\x00\x00II*\x00\x08\x00\x00\x00\x08\x00\x12\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\x00\x1a\x01\x05\x00\x01\x00\x00\x00n\x00\x00\x00\x1b\x01\x05\x00\x01\x00\x00\x00v\x00\x00\x00(\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\x001\x01\x02\x00\x0b\x00\x00\x00~\x00\x00\x002\x01\x02\x00\x14\x00\x00\x00\ufffd\x00\x00\x00\x13\x02\x03\x00\x01\x00\x00\x00\x01\x00\x00\x00i\ufffd\x04\x00\x01\x00\x00\x00\ufffd\x00\x00\x00\x00\x00\x00\x00`\x00\x00\x00\x01\x00\x00\x00`\x00\x00\x00\x01\x00\x00\x00GIMP 2.8.2\x00\x002013:07:29 10:41:35\x00\x07\x00\x00\ufffd\x07\x00\x04\x00\x00\x000220\ufffd\ufffd\x02\x00\x04\x00\x00\x00407\x00\x00\ufffd\x07\x00\x04\x00\x00\x000100\x01\ufffd\x03\x00\x01\x00\x00\x00\ufffd\ufffd\x00\x00\x02\ufffd\x04\x00\x01\x00\x00\x00\x04\x04\x00\x00\x03\ufffd\x04\x00\x01\x00\x00\x00X\x01\x00\x00\x05\ufffd\x04\x00\x01\x00\x00\x00\ufffd\x00\x00\x00\x00\x00\x00\x00\x02\x00\x01\x00\x02\x00\x04\x00\x00\x00R98\x00\x02\x00\x07\x00\x04\x00\x00\x000100\x00\x00\x00\x00\ufffd\ufffd\x04_http://ns.adobe.com/xap/1.0/\x00<?xpacket begin=\'\ufeff\' id=\'W5M0MpCehiHzreSzNTczkc9d\'?>\n<x:xmpmeta xmlns:x=\'adobe:ns:meta/\'>\n<rdf:RDF xmlns:rdf=\'http://www.w3.org/1999/02/22-rdf-syntax-ns#\'>\n\n <rdf:Description xmlns:exif=\'http://ns.adobe.com/exif/1.0/\'>\n <exif:Orientation>Top-left</exif:Orientation>\n <exif:XResolution>96</exif:XResolution>\n <exif:YResolution>96</exif:YResolution>\n <exif:ResolutionUnit>Inch</exif:ResolutionUnit>\n <exif:Software>ACD Systems Digital Imaging</exif:Software>\n <exif:DateTime>2013:07:29 10:37:00</exif:DateTime>\n <exif:YCbCrPositioning>Centered</exif:YCbCrPositioning>\n <exif:ExifVersion>Exif Version 2.2</exif:ExifVersion>\n <exif:SubsecTime>407</exif:SubsecTime>\n <exif:FlashPixVersion>FlashPix Version 1.0</exif:FlashPixVersion>\n <exif:ColorSpace>Uncalibrated</exif:ColorSpace>\n
仔细观察,实际上有些角色看起来像
这样的元数据...
<x:xmpmeta xmlns:x=\'adobe:ns:meta/\'>\n<rdf:RDF xmlns:rdf=\'http://www.w3.org/1999/02/22-rdf-syntax-ns#\'>\n\n
<rdf:Description xmlns:exif=\'http://ns.adobe.com/exif/1.0/\'>\n
<exif:Orientation>Top-left</exif:Orientation>\n
<exif:XResolution>96</exif:XResolution>\n
<exif:YResolution>96</exif:YResolution>\n
...
我以前的经验是使用包scipy和相关函数,如'imread'...而输入通常是文件名。现在我真的迷失了那些unicode意味着什么以及我能做些什么来将它转换成我熟悉的格式。
任何人都可以与我分享如何将这些unicode读入scipy图像(ndarray)?
答案 0 :(得分:7)
您的数据看起来像真实图像文件中的原始字节(JPG?)。您的数据的问题是它应该是字节,而不是unicode。你必须弄清楚如何从unicode转换为字节。有一大堆蠕虫充满了你必须处理的编码陷阱,但你可能很幸运使用img.encode('iso-8859-1')
。我不知道,我不会在答案中处理这个问题。
PNG图像的原始数据如下所示:
rawdata = '\x89PNG\r\n\x1a\n\x00\x00...\x00\x00IEND\xaeB`\x82'
一旦你以字节为单位,你可以从原始数据创建PIL图像,并将其作为nparray读取:
>>> from StringIO import StringIO
>>> from PIL import Image
>>> import numpy as np
>>> np.asarray(Image.open(StringIO(rawdata)))
array([[[255, 255, 255, 0],
[255, 255, 255, 0],
[255, 255, 255, 0],
...,
[255, 255, 255, 0],
[255, 255, 255, 0],
[255, 255, 255, 0]]], dtype=uint8)
所有你需要让它在Spark上工作的是SparkContext.binaryFiles
:
>>> images = sc.binaryFiles("path/to/images/")
>>> image_to_array = lambda rawdata: np.asarray(Image.open(StringIO(rawdata)))
>>> images.values().map(image_to_array)
答案 1 :(得分:2)
在Spark 2.3或更高版本中,您可以使用内置的Spark工具将图像数据加载到Spark DataFrame
中。在2.3
from pyspark.ml.image import ImageSchema
ImageSchema.readImages("path/to/images/")
在Spark 2.4或更高版本中:
spark.read.format("image").load("path/to/images/")
这将创建具有以下架构的对象:
root
|-- image: struct (nullable = true)
| |-- origin: string (nullable = true)
| |-- height: integer (nullable = false)
| |-- width: integer (nullable = false)
| |-- nChannels: integer (nullable = false)
| |-- mode: integer (nullable = false)
| |-- data: binary (nullable = false)
将图像内容加载到image.data
中。
此功能目前处于试验阶段,缺少必需的生态系统,但将来会改进。