Skip to main content
Version: Next

OpenCV - 管道图像转换

此示例展示了如何操作图像集合。 首先,图像被下载到本地目录。 其次,它们被复制到集群附加的HDFS中。

图像从目录中加载(为了快速原型设计,考虑加载一部分图像)。在数据框中,每个图像都是图像列中的一个字段。图像有子字段(路径、高度、宽度、OpenCV类型和OpenCV字节)。

from synapse.ml.opencv import toNDArray
from synapse.ml.io import *

imageDir = "wasbs://publicwasb@mmlspark.blob.core.windows.net/sampleImages"
images = spark.read.image().load(imageDir).cache()
images.printSchema()
print(images.count())

我们也可以使用类似的API来流式传输图像。 有关流式传输的更多详细信息,请查看Structured Streaming Programming Guide

当从DataFrame中收集时,图像数据存储在Row中,这是Spark表示结构的方式(在当前示例中,每个数据帧行都有一个Image,它本身是一个Row)。可以通过名称访问图像字段,并使用toNDArray()辅助函数将图像转换为numpy数组以进行进一步操作。

from synapse.ml.core.platform import running_on_binder

if running_on_binder():
from IPython import get_ipython
from PIL import Image
import matplotlib.pyplot as plt

data = images.take(3) # take first three rows of the dataframe
im = data[2][0] # the image is in the first column of a given row

print("image type: {}, number of fields: {}".format(type(im), len(im)))
print("image path: {}".format(im.origin))
print("height: {}, width: {}, OpenCV type: {}".format(im.height, im.width, im.mode))

arr = toNDArray(im) # convert to numpy array
print(images.count())
plt.imshow(Image.fromarray(arr, "RGB")) # display the image inside notebook

使用ImageTransformer进行基本的图像处理:调整大小、裁剪等。 在内部,操作是通过OpenCV实现进行管道化和支持的。

from synapse.ml.opencv import ImageTransformer

tr = (
ImageTransformer() # images are resized and then cropped
.setOutputCol("transformed")
.resize(size=(200, 200))
.crop(0, 0, height=180, width=180)
)

small = tr.transform(images).select("transformed")

im = small.take(3)[2][0] # take third image
plt.imshow(Image.fromarray(toNDArray(im), "RGB")) # display the image inside notebook

对于高级图像处理,请使用Spark UDFs。 SynapseML包提供了Spark Rowndarray图像表示之间的转换函数。

from pyspark.sql.functions import udf
from synapse.ml.opencv import ImageSchema, toNDArray, toImage


def u(row):
array = toNDArray(row) # convert Image to numpy ndarray[height, width, 3]
array[:, :, 2] = 0
return toImage(array) # numpy array back to Spark Row structure


noBlueUDF = udf(u, ImageSchema)

noblue = small.withColumn("noblue", noBlueUDF(small["transformed"])).select("noblue")

im = noblue.take(3)[2][0] # take second image
plt.imshow(Image.fromarray(toNDArray(im), "RGB")) # display the image inside notebook

图像可以展开为适合CNTK评估的密集一维向量。

from synapse.ml.image import UnrollImage

unroller = UnrollImage().setInputCol("noblue").setOutputCol("unrolled")

unrolled = unroller.transform(noblue).select("unrolled")

vector = unrolled.take(1)[0][0]
print(type(vector))
len(vector.toArray())