玩转 ArrayFire:09 Forge 下的可视化

目录

  • 前言
  • 一、介绍
  • 二、窗口设置
  • 三、绘图函数
    •     1. Image
    •     2. Plot
    •     3. Plot3
    •     4. Histogram
    •     5. Surface
  • 四、结论


前言

在《玩转 ArrayFire:08 数组和矩阵操作》中,我们已经了解到 ArrayFire 的统一后端,在这一篇中,我们继续学习 ArrayFire 在 Forge 下的可视化操作。


一、介绍

     ArrayFire 作为一个库,旨在为高性能、并行和 GPU 计算提供一个健壮且易于使用的平台。 Forge ——一个 OpenGL 可视化库——的目标也是提供同样健壮的可视化,并且能使 Arrayfire 数据结构和 OpenGL 互操作。
     Arrayfire 提供了包装函数,它被设计成一个简单的接口来可视化 af::array。这些函数执行各种互操作任务。其中一个特别的例子是,我们可以直接从 GPU-dataGPU-framebuffer 中提取数据绘图,而不是浪费时间从 GPU 复制和重新格式化数据到主机再返回给 GPU !这节省了 2 份内存拷贝。
    可视化可以用鼠标操作。可以采取以下措施:

       - 缩放(Alt +鼠标左键点击,上下移动)
       - 平移(左键点击并拖动)
       - 旋转(鼠标右键-跟踪球旋转)

    现在,让我们来看看:我们可以用 Forge 展示什么样的视觉效果,以及 Arrayfire 是如何在两个库之间处理数据的。

二、窗口设置

    在调用 Forge 函数之前,我们需要建立相关的 “canvas” 类。Forge 函数被添加到 af::Window 类。首先让我们创建一个窗口:

	const static int width = 512, height = 512;
	af::Window window(width, height, "2D plot example title");
	do{
     
	//drawing functions here
	} while( !window.close() );

    ArrayFire 还添加了一个绘图循环,所以可以使用 Forge 的绘图函数来绘制窗口。

三、绘图函数

    下面,介绍几种常见的绘图函数:

    1. Image

     af::Window::image() 函数的作用是绘制灰度或彩色图像。要绘制灰度图像,应该将 2D 数组传递到函数中。让我们看一个静态噪声的例子:

	array img = constant(0, width, height); //make a black image
	array random = randu(width, height);      //make random [0,1] distribution
	img(random > 0.5) = 1; //set all pixels where distribution > 0.5 to white
	window.image(img);

    通过调整前面的例子,设置图像的RGB值为3,即产生彩色噪声:

	array img = 255 * randu(width, height, 3);      //make random [0, 255] distribution
	window.image( img.as(u8) );

    注意:Forge 会自动处理任何从 ArrayFire 传入的 af::array 类型。在第一个示例中,我们传入了一个范围为 [0,1] 的浮点数图像。在上一个示例中,我们将数组转换为范围为 [0,255] 的无符号字节数组。所有 Forge 绘图函数的类型处理属性是一致的。

    2. Plot

     af::Window::plot() 函数将数组可视化为二维线图。让我们看一个简单的例子:

	array X = seq(-af::Pi, af::Pi, 0.01);
	array Y = sin(X);
	window.plot(X, Y);

     plot 函数具有如下特征:

	void plot( const array &X, const array &Y, const char * const title = NULL );

    绘图时需要这些点的x坐标和y坐标。这些参数可以是非均匀的,或参数化的:

	array t = seq(0, 100, 0.01);
	array X = sin(t) * (exp(cos(t)) - 2 * cos(4 * t) - pow(sin(t / 12), 5));
	array Y = cos(t) * (exp(cos(t)) - 2 * cos(4 * t) - pow(sin(t / 12), 5));
	window.plot(X, Y);

    3. Plot3

     af::Window::plot3() 函数具有如下特征:

	void plot3 (const array &in, const char * title = NULL);

    输入数组需要按顺序输入 XYZ 坐标。这些点可以是一维(3n x 1)数组,也可以是 (3 x n) 或 (n x 3) 的矩阵。

	array Z = seq(0.1f, 10.f, 0.01);
	array Y = sin(10 * Z) / Z;
	array X = cos(10 * Z) / Z;
	array Pts = join(1, X, Y, Z);
	//Pts can be passed in as a matrix in the from n x 3, 3 x n
	//or in the flattened xyz-triplet array with size 3n x 1
	window.plot3(Pts);
	//both of the following are equally valid
	//window.plot3(transpose(Pts));
	//window.plot3(flat(Pts));

    4. Histogram

     af::Window::hist() 函数的作用是将输入数组渲染成直方图。在下面的示例中,输入数组将使用 Arrayfire 的 histogram() 函数创建,该函数计算并存储每个样本。histogram() 的输出可以直接输入到 af::Window::hist() 函数。

	const int BINS = 128; SAMPLES = 9162;
	array norm = randn(SAMPLES);
	array hist_arr = histogram(norm, BINS);
	win.hist(hist_arr, 0, BINS);

    除了直方图数组外,af::Window::hist() 函数还接受两个其他参数:直方图数组中所有数据点的最小值和最大值。这有效地设置了存储数据的范围。

	void hist(const array & X, const double minval, const double maxval, const char * const title = NULL);

    5. Surface

     af::Window::surface() 函数将数组绘制成一个 3D 曲面。

	array Z = randu(21, 21);
	window.surface(Z, "Random Surface");    //equal to next function call
	//window.surface( seq(-1, 1, 0.1), seq(-1, 1, 0.1), Z, "Random Surface");

     af::Window::surface() 函数有两个重载:

	void surface (const array & S, const char * const title ) // Accepts a 2d matrix with the z values of the surface
	
	void surface (const array &xVals, const array &yVals, const array &S, const char * const title) // accepts additional vectors that define the x,y coordinates for the surface points.

    第二个重载对于 X、Y 坐标向量有两个选项。假设一个大小为 m x n 的表面网格:

  • 定义沿每个轴的间距的向量。向量的大小是 m x 1 和 n x 1 。
  • 包含每个点坐标的向量。每个向量的长度都是 mn x 1 。这可以用于完全非均匀曲面或参数曲面。

四、结论

     ArrayFire 中有相当全面的方法来可视化数据。由于使用高性能 GPU 绘图库 Forge ,所提供的 Arrayfire 函数不仅使可视化尽可能简单,而且保持了 Arrayfire 库的其余部分的健壮性。


你可能感兴趣的:(ArrayFire,矩阵,经验分享)