(5712,17795,'2014-05-27 23:50:53','2014-05-27 23:50:53','During the next months, we will be working on a lot of new Computer Vision functionality for ArrayFire. This means dozens of new functions specifically targeted for the most common and used applications in this field, like feature tracking, object classification, scene segmentation, optical flow, stereo-vision, among others, will be added to take full advantage of GPU devices.\r\n\r\nFeature tracking consists of three basic steps:\r\n<ol>\r\n	<li>Detecting good or unique features, normally they are corners or blobs of an image;</li>\r\n	<li>Extracting a descriptor for each feature, that consists of understanding the texture of a small patch around each feature;</li>\r\n	<li>Descriptor matching, finding out the best match for each pair of descriptors (one from the object being tracked, another from a scene that potentially contains that object), if any.</li>\r\n</ol>\r\n<h3>Harris corner detector</h3>\r\nTo get started on what is coming to ArrayFire, in this article we dive deeper in the first step of feature tracking, detecting good features. Through a step-by-step guide, we will develop a simple corner detector, known as the Harris corner detector [1].\r\n\r\nThe Harris corner detector is very simple to implement, especially when you have so many good tools and libraries out there to do the core matrix manipulation. What we specifically need for Harris are some convolutions, together with a few element-wise matrix addition and multiplication operations, all of these operations are present in most scientific tools and libraries that work with matrix manipulation. I will try to avoid going into the mathematical details in this post and go directly to the implementation.\r\n<h5>Loading an image</h5>\r\nBefore starting writing the code for the corner detector, we need to load an image. The image can be either color or gray-scale, but it will only work on the gray-scale version, so if it is a color image, we have to convert it before proceeding.\r\n<pre>// Load a color image\r\narray img_color = loadimage(\"lena.jpg\", true);\r\n// Convert the image from RGB to gray-scale\r\narray img_gray = colorspace(img_color, af_gray, af_rgb);\r\n// For visualization in ArrayFire, color images must be in the [0.0f-1.0f] interval\r\nimg /= 255.f;\r\n</pre>\r\n<h5>Compute first-order derivatives</h5>\r\nThe first step in the Harris corner detector is to determine first order derivatives of an image, in both horizontal and vertical directions. This can be achieved by one convolution for each direction, with the special filter (-1, 0, 1)  for horizontal derivative and its transpose for vertical derivative. ArrayFire contains a function called<code>grad</code>, it calculates gradients in both directions and will perform faster than the two convolutions. The only difference is <conv>grad</code> divides the result by 2, thus the response factor will change, but this can be compensated by using a smaller response while improving computation performance, so it will be used instead.\r\n<pre>\r\n// Calculate image gradients\r\narray ix, iy;\r\ngrad(ix, iy, img_gray);\r\n</pre>\r\n<h5>Compute second-order derivatives</h5>\r\nAt this point, we have both horizontal and vertical first order derivatives of our image, but Harris corner detector is processed with second-order derivatives, which can be easily computed in ArrayFire with simple element-wise multiplications of the first-order derivatives.\r\n<pre>// Compute second-order derivatives\r\narray ixx = ix * ix;\r\narray ixy = ix * iy;\r\narray iyy = iy * iy;\r\n</pre>\r\n<h5>Compute an isotropic window</h5>\r\nTo check the cornerness of each pixel of an image, it\'s not enough to check the pixel value itself, but a small window around that pixel. To reduce noise sensitivity and have an isotropic response, Harris claims that a smooth circular window should be used, and it can be achieved by filtering of all three second-order derivatives with a Gaussian kernel.\r\n<pre>// Compute a Gaussian kernel with standard deviation of 1.0 and length of 5 pixels\r\n// These values can be changed to use a smaller or larger window\r\narray gauss_filt = gaussiankernel(5, 5, 1.0, 1.0);\r\n\r\n// Filter second-order derivatives with Gaussian kernel computed previously\r\nixx = convolve(ixx, gauss_filt);\r\nixy = convolve(ixy, gauss_filt);\r\niyy = convolve(iyy, gauss_filt);\r\n</pre>\r\n<h5>Compute trace and determinant</h5>\r\nFrom a second-order Hessian matrix, we then compute the values of its trace and determinant. These are the values we will need later to calculate the Harris response for each pixel in the image.\r\n<pre>// Calculate trace\r\narray tr = ixx + iyy;\r\n// Calculate determinant\r\narray det = ixx * iyy - ixy * ixy;\r\n</pre>\r\n<h5>Compute Harris response</h5>\r\nFinally, we then calculate the Harris response for each pixel. For this calculation, Harris uses an empirically defined constant <code>k</code>. This constant is usually very small, and usually it ranges from <code>0.04</code> to <code>0.06</code>. In our case, we will use <code>k = 0.04</code>, but we encourage you to play with this value and see how the result changes.\r\n<pre>// Calculate Harris response\r\narray response = det - 0.04f * (tr * tr);\r\n</pre>\r\n<h5>Selection of good corners</h5>\r\nNow we already have our Harris responses for each pixel in the image. This value is used to determine whether a pixel is a corner or not. The standard way is to perform a non-maximal suppression, meaning that for each pixel it can only be a corner if it is a maximum compared to its 8 adjacent pixels. At the moment we do not have an easy way to compute a non-maximal suppression with ArrayFire, we have to write our own kernel for that, and that is only one of the cool things we will be able to do with our new computer vision toolset for ArrayFire.\r\n\r\nAn alternative is to do the non-maximal suppression in a naive way. To do this, we will use ArrayFire\'s <code>maxfilt</code> function, that filters the image with a mask of <code>NxM</code> pixel and returns the maximum value of the neighborhood to the pixel centered within the mask. In this case we will use a <code>3x3</code> pixel mask to return the maximum of the 8-neighborhood, including the central pixel itself.\r\n\r\nThe <code>maxfilt</code> function alone will not perform a non-maximal suppression, but with a few more lines of code we can get the proper responses.\r\n\r\nThe nature of a pixel can be determined by the Harris responses, a negative response means that a pixel corresponds to the segment of an edge. If the response is small but positive, it corresponds to a flat region. Only a large response corresponds to a corner. By thresholding the response array with the minimum desired Harris response, that for our example will be 10<sup>5</sup>, we can calculate a binary response array for which only pixels with a value greater than this threshold will be true. We then multiply it to the original response array to get a new array containing only responses greater that 10<sup>5</sup>.\r\n\r\nHere, we will use a threshold of 10<sup>5</sup>. For the implementation presented in this article, we found that corners seem to be better for responses larger than 10<sup>4</sup>, but you can and should play with these values to see how it will affect the image you are working on.\r\n\r\nThe last step for this is testing whether each pixel is equal to the maximum Harris response of the neighborhood. If it is equal, then we keep it, else, the response is not a local maximum and we discard it.\r\n\r\n<pre>\r\n// Gets maximum response for each 3x3 neighborhood\r\narray max_resp = maxfilt(response, 3, 3);\r\n\r\n// Discard responses that are not greater than threshold\r\narray corners = response > 1e5f;\r\ncorners = corners * response;\r\n\r\n// Discard responses that are not equal to maximum neighborhood response,\r\n// scale them to original response value\r\ncorners = (corners == max_resp) * corners;\r\n</pre>\r\n\r\nIf you still think you want a non-maximal suppression kernel for yourself, you can still write it instead of using the last piece of code above. If you have never written your own kernel to work with an ArrayFire array, check out the <a href=\"http://sandbox.arrayfire.com/custom-kernels-with-arrayfire/\">Custom Kernels with ArrayFire</a> post. Writing the non-maximal suppression kernel itself will not take more than 20 or 30 lines of code.\r\n\r\n<h5>Plotting corners</h5>\r\n\r\nThis last step is done on the CPU side, we only do this to show the corners that are detected. Most likely, you will not need to do this unless you want to visualize, but for the sake of clarity, we include this part to show the result.\r\n<pre>// Gets host pointer to response data\r\nfloat* h_corners = corners.host<float>();\r\n\r\n// Draw draw_len x draw_len crosshairs where the corners are\r\nconst int draw_len = 3;\r\nfor (int y = draw_len; y < img.dims(0) - draw_len; y++) {\r\n    for (int x = draw_len; x < img.dims(1) - draw_len; x++) {\r\n        // Only draws crosshair if is a corner\r\n        if (h_corners[x * corners.dims(0) + y] > 1e5f) {\r\n            // Draw horizontal line of (draw_len * 2 + 1) pixels centered on the corner\r\n            // Set only the first channel to 1 (green lines)\r\n            img_color(y, seq(x-draw_len, x+draw_len), 0) = 0.f;\r\n            img_color(y, seq(x-draw_len, x+draw_len), 1) = 1.f;\r\n            img_color(y, seq(x-draw_len, x+draw_len), 2) = 0.f;\r\n\r\n            // Draw vertical line of (draw_len * 2 + 1) pixels centered on  the corner\r\n            // Set only the first channel to 1 (green lines)\r\n            img_color(seq(y-draw_len, y+draw_len), x, 0) = 0.f;\r\n            img_color(seq(y-draw_len, y+draw_len), x, 1) = 1.f;\r\n            img_color(seq(y-draw_len, y+draw_len), x, 2) = 0.f;\r\n        }\r\n    }\r\n}</pre>\r\n<h5>Visualize results</h5>\r\nFinally, the image can be visualized.\r\n<pre>// Previews color image with green crosshairs\r\nimage(img_color);\r\n</pre>\r\nBelow you can see Lena\'s picture after the Harris corner detection and plotting. The green crosshairs indicate where corners are.\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_lena.png\"><img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_lena.png\" alt=\"Harris Corners - Lena\" width=\"1024\" height=\"600\" class=\"alignnone size-full wp-image-5710\" /></a>\r\n\r\nTo test for correctness of the algorithm, nothing better than a picture with well-defined corners. Below you can see the picture of a white square on a black background and the corners marked by green crosshairs.\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_square.png\"><img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_square.png\" alt=\"Harris Corners - Square\" width=\"1024\" height=\"600\" class=\"alignnone size-full wp-image-5711\" /></a>\r\n\r\nWe would like to hear from you, what you are working on the computer vision field and which features you would like to see in ArrayFire. Please share your thoughts and requests below or contact us at <a href=\"mailto:sales@arrayfire.com\">sales@arrayfire.com</a>.\r\n<h5>References</h5>\r\n[1] Harris, Chris, and Mike Stephens. \"A combined corner and edge detector.\" <em>Alvey vision conference</em>. Vol. 15. 1988.\r\n','Writing a Simple Corner Detector with ArrayFire','','inherit','open','closed','','5659-revision-v1','','','2014-05-27 23:50:53','2014-05-27 23:50:53','',5659,'http://sandbox.arrayfire.com/5659-revision-v1/',0,'revision','',0),(5713,17795,'2014-05-27 23:53:11','2014-05-27 23:53:11','During the next months, we will be working on a lot of new Computer Vision functionality for ArrayFire. This means dozens of new functions specifically targeted for the most common and used applications in this field, like feature tracking, object classification, scene segmentation, optical flow, stereo-vision, among others, will be added to take full advantage of GPU devices.\r\n\r\nFeature tracking consists of three basic steps:\r\n<ol>\r\n	<li>Detecting good or unique features, normally they are corners or blobs of an image;</li>\r\n	<li>Extracting a descriptor for each feature, that consists of understanding the texture of a small patch around each feature;</li>\r\n	<li>Descriptor matching, finding out the best match for each pair of descriptors (one from the object being tracked, another from a scene that potentially contains that object), if any.</li>\r\n</ol>\r\n<h3>Harris corner detector</h3>\r\nTo get started on what is coming to ArrayFire, in this article we dive deeper in the first step of feature tracking, detecting good features. Through a step-by-step guide, we will develop a simple corner detector, known as the Harris corner detector [1].\r\n\r\nThe Harris corner detector is very simple to implement, especially when you have so many good tools and libraries out there to do the core matrix manipulation. What we specifically need for Harris are some convolutions, together with a few element-wise matrix addition and multiplication operations, all of these operations are present in most scientific tools and libraries that work with matrix manipulation. I will try to avoid going into the mathematical details in this post and go directly to the implementation.\r\n<h5>Loading an image</h5>\r\nBefore starting writing the code for the corner detector, we need to load an image. The image can be either color or gray-scale, but it will only work on the gray-scale version, so if it is a color image, we have to convert it before proceeding.\r\n<pre>// Load a color image\r\narray img_color = loadimage(\"lena.jpg\", true);\r\n// Convert the image from RGB to gray-scale\r\narray img_gray = colorspace(img_color, af_gray, af_rgb);\r\n// For visualization in ArrayFire, color images must be in the [0.0f-1.0f] interval\r\nimg /= 255.f;\r\n</pre>\r\n<h5>Compute first-order derivatives</h5>\r\nThe first step in the Harris corner detector is to determine first order derivatives of an image, in both horizontal and vertical directions. This can be achieved by one convolution for each direction, with the special filter (-1, 0, 1)  for horizontal derivative and its transpose for vertical derivative. ArrayFire contains a function called<code>grad</code>, it calculates gradients in both directions and will perform faster than the two convolutions. The only difference is <conv>grad</code> divides the result by 2, thus the response factor will change, but this can be compensated by using a smaller response while improving computation performance, so it will be used instead.\r\n<pre>\r\n// Calculate image gradients\r\narray ix, iy;\r\ngrad(ix, iy, img_gray);\r\n</pre>\r\n<h5>Compute second-order derivatives</h5>\r\nAt this point, we have both horizontal and vertical first order derivatives of our image, but Harris corner detector is processed with second-order derivatives, which can be easily computed in ArrayFire with simple element-wise multiplications of the first-order derivatives.\r\n<pre>// Compute second-order derivatives\r\narray ixx = ix * ix;\r\narray ixy = ix * iy;\r\narray iyy = iy * iy;\r\n</pre>\r\n<h5>Compute an isotropic window</h5>\r\nTo check the cornerness of each pixel of an image, it\'s not enough to check the pixel value itself, but a small window around that pixel. To reduce noise sensitivity and have an isotropic response, Harris claims that a smooth circular window should be used, and it can be achieved by filtering of all three second-order derivatives with a Gaussian kernel.\r\n<pre>// Compute a Gaussian kernel with standard deviation of 1.0 and length of 5 pixels\r\n// These values can be changed to use a smaller or larger window\r\narray gauss_filt = gaussiankernel(5, 5, 1.0, 1.0);\r\n\r\n// Filter second-order derivatives with Gaussian kernel computed previously\r\nixx = convolve(ixx, gauss_filt);\r\nixy = convolve(ixy, gauss_filt);\r\niyy = convolve(iyy, gauss_filt);\r\n</pre>\r\n<h5>Compute trace and determinant</h5>\r\nFrom a second-order Hessian matrix, we then compute the values of its trace and determinant. These are the values we will need later to calculate the Harris response for each pixel in the image.\r\n<pre>// Calculate trace\r\narray tr = ixx + iyy;\r\n// Calculate determinant\r\narray det = ixx * iyy - ixy * ixy;\r\n</pre>\r\n<h5>Compute Harris response</h5>\r\nFinally, we then calculate the Harris response for each pixel. For this calculation, Harris uses an empirically defined constant <code>k</code>. This constant is usually very small, and usually it ranges from <code>0.04</code> to <code>0.06</code>. In our case, we will use <code>k = 0.04</code>, but we encourage you to play with this value and see how the result changes.\r\n<pre>// Calculate Harris response\r\narray response = det - 0.04f * (tr * tr);\r\n</pre>\r\n<h5>Selection of good corners</h5>\r\nNow we already have our Harris responses for each pixel in the image. This value is used to determine whether a pixel is a corner or not. The standard way is to perform a non-maximal suppression, meaning that for each pixel it can only be a corner if it is a maximum compared to its 8 adjacent pixels. At the moment we do not have an easy way to compute a non-maximal suppression with ArrayFire, we have to write our own kernel for that, and that is only one of the cool things we will be able to do with our new computer vision toolset for ArrayFire.\r\n\r\nAn alternative is to do the non-maximal suppression in a naive way. To do this, we will use ArrayFire\'s <code>maxfilt</code> function, that filters the image with a mask of <code>NxM</code> pixel and returns the maximum value of the neighborhood to the pixel centered within the mask. In this case we will use a <code>3x3</code> pixel mask to return the maximum of the 8-neighborhood, including the central pixel itself.\r\n\r\nThe <code>maxfilt</code> function alone will not perform a non-maximal suppression, but with a few more lines of code we can get the proper responses.\r\n\r\nThe nature of a pixel can be determined by the Harris responses, a negative response means that a pixel corresponds to the segment of an edge. If the response is small but positive, it corresponds to a flat region. Only a large response corresponds to a corner. By thresholding the response array with the minimum desired Harris response, that for our example will be 10<sup>5</sup>, we can calculate a binary response array for which only pixels with a value greater than this threshold will be true. We then multiply it to the original response array to get a new array containing only responses greater that 10<sup>5</sup>.\r\n\r\nHere, we will use a threshold of 10<sup>5</sup>. For the implementation presented in this article, we found that corners seem to be better for responses larger than 10<sup>4</sup>, but you can and should play with these values to see how it will affect the image you are working on.\r\n\r\nThe last step for this is testing whether each pixel is equal to the maximum Harris response of the neighborhood. If it is equal, then we keep it, else, the response is not a local maximum and we discard it.\r\n\r\n<pre>\r\n// Gets maximum response for each 3x3 neighborhood\r\narray max_resp = maxfilt(response, 3, 3);\r\n\r\n// Discard responses that are not greater than threshold\r\narray corners = response > 1e5f;\r\ncorners = corners * response;\r\n\r\n// Discard responses that are not equal to maximum neighborhood response,\r\n// scale them to original response value\r\ncorners = (corners == max_resp) * corners;\r\n</pre>\r\n\r\nIf you still think you want a non-maximal suppression kernel for yourself, you can write it instead of using the last piece of code above. If you have never written your own kernel to work with an ArrayFire array, check out the <a href=\"http://sandbox.arrayfire.com/custom-kernels-with-arrayfire/\">Custom Kernels with ArrayFire</a> post. Writing the non-maximal suppression kernel itself will not take more than 20 or 30 lines of code.\r\n\r\n<h5>Plotting corners</h5>\r\n\r\nThis last step is done on the CPU side, we only do this to show the corners that are detected. Most likely, you will not need to do this unless you want to visualize, but for the sake of clarity, we include this part to show the result.\r\n<pre>// Gets host pointer to response data\r\nfloat* h_corners = corners.host<float>();\r\n\r\n// Draw draw_len x draw_len crosshairs where the corners are\r\nconst int draw_len = 3;\r\nfor (int y = draw_len; y < img.dims(0) - draw_len; y++) {\r\n    for (int x = draw_len; x < img.dims(1) - draw_len; x++) {\r\n        // Only draws crosshair if is a corner\r\n        if (h_corners[x * corners.dims(0) + y] > 1e5f) {\r\n            // Draw horizontal line of (draw_len * 2 + 1) pixels centered on the corner\r\n            // Set only the first channel to 1 (green lines)\r\n            img_color(y, seq(x-draw_len, x+draw_len), 0) = 0.f;\r\n            img_color(y, seq(x-draw_len, x+draw_len), 1) = 1.f;\r\n            img_color(y, seq(x-draw_len, x+draw_len), 2) = 0.f;\r\n\r\n            // Draw vertical line of (draw_len * 2 + 1) pixels centered on  the corner\r\n            // Set only the first channel to 1 (green lines)\r\n            img_color(seq(y-draw_len, y+draw_len), x, 0) = 0.f;\r\n            img_color(seq(y-draw_len, y+draw_len), x, 1) = 1.f;\r\n            img_color(seq(y-draw_len, y+draw_len), x, 2) = 0.f;\r\n        }\r\n    }\r\n}</pre>\r\n<h5>Visualize results</h5>\r\nFinally, the image can be visualized.\r\n<pre>// Previews color image with green crosshairs\r\nimage(img_color);\r\n</pre>\r\nBelow you can see Lena\'s picture after the Harris corner detection and plotting. The green crosshairs indicate where corners are.\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_lena.png\"><img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_lena.png\" alt=\"Harris Corners - Lena\" width=\"1024\" height=\"600\" class=\"alignnone size-full wp-image-5710\" /></a>\r\n\r\nTo test for correctness of the algorithm, nothing better than a picture with well-defined corners. Below you can see the picture of a white square on a black background and the corners marked by green crosshairs.\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_square.png\"><img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_square.png\" alt=\"Harris Corners - Square\" width=\"1024\" height=\"600\" class=\"alignnone size-full wp-image-5711\" /></a>\r\n\r\nWe would like to hear from you, what you are working on the computer vision field and which features you would like to see in ArrayFire. Please share your thoughts and requests below or contact us at <a href=\"mailto:sales@arrayfire.com\">sales@arrayfire.com</a>.\r\n<h5>References</h5>\r\n[1] Harris, Chris, and Mike Stephens. \"A combined corner and edge detector.\" <em>Alvey vision conference</em>. Vol. 15. 1988.\r\n','Writing a Simple Corner Detector with ArrayFire','','inherit','open','closed','','5659-revision-v1','','','2014-05-27 23:53:11','2014-05-27 23:53:11','',5659,'http://sandbox.arrayfire.com/5659-revision-v1/',0,'revision','',0),(5714,17795,'2014-05-27 23:56:40','2014-05-27 23:56:40','During the next months, we will be working on a lot of new Computer Vision functionality for ArrayFire. This means dozens of new functions specifically targeted for the most common and used applications in this field, like feature tracking, object classification, scene segmentation, optical flow, stereo-vision, among others, will be added to take full advantage of GPU devices.\r\n\r\nFeature tracking consists of three basic steps:\r\n<ol>\r\n	<li>Detecting good or unique features, normally they are corners or blobs of an image;</li>\r\n	<li>Extracting a descriptor for each feature, that consists of understanding the texture of a small patch around each feature;</li>\r\n	<li>Descriptor matching, finding out the best match for each pair of descriptors (one from the object being tracked, another from a scene that potentially contains that object), if any.</li>\r\n</ol>\r\n<h3>Harris corner detector</h3>\r\nTo get started on what is coming to ArrayFire, in this article we dive deeper in the first step of feature tracking, detecting good features. Through a step-by-step guide, we will develop a simple corner detector, known as the Harris corner detector [1].\r\n\r\nThe Harris corner detector is very simple to implement, especially when you have so many good tools and libraries out there to do the core matrix manipulation. What we specifically need for Harris are some convolutions, together with a few element-wise matrix addition and multiplication operations, all of these operations are present in most scientific tools and libraries that work with matrix manipulation. I will try to avoid going into the mathematical details in this post and go directly to the implementation.\r\n<h5>Loading an image</h5>\r\nBefore starting writing the code for the corner detector, we need to load an image. The image can be either color or gray-scale, but it will only work on the gray-scale version, so if it is a color image, we have to convert it before proceeding.\r\n<pre>// Load a color image\r\narray img_color = loadimage(\"lena.jpg\", true);\r\n// Convert the image from RGB to gray-scale\r\narray img_gray = colorspace(img_color, af_gray, af_rgb);\r\n// For visualization in ArrayFire, color images must be in the [0.0f-1.0f] interval\r\nimg /= 255.f;\r\n</pre>\r\n<h5>Compute first-order derivatives</h5>\r\nThe first step in the Harris corner detector is to determine first order derivatives of an image, in both horizontal and vertical directions. This can be achieved by one convolution for each direction, with the special filter (-1, 0, 1)  for horizontal derivative and its transpose for vertical derivative. ArrayFire contains a function called <a href=\"http://www.accelereyes.com/arrayfire/c/group__math__func__cpp__grad.htm\">grad</a>, it calculates gradients in both directions and will perform faster than the two convolutions. The only difference is <a href=\"http://www.accelereyes.com/arrayfire/c/group__math__func__cpp__grad.htm\">grad</a> divides the result by 2, thus the response factor will change, but this can be compensated by using a smaller response while improving computation performance, so it will be used instead.\r\n<pre>\r\n// Calculate image gradients\r\narray ix, iy;\r\ngrad(ix, iy, img_gray);\r\n</pre>\r\n<h5>Compute second-order derivatives</h5>\r\nAt this point, we have both horizontal and vertical first order derivatives of our image, but Harris corner detector is processed with second-order derivatives, which can be easily computed in ArrayFire with simple element-wise multiplications of the first-order derivatives.\r\n<pre>// Compute second-order derivatives\r\narray ixx = ix * ix;\r\narray ixy = ix * iy;\r\narray iyy = iy * iy;\r\n</pre>\r\n<h5>Compute an isotropic window</h5>\r\nTo check the cornerness of each pixel of an image, it\'s not enough to check the pixel value itself, but a small window around that pixel. To reduce noise sensitivity and have an isotropic response, Harris claims that a smooth circular window should be used, and it can be achieved by filtering of all three second-order derivatives with a Gaussian kernel.\r\n<pre>// Compute a Gaussian kernel with standard deviation of 1.0 and length of 5 pixels\r\n// These values can be changed to use a smaller or larger window\r\narray gauss_filt = gaussiankernel(5, 5, 1.0, 1.0);\r\n\r\n// Filter second-order derivatives with Gaussian kernel computed previously\r\nixx = convolve(ixx, gauss_filt);\r\nixy = convolve(ixy, gauss_filt);\r\niyy = convolve(iyy, gauss_filt);\r\n</pre>\r\n<h5>Compute trace and determinant</h5>\r\nFrom a second-order Hessian matrix, we then compute the values of its trace and determinant. These are the values we will need later to calculate the Harris response for each pixel in the image.\r\n<pre>// Calculate trace\r\narray tr = ixx + iyy;\r\n// Calculate determinant\r\narray det = ixx * iyy - ixy * ixy;\r\n</pre>\r\n<h5>Compute Harris response</h5>\r\nFinally, we then calculate the Harris response for each pixel. For this calculation, Harris uses an empirically defined constant <code>k</code>. This constant is usually very small, and usually it ranges from <code>0.04</code> to <code>0.06</code>. In our case, we will use <code>k = 0.04</code>, but we encourage you to play with this value and see how the result changes.\r\n<pre>// Calculate Harris response\r\narray response = det - 0.04f * (tr * tr);\r\n</pre>\r\n<h5>Selection of good corners</h5>\r\nNow we already have our Harris responses for each pixel in the image. This value is used to determine whether a pixel is a corner or not. The standard way is to perform a non-maximal suppression, meaning that for each pixel it can only be a corner if it is a maximum compared to its 8 adjacent pixels. At the moment we do not have an easy way to compute a non-maximal suppression with ArrayFire, we have to write our own kernel for that, and that is only one of the cool things we will be able to do with our new computer vision toolset for ArrayFire.\r\n\r\nAn alternative is to do the non-maximal suppression in a naive way. To do this, we will use ArrayFire\'s <a href=\"http://www.accelereyes.com/arrayfire/c/group__image__func__cpp__maxfilt.htm\">maxfilt</a> function, that filters the image with a mask of <code>NxM</code> pixel and returns the maximum value of the neighborhood to the pixel centered within the mask. In this case we will use a <code>3x3</code> pixel mask to return the maximum of the 8-neighborhood, including the central pixel itself.\r\n\r\nThe <a href=\"http://www.accelereyes.com/arrayfire/c/group__image__func__cpp__maxfilt.htm\">maxfilt</a> function alone will not perform a non-maximal suppression, but with a few more lines of code we can get the proper responses.\r\n\r\nThe nature of a pixel can be determined by the Harris responses, a negative response means that a pixel corresponds to the segment of an edge. If the response is small but positive, it corresponds to a flat region. Only a large response corresponds to a corner. By thresholding the response array with the minimum desired Harris response, that for our example will be 10<sup>5</sup>, we can calculate a binary response array for which only pixels with a value greater than this threshold will be true. We then multiply it to the original response array to get a new array containing only responses greater that 10<sup>5</sup>.\r\n\r\nHere, we will use a threshold of 10<sup>5</sup>. For the implementation presented in this article, we found that corners seem to be better for responses larger than 10<sup>4</sup>, but you can and should play with these values to see how it will affect the image you are working on.\r\n\r\nThe last step for this is testing whether each pixel is equal to the maximum Harris response of the neighborhood. If it is equal, then we keep it, else, the response is not a local maximum and we discard it.\r\n\r\n<pre>\r\n// Gets maximum response for each 3x3 neighborhood\r\narray max_resp = maxfilt(response, 3, 3);\r\n\r\n// Discard responses that are not greater than threshold\r\narray corners = response > 1e5f;\r\ncorners = corners * response;\r\n\r\n// Discard responses that are not equal to maximum neighborhood response,\r\n// scale them to original response value\r\ncorners = (corners == max_resp) * corners;\r\n</pre>\r\n\r\nIf you still think you want a non-maximal suppression kernel for yourself, you can write it instead of using the last piece of code above. If you have never written your own kernel to work with an ArrayFire array, check out the <a href=\"http://sandbox.arrayfire.com/custom-kernels-with-arrayfire/\">Custom Kernels with ArrayFire</a> post. Writing the non-maximal suppression kernel itself will not take more than 20 or 30 lines of code.\r\n\r\n<h5>Plotting corners</h5>\r\n\r\nThis last step is done on the CPU side, we only do this to show the corners that are detected. Most likely, you will not need to do this unless you want to visualize, but for the sake of clarity, we include this part to show the result.\r\n<pre>// Gets host pointer to response data\r\nfloat* h_corners = corners.host<float>();\r\n\r\n// Draw draw_len x draw_len crosshairs where the corners are\r\nconst int draw_len = 3;\r\nfor (int y = draw_len; y < img.dims(0) - draw_len; y++) {\r\n    for (int x = draw_len; x < img.dims(1) - draw_len; x++) {\r\n        // Only draws crosshair if is a corner\r\n        if (h_corners[x * corners.dims(0) + y] > 1e5f) {\r\n            // Draw horizontal line of (draw_len * 2 + 1) pixels centered on the corner\r\n            // Set only the first channel to 1 (green lines)\r\n            img_color(y, seq(x-draw_len, x+draw_len), 0) = 0.f;\r\n            img_color(y, seq(x-draw_len, x+draw_len), 1) = 1.f;\r\n            img_color(y, seq(x-draw_len, x+draw_len), 2) = 0.f;\r\n\r\n            // Draw vertical line of (draw_len * 2 + 1) pixels centered on  the corner\r\n            // Set only the first channel to 1 (green lines)\r\n            img_color(seq(y-draw_len, y+draw_len), x, 0) = 0.f;\r\n            img_color(seq(y-draw_len, y+draw_len), x, 1) = 1.f;\r\n            img_color(seq(y-draw_len, y+draw_len), x, 2) = 0.f;\r\n        }\r\n    }\r\n}</pre>\r\n<h5>Visualize results</h5>\r\nFinally, the image can be visualized.\r\n<pre>// Previews color image with green crosshairs\r\nimage(img_color);\r\n</pre>\r\nBelow you can see Lena\'s picture after the Harris corner detection and plotting. The green crosshairs indicate where corners are.\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_lena.png\"><img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_lena.png\" alt=\"Harris Corners - Lena\" width=\"1024\" height=\"600\" class=\"alignnone size-full wp-image-5710\" /></a>\r\n\r\nTo test for correctness of the algorithm, nothing better than a picture with well-defined corners. Below you can see the picture of a white square on a black background and the corners marked by green crosshairs.\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_square.png\"><img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_square.png\" alt=\"Harris Corners - Square\" width=\"1024\" height=\"600\" class=\"alignnone size-full wp-image-5711\" /></a>\r\n\r\nWe would like to hear from you, what you are working on the computer vision field and which features you would like to see in ArrayFire. Please share your thoughts and requests below or contact us at <a href=\"mailto:sales@arrayfire.com\">sales@arrayfire.com</a>.\r\n<h5>References</h5>\r\n[1] Harris, Chris, and Mike Stephens. \"A combined corner and edge detector.\" <em>Alvey vision conference</em>. Vol. 15. 1988.\r\n','Writing a Simple Corner Detector with ArrayFire','','inherit','open','closed','','5659-revision-v1','','','2014-05-27 23:56:40','2014-05-27 23:56:40','',5659,'http://sandbox.arrayfire.com/5659-revision-v1/',0,'revision','',0),(5715,17795,'2014-05-28 00:22:20','2014-05-28 00:22:20','During the next months, we will be working on a lot of new Computer Vision functionality for ArrayFire. This means dozens of new functions specifically targeted for the most common and used applications in this field, like feature tracking, object classification, scene segmentation, optical flow, stereo-vision, among others, will be added to take full advantage of GPU devices.\r\n\r\nFeature tracking consists of three basic steps:\r\n<ol>\r\n	<li>Detecting good or unique features, normally they are corners or blobs of an object;</li>\r\n	<li>Extracting a descriptor for each feature, understanding the texture of a small patch around each feature;</li>\r\n	<li>Descriptor matching, finding out the best match for each pair of descriptors (one from the object being tracked, another from a scene that potentially contains that object), if any.</li>\r\n</ol>\r\n<h3>Harris corner detector</h3>\r\nTo get started on what is coming to ArrayFire, in this article we dive deeper in the first step of feature tracking, detecting good features. Through a step-by-step guide, we will develop a simple corner detector, known as the Harris corner detector [1].\r\n\r\nThe Harris corner detector is very simple to implement, especially when you have so many good tools and libraries out there to do the core matrix manipulation. What we specifically need for Harris are some convolutions, together with a few element-wise matrix addition and multiplication operations, all of these operations are present in most scientific tools and libraries that work with matrix manipulation. I will try to avoid going into the mathematical details in this post and go directly to the implementation.\r\n<h5>Loading an image</h5>\r\nBefore starting writing the code for the corner detector, we need to load an image. The image can be either color or gray-scale, but it will only work on the gray-scale version, so if it is a color image, we have to convert it before proceeding.\r\n<pre>// Load a color image\r\narray img_color = loadimage(\"lena.jpg\", true);\r\n// Convert the image from RGB to gray-scale\r\narray img_gray = colorspace(img_color, af_gray, af_rgb);\r\n// For visualization in ArrayFire, color images must be in the [0.0f-1.0f] interval\r\nimg /= 255.f;\r\n</pre>\r\n<h5>Compute first-order derivatives</h5>\r\nThe first step in the Harris corner detector is to determine first order derivatives of an image, in both horizontal and vertical directions. This can be achieved by one convolution for each direction, with the kernel (-1, 0, 1)  for horizontal derivative and its transpose for vertical derivative. ArrayFire contains a function called <a href=\"http://www.accelereyes.com/arrayfire/c/group__math__func__cpp__grad.htm\">grad</a>, it calculates gradients in both directions and will perform faster than the two convolutions. The only difference is <a href=\"http://www.accelereyes.com/arrayfire/c/group__math__func__cpp__grad.htm\">grad</a> divides the result by 2, thus, the response factor will change, but this can be compensated by using a smaller response, while computation performance is improved, so <a href=\"http://www.accelereyes.com/arrayfire/c/group__math__func__cpp__grad.htm\">grad</a> be used instead.\r\n<pre>\r\n// Calculate image gradients\r\narray ix, iy;\r\ngrad(ix, iy, img_gray);\r\n</pre>\r\n<h5>Compute second-order derivatives</h5>\r\nAt this point, we have both horizontal and vertical first order derivatives of our image, but Harris corner detector is processed with second-order derivatives, which can be easily computed in ArrayFire with simple element-wise multiplications of the first-order derivatives.\r\n<pre>// Compute second-order derivatives\r\narray ixx = ix * ix;\r\narray ixy = ix * iy;\r\narray iyy = iy * iy;\r\n</pre>\r\n<h5>Compute an isotropic window</h5>\r\nTo check the cornerness of each pixel of an image, it\'s not enough to check the pixel value itself, but a small window around that pixel. To reduce noise sensitivity and have an isotropic response, Harris claims that a smooth circular window should be used, and it can be achieved by filtering of all three second-order derivatives with a Gaussian kernel.\r\n<pre>// Compute a Gaussian kernel with standard deviation of 1.0 and length of 5 pixels\r\n// These values can be changed to use a smaller or larger window\r\narray gauss_filt = gaussiankernel(5, 5, 1.0, 1.0);\r\n\r\n// Filter second-order derivatives with Gaussian kernel computed previously\r\nixx = convolve(ixx, gauss_filt);\r\nixy = convolve(ixy, gauss_filt);\r\niyy = convolve(iyy, gauss_filt);\r\n</pre>\r\n<h5>Compute trace and determinant</h5>\r\nFrom a second-order Hessian matrix, we then compute the values of its trace and determinant. These are the values we will need later to calculate the Harris response for each pixel in the image.\r\n<pre>// Calculate trace\r\narray tr = ixx + iyy;\r\n// Calculate determinant\r\narray det = ixx * iyy - ixy * ixy;\r\n</pre>\r\n<h5>Compute Harris response</h5>\r\nNext, we calculate the Harris response for each pixel. For this calculation, Harris uses an empirically defined constant <code>k</code>. This constant is usually very small, and usually it ranges from <code>0.04</code> to <code>0.06</code>. In our case, we will use <code>k = 0.04</code>, but we encourage you to play with this value and see how the result is affected.\r\n<pre>// Calculate Harris response\r\narray response = det - 0.04f * (tr * tr);\r\n</pre>\r\n<h5>Selection of good corners</h5>\r\nNow we already have our Harris responses for each pixel in the image. This value is used to determine whether a pixel is a corner or not. The standard way is to perform a non-maximal suppression, meaning that for each pixel it can only be a corner if it is a maximum compared to its 8 adjacent pixels. At the moment we do not have a direct way to compute a non-maximal suppression with ArrayFire, we have to write our own kernel for that. Non-maximal suppression is only one of the cool things we will be able to do with our new computer vision toolset for ArrayFire.\r\n\r\nAn alternative is to do the non-maximal suppression in a naive way. To do this, we will use ArrayFire\'s <a href=\"http://www.accelereyes.com/arrayfire/c/group__image__func__cpp__maxfilt.htm\">maxfilt</a> function, that filters the image with a mask of <code>NxM</code> pixel and returns the maximum value of the neighborhood to the pixel centered within the mask. In this case we will use a <code>3x3</code> pixel mask to return the maximum of the 8-neighborhood, including the central pixel itself.\r\n\r\nThe <a href=\"http://www.accelereyes.com/arrayfire/c/group__image__func__cpp__maxfilt.htm\">maxfilt</a> function alone will not perform a non-maximal suppression, but combining with a few other steps, we can get the proper responses.\r\n\r\nThe nature of a pixel can be determined by the Harris responses, a negative response means that a pixel corresponds to the segment of an edge. If the response is small but positive, it corresponds to a flat region. Only a large response corresponds to a corner. By thresholding the response array with the minimum desired Harris response, that for our example will be 10<sup>5</sup>, we can calculate a binary response array for which only pixels with a value greater than this threshold will be true. We then multiply it to the original response array to get a new array containing only responses greater that 10<sup>5</sup>.\r\n\r\nHere, we will use a threshold of 10<sup>5</sup>. For the implementation presented in this article, we found that corners seem to be better for responses larger than 10<sup>4</sup>, but you can and should play with these values to see how it will affect the image you are working on.\r\n\r\nThe last step for this is testing whether each pixel is equal to the maximum Harris response of the neighborhood. If it is equal, then we keep it, else, the response is not a local maximum and we discard it.\r\n\r\n<pre>\r\n// Gets maximum response for each 3x3 neighborhood\r\narray max_resp = maxfilt(response, 3, 3);\r\n\r\n// Discard responses that are not greater than threshold\r\narray corners = response > 1e5f;\r\ncorners = corners * response;\r\n\r\n// Discard responses that are not equal to maximum neighborhood response,\r\n// scale them to original response value\r\ncorners = (corners == max_resp) * corners;\r\n</pre>\r\n\r\nIf you still think you want a non-maximal suppression kernel for yourself, you can write it instead of using the last piece of code above. If you have never written your own kernel to work with an ArrayFire array, check out the <a href=\"http://sandbox.arrayfire.com/custom-kernels-with-arrayfire/\">Custom Kernels with ArrayFire</a> post. Writing the non-maximal suppression kernel itself will not take more than 20 or 30 lines of code.\r\n\r\n<h5>Plotting corners</h5>\r\n\r\nThis last step is done on the CPU side, we only do this to show the corners that are detected. Most likely, you will not need to do this unless you want to visualize, but for the sake of clarity, we include this part to show the result.\r\n<pre>// Gets host pointer to response data\r\nfloat* h_corners = corners.host<float>();\r\n\r\n// Draw draw_len x draw_len crosshairs where the corners are\r\nconst int draw_len = 3;\r\nfor (int y = draw_len; y < img.dims(0) - draw_len; y++) {\r\n    for (int x = draw_len; x < img.dims(1) - draw_len; x++) {\r\n        // Only draws crosshair if is a corner\r\n        if (h_corners[x * corners.dims(0) + y] > 1e5f) {\r\n            // Draw horizontal line of (draw_len * 2 + 1) pixels centered on the corner\r\n            // Set only the first channel to 1 (green lines)\r\n            img_color(y, seq(x-draw_len, x+draw_len), 0) = 0.f;\r\n            img_color(y, seq(x-draw_len, x+draw_len), 1) = 1.f;\r\n            img_color(y, seq(x-draw_len, x+draw_len), 2) = 0.f;\r\n\r\n            // Draw vertical line of (draw_len * 2 + 1) pixels centered on  the corner\r\n            // Set only the first channel to 1 (green lines)\r\n            img_color(seq(y-draw_len, y+draw_len), x, 0) = 0.f;\r\n            img_color(seq(y-draw_len, y+draw_len), x, 1) = 1.f;\r\n            img_color(seq(y-draw_len, y+draw_len), x, 2) = 0.f;\r\n        }\r\n    }\r\n}</pre>\r\n<h5>Visualize results</h5>\r\nFinally, the image can be visualized.\r\n<pre>// Previews color image with green crosshairs\r\nimage(img_color);\r\n</pre>\r\nBelow you can see Lena\'s picture after the Harris corner detection and plotting. The green crosshairs indicate where corners are.\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_lena.png\"><img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_lena.png\" alt=\"Harris Corners - Lena\" width=\"1024\" height=\"600\" class=\"alignnone size-full wp-image-5710\" /></a>\r\n\r\nTo test for correctness of the algorithm, nothing better than a picture with well-defined corners. Below you can see the picture of a white square on a black background and the corners marked by green crosshairs.\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_square.png\"><img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_square.png\" alt=\"Harris Corners - Square\" width=\"1024\" height=\"600\" class=\"alignnone size-full wp-image-5711\" /></a>\r\n\r\nWe would like to hear from you, what you are working on the computer vision field and which features you would like to see in ArrayFire. Please share your thoughts and requests below or contact us at <a href=\"mailto:sales@arrayfire.com\">sales@arrayfire.com</a>.\r\n<h5>References</h5>\r\n[1] Harris, Chris, and Mike Stephens. \"A combined corner and edge detector.\" <em>Alvey vision conference</em>. Vol. 15. 1988.\r\n','Writing a Simple Corner Detector with ArrayFire','','inherit','open','closed','','5659-revision-v1','','','2014-05-28 00:22:20','2014-05-28 00:22:20','',5659,'http://sandbox.arrayfire.com/5659-revision-v1/',0,'revision','',0),(5717,17794,'2014-05-28 01:19:48','2014-05-28 01:19:48','In the upcoming months we will be adding a lot of new Computer Vision functionality to ArrayFire. This means dozens of new functions specifically targeted for the most commonly used applications in this field, like feature tracking, object classification, scene segmentation, optical flow, stereo-vision, among others, will be added to take full advantage of <abbr title=\"Graphics Processing Unit\">GPU</abbr> devices.\r\n\r\nFeature tracking consists of three basic steps:\r\n<ol>\r\n	<li>Detecting good or unique features, normally they are corners or blobs of an object</li>\r\n	<li>Extracting a descriptor for each feature, understanding the texture of a small patch around each feature</li>\r\n	<li>Descriptor matching, finding out the best match for each pair of descriptors (one from the object being tracked, another from a scene that potentially contains that object), if any.</li>\r\n</ol>\r\n<h3>Harris corner detector</h3>\r\nIn this article we will be using ArrayFire to dive deeper into the first step of feature tracking: detecting good features. Through a step-by-step guide, we will develop a simple corner detector, known as the Harris corner detector [1].\r\n\r\nThe Harris corner detector is very simple to implement, especially when you have so many good tools and libraries out there to do the core matrix manipulation. What we specifically need for Harris are some convolutions, together with a few element-wise matrix addition and multiplication operations, all of these operations are present in most scientific tools and libraries that work with matrix manipulation. I will try to avoid going into the mathematical details in this post and go directly to the implementation.\r\n<h5>Loading an image</h5>\r\nBefore starting writing the code for the corner detector, we need to load an image. The image can be either color or gray-scale, but it will only work on the gray-scale version, so if it is a color image, we have to convert it before proceeding.\r\n<pre>// Load a color image\r\narray img_color = loadimage(\"lena.jpg\", true);\r\n// Convert the image from RGB to gray-scale\r\narray img_gray = colorspace(img_color, af_gray, af_rgb);\r\n// For visualization in ArrayFire, color images must be in the [0.0f-1.0f] interval\r\nimg /= 255.f;\r\n</pre>\r\n<h5>Compute first-order derivatives</h5>\r\nThe first step in the Harris corner detector is to determine first order derivatives of an image, in both horizontal and vertical directions. This can be achieved by one convolution for each direction, with the kernel (-1, 0, 1)  for horizontal derivative and its transpose for vertical derivative. ArrayFire contains a function called <a href=\"http://www.accelereyes.com/arrayfire/c/group__math__func__cpp__grad.htm\">grad</a>, it calculates gradients in both directions and will perform faster than the two convolutions. The only difference is <a href=\"http://www.accelereyes.com/arrayfire/c/group__math__func__cpp__grad.htm\">grad</a> divides the result by 2, thus, the response factor will change, but this can be compensated by using a smaller response, while computation performance is improved, so <a href=\"http://www.accelereyes.com/arrayfire/c/group__math__func__cpp__grad.htm\">grad</a> be used instead.\r\n<pre>// Calculate image gradients\r\narray ix, iy;\r\ngrad(ix, iy, img_gray);\r\n</pre>\r\n<h5>Compute second-order derivatives</h5>\r\nAt this point, we have both horizontal and vertical first order derivatives of our image, but Harris corner detector is processed with second-order derivatives, which can be easily computed in ArrayFire with simple element-wise multiplications of the first-order derivatives.\r\n<pre>// Compute second-order derivatives\r\narray ixx = ix * ix;\r\narray ixy = ix * iy;\r\narray iyy = iy * iy;\r\n</pre>\r\n<h5>Compute an isotropic window</h5>\r\nTo check the cornerness of each pixel of an image, it\'s not enough to check the pixel value itself, but a small window around that pixel. To reduce noise sensitivity and have an isotropic response, Harris claims that a smooth circular window should be used, and it can be achieved by filtering of all three second-order derivatives with a Gaussian kernel.\r\n<pre>// Compute a Gaussian kernel with standard deviation of 1.0 and length of 5 pixels\r\n// These values can be changed to use a smaller or larger window\r\narray gauss_filt = gaussiankernel(5, 5, 1.0, 1.0);\r\n\r\n// Filter second-order derivatives with Gaussian kernel computed previously\r\nixx = convolve(ixx, gauss_filt);\r\nixy = convolve(ixy, gauss_filt);\r\niyy = convolve(iyy, gauss_filt);\r\n</pre>\r\n<h5>Compute trace and determinant</h5>\r\nFrom a second-order Hessian matrix, we then compute the values of its trace and determinant. These are the values we will need later to calculate the Harris response for each pixel in the image.\r\n<pre>// Calculate trace\r\narray tr = ixx + iyy;\r\n// Calculate determinant\r\narray det = ixx * iyy - ixy * ixy;\r\n</pre>\r\n<h5>Compute Harris response</h5>\r\nNext, we calculate the Harris response for each pixel. For this calculation, Harris uses an empirically defined constant <code>k</code>. This constant is usually very small, and usually it ranges from <code>0.04</code> to <code>0.06</code>. In our case, we will use <code>k = 0.04</code>, but we encourage you to play with this value and see how the result is affected.\r\n<pre>// Calculate Harris response\r\narray response = det - 0.04f * (tr * tr);\r\n</pre>\r\n<h5>Selection of good corners</h5>\r\nNow we already have our Harris responses for each pixel in the image. This value is used to determine whether a pixel is a corner or not. The standard way is to perform a non-maximal suppression, meaning that for each pixel it can only be a corner if it is a maximum compared to its 8 adjacent pixels. At the moment we do not have a direct way to compute a non-maximal suppression with ArrayFire, we have to write our own kernel for that. Non-maximal suppression is only one of the cool things we will be able to do with our new computer vision toolset for ArrayFire.\r\n\r\nAn alternative is to do the non-maximal suppression in a naive way. To do this, we will use ArrayFire\'s <a href=\"http://www.accelereyes.com/arrayfire/c/group__image__func__cpp__maxfilt.htm\">maxfilt</a> function, that filters the image with a mask of <code>NxM</code> pixel and returns the maximum value of the neighborhood to the pixel centered within the mask. In this case we will use a <code>3x3</code> pixel mask to return the maximum of the 8-neighborhood, including the central pixel itself.\r\n\r\nThe <a href=\"http://www.accelereyes.com/arrayfire/c/group__image__func__cpp__maxfilt.htm\">maxfilt</a> function alone will not perform a non-maximal suppression, but combining with a few other steps, we can get the proper responses.\r\n\r\nThe nature of a pixel can be determined by the Harris responses, a negative response means that a pixel corresponds to the segment of an edge. If the response is small but positive, it corresponds to a flat region. Only a large response corresponds to a corner. By thresholding the response array with the minimum desired Harris response, that for our example will be 10<sup>5</sup>, we can calculate a binary response array for which only pixels with a value greater than this threshold will be true. We then multiply it to the original response array to get a new array containing only responses greater that 10<sup>5</sup>.\r\n\r\nHere, we will use a threshold of 10<sup>5</sup>. For the implementation presented in this article, we found that corners seem to be better for responses larger than 10<sup>4</sup>, but you can and should play with these values to see how it will affect the image you are working on.\r\n\r\nThe last step for this is testing whether each pixel is equal to the maximum Harris response of the neighborhood. If it is equal, then we keep it, else, the response is not a local maximum and we discard it.\r\n<pre>// Gets maximum response for each 3x3 neighborhood\r\narray max_resp = maxfilt(response, 3, 3);\r\n\r\n// Discard responses that are not greater than threshold\r\narray corners = response &gt; 1e5f;\r\ncorners = corners * response;\r\n\r\n// Discard responses that are not equal to maximum neighborhood response,\r\n// scale them to original response value\r\ncorners = (corners == max_resp) * corners;\r\n</pre>\r\nIf you still think you want a non-maximal suppression kernel for yourself, you can write it instead of using the last piece of code above. If you have never written your own kernel to work with an ArrayFire array, check out the <a href=\"http://sandbox.arrayfire.com/custom-kernels-with-arrayfire/\">Custom Kernels with ArrayFire</a> post. Writing the non-maximal suppression kernel itself will not take more than 20 or 30 lines of code.\r\n<h5>Plotting corners</h5>\r\nThis last step is done on the <abbr title=\"Central Processing Unit\">CPU</abbr> side, we only do this to show the corners that are detected. Most likely, you will not need to do this unless you want to visualize, but for the sake of clarity, we include this part to show the result.\r\n<pre>// Gets host pointer to response data\r\nfloat* h_corners = corners.host();\r\n\r\n// Draw draw_len x draw_len crosshairs where the corners are\r\nconst int draw_len = 3;\r\nfor (int y = draw_len; y &lt; img.dims(0) - draw_len; y++) {\r\n    for (int x = draw_len; x &lt; img.dims(1) - draw_len; x++) {\r\n        // Only draws crosshair if is a corner\r\n        if (h_corners[x * corners.dims(0) + y] &gt; 1e5f) {\r\n            // Draw horizontal line of (draw_len * 2 + 1) pixels centered on the corner\r\n            // Set only the first channel to 1 (green lines)\r\n            img_color(y, seq(x-draw_len, x+draw_len), 0) = 0.f;\r\n            img_color(y, seq(x-draw_len, x+draw_len), 1) = 1.f;\r\n            img_color(y, seq(x-draw_len, x+draw_len), 2) = 0.f;\r\n\r\n            // Draw vertical line of (draw_len * 2 + 1) pixels centered on  the corner\r\n            // Set only the first channel to 1 (green lines)\r\n            img_color(seq(y-draw_len, y+draw_len), x, 0) = 0.f;\r\n            img_color(seq(y-draw_len, y+draw_len), x, 1) = 1.f;\r\n            img_color(seq(y-draw_len, y+draw_len), x, 2) = 0.f;\r\n        }\r\n    }\r\n}</pre>\r\n<h5>Visualize results</h5>\r\nFinally, the image can be visualized.\r\n<pre>// Previews color image with green crosshairs\r\nimage(img_color);\r\n</pre>\r\nBelow you can see Lena\'s picture after the Harris corner detection and plotting. The green crosshairs indicate where corners are.\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_lena.png\"><img class=\"alignnone size-full wp-image-5710\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_lena.png\" alt=\"Harris Corners - Lena\" width=\"1024\" height=\"600\" /></a>\r\n\r\nTo test for correctness of the algorithm, nothing better than a picture with well-defined corners. Below you can see the picture of a white square on a black background and the corners marked by green crosshairs.\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_square.png\"><img class=\"alignnone size-full wp-image-5711\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_square.png\" alt=\"Harris Corners - Square\" width=\"1024\" height=\"600\" /></a>\r\n\r\nWe would like to hear from you, what you are working on the computer vision field and which features you would like to see in ArrayFire. Please share your thoughts and requests below or contact us at <a href=\"mailto:sales@arrayfire.com\">sales@arrayfire.com</a>.\r\n<h5>References</h5>\r\n[1] Harris, Chris, and Mike Stephens. \"A combined corner and edge detector.\" <em>Alvey vision conference</em>. Vol. 15. 1988.','Writing a Simple Corner Detector with ArrayFire','','inherit','open','closed','','5659-autosave-v1','','','2014-05-28 01:19:48','2014-05-28 01:19:48','',5659,'http://sandbox.arrayfire.com/5659-autosave-v1/',0,'revision','',0),(5718,17794,'2014-05-28 01:17:48','2014-05-28 01:17:48','In the upcoming months we will be adding a lot of new Computer Vision functionality to ArrayFire. This means dozens of new functions specifically targeted for the most commonly used applications in this field, like feature tracking, object classification, scene segmentation, optical flow, stereo-vision, among others, will be added to take full advantage of <abbr title=\"Graphics Processing Unit\">GPU</abbr> devices.\r\n\r\nFeature tracking consists of three basic steps:\r\n<ol>\r\n	<li>Detecting good or unique features, normally they are corners or blobs of an object</li>\r\n	<li>Extracting a descriptor for each feature, understanding the texture of a small patch around each feature</li>\r\n	<li>Descriptor matching, finding out the best match for each pair of descriptors (one from the object being tracked, another from a scene that potentially contains that object), if any.</li>\r\n</ol>\r\n<h3>Harris corner detector</h3>\r\nIn this article we will be using ArrayFire to dive deeper into the first step of feature tracking: detecting good features. Through a step-by-step guide, we will develop a simple corner detector, known as the Harris corner detector [1].\r\n\r\nThe Harris corner detector is very simple to implement, especially when you have so many good tools and libraries out there to do the core matrix manipulation. What we specifically need for Harris are some convolutions, together with a few element-wise matrix addition and multiplication operations, all of these operations are present in most scientific tools and libraries that work with matrix manipulation. I will try to avoid going into the mathematical details in this post and go directly to the implementation.\r\n<h5>Loading an image</h5>\r\nBefore starting writing the code for the corner detector, we need to load an image. The image can be either color or gray-scale, but it will only work on the gray-scale version, so if it is a color image, we have to convert it before proceeding.\r\n<pre>// Load a color image\r\narray img_color = loadimage(\"lena.jpg\", true);\r\n// Convert the image from RGB to gray-scale\r\narray img_gray = colorspace(img_color, af_gray, af_rgb);\r\n// For visualization in ArrayFire, color images must be in the [0.0f-1.0f] interval\r\nimg /= 255.f;\r\n</pre>\r\n<h5>Compute first-order derivatives</h5>\r\nThe first step in the Harris corner detector is to determine first order derivatives of an image, in both horizontal and vertical directions. This can be achieved by one convolution for each direction, with the kernel (-1, 0, 1)  for horizontal derivative and its transpose for vertical derivative. ArrayFire contains a function called <a href=\"http://www.accelereyes.com/arrayfire/c/group__math__func__cpp__grad.htm\">grad</a>, it calculates gradients in both directions and will perform faster than the two convolutions. The only difference is <a href=\"http://www.accelereyes.com/arrayfire/c/group__math__func__cpp__grad.htm\">grad</a> divides the result by 2, thus, the response factor will change, but this can be compensated by using a smaller response, while computation performance is improved, so <a href=\"http://www.accelereyes.com/arrayfire/c/group__math__func__cpp__grad.htm\">grad</a> be used instead.\r\n<pre>// Calculate image gradients\r\narray ix, iy;\r\ngrad(ix, iy, img_gray);\r\n</pre>\r\n<h5>Compute second-order derivatives</h5>\r\nAt this point, we have both horizontal and vertical first order derivatives of our image, but Harris corner detector is processed with second-order derivatives, which can be easily computed in ArrayFire with simple element-wise multiplications of the first-order derivatives.\r\n<pre>// Compute second-order derivatives\r\narray ixx = ix * ix;\r\narray ixy = ix * iy;\r\narray iyy = iy * iy;\r\n</pre>\r\n<h5>Compute an isotropic window</h5>\r\nTo check the cornerness of each pixel of an image, it\'s not enough to check the pixel value itself, but a small window around that pixel. To reduce noise sensitivity and have an isotropic response, Harris claims that a smooth circular window should be used, and it can be achieved by filtering of all three second-order derivatives with a Gaussian kernel.\r\n<pre>// Compute a Gaussian kernel with standard deviation of 1.0 and length of 5 pixels\r\n// These values can be changed to use a smaller or larger window\r\narray gauss_filt = gaussiankernel(5, 5, 1.0, 1.0);\r\n\r\n// Filter second-order derivatives with Gaussian kernel computed previously\r\nixx = convolve(ixx, gauss_filt);\r\nixy = convolve(ixy, gauss_filt);\r\niyy = convolve(iyy, gauss_filt);\r\n</pre>\r\n<h5>Compute trace and determinant</h5>\r\nFrom a second-order Hessian matrix, we then compute the values of its trace and determinant. These are the values we will need later to calculate the Harris response for each pixel in the image.\r\n<pre>// Calculate trace\r\narray tr = ixx + iyy;\r\n// Calculate determinant\r\narray det = ixx * iyy - ixy * ixy;\r\n</pre>\r\n<h5>Compute Harris response</h5>\r\nNext, we calculate the Harris response for each pixel. For this calculation, Harris uses an empirically defined constant <code>k</code>. This constant is usually very small, and usually it ranges from <code>0.04</code> to <code>0.06</code>. In our case, we will use <code>k = 0.04</code>, but we encourage you to play with this value and see how the result is affected.\r\n<pre>// Calculate Harris response\r\narray response = det - 0.04f * (tr * tr);\r\n</pre>\r\n<h5>Selection of good corners</h5>\r\nNow we already have our Harris responses for each pixel in the image. This value is used to determine whether a pixel is a corner or not. The standard way is to perform a non-maximal suppression, meaning that for each pixel it can only be a corner if it is a maximum compared to its 8 adjacent pixels. At the moment we do not have a direct way to compute a non-maximal suppression with ArrayFire, we have to write our own kernel for that. Non-maximal suppression is only one of the cool things we will be able to do with our new computer vision toolset for ArrayFire.\r\n\r\nAn alternative is to do the non-maximal suppression in a naive way. To do this, we will use ArrayFire\'s <a href=\"http://www.accelereyes.com/arrayfire/c/group__image__func__cpp__maxfilt.htm\">maxfilt</a> function, that filters the image with a mask of <code>NxM</code> pixel and returns the maximum value of the neighborhood to the pixel centered within the mask. In this case we will use a <code>3x3</code> pixel mask to return the maximum of the 8-neighborhood, including the central pixel itself.\r\n\r\nThe <a href=\"http://www.accelereyes.com/arrayfire/c/group__image__func__cpp__maxfilt.htm\">maxfilt</a> function alone will not perform a non-maximal suppression, but combining with a few other steps, we can get the proper responses.\r\n\r\nThe nature of a pixel can be determined by the Harris responses, a negative response means that a pixel corresponds to the segment of an edge. If the response is small but positive, it corresponds to a flat region. Only a large response corresponds to a corner. By thresholding the response array with the minimum desired Harris response, that for our example will be 10<sup>5</sup>, we can calculate a binary response array for which only pixels with a value greater than this threshold will be true. We then multiply it to the original response array to get a new array containing only responses greater that 10<sup>5</sup>.\r\n\r\nHere, we will use a threshold of 10<sup>5</sup>. For the implementation presented in this article, we found that corners seem to be better for responses larger than 10<sup>4</sup>, but you can and should play with these values to see how it will affect the image you are working on.\r\n\r\nThe last step for this is testing whether each pixel is equal to the maximum Harris response of the neighborhood. If it is equal, then we keep it, else, the response is not a local maximum and we discard it.\r\n<pre>// Gets maximum response for each 3x3 neighborhood\r\narray max_resp = maxfilt(response, 3, 3);\r\n\r\n// Discard responses that are not greater than threshold\r\narray corners = response &gt; 1e5f;\r\ncorners = corners * response;\r\n\r\n// Discard responses that are not equal to maximum neighborhood response,\r\n// scale them to original response value\r\ncorners = (corners == max_resp) * corners;\r\n</pre>\r\nIf you still think you want a non-maximal suppression kernel for yourself, you can write it instead of using the last piece of code above. If you have never written your own kernel to work with an ArrayFire array, check out the <a href=\"http://sandbox.arrayfire.com/custom-kernels-with-arrayfire/\">Custom Kernels with ArrayFire</a> post. Writing the non-maximal suppression kernel itself will not take more than 20 or 30 lines of code.\r\n<h5>Plotting corners</h5>\r\nThis last step is done on the <abbr title=\"Central Processing Unit\">CPU</abbr> side, we only do this to show the corners that are detected. Most likely, you will not need to do this unless you want to visualize, but for the sake of clarity, we include this part to show the result.\r\n<pre>// Gets host pointer to response data\r\nfloat* h_corners = corners.host();\r\n\r\n// Draw draw_len x draw_len crosshairs where the corners are\r\nconst int draw_len = 3;\r\nfor (int y = draw_len; y &lt; img.dims(0) - draw_len; y++) {\r\n    for (int x = draw_len; x &lt; img.dims(1) - draw_len; x++) {\r\n        // Only draws crosshair if is a corner\r\n        if (h_corners[x * corners.dims(0) + y] &gt; 1e5f) {\r\n            // Draw horizontal line of (draw_len * 2 + 1) pixels centered on the corner\r\n            // Set only the first channel to 1 (green lines)\r\n            img_color(y, seq(x-draw_len, x+draw_len), 0) = 0.f;\r\n            img_color(y, seq(x-draw_len, x+draw_len), 1) = 1.f;\r\n            img_color(y, seq(x-draw_len, x+draw_len), 2) = 0.f;\r\n\r\n            // Draw vertical line of (draw_len * 2 + 1) pixels centered on  the corner\r\n            // Set only the first channel to 1 (green lines)\r\n            img_color(seq(y-draw_len, y+draw_len), x, 0) = 0.f;\r\n            img_color(seq(y-draw_len, y+draw_len), x, 1) = 1.f;\r\n            img_color(seq(y-draw_len, y+draw_len), x, 2) = 0.f;\r\n        }\r\n    }\r\n}</pre>\r\n<h5>Visualize results</h5>\r\nFinally, the image can be visualized.\r\n<pre>// Previews color image with green crosshairs\r\nimage(img_color);\r\n</pre>\r\nBelow you can see Lena\'s picture after the Harris corner detection and plotting. The green crosshairs indicate where corners are.\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_lena.png\"><img class=\"alignnone size-full wp-image-5710\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_lena.png\" alt=\"Harris Corners - Lena\" width=\"1024\" height=\"600\" /></a>\r\n\r\nTo test for correctness of the algorithm, nothing better than a picture with well-defined corners. Below you can see the picture of a white square on a black background and the corners marked by green crosshairs.\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_square.png\"><img class=\"alignnone size-full wp-image-5711\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_square.png\" alt=\"Harris Corners - Square\" width=\"1024\" height=\"600\" /></a>\r\n\r\nWe would like to hear from you, what you are working on the computer vision field and which features you would like to see in ArrayFire. Please share your thoughts and requests below or contact us at <a href=\"mailto:sales@arrayfire.com\">sales@arrayfire.com</a>.\r\n<h5>References</h5>\r\n[1] Harris, Chris, and Mike Stephens. \"A combined corner and edge detector.\" <em>Alvey vision conference</em>. Vol. 15. 1988.','Writing a Simple Corner Detector with ArrayFire','','inherit','open','closed','','5659-revision-v1','','','2014-05-28 01:17:48','2014-05-28 01:17:48','',5659,'http://sandbox.arrayfire.com/5659-revision-v1/',0,'revision','',0),(5719,17795,'2014-05-28 01:34:03','2014-05-28 01:34:03','In the upcoming months we will be adding a lot of new Computer Vision functionality to ArrayFire. This means dozens of new functions specifically targeted for the most commonly used applications in this field, like feature tracking, object classification, scene segmentation, optical flow, stereo-vision, among others, will be added to take full advantage of <abbr title=\"Graphics Processing Unit\">GPU</abbr> devices.\r\n\r\nFeature tracking consists of three basic steps:\r\n<ol>\r\n	<li>Detecting good or unique features, normally they are corners or blobs of an object</li>\r\n	<li>Extracting a descriptor for each feature, understanding the texture of a small patch around each feature</li>\r\n	<li>Descriptor matching, finding out the best match for each pair of descriptors (one from the object being tracked, another from a scene that potentially contains that object), if any.</li>\r\n</ol>\r\n<h3>Harris corner detector</h3>\r\nIn this article we will be using ArrayFire to dive deeper into the first step of feature tracking: detecting good features. Through a step-by-step guide, we will develop a simple corner detector, known as the Harris corner detector [1].\r\n\r\nThe Harris corner detector is very simple to implement, especially when you have so many good tools and libraries out there to do the core matrix manipulation. What we specifically need for Harris are some convolutions, together with a few element-wise matrix addition and multiplication operations, all of these operations are present in most scientific tools and libraries that work with matrix manipulation. I will try to avoid going into the mathematical details in this post and go directly to the implementation.\r\n<h5>Loading an image</h5>\r\nBefore starting writing the code for the corner detector, we need to load an image. The image can be either color or gray-scale, but it will only work on the gray-scale version, so if it is a color image, we have to convert it before proceeding.\r\n<pre>// Load a color image\r\narray img_color = loadimage(\"lena.jpg\", true);\r\n// Convert the image from RGB to gray-scale\r\narray img_gray = colorspace(img_color, af_gray, af_rgb);\r\n// For visualization in ArrayFire, color images must be in the [0.0f-1.0f] interval\r\nimg /= 255.f;\r\n</pre>\r\n<h5>Compute first-order derivatives</h5>\r\nThe first step in the Harris corner detector is to determine first order derivatives of an image, in both horizontal and vertical directions. This can be achieved by one convolution for each direction, with the kernel (-1, 0, 1)  for horizontal derivative and its transpose for vertical derivative. ArrayFire contains a function called <a href=\"http://www.accelereyes.com/arrayfire/c/group__math__func__cpp__grad.htm\">grad</a>, it calculates gradients in both directions and will perform faster than the two convolutions. The only difference is <a href=\"http://www.accelereyes.com/arrayfire/c/group__math__func__cpp__grad.htm\">grad</a> divides the result by 2, thus, the response factor will change, but this can be compensated by using a smaller response, while computation performance is improved, so <a href=\"http://www.accelereyes.com/arrayfire/c/group__math__func__cpp__grad.htm\">grad</a> be used instead.\r\n<pre>// Calculate image gradients\r\narray ix, iy;\r\ngrad(ix, iy, img_gray);\r\n</pre>\r\n<h5>Compute second-order derivatives</h5>\r\nAt this point, we have both horizontal and vertical first order derivatives of our image, but Harris corner detector is processed with second-order derivatives, which can be easily computed in ArrayFire with simple element-wise multiplications of the first-order derivatives.\r\n<pre>// Compute second-order derivatives\r\narray ixx = ix * ix;\r\narray ixy = ix * iy;\r\narray iyy = iy * iy;\r\n</pre>\r\n<h5>Compute an isotropic window</h5>\r\nTo check the cornerness of each pixel of an image, it\'s not enough to check the pixel value itself, but a small window around that pixel. To reduce noise sensitivity and have an isotropic response, Harris claims that a smooth circular window should be used, and it can be achieved by filtering of all three second-order derivatives with a Gaussian kernel.\r\n<pre>// Compute a Gaussian kernel with standard deviation of 1.0 and length of 5 pixels\r\n// These values can be changed to use a smaller or larger window\r\narray gauss_filt = gaussiankernel(5, 5, 1.0, 1.0);\r\n\r\n// Filter second-order derivatives with Gaussian kernel computed previously\r\nixx = convolve(ixx, gauss_filt);\r\nixy = convolve(ixy, gauss_filt);\r\niyy = convolve(iyy, gauss_filt);\r\n</pre>\r\n<h5>Compute trace and determinant</h5>\r\nFrom a second-order Hessian matrix, we then compute the values of its trace and determinant. These are the values we will need later to calculate the Harris response for each pixel in the image.\r\n<pre>// Calculate trace\r\narray tr = ixx + iyy;\r\n// Calculate determinant\r\narray det = ixx * iyy - ixy * ixy;\r\n</pre>\r\n<h5>Compute Harris response</h5>\r\nNext, we calculate the Harris response for each pixel. For this calculation, Harris uses an empirically defined constant <code>k</code>. This constant is usually very small, normally ranging from <code>0.04</code> to <code>0.06</code>. In our case, we will use <code>k = 0.04</code>, but we encourage you to play with this value and see how the result is affected.\r\n<pre>// Calculate Harris response\r\narray response = det - 0.04f * (tr * tr);\r\n</pre>\r\n<h5>Selection of good corners</h5>\r\nNow we already have our Harris responses for each pixel in the image. This value is used to determine whether a pixel is a corner or not. The standard way is to perform a non-maximal suppression, meaning that for each pixel it can only be a corner if it is a maximum compared to its 8 adjacent pixels. At the moment we do not have a direct way to compute a non-maximal suppression with ArrayFire, we have to write our own kernel for that. Non-maximal suppression is only one of the cool things we will be able to do with our new computer vision toolset for ArrayFire.\r\n\r\nAn alternative is to do the non-maximal suppression in a naive way. To do this, we will use ArrayFire\'s <a href=\"http://www.accelereyes.com/arrayfire/c/group__image__func__cpp__maxfilt.htm\">maxfilt</a> function, that filters the image with a mask of <code>NxM</code> pixel and returns the maximum value of the neighborhood to the pixel centered within the mask. In this case we will use a <code>3x3</code> pixel mask to return the maximum of the 8-neighborhood, including the central pixel itself.\r\n\r\nThe <a href=\"http://www.accelereyes.com/arrayfire/c/group__image__func__cpp__maxfilt.htm\">maxfilt</a> function alone will not perform a non-maximal suppression, but combining with a few other steps, we can get the proper responses.\r\n\r\nThe nature of a pixel can be determined by the Harris responses, a negative response means that a pixel corresponds to the segment of an edge. If the response is small but positive, it corresponds to a flat region. Only a large response corresponds to a corner. By thresholding the response array with the minimum desired Harris response, that for our example will be 10<sup>5</sup>, we can calculate a binary response array for which only pixels with a value greater than this threshold will be true. We then multiply it to the original response array to get a new array containing only responses greater that 10<sup>5</sup>.\r\n\r\nHere, we will use a threshold of 10<sup>5</sup>. For the implementation presented in this article, we found that corners seem to be better for responses larger than 10<sup>4</sup>, but you can and should play with these values to see how it will affect the image you are working on.\r\n\r\nThe last step for this is testing whether each pixel is equal to the maximum Harris response of the neighborhood. If it is equal, then we keep it, else, the response is not a local maximum and we discard it.\r\n<pre>// Gets maximum response for each 3x3 neighborhood\r\narray max_resp = maxfilt(response, 3, 3);\r\n\r\n// Discard responses that are not greater than threshold\r\narray corners = response &gt; 1e5f;\r\ncorners = corners * response;\r\n\r\n// Discard responses that are not equal to maximum neighborhood response,\r\n// scale them to original response value\r\ncorners = (corners == max_resp) * corners;\r\n</pre>\r\nIf you still think you want a non-maximal suppression kernel for yourself, you can write it instead of using the last piece of code above. If you have never written your own kernel to work with an ArrayFire array, check out the <a href=\"http://sandbox.arrayfire.com/custom-kernels-with-arrayfire/\">Custom Kernels with ArrayFire</a> post. Writing the non-maximal suppression kernel itself will not take more than 20 or 30 lines of code.\r\n<h5>Plotting corners</h5>\r\nThis last step is done on the <abbr title=\"Central Processing Unit\">CPU</abbr> side, we only do this to show the corners that are detected. Most likely, you will not need to do this unless you want to visualize, but for the sake of clarity, we include this part to show the result.\r\n<pre>// Gets host pointer to response data\r\nfloat* h_corners = corners.host();\r\n\r\n// Draw draw_len x draw_len crosshairs where the corners are\r\nconst int draw_len = 3;\r\nfor (int y = draw_len; y &lt; img.dims(0) - draw_len; y++) {\r\n    for (int x = draw_len; x &lt; img.dims(1) - draw_len; x++) {\r\n        // Only draws crosshair if is a corner\r\n        if (h_corners[x * corners.dims(0) + y] &gt; 1e5f) {\r\n            // Draw horizontal line of (draw_len * 2 + 1) pixels centered on the corner\r\n            // Set only the first channel to 1 (green lines)\r\n            img_color(y, seq(x-draw_len, x+draw_len), 0) = 0.f;\r\n            img_color(y, seq(x-draw_len, x+draw_len), 1) = 1.f;\r\n            img_color(y, seq(x-draw_len, x+draw_len), 2) = 0.f;\r\n\r\n            // Draw vertical line of (draw_len * 2 + 1) pixels centered on  the corner\r\n            // Set only the first channel to 1 (green lines)\r\n            img_color(seq(y-draw_len, y+draw_len), x, 0) = 0.f;\r\n            img_color(seq(y-draw_len, y+draw_len), x, 1) = 1.f;\r\n            img_color(seq(y-draw_len, y+draw_len), x, 2) = 0.f;\r\n        }\r\n    }\r\n}</pre>\r\n<h5>Visualize results</h5>\r\nFinally, the image can be visualized.\r\n<pre>// Previews color image with green crosshairs\r\nimage(img_color);\r\n</pre>\r\nBelow you can see Lena\'s picture after the Harris corner detection and plotting. The green crosshairs indicate where corners are.\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_lena.png\"><img class=\"alignnone size-full wp-image-5710\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_lena.png\" alt=\"Harris Corners - Lena\" width=\"1024\" height=\"600\" /></a>\r\n\r\nTo test for correctness of the algorithm, nothing better than a picture with well-defined corners. Below you can see the picture of a white square on a black background and the corners marked by green crosshairs.\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_square.png\"><img class=\"alignnone size-full wp-image-5711\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_square.png\" alt=\"Harris Corners - Square\" width=\"1024\" height=\"600\" /></a>\r\n\r\nWe would like to hear from you, what you are working on the computer vision field and which features you would like to see in ArrayFire. Please share your thoughts and requests below or contact us at <a href=\"mailto:sales@arrayfire.com\">sales@arrayfire.com</a>.\r\n<h5>References</h5>\r\n[1] Harris, Chris, and Mike Stephens. \"A combined corner and edge detector.\" <em>Alvey vision conference</em>. Vol. 15. 1988.','Writing a Simple Corner Detector with ArrayFire','','inherit','open','closed','','5659-revision-v1','','','2014-05-28 01:34:03','2014-05-28 01:34:03','',5659,'http://sandbox.arrayfire.com/5659-revision-v1/',0,'revision','',0),(5720,1,'2014-05-28 16:47:33','2014-05-28 16:47:33','','Order &ndash; May 28, 2014 @ 04:47 PM','PO# 6384','wc-completed','open','closed','order_5386132314cf3','order-may-28-2014-0447-pm','','','2014-05-28 16:47:35','2014-05-28 16:47:35','',0,'http://sandbox.arrayfire.com/?post_type=shop_order&#038;p=5720',0,'shop_order','',4),(5722,7,'2014-05-29 16:06:23','2014-05-29 16:06:23','[content_band inner_container=\"true\" no_margin=\"true\" border=\"none\" padding_top=\"40px\" padding_bottom=\"40px\"][column type=\"two-fifths\"]\r\n\r\n[custom_headline type=\"left\" level=\"h3\"]If you want faster code, you\'ve come to the right place.[/custom_headline][gap size=\"15%\"][button  type=\"flat\" shape=\"rounded\" href=\"http://www.sandbox.arrayfire.com/docs/installation.htm\" size=\"x-large\" block=\"true\"]Download ArrayFire[/button]\r\n\r\n[gap size=\"10%\"]\r\n\r\n[button  type=\"flat\" block=\"true\" shape=\"rounded\" href=\"http://www.meetme.so/arrayfire\" size=\"x-large\" ]Schedule a consultation[/button]\r\n\r\n[/column][column type=\"three-fifths\" last=\"true\"][gap size=\"7%\"]\r\n<div id=\"wistia_rj2bar3xxp\" class=\"wistia_embed\" style=\"width: 640px; height: 388px;\"></div>\r\n<script src=\"//fast.wistia.com/assets/external/E-v1.js\" charset=\"ISO-8859-1\"></script><script>// <![CDATA[\r\nwistiaEmbed = Wistia.embed(\"rj2bar3xxp\");\r\n// ]]></script>[/column]\r\n<div id=\"arrayfire\"></div>\r\n[/content_band]\r\n\r\n[content_band inner_container=\"true\" no_margin=\"true\" border=\"top\" padding_top=\"40px\" padding_bottom=\"40px\"][column type=\"one-half\"][custom_headline type=\"left\" level=\"h3\"]Faster code[/custom_headline]\r\n\r\nArrayFire is a fast, hardware-neutral software library for GPU computing with an easy-to-use API. Its array-based function set makes GPU programming simple. A few lines of code in ArrayFire can replace dozens of lines of raw GPU code, saving you valuable time and lowering development costs.\r\n\r\n[gap size=\"10%\"][button  type=\"flat\" shape=\"rounded\" href=\"http://www.sandbox.arrayfire.com/docs/installation.htm\" size=\"x-large\" ]Download ArrayFire[/button][/column][column type=\"one-half\" last=\"true\" class=\"center-text\"][gap size=\"5%\"][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/Triumvirate_Exported.png\"][/column] [gap size=\"5%\"]\r\n\r\n[column type=\"one-third\" class=\"center-text\"][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/04/Googlelogo-e1396387097279.png\"][line]Video content analysis is the basis for categorizing videos and enabling search by content. Google used ArrayFire to extract motion features in video, improving performance by substantially accelerating the solution of the L1-regularized least-squares optimization problem.[/column][column type=\"one-third\" class=\"center-text\"][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/04/Koch-Industries-e1396387359637.jpg\"][line]Andrew Shin, Market Risk Manager of Koch Supply &amp; Trading, achieves significant performance increases on option pricing algorithms using ArrayFire software, \"My buddy and I are, at best, novice programmers and we couldn\'t imagine having to figure out how to code all this in CUDA.\"[/column][column type=\"one-third\" last=\"true\" class=\"center-text\"][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/04/nasa-e1396387230473.png\"][line]The main thrust of this research was improving Mars rover image compression via GPUs and genetic algorithms. With ArrayFire software and GPUs, the researchers were able to achieve 5X speedups on the larger data sizes.[/column]\r\n<div id=\"hardware\"></div>\r\n[/content_band]\r\n[content_band inner_container=\"true\" no_margin=\"true\" border=\"top\" padding_top=\"40px\" padding_bottom=\"40px\"]\r\n\r\n[column type=\"one-half\"][gap size=\"15%\"]\r\n\r\n<img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/CUDA-logo.jpg\" alt=\"CUDA logo\" width=\"231\" height=\"140\" />\r\n\r\n<img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/OpenCLLogo_678x452.png\" alt=\"OpenCL\" width=\"326\" height=\"217\" />\r\n\r\n[/column][column type=\"one-half\" last=\"true\"][gap size=\"10%\"]\r\n\r\n[custom_headline type=\"left\" level=\"h3\"] ArrayFire for CUDA and OpenCL[/custom_headline]\r\n\r\nArrayFire supports CUDA-capable NVIDIA GPUs and most OpenCL devices, including AMD GPUs/APUs and Intel Xeon Phi co-processors. It also supports mobile OpenCL devices from ARM, Qualcomm, and others.\r\n\r\nArrayFire is a high-performance software library designed for maximum productivity and speed without the hassle of writing difficult low-level device code. Each of ArrayFire\'s functions has been hand-tuned by our CUDA and OpenCL experts.\r\n\r\n[/column]\r\n<div id=\"mobile\"></div>\r\n[/content_band]\r\n\r\n[content_band inner_container=\"true\" no_margin=\"true\" border=\"top\" padding_top=\"40px\" padding_bottom=\"40px\"]\r\n[column type=\"one-half\"][custom_headline type=\"left\" level=\"h3\"  ]Mobile GPU Computing[/custom_headline]\r\n\r\nMobile GPUs offer accelerated performance. If you would like to use ArrayFire in a mobile application or if you would like to hire our mobile acceleration services, email us at <a href=\"mailto:sales@arrayfire.com\" target=\"_blank\">sales@arrayfire.com</a> and include a description of your application.\r\n\r\nOur clients have achieved between 5X to 30X speed boosts for convolutions and other compute functions on mobile devices. It enables:[icon_list][icon_list_item type=\"angle-double-right\"]Real-time video processing[/icon_list_item][icon_list_item type=\"angle-double-right\"]Better augmented reality [/icon_list_item][icon_list_item type=\"angle-double-right\"]Better computational photograph[/icon_list_item][icon_list_item type=\"angle-double-right\"]Faster data processing[/icon_list_item][/icon_list]\r\n\r\nAll mobile devices have a GPU which can deliver greater compute throughput than the CPU. Why not use the GPU to make your app faster?[/column][column type=\"one-half\" fade=\"true\" last=\"true\" fade_animation=\"in-from-right\" class=\"center-text\"][gap size=\"10%\"][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/02/mobile_Exported1-e1395437261846.png\"][/column]\r\n<div id=\"documentation\"></div>\r\n[/content_band]\r\n\r\n[content_band inner_container=\"true\" no_margin=\"true\" border=\"top\" padding_top=\"40px\" padding_bottom=\"40px\"][column type=\"one-half\"][custom_headline type=\"left\" level=\"h3\"]Documentation[/custom_headline]\r\n\r\nArrayFire for C, C++, and Fortran\r\nOpen the hood—take a look at the beautiful nitty-gritty.\r\n\r\n[icon type=\"angle-double-right\"] <a href=\"http://www.sandbox.arrayfire.com/docs/\" target=\"_blank\">CUDA &amp; OpenCL C/C++</a>\r\n\r\nFunctions\r\nHundreds of functions, hand-tuned and optimized by our engineers.\r\n\r\n[icon type=\"angle-double-right\"] <a title=\"ArrayFire Functions\" href=\"http://www.sandbox.arrayfire.com/docs/modules.htm\">ArrayFire Functions</a>\r\n\r\nUser Forums\r\nEvery post gets a response from ArrayFire engineers.\r\n\r\n[icon type=\"angle-double-right\"] <a href=\"http://forums.accelereyes.com/\" target=\"_blank\">User Forums</a>\r\n\r\n[/column][column class=\"center-text\" type=\"one-half\" last=\"true\" fade=\"true\" fade_animation=\"in-from-right\" ][gap size=\"5%\"][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/gears1.png\"][/column]\r\n<div id=\"benchmarks\"></div>\r\n[/content_band]\r\n\r\n[content_band inner_container=\"true\" no_margin=\"true\" border=\"top\" padding_top=\"40px\" padding_bottom=\"40px\"]\r\n[column type=\"one-half\" fade=\"true\" fade_animation=\"in-from-left\" ][gap size=\"5%\"][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/02/Benchmark-guy-torso-opposite-e1392155948298.png\"][/column]\r\n\r\n[column type=\"one-half\" last=\"true\"][custom_headline type=\"left\" level=\"h3\" ]Benchmarks[/custom_headline]\r\n\r\nAll benchmarks were performed on a NVIDIA Tesla C2050 with an Intel i7-950 processor. The benchmarks compare ArrayFire with several popular CPU-based acceleration libraries, including <a href=\"http://software.intel.com/en-us/articles/intel-mkl/\" target=\"_new\">Intel Math Kernel Library</a>, <a href=\"http://software.intel.com/en-us/articles/intel-ipp/\" target=\"_new\">Intel Integrated Performance Primitives</a>, <a href=\"http://eigen.tuxfamily.org/index.php?title=Main_Page\" target=\"_new\">Eigen</a>, and <a href=\"http://arma.sourceforge.net/\" target=\"_new\">Armadillo</a>.[/column]\r\n\r\n[column type=\"one-fifth\"].[/column][column type=\"three-fifths\"][tab_nav type=\"four-up\"][tab_nav_item title=\"Base\" active=\"true\"][tab_nav_item title=\"Linear Algebra\" active=\"\"][tab_nav_item title=\"Convolution\" active=\"\"][tab_nav_item title=\"Utility\" active=\"\"][/tab_nav][tabs][tab active=\"true\"]<img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/matrix_multiply-1024x730.png\" alt=\"Matrix Multiply\" width=\"491\" height=\"350\" />[line]<img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/matrix_transpose-1024x730.png\" alt=\"Matrix Transpose\" width=\"491\" height=\"350\" />[line]<img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/fft-1024x730.png\" alt=\"FFT\" width=\"491\" height=\"350\" />[/tab][tab]<img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/lu-1024x730.png\" alt=\"LU\" width=\"491\" height=\"350\" />[line]<img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/svd-1024x730.png\" alt=\"SVD\" width=\"491\" height=\"350\" />[line]<img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/solve-1024x730.png\" alt=\"Solve\" width=\"491\" height=\"350\" />[/tab][tab]<img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/convs-1024x730.png\" alt=\"Convs\" width=\"491\" height=\"350\" />[line]<img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/conv-1024x730.png\" alt=\"Conv\" width=\"491\" height=\"350\" />[/tab][tab]<img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/sum-1024x730.png\" alt=\"sum\" width=\"491\" height=\"350\" />[line]<img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/sort-1024x730.png\" alt=\"sort\" width=\"491\" height=\"350\" />[line]<img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/scan-1024x730.png\" alt=\"scan\" width=\"491\" height=\"350\" />[/tab][/tabs][/column][column type=\"one-fifth\" last=\"true\"].[/column]\r\n<div id=\"free\"></div>\r\n[/content_band]\r\n\r\n[content_band inner_container=\"true\" no_margin=\"true\" border=\"top\" padding_top=\"40px\" padding_bottom=\"40px\" ]\r\n\r\n[column type=\"one-half\"].[/column][column type=\"one-fourth\"].[custom_headline type=\"center\"  level=\"h3\" class=\"mtn\"]ArrayFire Free[/custom_headline][/column][column type=\"one-fourth\" last=\"true\"].[/column][column type=\"one-fourth\"  fade=\"true\" fade_animation=\"in-from-left\" ][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/right-leaning-e1391788779101.png\"][/column][column type=\"one-fourth\"]\r\n<table>\r\n<tbody>\r\n<tr>\r\n<td>[custom_headline type=\"center\" level=\"h5\"]Functions[/custom_headline]</td>\r\n</tr>\r\n<tr>\r\n<td>[icon type=\"check-circle\" style=\"color: #8cc540;\"] Basic Operations</td>\r\n</tr>\r\n<tr>\r\n<td>[icon type=\"check-circle\" style=\"color: #8cc540;\"] Arithmetic</td>\r\n</tr>\r\n<tr>\r\n<td>[icon type=\"check-circle\" style=\"color: #8cc540;\"] Signal Processing</td>\r\n</tr>\r\n<tr>\r\n<td>[icon type=\"check-circle\" style=\"color: #8cc540;\"] Image Processing</td>\r\n</tr>\r\n<tr>\r\n<td>[icon type=\"check-circle\" style=\"color: #8cc540;\"] Statistics</td>\r\n</tr>\r\n<tr>\r\n<td>[icon type=\"check-circle\" style=\"color: #8cc540;\"] Visualization</td>\r\n</tr>\r\n</tbody>\r\n</table>\r\n[gap size=\"17%\"][button type=\"flat\" block=\"true\" shape=\"rounded\" size=\"large\"  href=\"http://www.sandbox.arrayfire.com/docs/installation.htm\"]Download ArrayFire[/button] [/column][column type=\"one-fourth\"]\r\n<table>\r\n<tbody>\r\n<tr>\r\n<td>[custom_headline type=\"center\" level=\"h5\"]Hardware[/custom_headline]</td>\r\n</tr>\r\n<tr>\r\n<td>[icon type=\"check-circle\" style=\"color: #8cc540;\"] CUDA</td>\r\n</tr>\r\n<tr>\r\n<td>[icon type=\"check-circle\" style=\"color: #8cc540;\"] OpenCL</td>\r\n</tr>\r\n<tr>\r\n<td>[custom_headline type=\"center\" level=\"h5\"]Languages[/custom_headline]</td>\r\n</tr>\r\n<tr>\r\n<td>[icon type=\"check-circle\" style=\"color: #8cc540;\"] C/C++</td>\r\n</tr>\r\n<tr>\r\n<td>[icon type=\"check-circle\" style=\"color: #8cc540;\"] Fortran</td>\r\n</tr>\r\n<tr>\r\n<td>[custom_headline type=\"center\" level=\"h5\"]Advanced[/custom_headline]</td>\r\n</tr>\r\n<tr>\r\n<td> [icon type=\"check-circle\" style=\"color: #8cc540;\"] GFOR Loop</td>\r\n</tr>\r\n</tbody>\r\n</table>\r\n[/column][column type=\"one-fourth\" last=\"true\"]\r\n<table>\r\n<tbody>\r\n<tr>\r\n<td>[custom_headline type=\"center\" level=\"h5\"]Platforms[/custom_headline]</td>\r\n</tr>\r\n<tr>\r\n<td>[icon type=\"check-circle\" style=\"color: #8cc540;\"] Windows</td>\r\n</tr>\r\n<tr>\r\n<td>[icon type=\"check-circle\" style=\"color: #8cc540;\"] Linux</td>\r\n</tr>\r\n<tr>\r\n<td>[icon type=\"check-circle\" style=\"color: #8cc540;\"] Mac</td>\r\n</tr>\r\n<tr>\r\n<td>[custom_headline type=\"center\" level=\"h5\"]Data Types[/custom_headline]</td>\r\n</tr>\r\n<tr>\r\n<td>[icon type=\"check-circle\" style=\"color: #8cc540;\"] All types</td>\r\n</tr>\r\n<tr>\r\n<td>[custom_headline type=\"center\" level=\"h5\"]Support[/custom_headline]</td>\r\n</tr>\r\n<tr>\r\n<td> [icon type=\"check-circle\" style=\"color: #8cc540;\"] Forums</td>\r\n</tr>\r\n</tbody>\r\n</table>\r\n<div id=\"licensing\"></div>\r\n[/column][gap size=\"8%\"]\r\n\r\n[pricing_table id=\"pricing\" columns=\"3\"][pricing_table_column  featured=\"false\" title=\"ArrayFire Developer\" currency=\"$\" price=\"499 / year\" interval=\"$149 / year (Academic)\"] [icon_list] [icon_list_item type=\"star\" ]Dedicated license [/icon_list_item] [icon_list_item  type=\"times-circle\"] Starts at 2 GPUs or devices [/icon_list_item] [icon_list_item type=\"times-circle\"] Linear algebra [/icon_list_item] [icon_list_item type=\"times-circle\"] Sparse matrices [/icon_list_item][icon_list_item type=\"times-circle\"] Phone support [/icon_list_item][icon_list_item type=\"times-circle\"] Premium support &amp; consulting [/icon_list_item][/icon_list] [button href=\"http://sandbox.arrayfire.com/shop\"] Purchase [/button] [/pricing_table_column] [pricing_table_column featured=\"true\" featured_sub=\"Most Popular\" title=\"ArrayFire Pro\" currency=\"$\" price=\"1,499 / year\" interval=\"$525 / year (Academic)\"] [icon_list] [icon_list_item type=\"star\"] Dedicated license [/icon_list_item] [icon_list_item type=\"star\"] Starts at 2 GPUs or devices [/icon_list_item] [icon_list_item type=\"star\"] Linear algebra [/icon_list_item][icon_list_item type=\"star\"] Sparse matrices [/icon_list_item][icon_list_item type=\"times-circle\"] Phone support [/icon_list_item][icon_list_item type=\"times-circle\"] Premium support &amp; consulting [/icon_list_item] [/icon_list] [button href=\"http://sandbox.arrayfire.com/shop\"]Purchase [/button] [/pricing_table_column] [pricing_table_column featured=\"false\" title=\"ArrayFire Enterprise\" currency=\"$\" price=\"2,999 / year\" interval=\"$1,049 / year (Academic)\"] [icon_list] [icon_list_item type=\"star\"] Dedicated license [/icon_list_item] [icon_list_item type=\"star\"] Starts at 2 GPUs or devices [/icon_list_item] [icon_list_item type=\"star\"] Linear algebra [/icon_list_item][icon_list_item type=\"star\"]Sparse matrices [/icon_list_item][icon_list_item type=\"star\"] Phone support[/icon_list_item][icon_list_item type=\"star\"]Premium support &amp; consulting [/icon_list_item][/icon_list] [button href=\"http://sandbox.arrayfire.com/shop\"] Purchase [/button] [/pricing_table_column] [/pricing_table]\r\n<div id=\"whitepapers\"></div>\r\n[/content_band]\r\n\r\n[content_band inner_container=\"true\" no_margin=\"true\" border=\"top\" padding_top=\"40px\" padding_bottom=\"40px\" ]\r\n\r\n[column type=\"one-half\"][gap size=\"20%\"][image type=\"thumbnail\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/02/wp2.jpg\"][button href=\"http://go.sandbox.arrayfire.com/l/37882/2014-05-29/dw83/37882/18534/arrayfire_matrix_computations_chrzeszczyk.pdf\" shape=\"rounded\" size=\"regular\" block=\"true\"]Download Matrix Computations on the GPU with ArrayFire for C/C++[/button][/column][column type=\"one-half\" last=\"true\"]\r\n\r\n[custom_headline type=\"left\" level=\"h3\" ]Whitepapers[/custom_headline]\r\n\r\n<img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/02/Whitepaper-1.png\" alt=\"Whitepaper 1\" width=\"466\" height=\"374\" />\r\n\r\n&nbsp;\r\n\r\n[/column][gap size=\"10%\"]\r\n\r\n[column type=\"one-half\"]<img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/02/Whitepaper-2.png\" alt=\"Whitepaper 2\" width=\"442\" height=\"304\" />[/column][column type=\"one-half\" last=\"true\"][image type=\"thumbnail\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/02/wp1.jpg\"][button href=\"http://go.sandbox.arrayfire.com/l/37882/2014-05-29/dw81/37882/18532/arrayfire_whitepaper.pdf\" shape=\"rounded\" size=\"regular\"  block=\"true\" float=\"right\"]Download High-level GPU Computing in C, C++, and Fortran[/button][/column]\r\n<div id=\"casestudies\"></div>\r\n[/content_band]\r\n\r\n[content_band inner_container=\"true\" no_margin=\"true\" border=\"top\" padding_top=\"40px\" padding_bottom=\"40px\" ]\r\n\r\n[column type=\"one-half\"][gap size=\"12%\"][custom_headline type=\"left\" level=\"h3\" ]Case Studies[/custom_headline]\r\n\r\nLearn how ArrayFire has worked in real code, including applications in academia, finance, government, life sciences, manufacturing, media, and oil &amp; gas.[/column][column type=\"one-half\" last=\"true\" fade=\"true\" fade_animation=\"in-from right\"][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/02/model-A.png\"][/column][custom_headline type=\"left\" level=\"h5\"]Academia [/custom_headline][accordion][accordion_item title=\"Accelerating LTE Simulation | Tsinghua University\"]\r\n\r\nAuthors: Yuan Gao, Yin Sun, Chun Hui Zhou, Xin Su, Xi Bin Xu, Shi Dong Zhou, Tsinghua University\r\nSpeedup: 3X\r\n\r\nFast simulations are a driving force in several research projects. However, the accompanying long simulation times can tend to be a drag in many of these projects. In this article, we shall bring up the example of the work on 3GPP LTE System Simulation by Yuan Gao et al (from Tsinghua University, Beijing) and demonstrate how the use of ArrayFire software can significantly improve the simulator performance and lead to faster validation times in simulation projects.[/accordion_item]\r\n\r\n[accordion_item title=\"High Performance Compressive Sensing | Rice University\"]\r\n\r\nAuthors: Nabor Reyna and Wotao Yin from Rice University\r\nSpeedup: 5X\r\n\r\nThis work deals with reconstruction of signals using partial Fourier matrices (RecPF). The major computational components of the algorithm involve shrinkage and FFTs. ArrayFire software is employed to accelerate this compute-heavy code.[/accordion_item]\r\n\r\n[accordion_item title=\"Power System Simulations | Indian Institute of Technology, Roorkee, India\"]\r\nAuthors: Indian Institute of Technology, Roorkee\r\nSpeedup: 35X\r\n\r\nPower flow studies are one of the most important aspects of power system planning and operation. The power flow reveals the sinusoidal steady state characteristics of the entire system - voltages, real and reactive power generated, and absorbed and line losses- elucidating the voltage magnitudes and angles at each bus, the generation of each generating unit, and real and reactive power losses in the system. All this is necessary to ensure the security, economy, and control of electrical energy distribution. Learn how ArrayFire software can deliver magnitudes of performance improvement over CPU-based solutions.[/accordion_item]\r\n\r\n[accordion_item title=\"Antenna Array Simulations | University of Naples Federico II\"]\r\n\r\nAuthors: A. Capozzoli, C. Cucio, A. Liseno at University of Naples Federico II\r\nSpeedup: 24X\r\n\r\nAntenna array design involves repeated simulation to tune the many parameters involved, and waiting around for simulations to finish is no fun. Offloading the optimization problem onto the GPU cuts that time down significantly. In their recent paper, Capozzoli, Curcio, and Liseno of University of Naples Federico II demonstrated how a simple modification to their echo generator array simulation took advantage of the GPU to bring immediate speedups.[/accordion_item]\r\n\r\n[accordion_item title=\"Laplace Transform Inversion | Acunum Algorithms and Simulations\"]\r\n\r\nAuthors: Patrick Kano and Moysey Brio at Acunum Algorithms and Simulations\r\nSpeedup: 3.8X\r\n\r\nThe numerical inversion of the Laplace transform is a long standing problem due its implicit ill-posedness. Patrick Kano and Moysey Brio of Acunum Algorithms and Simulations, with their experience in computational methods and algorithm development, found a solution that not only works, but is very fast.[/accordion_item]\r\n\r\n[accordion_item title=\"Compressed Sensing for Image Reconstruction | College of Engineering, Roorkee, India\"]\r\n\r\nAuthors: Kuldeep Yadav, Ankush Mittal, M. A. Ansar, and Avi Srivastava, College of Engineering, Roorkee, India\r\nSpeedup: 8X\r\n\r\nCompressed sensing is very critical in the areas of medical image reconstruction, image acquisition or sensor networks. An algorithm for compressed sensing developed using a Basis Pursuit Algorithm shows over 8X speedup when run on an NVIDIA GPU.[/accordion_item]\r\n\r\n[accordion_item title=\"Fat/Water Reconstruction for Medical Images | Case Western Reserve University\"]\r\n\r\nAuthors: D. H. Johnson, S. Narayan, C. A. Flask, and D. L. Wilson, Case Western Reserve University\r\nSpeedup: 11.6X\r\n\r\nCase Western Reserve University researchers turned to GPUs running ArrayFire software to develop a fast and robust version of the \"Iterative Decomposition of water and fat with an Echo Asymmetry and Least-squares\" (IDEAL) reconstruction algorithm. This algorithm uses a lot of Image Processing algorithms for reconstruction, and was shown to achieve very high speedups.\r\n[/accordion_item]\r\n\r\n[/accordion]\r\n<h5>Finance</h5>\r\n[accordion][accordion_item title=\"Option Pricing | Koch Supply and Trading\"]\r\n\r\nAuthors: Koch Supply &amp; Trading\r\nSpeedup: 51.8X\r\n\r\nAndrew Shin, Market Risk Manager of Koch Supply &amp; Trading, achieves significant performance increases on option pricing algorithms using ArrayFire software to accelerate his code with GPUs. Andrew says, \"My buddy and I are, at best, novice programmers and we couldn\'t imagine having to figure out how to code all this in CUDA.\" But he found ArrayFire software to be straight-forward. With these results, he says he can see ArrayFire software and GPUs populating Koch\'s mark-to-futures cube, which contains its assets, simulations, and simulated asset prices.[/accordion_item]\r\n\r\n[accordion_item title=\"GPU Computing in Automated Trader | Automated Trader\"]\r\n\r\nAuthors: Automated Trader\r\nSpeedup: 37.5X\r\n\r\nThe Q1 2012 issue of Automated Trader contains an excellent Mashup piece reviewing software for algorithmic trading. The article provides a wonderful glimpse into the 1-2 month adventure of Andy Webb, Automated Trader.s Founder, and Wrecking Crew building a fast trading platform from several technologies. The full trading platform they built was quite extensive. The part that caught our eye was the core computational component of the pipeline. That component involved permuting 1,000 potential pairs with cointegration tests for 350 time windows on each potential pair.\r\n[/accordion_item]\r\n[accordion_item title=\"GPUs in Quantitative Analytics and Finance | Private Bank\"]\r\n\r\nThe world of Quantitative finance is all about getting accurate results really, really fast. ArrayFire is working with one of the largest banks in Spain to maximize their output using GPUs. Click the link below for an overview of the uses of GPU computing in finance.[/accordion_item][/accordion]\r\n<h5>Government</h5>\r\n[accordion][accordion_item title=\"Powering Mars Research | NASA and UAA in Anchorage\" ]\r\n\r\nAuthors: NASA and UAA in Anchorage\r\nSpeedup: 5X\r\n\r\nThe main thrust of this research is improving mars rover image compression via GPUs and genetic algorithms. With ArrayFire software and GPUs, the researchers were able to achieve 5X speedups on the larger data sizes. The algorithm works by pairing neighboring pixels with a random one and then adjusting the random pixel based on whether it incrementally improves the original image. Babb described the algorithm as an embarrassingly parallel process, ideally suited to GPU acceleration. He estimates he has been able to achieve a 20 to 30 percent error reduction in subjects like fingerprints and satellite imagery.[/accordion_item]\r\n\r\n[accordion_item title=\"Radar Image Formation | System Planning Corporation\"]\r\n\r\nAuthors: Gary Rubin and Earl Sager - System Planning Corporation\r\nSpeedup: ~45X\r\n\r\nRadar imaging is computationally intensive. As a result, many imaging algorithms apply FFT-based approximations. While efficient, these algorithms sacrifice data fidelity for speed. Other algorithms better preserve information, but are often too slow for many applications. At System Planning Corporation (SPC) , we have implemented a SAR/ISAR imaging routine based on the Backprojection algorithm. Using ArrayFire software, we have demonstrated speedups of roughly 45x for large datasets.[/accordion_item]\r\n\r\n[accordion_item title=\"Radar Clutter Reduction | System Planning Corporation\"]\r\n\r\nAuthors: David Berger and Gary Rubin - System Planning Corporation\r\nSpeedup: 5-10X\r\n\r\nSystem Planning Corporation (SPC) uses ArrayFire software to accelerate radar processing algorithms. The system processes raw data from marine navigation radars using a variety of thresholding techniques to extract real targets from clutter. This involves highly data-parallel processing in which each radar pulse is subjected to the same computations; very few operations occur across multiple pulses. Using ArrayFire software, SPC has achieved 10x speed improvements relative to a Core i7-920 CPU and 5x improvements relative to a realtime DSP implementation.[/accordion_item]\r\n\r\n[accordion_item title=\"Novel Algorithms for Linear Algebra | SAIC\" ]\r\n\r\nAuthors: Nolan Davis and Daniel Redig, SAIC\r\nSpeedup: 3.5X\r\n\r\nNolan Davis and Daniel Redig at SAIC recently presented work on Hybrid GPU/Multicore Solutions for Large Linear Algebra Problems where they developed a novel algorithm for LU decomposition, one of the most important routines in linear algebra. They presented a Hybrid CPU/GPU computing approach, where problems too large to fit in GPU memory can also be solved faster than using only the CPU.\r\n[/accordion_item]\r\n[accordion_item title=\"Geolocation | BAE Systems\"]\r\n\r\nAuthors: BAE Systems\r\nSpeedup: 17X\r\n\r\nGeolocation is the identification of the real-world geographic location of a target of interest. In this application, the system receives the signal with an array of several antennas and computes the direction of arrival of the radio energy by measuring the time difference of arrival (or the phase difference) at the different antennas.\r\n[/accordion_item]\r\n[accordion_item title=\"Tsunami Modeling | University of Minnesota, Boise State, Saint Scholastica, and NCAR\"]\r\n\r\nAuthors: University of Minnesota, Boise State, Saint Scholastica, and NCAR\r\nSpeedup: 3-5X\r\n\r\nNatural catastrophic disasters like tsunamis commonly strike with little warning. For most people, tsunamis are underrated as major hazards. People sometimes wrongly believe that they occur infrequently and only along distant coasts. Tsunamis are usually caused by earthquakes. Seismic signals can give some margin of warning since the speed of tsunami waves travels at 1/30 the speed of seismic waves. Still there is little time between the creation of the tsunami and its impact making fast processing critical to producing effective warning systems. ArrayFire software was used to run an RBF simulation on the GPU with a time to solution not available by other alternatives.\r\n[/accordion_item][/accordion]\r\n<h5>Life Sciences</h5>\r\n[accordion][accordion_item title=\"Parallelized Gene Predictors | University of Quebec\" ]\r\n\r\nAuthors: University of Quebec\r\nSpeedup: 43X\r\n\r\nComputerized approaches to studying the human genome are challenged by the exploding amount of data, which doubles roughly every 6 months. In order to deal with this burgeoning datasets, demands for faster processing power continue to arise. This work focuses on predicting genes using frequency analysis with FFTs and with an equivalent technique known as Goertzel\'s algorithm. In these applications, the emphasis of this paper is to propose tools to geneticists and molecular biologists for the prediction or identification of new genes using existing complementary strategies. The criteria for these tools are speed, reliability, accuracy and ease of use, thus requiring little training.\r\n[/accordion_item]\r\n[accordion_item title=\"Pathology Advances with GPUs | Northeastern University\" ]\r\n\r\nAuthors: Laboratory for Spectral Diagnosis at Northeastern University\r\nSpeedup: 100X+\r\n\r\nOne element of the hyperspectral image analysis workflow that requires more than a traditional desktop workstation or personal computer is Hierarchical Cluster analysis (HCA). HCA requires a large amount of data space and substantial computation time (~11 hours) for typical datasets using a single processor personal computer. Rather than following the traditional approach of moving to a lower level programming language like C or C++ and complex parallel programming paradigms such as OpenMP or the Massage Passing Interface (MPI), the lab utilized graphics processing units, or GPUs, and the ArrayFire software platform. The solution allowed the lab to dramatically increase the performance of the analysis while substantially decreasing the amount of calendar time to reach the desired results.\r\n[/accordion_item]\r\n[accordion_item title=\"Hepatitis C Virus - Mutation Modeling | Centers for Disease Control and Prevention\" ]\r\n\r\nAuthors: CDC Research and Development Team\r\nSpeedup: ~20X\r\n\r\nThis case study provides a look at biological research regarding coordinated mutations of the Hepatitis C Virus (HCV). ArrayFire provided collaborative R&amp;D resources and greatly improved the speed of this HCV research with the use of parallelization, reducing the computing time from 40 days to less than 1 day. Most importantly, the conclusion of the case study illustrates the the relative price-performance of personal supercomputers that leverage GPUs and ArrayFire software provides a compelling solution versus other architectures and approaches.\r\n[/accordion_item]\r\n[accordion_item title=\"Accelerating the SPM Package for Neuroimaging | Georgia Institute of Technology\" ]\r\n\r\nAuthors: Georgia Institute of Technology\r\nSpeedup: 3.5X\r\n\r\nThe Georgia Tech team explores the value of ArrayFire software and GPUs for fMRI workflows within the popular SPM - Statistical Parametric Mapping software widely used in neuroscience research.\r\n[/accordion_item]\r\n[accordion_item title=\"Medical Image Compression | Indian Institute of Technology, Roorkee, India\" ]\r\n\r\nAuthors: Jaideep Singh, Ipseeta Aruni, R. Balasubramanian - IIT - Roorkee, India\r\nSpeedup: 38X\r\n\r\nThis study presents the acceleration of Haar wavelet-based image compression algorithm for medical imaging on the Graphics Processing Unit (GPU) using ArrayFire software. Due to bandwidth and image size constraints of medical imaging systems, image compression plays a vital role in reducing the bit rate of transmission or storage. Wavelet-based image compression provides the most promising approach for high quality image compression.\r\n[/accordion_item]\r\n[accordion_item title=\"Brain Displacement | Spencer Technologies\"]\r\n\r\nAuthors: Spencer Technologies\r\nSpeedup: 12X\r\n\r\nSpencer describes how ArrayFire software facilitates the development of fast algorithms enabling observation of brain displacement across depth with sampling density that far surpasses previous benchmarks.\r\n[/accordion_item]\r\n[accordion_item title=\"Multidimensional Scaling for Genomics | Leibniz Institute of Plant Genetics and Crop Plant Research\" ]\r\n\r\nAuthors: Leibniz Institute of Plant Genetics and Crop Plant Research\r\nSpeedup: 20-35X\r\n\r\nMultidimensional scaling (MDS) is a general computing technique to turn a distance matrix into a set of reconstructed points with pair-wise relationships approximating the original distances by points located in a usually low-dimensional space. ArrayFire software is used to enhance execution of the HiT-MDS procedure and delivers considerable performance improvement.\r\n[/accordion_item]\r\n[accordion_item title=\"Drug Delivery Model | Georgia Institute of Technology\"]\r\n\r\nAuthors: Georgia Institute of Technology\r\nSpeedup: 70X\r\n\r\nIn this work, the researchers simulate the delivery of a novel nanoparticle chemotherapy drug to cancerous tissue. Simulation allows scientists to predict experimental outcomes and thus reduce the cost of development and time to clinical relevance. The simulation model includes blood vessels, tumor cells, and healthy cells and an engine to calculate the spatial distributions of both drug and oxygen. ArrayFire software is used to speed up the diffusion calculations for the drug and oxygen within the tissue.\r\n[/accordion_item]\r\n[accordion_item title=\"Biomedical Infrared Spectroscopy | University of Manchester and Nofima Mat, Norway\" ]\r\n\r\nAuthors: University of Manchester and Nofima Mat, Norway\r\nSpeedup: Hours of runtime reduction\r\n\r\nThe authors present an iterative algorithm that applies full Mie scattering theory and avoids noise accumulation in their iterative algorithm by integrating a curve-fitting step. ArrayFire software along with NVIDIA GPUs are leveraged to reduce the time added by the curve-fitting step.\r\n[/accordion_item][/accordion]\r\n<h5>Manufacturing</h5>\r\n[accordion][accordion_item title=\"Feature Learning on Images | Stanford\" ]\r\n\r\nAuthors: Andrew Ng, Stanford University\r\nSpeedup: Ability to process many images in parallel\r\n\r\nStanford researchers in Andrew Ng\'s group used GPUs and ArrayFire software to speed up their work on Feature Learning Architectures. They decided to use ArrayFire software for this study because of the need to quickly evaluate many architectures on thousands of images. ArrayFire software taps into the immense computing power of GPUs and speeds up research utilizing many images.\r\n[/accordion_item]\r\n[accordion_item title=\"Tomography of Vegetation - Filtered Back-Projection and Non-Uniform FFTs | Universita di Napoli Federico II\" ]\r\n\r\nAuthors: Drs. Capozzoli, Curcio, di Vico, and Liseno, Universita di Napoli Federico II\r\nSpeedup: 10X\r\n\r\nIn order to investigate changes of forest biomass, scientists use microwave tomography to image the vegetation. At the smallest scale, individual plants can be imaged to investigate branching and growth, but even synthetic aperture radar can reveal large-scale changes in regional ecology. To the right, you can see the experimental setup to image an individual plant.\r\n[/accordion_item]\r\n[accordion_item title=\"Action Recognition with Independent Subspace Analysis | Stanford University\" ]\r\n\r\nAuthors: Quoc Le, Will Zou, Serena Yeung, Andrew Ng, Stanford University\r\nSpeedup: 4.4X\r\n\r\nIn a paper at this year\'s CVPR 2011, entitled \"Learning hierarchical invariant spatio-temporal features for action recognition with independent subspace analysis\", the authors explain how their unsupervised feature learning algorithm competes with other algorithms that are hand crafted or use learned features. For their training purposes, they used a multi-layered stacked convolutional ISA (Independent subspace analysis) network. An ISA is used for learning features from image patches without supervision.\r\n[/accordion_item][/accordion]\r\n<h5>Media and Computer Vision</h5>\r\n[accordion][accordion_item title=\"Fast Computer Vision with OpenCV and ArrayFire | OpenCV Blogger\" ]\r\n\r\nAuthors: OpenCV Blogger\r\nSpeedup: ~10X\r\n\r\nThe OpenCV library is the defacto standard for doing computer vision and image processing research projects. OpenCV includes several hundreds of computer vision algorithms, aimed for use in realtime vision applications. This case study shows how to use both libraries together. There is a simple example application that demonstrates using OpenCV for webcam access and ArrayFire for some basic processing routines and displaying results.\r\n[/accordion_item]\r\n[accordion_item title=\"Video Processing | Google\" ]\r\n\r\nAuthors: Google and Stanford\r\nSpeedup: 10-20X\r\n\r\nVideo content analysis is the basis for categorizing videos and enabling search by content. Growing interest in using sparse-coding methods to extract motion features in video in support of video content analysis led to the application of ArrayFire software to improve performance by substantially accelerating the solution of the L1-regularized least-squares optimization problem.\r\n[/accordion_item]\r\n[accordion_item title=\"Action Recognition with Independent Subspace Analysis | Stanford University\"]\r\n\r\nAuthors: Quoc Le, Will Zou, Serena Yeung, Andrew Ng, Stanford University\r\nSpeedup: 4.4X\r\n\r\nIn a paper at this year\'s CVPR 2011, entitled \"Learning hierarchical invariant spatio-temporal features for action recognition with independent subspace analysis\", the authors explain how their unsupervised feature learning algorithm competes with other algorithms that are hand crafted or use learned features. For their training purposes, they used a multi-layered stacked convolutional ISA (Independent subspace analysis) network. An ISA is used for learning features from image patches without supervision.\r\n[/accordion_item]\r\n[accordion_item title=\"Music Beat Analysis | Georgia Tech\"]\r\n\r\nAuthors: Vidhur Vohra - Georgia Tech\r\nSpeedup: 15X\r\n\r\nDid you ever wonder how the music visualizer in your media player works? Watching it pulsate in synchrony with the beats of the song is almost as entertaining as listening to the song itself! Researchers have been attempting to detect beats in audio signals for many years, and there are many techniques available, from the simplest (and least accurate) to more complicated algorithms that are highly accurate. All algorithms, though, perform some form of signal processing and frequency analysis, applications highly suited to GPU Computing.\r\n[/accordion_item]\r\n[accordion_item title=\"Optimization Methods for Deep Learning | Stanford Artificial Intelligence Laboratory\" ]\r\n\r\nAuthors: Stanford Artificial Intelligence Laboratory\r\nSpeedup: Improved accuracy\r\n\r\nResearchers at SAIL (Stanford Artificial Intelligence Laboratory), have done it again. They have successfully used ArrayFire software to speed up the training part of Deep Learning algorithms. In their paper titled .On Optimization Methods for Deep Learning., they experiment with some of the well known training algorithms and demostrate their scalability across parallel architectures (GPUs as well as multi-machine networks). The algorithms include SGDs (Stochastic Gradient Descent) L-BFGS (Limited BFGS used for solving non-linear problems), CG (Conjugate Gradient).\r\n[/accordion_item]\r\n[accordion_item title=\"Feature Learning on Images | Stanford University\" ]\r\n\r\nAuthors: Andrew Ng, Stanford University\r\nSpeedup: Ability to process many images in parallel\r\n\r\nStanford researchers in Andrew Ng’s group used ArrayFire software to speed up their work on Feature Learning Architectures. They decided to use ArrayFire software for this study because of the need to quickly evaluate many architectures on thousands of images. ArrayFire software taps into the immense computing power of GPUs and speeds up research utilizing many images.\r\n[/accordion_item]\r\n[accordion_item title=\"Digital Holography for Imaging | National University of Ireland, Maynooth\" ]\r\n\r\nAuthors: Nitesh Pandey, Damien Kelly, Bryan Hennelly and Thomas Naughton from the National University of Ireland, Maynooth\r\nSpeedup: 17X\r\n\r\nDigital holography is a powerful imaging technique with many new applications like true 3D display. It allows the capture of both amplitude and phase information of the light reflected off the surface of 3D objects. Researchers at the National University of Ireland, Maynooth are developing techniques based on digital holography for 3D display applications.\r\nReconstruction of large digital holograms can be computationally intensive to generate on CPUs, but GPUs running ArrayFire software offer amazing possibilities.\r\n[/accordion_item][/accordion]\r\n<h5>Oil and Gas</h5>\r\n[accordion][accordion_item title=\"3D Mantle Convection - Geodynamics | Boise State, University of Colorado, University of Minnesota\" ]\r\n\r\nAuthors: Boise State, University of Colorado, University of Minnesota\r\nSpeedup: 2.5-4.5X\r\n\r\nThe authors introduce a GPU implementation of a three-dimensional mantle convection modeling at a high Rayleigh number to the solid earth geophysics community. They outline code development time, compare performance of CPUs versus GPUs, and deliver powerful visualizations.\r\n[/accordion_item]\r\n[accordion_item title=\"Ground Water Simulations | Louisiana State University\" ]\r\n\r\nAuthors: Kevin R. Tubbs and Frank T-C. Tsai at Louisiana State University\r\nSpeedup: &gt;20X\r\n\r\nA lattice Boltzmann method for solving the shallow water equations and the advection-dispersion equation is developed and implemented on graphics processing unit (GPU)-based architectures. The proposed LBM is implemented to an NVIDIA Computing Processor in a single GPU workstation. GPU computing is performed using ArrayFire software. Mass transport with velocity-dependent dispersion in shallow water flow is simulated by combining the MRT-LBM model and the TRT-LBM model. The GPU parallel performance increases as the grid size increases. The results indicate the promise of the GPU-accelerated LBM for modeling mass transport phenomena in shallow water flows.\r\n[/accordion_item]\r\n[accordion_item title=\"Shallow Water Fluid Flow | Louisiana State University\" ]\r\n\r\nAuthors: Louisiana State University\r\nSpeedup: &gt;10X\r\n\r\nA lattice Boltzmann method (LBM) on high performance computing (HPC) environments for three-dimensional shallow water flow fields coupled to mass transport is developed. LBM is an attractive method for solving the multilayered shallow water equations because the extension to multilayer is straight forward with all of the simplicities and advantages of the LBM in mass transport in shallow water flows and the LBM performance on central processing unit (CPU)-based and graphics processing unit (GPU)-based HPC environments.\r\n[/accordion_item][/accordion]\r\n<div id=\"consulting\"></div>\r\n[/content_band]\r\n<div id=\"services\"></div>\r\n[content_band inner_container=\"true\" no_margin=\"true\" border=\"top\" padding_top=\"40px\" padding_bottom=\"40px\"][column type=\"one-half\"][custom_headline type=\"left\" level=\"h3\"]Hire our acceleration gang[/custom_headline]\r\n\r\nHire us to accelerate your code. Or to train your pros. Or even to write new code for your organization!\r\n\r\nWe’ve already helped thousands of organizations speedup their code. We’ve accelerated algorithms, data sets, and challenging problems of all types in the past, and we’re confident that we can accelerate your code too.\r\n\r\n[gap size=\"10%\"][button  type=\"flat\" shape=\"rounded\" href=\"http://meetme.so/arrayfire\" size=\"x-large\" ]Schedule a consultation[/button][/column][column type=\"one-half\" last=\"true\" class=\"center-text\"][gap size=\"5%\"][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/Bat-signal-e1391790016951.png\"][/column] [gap size=\"7%\"]\r\n\r\n[column type=\"one-third\" class=\"center-text\"][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/04/LFG-B-HORZ_202_K-e1396448935778.jpg\"][line]Lincoln Financial Group ported their CPU code (C/C++) to CUDA, and this enabled them to speed up the necessary financial calculations. Their primary objective was to reduce the time taken to run this code. Before porting to CUDA, they required 10-12 hours to run the entire code. After porting to CUDA, they were able to do the same work in about 30 minutes.[/column][column type=\"one-third\" class=\"center-text\"][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/02/reveal_logo-e1396449044651.jpg\"][line]Reveal Imaging, an SAIC company, uses ArrayFire in developing threat-detection products for transportation systems—such as cargo and baggage screening in airports—and in securing facilities and public events.[/column][column type=\"one-third\" last=\"true\" class=\"center-text\"][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/04/1800contactlogo.png\"][line]The Glasses.com app relies on computer vision to recognize the features of a user’s face. The application then generates an accurate, high-fidelity, three-dimensional model of that face, and virtually places selected frames on the image.[/column]\r\n<div id=\"starterpackage\"></div>\r\n[/content_band]\r\n\r\n[content_band inner_container=\"true\" no_margin=\"true\" border=\"top\" padding_top=\"40px\" padding_bottom=\"40px\"]\r\n\r\n[column type=\"one-half\" last=\"false\" fade=\"true\" fade_animation=\"in-from-left\" ][gap size=\"10%\"][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/comingatyou.png\"][/column][column type=\"one-half\" last=\"true\"] [custom_headline type=\"left\" level=\"h3\"]Starter Package ($500)* [/custom_headline] Hire us for 1-day. We set you up with one engineer dedicated for a full day, as well as support from senior and test engineers throughout the day. Here\'s how it works:\r\n\r\n[icon_list] [icon_list_item type=\"angle-double-right\"]Initial phone call[/icon_list_item] [icon_list_item type=\"angle-double-right\"]You send us your code or algorithm [/icon_list_item] [icon_list_item type=\"angle-double-right\"]We analyze your code for potential GPU benefit[/icon_list_item][icon_list_item type=\"angle-double-right\"]We accelerate as much of the code as is possible within the 1-day effort, applying our extensive GPU software libraries[/icon_list_item][icon_list_item type=\"angle-double-right\"]We produce a final report, along with code[/icon_list_item] [/icon_list] The final report outlines the best approach to follow for full GPU-acceleration of your code.\r\n\r\n&nbsp;\r\n\r\n[button type=\"flat\" shape=\"rounded\" size=\"regular\" href=\"http://sandbox.arrayfire.com/product/consulting-starter-package/\" title=\"Starter Package\"]Buy the Starter Package[/button]\r\n\r\n&nbsp;\r\n\r\n*Limit one (1) per customer.\r\n\r\n[/column]\r\n<div id=\"customcode\"></div>\r\n[/content_band] [content_band inner_container=\"true\" no_margin=\"true\" border=\"top\" padding_top=\"40px\" padding_bottom=\"40px\" ]\r\n\r\n[column type=\"one-half\"][custom_headline type=\"left\" level=\"h3\" ]Custom Coding Work[/custom_headline]\r\n\r\n[custom_headline type=\"left\" level=\"h6\" ]Why Choose Us?[/custom_headline] [icon_list] [icon_list_item type=\"angle-double-right\"]Deep experience, already servicing thousands of customers[/icon_list_item] [icon_list_item type=\"angle-double-right\"]Quality work, with leading GPU software [/icon_list_item] [icon_list_item type=\"angle-double-right\"]Efficient delivery, with ArrayFire\'s code base we can deliver results fast[/icon_list_item][icon_list_item type=\"angle-double-right\"]Proven, we make customers happy through faster code[/icon_list_item][/icon_list] [custom_headline type=\"left\" level=\"h6\" ]Our Strengths[/custom_headline] [icon_list] [icon_list_item type=\"angle-double-right\"]Excellence in GPU code[/icon_list_item] [icon_list_item type=\"angle-double-right\"]Well-written, efficient C, C++, Fortran, Java, or .NET [/icon_list_item] [icon_list_item type=\"angle-double-right\"]Application porting and integration[/icon_list_item][icon_list_item type=\"angle-double-right\"]Tuning software to peak hardware performance[/icon_list_item][icon_list_item type=\"angle-double-right\"]Scalability of algorithms to handle enterprise-level programs[/icon_list_item] [/icon_list][button type=\"flat\" shape=\"rounded\" size=\"regular\" href=\"http://meetme.so/arrayfire\" title=\"Tech Consultation\"]Schedule a consultation[/button] [/column][column type=\"one-half\"  fade=\"true\" fade_animation=\"in-from-right\" last=\"true\" ][gap size=\"25%\"][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/02/Holoham.png\"][/column]\r\n<div id=\"training\"></div>\r\n[/content_band] [content_band inner_container=\"true\" no_margin=\"true\" border=\"top\" padding_top=\"40px\" padding_bottom=\"40px\" ]\r\n\r\n[column type=\"one-half\"][custom_headline type=\"left\" level=\"h3\" ]Training[/custom_headline] Attendees will receive the latest industry knowledge and techniques for GPU computing in CUDA and OpenCL.\r\n\r\nArrayFire offers up to four days of specialized GPU training in CUDA and OpenCL programming. We provide customized on-site training courses for customers that have 3 or more attendees from their organization. We can travel to your location and provide a CUDA or OpenCL training course tailored to meet your application-specific needs. We also offer individual trainings at our Atlanta office. Please <a href=\"mailto:sales@arrayfire.com\">contact us</a> to learn more about our training offerings.\r\n\r\nWe recommend that attendees have a working knowledge of C/C++ in order to gain the most from the training courses. For more information about the content of our training lectures and hands-on practicums, please see the following training course syllabus.\r\n\r\n[/column]\r\n\r\n[column type=\"one-half\" last=\"true\" fade=\"true\" fade_animation=\"in-from-right\" class=\"center-text\"][gap size=\"15%\"][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/02/Professor-AF_Exported-e1395436350363.png\" ][/column]\r\n\r\n[column type=\"one-half\" class=\"center-text\"] [gap size=\"17%\"]\r\n<div>[button type=\"flat\" shape=\"rounded\" size=\"jumbo\" href=\"mailto:sales@arrayfire.com?Subject=Training%20Inquiry\"] Register for Training[/button]</div>\r\n[/column][column type=\"one-half\" last=\"true\"][custom_headline type=\"left\" level=\"h3\"]Included in Course[/custom_headline]\r\n\r\n[icon_list] [icon_list_item type=\"angle-double-right\"]Instruction by an excellent and interesting expert, with hands-on exercises[/icon_list_item] [icon_list_item type=\"angle-double-right\"]Use of a laptop with CUDA and OpenCL capable GPUs and CPUs [/icon_list_item] [icon_list_item type=\"angle-double-right\"]Choice of Linux or Windows operating system[/icon_list_item][icon_list_item type=\"angle-double-right\"]Printed manual of lecture material[/icon_list_item][icon_list_item type=\"angle-double-right\"]Electronic copy of programming exercises[/icon_list_item][/icon_list]\r\n\r\n[/column]\r\n\r\n<span style=\"line-height: 1.5em;\">[gap size=\"5%\"]</span>\r\n\r\n[custom_headline type=\"left\" level=\"h3\"]Training Course Syllabus[/custom_headline] [column type=\"one-half\"] [custom_headline type=\"left\" level=\"h5\"  accent=\"false\"]Day 1, Introduction[/custom_headline] Lectures:\r\nGPU Computing Overview\r\nThe Programming Model\r\nBasic Dataset Mapping Techniques\r\nLibraries, ArrayFire\r\nProfiling Tools\r\n\r\nPractice:\r\nA Simple Kernel\r\nEquivalent ArrayFire Example\r\nUsing Libraries\r\nMonte Carlo Pi Estimation\r\nTiming and ArrayFire\r\nDebugging Code\r\n\r\n[custom_headline type=\"left\" level=\"h5\" accent=\"false\"]Day 3, Multi-GPU[/custom_headline] Lectures:\r\nMulti-GPU Use Cases\r\nMulti-GPUs: Contexts\r\nExisting Libraries\r\nScaling Across Multiple GPUs\r\n\r\nPractice:\r\nOut of Core Problems: Matrix Multiply\r\nTask Level Parallelism: Optimization\r\nArrayFire Multi-GPU[/column]\r\n\r\n[column type=\"one-half\" last=\"true\"] [custom_headline type=\"left\" level=\"h5\" accent=\"false\"]Day 2, Optimization[/custom_headline] Lectures:\r\nArchitecture: Grids, Blocks, and Threads\r\nMemory Model: Global, Shared, and Constant Memory\r\nAdvanced Mapping Techniques\r\nStreams: Asynchronos Launches and Concurrent Execution\r\nArrayFire: Lazy Evaluation and Code Vectorization\r\n\r\nPractice:\r\nMatrix Transpose\r\nOptimization Using Shared Memory\r\nMedian Filter\r\nOptimization Using Constant Memory\r\nStream Example\r\nArrayFire Example: Nearest Neighbor Algorithm\r\n\r\n[custom_headline type=\"left\" level=\"h5\" accent=\"false\"]Day 4, Algorithm Problems[/custom_headline]\r\n\r\nLectures and Practice:\r\nReductions\r\nScan Algorithms\r\nSort\r\nConvolution\r\nCustomer-Specific Problem [/column][/content_band]','Home','','inherit','open','closed','','245-revision-v1','','','2014-05-29 16:06:23','2014-05-29 16:06:23','',245,'http://sandbox.arrayfire.com/245-revision-v1/',0,'revision','',0),(5723,7,'2014-05-29 16:07:38','2014-05-29 16:07:38','[content_band inner_container=\"true\" no_margin=\"true\" border=\"none\" padding_top=\"40px\" padding_bottom=\"40px\"][column type=\"two-fifths\"]\r\n\r\n[custom_headline type=\"left\" level=\"h3\"]If you want faster code, you\'ve come to the right place.[/custom_headline][gap size=\"15%\"][button  type=\"flat\" shape=\"rounded\" href=\"http://www.sandbox.arrayfire.com/docs/installation.htm\" size=\"x-large\" block=\"true\"]Download ArrayFire[/button]\r\n\r\n[gap size=\"10%\"]\r\n\r\n[button  type=\"flat\" block=\"true\" shape=\"rounded\" href=\"http://www.meetme.so/arrayfire\" size=\"x-large\" ]Schedule a consultation[/button]\r\n\r\n[/column][column type=\"three-fifths\" last=\"true\"][gap size=\"7%\"]\r\n<div id=\"wistia_rj2bar3xxp\" class=\"wistia_embed\" style=\"width: 640px; height: 388px;\"></div>\r\n<script src=\"//fast.wistia.com/assets/external/E-v1.js\" charset=\"ISO-8859-1\"></script><script>// <![CDATA[\r\nwistiaEmbed = Wistia.embed(\"rj2bar3xxp\");\r\n// ]]></script>[/column]\r\n<div id=\"arrayfire\"></div>\r\n[/content_band]\r\n\r\n[content_band inner_container=\"true\" no_margin=\"true\" border=\"top\" padding_top=\"40px\" padding_bottom=\"40px\"][column type=\"one-half\"][custom_headline type=\"left\" level=\"h3\"]Faster code[/custom_headline]\r\n\r\nArrayFire is a fast, hardware-neutral software library for GPU computing with an easy-to-use API. Its array-based function set makes GPU programming simple. A few lines of code in ArrayFire can replace dozens of lines of raw GPU code, saving you valuable time and lowering development costs.\r\n\r\n[gap size=\"10%\"][button  type=\"flat\" shape=\"rounded\" href=\"http://www.sandbox.arrayfire.com/docs/installation.htm\" size=\"x-large\" ]Download ArrayFire[/button][/column][column type=\"one-half\" last=\"true\" class=\"center-text\"][gap size=\"5%\"][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/Triumvirate_Exported.png\"][/column] [gap size=\"5%\"]\r\n\r\n[column type=\"one-third\" class=\"center-text\"][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/04/Googlelogo-e1396387097279.png\"][line]Video content analysis is the basis for categorizing videos and enabling search by content. Google used ArrayFire to extract motion features in video, improving performance by substantially accelerating the solution of the L1-regularized least-squares optimization problem.[/column][column type=\"one-third\" class=\"center-text\"][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/04/Koch-Industries-e1396387359637.jpg\"][line]Andrew Shin, Market Risk Manager of Koch Supply &amp; Trading, achieves significant performance increases on option pricing algorithms using ArrayFire software, \"My buddy and I are, at best, novice programmers and we couldn\'t imagine having to figure out how to code all this in CUDA.\"[/column][column type=\"one-third\" last=\"true\" class=\"center-text\"][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/04/nasa-e1396387230473.png\"][line]The main thrust of this research was improving Mars rover image compression via GPUs and genetic algorithms. With ArrayFire software and GPUs, the researchers were able to achieve 5X speedups on the larger data sizes.[/column]\r\n<div id=\"hardware\"></div>\r\n[/content_band]\r\n[content_band inner_container=\"true\" no_margin=\"true\" border=\"top\" padding_top=\"40px\" padding_bottom=\"40px\"]\r\n\r\n[column type=\"one-half\"][gap size=\"15%\"]\r\n\r\n<img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/CUDA-logo.jpg\" alt=\"CUDA logo\" width=\"231\" height=\"140\" />\r\n\r\n<img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/OpenCLLogo_678x452.png\" alt=\"OpenCL\" width=\"326\" height=\"217\" />\r\n\r\n[/column][column type=\"one-half\" last=\"true\"][gap size=\"10%\"]\r\n\r\n[custom_headline type=\"left\" level=\"h3\"] ArrayFire for CUDA and OpenCL[/custom_headline]\r\n\r\nArrayFire supports CUDA-capable NVIDIA GPUs and most OpenCL devices, including AMD GPUs/APUs and Intel Xeon Phi co-processors. It also supports mobile OpenCL devices from ARM, Qualcomm, and others.\r\n\r\nArrayFire is a high-performance software library designed for maximum productivity and speed without the hassle of writing difficult low-level device code. Each of ArrayFire\'s functions has been hand-tuned by our CUDA and OpenCL experts.\r\n\r\n[/column]\r\n<div id=\"mobile\"></div>\r\n[/content_band]\r\n\r\n[content_band inner_container=\"true\" no_margin=\"true\" border=\"top\" padding_top=\"40px\" padding_bottom=\"40px\"]\r\n[column type=\"one-half\"][custom_headline type=\"left\" level=\"h3\"  ]Mobile GPU Computing[/custom_headline]\r\n\r\nMobile GPUs offer accelerated performance. If you would like to use ArrayFire in a mobile application or if you would like to hire our mobile acceleration services, email us at <a href=\"mailto:sales@arrayfire.com\" target=\"_blank\">sales@arrayfire.com</a> and include a description of your application.\r\n\r\nOur clients have achieved between 5X to 30X speed boosts for convolutions and other compute functions on mobile devices. It enables:[icon_list][icon_list_item type=\"angle-double-right\"]Real-time video processing[/icon_list_item][icon_list_item type=\"angle-double-right\"]Better augmented reality [/icon_list_item][icon_list_item type=\"angle-double-right\"]Better computational photograph[/icon_list_item][icon_list_item type=\"angle-double-right\"]Faster data processing[/icon_list_item][/icon_list]\r\n\r\nAll mobile devices have a GPU which can deliver greater compute throughput than the CPU. Why not use the GPU to make your app faster?[/column][column type=\"one-half\" fade=\"true\" last=\"true\" fade_animation=\"in-from-right\" class=\"center-text\"][gap size=\"10%\"][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/02/mobile_Exported1-e1395437261846.png\"][/column]\r\n<div id=\"documentation\"></div>\r\n[/content_band]\r\n\r\n[content_band inner_container=\"true\" no_margin=\"true\" border=\"top\" padding_top=\"40px\" padding_bottom=\"40px\"][column type=\"one-half\"][custom_headline type=\"left\" level=\"h3\"]Documentation[/custom_headline]\r\n\r\nArrayFire for C, C++, and Fortran\r\nOpen the hood—take a look at the beautiful nitty-gritty.\r\n\r\n[icon type=\"angle-double-right\"] <a href=\"http://www.sandbox.arrayfire.com/docs/\" target=\"_blank\">CUDA &amp; OpenCL C/C++</a>\r\n\r\nFunctions\r\nHundreds of functions, hand-tuned and optimized by our engineers.\r\n\r\n[icon type=\"angle-double-right\"] <a title=\"ArrayFire Functions\" href=\"http://www.sandbox.arrayfire.com/docs/modules.htm\">ArrayFire Functions</a>\r\n\r\nUser Forums\r\nEvery post gets a response from ArrayFire engineers.\r\n\r\n[icon type=\"angle-double-right\"] <a href=\"http://forums.accelereyes.com/\" target=\"_blank\">User Forums</a>\r\n\r\n[/column][column class=\"center-text\" type=\"one-half\" last=\"true\" fade=\"true\" fade_animation=\"in-from-right\" ][gap size=\"5%\"][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/gears1.png\"][/column]\r\n<div id=\"benchmarks\"></div>\r\n[/content_band]\r\n\r\n[content_band inner_container=\"true\" no_margin=\"true\" border=\"top\" padding_top=\"40px\" padding_bottom=\"40px\"]\r\n[column type=\"one-half\" fade=\"true\" fade_animation=\"in-from-left\" ][gap size=\"5%\"][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/02/Benchmark-guy-torso-opposite-e1392155948298.png\"][/column]\r\n\r\n[column type=\"one-half\" last=\"true\"][custom_headline type=\"left\" level=\"h3\" ]Benchmarks[/custom_headline]\r\n\r\nAll benchmarks were performed on a NVIDIA Tesla C2050 with an Intel i7-950 processor. The benchmarks compare ArrayFire with several popular CPU-based acceleration libraries, including <a href=\"http://software.intel.com/en-us/articles/intel-mkl/\" target=\"_new\">Intel Math Kernel Library</a>, <a href=\"http://software.intel.com/en-us/articles/intel-ipp/\" target=\"_new\">Intel Integrated Performance Primitives</a>, <a href=\"http://eigen.tuxfamily.org/index.php?title=Main_Page\" target=\"_new\">Eigen</a>, and <a href=\"http://arma.sourceforge.net/\" target=\"_new\">Armadillo</a>.[/column]\r\n\r\n[column type=\"one-fifth\"].[/column][column type=\"three-fifths\"][tab_nav type=\"four-up\"][tab_nav_item title=\"Base\" active=\"true\"][tab_nav_item title=\"Linear Algebra\" active=\"\"][tab_nav_item title=\"Convolution\" active=\"\"][tab_nav_item title=\"Utility\" active=\"\"][/tab_nav][tabs][tab active=\"true\"]<img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/matrix_multiply-1024x730.png\" alt=\"Matrix Multiply\" width=\"491\" height=\"350\" />[line]<img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/matrix_transpose-1024x730.png\" alt=\"Matrix Transpose\" width=\"491\" height=\"350\" />[line]<img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/fft-1024x730.png\" alt=\"FFT\" width=\"491\" height=\"350\" />[/tab][tab]<img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/lu-1024x730.png\" alt=\"LU\" width=\"491\" height=\"350\" />[line]<img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/svd-1024x730.png\" alt=\"SVD\" width=\"491\" height=\"350\" />[line]<img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/solve-1024x730.png\" alt=\"Solve\" width=\"491\" height=\"350\" />[/tab][tab]<img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/convs-1024x730.png\" alt=\"Convs\" width=\"491\" height=\"350\" />[line]<img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/conv-1024x730.png\" alt=\"Conv\" width=\"491\" height=\"350\" />[/tab][tab]<img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/sum-1024x730.png\" alt=\"sum\" width=\"491\" height=\"350\" />[line]<img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/sort-1024x730.png\" alt=\"sort\" width=\"491\" height=\"350\" />[line]<img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/scan-1024x730.png\" alt=\"scan\" width=\"491\" height=\"350\" />[/tab][/tabs][/column][column type=\"one-fifth\" last=\"true\"].[/column]\r\n<div id=\"free\"></div>\r\n[/content_band]\r\n\r\n[content_band inner_container=\"true\" no_margin=\"true\" border=\"top\" padding_top=\"40px\" padding_bottom=\"40px\" ]\r\n\r\n[column type=\"one-half\"].[/column][column type=\"one-fourth\"].[custom_headline type=\"center\"  level=\"h3\" class=\"mtn\"]ArrayFire Free[/custom_headline][/column][column type=\"one-fourth\" last=\"true\"].[/column][column type=\"one-fourth\"  fade=\"true\" fade_animation=\"in-from-left\" ][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/right-leaning-e1391788779101.png\"][/column][column type=\"one-fourth\"]\r\n<table>\r\n<tbody>\r\n<tr>\r\n<td>[custom_headline type=\"center\" level=\"h5\"]Functions[/custom_headline]</td>\r\n</tr>\r\n<tr>\r\n<td>[icon type=\"check-circle\" style=\"color: #8cc540;\"] Basic Operations</td>\r\n</tr>\r\n<tr>\r\n<td>[icon type=\"check-circle\" style=\"color: #8cc540;\"] Arithmetic</td>\r\n</tr>\r\n<tr>\r\n<td>[icon type=\"check-circle\" style=\"color: #8cc540;\"] Signal Processing</td>\r\n</tr>\r\n<tr>\r\n<td>[icon type=\"check-circle\" style=\"color: #8cc540;\"] Image Processing</td>\r\n</tr>\r\n<tr>\r\n<td>[icon type=\"check-circle\" style=\"color: #8cc540;\"] Statistics</td>\r\n</tr>\r\n<tr>\r\n<td>[icon type=\"check-circle\" style=\"color: #8cc540;\"] Visualization</td>\r\n</tr>\r\n</tbody>\r\n</table>\r\n[gap size=\"17%\"][button type=\"flat\" block=\"true\" shape=\"rounded\" size=\"large\"  href=\"http://www.sandbox.arrayfire.com/docs/installation.htm\"]Download ArrayFire[/button] [/column][column type=\"one-fourth\"]\r\n<table>\r\n<tbody>\r\n<tr>\r\n<td>[custom_headline type=\"center\" level=\"h5\"]Hardware[/custom_headline]</td>\r\n</tr>\r\n<tr>\r\n<td>[icon type=\"check-circle\" style=\"color: #8cc540;\"] CUDA</td>\r\n</tr>\r\n<tr>\r\n<td>[icon type=\"check-circle\" style=\"color: #8cc540;\"] OpenCL</td>\r\n</tr>\r\n<tr>\r\n<td>[custom_headline type=\"center\" level=\"h5\"]Languages[/custom_headline]</td>\r\n</tr>\r\n<tr>\r\n<td>[icon type=\"check-circle\" style=\"color: #8cc540;\"] C/C++</td>\r\n</tr>\r\n<tr>\r\n<td>[icon type=\"check-circle\" style=\"color: #8cc540;\"] Fortran</td>\r\n</tr>\r\n<tr>\r\n<td>[custom_headline type=\"center\" level=\"h5\"]Advanced[/custom_headline]</td>\r\n</tr>\r\n<tr>\r\n<td> [icon type=\"check-circle\" style=\"color: #8cc540;\"] GFOR Loop</td>\r\n</tr>\r\n</tbody>\r\n</table>\r\n[/column][column type=\"one-fourth\" last=\"true\"]\r\n<table>\r\n<tbody>\r\n<tr>\r\n<td>[custom_headline type=\"center\" level=\"h5\"]Platforms[/custom_headline]</td>\r\n</tr>\r\n<tr>\r\n<td>[icon type=\"check-circle\" style=\"color: #8cc540;\"] Windows</td>\r\n</tr>\r\n<tr>\r\n<td>[icon type=\"check-circle\" style=\"color: #8cc540;\"] Linux</td>\r\n</tr>\r\n<tr>\r\n<td>[icon type=\"check-circle\" style=\"color: #8cc540;\"] Mac</td>\r\n</tr>\r\n<tr>\r\n<td>[custom_headline type=\"center\" level=\"h5\"]Data Types[/custom_headline]</td>\r\n</tr>\r\n<tr>\r\n<td>[icon type=\"check-circle\" style=\"color: #8cc540;\"] All types</td>\r\n</tr>\r\n<tr>\r\n<td>[custom_headline type=\"center\" level=\"h5\"]Support[/custom_headline]</td>\r\n</tr>\r\n<tr>\r\n<td> [icon type=\"check-circle\" style=\"color: #8cc540;\"] Forums</td>\r\n</tr>\r\n</tbody>\r\n</table>\r\n<div id=\"licensing\"></div>\r\n[/column][gap size=\"8%\"]\r\n\r\n[pricing_table id=\"pricing\" columns=\"3\"][pricing_table_column  featured=\"false\" title=\"ArrayFire Developer\" currency=\"$\" price=\"499 / year\" interval=\"$149 / year (Academic)\"] [icon_list] [icon_list_item type=\"star\" ]Dedicated license [/icon_list_item] [icon_list_item  type=\"times-circle\"] Starts at 2 GPUs or devices [/icon_list_item] [icon_list_item type=\"times-circle\"] Linear algebra [/icon_list_item] [icon_list_item type=\"times-circle\"] Sparse matrices [/icon_list_item][icon_list_item type=\"times-circle\"] Phone support [/icon_list_item][icon_list_item type=\"times-circle\"] Premium support &amp; consulting [/icon_list_item][/icon_list] [button href=\"http://sandbox.arrayfire.com/shop\"] Purchase [/button] [/pricing_table_column] [pricing_table_column featured=\"true\" featured_sub=\"Most Popular\" title=\"ArrayFire Pro\" currency=\"$\" price=\"1,499 / year\" interval=\"$525 / year (Academic)\"] [icon_list] [icon_list_item type=\"star\"] Dedicated license [/icon_list_item] [icon_list_item type=\"star\"] Starts at 2 GPUs or devices [/icon_list_item] [icon_list_item type=\"star\"] Linear algebra [/icon_list_item][icon_list_item type=\"star\"] Sparse matrices [/icon_list_item][icon_list_item type=\"times-circle\"] Phone support [/icon_list_item][icon_list_item type=\"times-circle\"] Premium support &amp; consulting [/icon_list_item] [/icon_list] [button href=\"http://sandbox.arrayfire.com/shop\"]Purchase [/button] [/pricing_table_column] [pricing_table_column featured=\"false\" title=\"ArrayFire Enterprise\" currency=\"$\" price=\"2,999 / year\" interval=\"$1,049 / year (Academic)\"] [icon_list] [icon_list_item type=\"star\"] Dedicated license [/icon_list_item] [icon_list_item type=\"star\"] Starts at 2 GPUs or devices [/icon_list_item] [icon_list_item type=\"star\"] Linear algebra [/icon_list_item][icon_list_item type=\"star\"]Sparse matrices [/icon_list_item][icon_list_item type=\"star\"] Phone support[/icon_list_item][icon_list_item type=\"star\"]Premium support &amp; consulting [/icon_list_item][/icon_list] [button href=\"http://sandbox.arrayfire.com/shop\"] Purchase [/button] [/pricing_table_column] [/pricing_table]\r\n<div id=\"whitepapers\"></div>\r\n[/content_band]\r\n\r\n[content_band inner_container=\"true\" no_margin=\"true\" border=\"top\" padding_top=\"40px\" padding_bottom=\"40px\" ]\r\n\r\n[column type=\"one-half\"][gap size=\"20%\"][image type=\"thumbnail\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/02/wp2.jpg\"][button href=\"http://go.sandbox.arrayfire.com/l/37882/2014-05-29/dw83/37882/18534/arrayfire_matrix_computations_chrzeszczyk.pdf\" shape=\"rounded\" size=\"regular\" block=\"true\"]Download <em>Matrix Computations on the GPU with ArrayFire for C/C++</em>[/button][/column][column type=\"one-half\" last=\"true\"]\r\n\r\n[custom_headline type=\"left\" level=\"h3\" ]Whitepapers[/custom_headline]\r\n\r\n<img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/02/Whitepaper-1.png\" alt=\"Whitepaper 1\" width=\"466\" height=\"374\" />\r\n\r\n&nbsp;\r\n\r\n[/column][gap size=\"10%\"]\r\n\r\n[column type=\"one-half\"]<img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/02/Whitepaper-2.png\" alt=\"Whitepaper 2\" width=\"442\" height=\"304\" />[/column][column type=\"one-half\" last=\"true\"][image type=\"thumbnail\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/02/wp1.jpg\"][button href=\"http://go.sandbox.arrayfire.com/l/37882/2014-05-29/dw81/37882/18532/arrayfire_whitepaper.pdf\" shape=\"rounded\" size=\"regular\"  block=\"true\" float=\"right\"]Download <em>High-level GPU Computing in C, C++, and Fortran</em>[/button][/column]\r\n<div id=\"casestudies\"></div>\r\n[/content_band]\r\n\r\n[content_band inner_container=\"true\" no_margin=\"true\" border=\"top\" padding_top=\"40px\" padding_bottom=\"40px\" ]\r\n\r\n[column type=\"one-half\"][gap size=\"12%\"][custom_headline type=\"left\" level=\"h3\" ]Case Studies[/custom_headline]\r\n\r\nLearn how ArrayFire has worked in real code, including applications in academia, finance, government, life sciences, manufacturing, media, and oil &amp; gas.[/column][column type=\"one-half\" last=\"true\" fade=\"true\" fade_animation=\"in-from right\"][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/02/model-A.png\"][/column][custom_headline type=\"left\" level=\"h5\"]Academia [/custom_headline][accordion][accordion_item title=\"Accelerating LTE Simulation | Tsinghua University\"]\r\n\r\nAuthors: Yuan Gao, Yin Sun, Chun Hui Zhou, Xin Su, Xi Bin Xu, Shi Dong Zhou, Tsinghua University\r\nSpeedup: 3X\r\n\r\nFast simulations are a driving force in several research projects. However, the accompanying long simulation times can tend to be a drag in many of these projects. In this article, we shall bring up the example of the work on 3GPP LTE System Simulation by Yuan Gao et al (from Tsinghua University, Beijing) and demonstrate how the use of ArrayFire software can significantly improve the simulator performance and lead to faster validation times in simulation projects.[/accordion_item]\r\n\r\n[accordion_item title=\"High Performance Compressive Sensing | Rice University\"]\r\n\r\nAuthors: Nabor Reyna and Wotao Yin from Rice University\r\nSpeedup: 5X\r\n\r\nThis work deals with reconstruction of signals using partial Fourier matrices (RecPF). The major computational components of the algorithm involve shrinkage and FFTs. ArrayFire software is employed to accelerate this compute-heavy code.[/accordion_item]\r\n\r\n[accordion_item title=\"Power System Simulations | Indian Institute of Technology, Roorkee, India\"]\r\nAuthors: Indian Institute of Technology, Roorkee\r\nSpeedup: 35X\r\n\r\nPower flow studies are one of the most important aspects of power system planning and operation. The power flow reveals the sinusoidal steady state characteristics of the entire system - voltages, real and reactive power generated, and absorbed and line losses- elucidating the voltage magnitudes and angles at each bus, the generation of each generating unit, and real and reactive power losses in the system. All this is necessary to ensure the security, economy, and control of electrical energy distribution. Learn how ArrayFire software can deliver magnitudes of performance improvement over CPU-based solutions.[/accordion_item]\r\n\r\n[accordion_item title=\"Antenna Array Simulations | University of Naples Federico II\"]\r\n\r\nAuthors: A. Capozzoli, C. Cucio, A. Liseno at University of Naples Federico II\r\nSpeedup: 24X\r\n\r\nAntenna array design involves repeated simulation to tune the many parameters involved, and waiting around for simulations to finish is no fun. Offloading the optimization problem onto the GPU cuts that time down significantly. In their recent paper, Capozzoli, Curcio, and Liseno of University of Naples Federico II demonstrated how a simple modification to their echo generator array simulation took advantage of the GPU to bring immediate speedups.[/accordion_item]\r\n\r\n[accordion_item title=\"Laplace Transform Inversion | Acunum Algorithms and Simulations\"]\r\n\r\nAuthors: Patrick Kano and Moysey Brio at Acunum Algorithms and Simulations\r\nSpeedup: 3.8X\r\n\r\nThe numerical inversion of the Laplace transform is a long standing problem due its implicit ill-posedness. Patrick Kano and Moysey Brio of Acunum Algorithms and Simulations, with their experience in computational methods and algorithm development, found a solution that not only works, but is very fast.[/accordion_item]\r\n\r\n[accordion_item title=\"Compressed Sensing for Image Reconstruction | College of Engineering, Roorkee, India\"]\r\n\r\nAuthors: Kuldeep Yadav, Ankush Mittal, M. A. Ansar, and Avi Srivastava, College of Engineering, Roorkee, India\r\nSpeedup: 8X\r\n\r\nCompressed sensing is very critical in the areas of medical image reconstruction, image acquisition or sensor networks. An algorithm for compressed sensing developed using a Basis Pursuit Algorithm shows over 8X speedup when run on an NVIDIA GPU.[/accordion_item]\r\n\r\n[accordion_item title=\"Fat/Water Reconstruction for Medical Images | Case Western Reserve University\"]\r\n\r\nAuthors: D. H. Johnson, S. Narayan, C. A. Flask, and D. L. Wilson, Case Western Reserve University\r\nSpeedup: 11.6X\r\n\r\nCase Western Reserve University researchers turned to GPUs running ArrayFire software to develop a fast and robust version of the \"Iterative Decomposition of water and fat with an Echo Asymmetry and Least-squares\" (IDEAL) reconstruction algorithm. This algorithm uses a lot of Image Processing algorithms for reconstruction, and was shown to achieve very high speedups.\r\n[/accordion_item]\r\n\r\n[/accordion]\r\n<h5>Finance</h5>\r\n[accordion][accordion_item title=\"Option Pricing | Koch Supply and Trading\"]\r\n\r\nAuthors: Koch Supply &amp; Trading\r\nSpeedup: 51.8X\r\n\r\nAndrew Shin, Market Risk Manager of Koch Supply &amp; Trading, achieves significant performance increases on option pricing algorithms using ArrayFire software to accelerate his code with GPUs. Andrew says, \"My buddy and I are, at best, novice programmers and we couldn\'t imagine having to figure out how to code all this in CUDA.\" But he found ArrayFire software to be straight-forward. With these results, he says he can see ArrayFire software and GPUs populating Koch\'s mark-to-futures cube, which contains its assets, simulations, and simulated asset prices.[/accordion_item]\r\n\r\n[accordion_item title=\"GPU Computing in Automated Trader | Automated Trader\"]\r\n\r\nAuthors: Automated Trader\r\nSpeedup: 37.5X\r\n\r\nThe Q1 2012 issue of Automated Trader contains an excellent Mashup piece reviewing software for algorithmic trading. The article provides a wonderful glimpse into the 1-2 month adventure of Andy Webb, Automated Trader.s Founder, and Wrecking Crew building a fast trading platform from several technologies. The full trading platform they built was quite extensive. The part that caught our eye was the core computational component of the pipeline. That component involved permuting 1,000 potential pairs with cointegration tests for 350 time windows on each potential pair.\r\n[/accordion_item]\r\n[accordion_item title=\"GPUs in Quantitative Analytics and Finance | Private Bank\"]\r\n\r\nThe world of Quantitative finance is all about getting accurate results really, really fast. ArrayFire is working with one of the largest banks in Spain to maximize their output using GPUs. Click the link below for an overview of the uses of GPU computing in finance.[/accordion_item][/accordion]\r\n<h5>Government</h5>\r\n[accordion][accordion_item title=\"Powering Mars Research | NASA and UAA in Anchorage\" ]\r\n\r\nAuthors: NASA and UAA in Anchorage\r\nSpeedup: 5X\r\n\r\nThe main thrust of this research is improving mars rover image compression via GPUs and genetic algorithms. With ArrayFire software and GPUs, the researchers were able to achieve 5X speedups on the larger data sizes. The algorithm works by pairing neighboring pixels with a random one and then adjusting the random pixel based on whether it incrementally improves the original image. Babb described the algorithm as an embarrassingly parallel process, ideally suited to GPU acceleration. He estimates he has been able to achieve a 20 to 30 percent error reduction in subjects like fingerprints and satellite imagery.[/accordion_item]\r\n\r\n[accordion_item title=\"Radar Image Formation | System Planning Corporation\"]\r\n\r\nAuthors: Gary Rubin and Earl Sager - System Planning Corporation\r\nSpeedup: ~45X\r\n\r\nRadar imaging is computationally intensive. As a result, many imaging algorithms apply FFT-based approximations. While efficient, these algorithms sacrifice data fidelity for speed. Other algorithms better preserve information, but are often too slow for many applications. At System Planning Corporation (SPC) , we have implemented a SAR/ISAR imaging routine based on the Backprojection algorithm. Using ArrayFire software, we have demonstrated speedups of roughly 45x for large datasets.[/accordion_item]\r\n\r\n[accordion_item title=\"Radar Clutter Reduction | System Planning Corporation\"]\r\n\r\nAuthors: David Berger and Gary Rubin - System Planning Corporation\r\nSpeedup: 5-10X\r\n\r\nSystem Planning Corporation (SPC) uses ArrayFire software to accelerate radar processing algorithms. The system processes raw data from marine navigation radars using a variety of thresholding techniques to extract real targets from clutter. This involves highly data-parallel processing in which each radar pulse is subjected to the same computations; very few operations occur across multiple pulses. Using ArrayFire software, SPC has achieved 10x speed improvements relative to a Core i7-920 CPU and 5x improvements relative to a realtime DSP implementation.[/accordion_item]\r\n\r\n[accordion_item title=\"Novel Algorithms for Linear Algebra | SAIC\" ]\r\n\r\nAuthors: Nolan Davis and Daniel Redig, SAIC\r\nSpeedup: 3.5X\r\n\r\nNolan Davis and Daniel Redig at SAIC recently presented work on Hybrid GPU/Multicore Solutions for Large Linear Algebra Problems where they developed a novel algorithm for LU decomposition, one of the most important routines in linear algebra. They presented a Hybrid CPU/GPU computing approach, where problems too large to fit in GPU memory can also be solved faster than using only the CPU.\r\n[/accordion_item]\r\n[accordion_item title=\"Geolocation | BAE Systems\"]\r\n\r\nAuthors: BAE Systems\r\nSpeedup: 17X\r\n\r\nGeolocation is the identification of the real-world geographic location of a target of interest. In this application, the system receives the signal with an array of several antennas and computes the direction of arrival of the radio energy by measuring the time difference of arrival (or the phase difference) at the different antennas.\r\n[/accordion_item]\r\n[accordion_item title=\"Tsunami Modeling | University of Minnesota, Boise State, Saint Scholastica, and NCAR\"]\r\n\r\nAuthors: University of Minnesota, Boise State, Saint Scholastica, and NCAR\r\nSpeedup: 3-5X\r\n\r\nNatural catastrophic disasters like tsunamis commonly strike with little warning. For most people, tsunamis are underrated as major hazards. People sometimes wrongly believe that they occur infrequently and only along distant coasts. Tsunamis are usually caused by earthquakes. Seismic signals can give some margin of warning since the speed of tsunami waves travels at 1/30 the speed of seismic waves. Still there is little time between the creation of the tsunami and its impact making fast processing critical to producing effective warning systems. ArrayFire software was used to run an RBF simulation on the GPU with a time to solution not available by other alternatives.\r\n[/accordion_item][/accordion]\r\n<h5>Life Sciences</h5>\r\n[accordion][accordion_item title=\"Parallelized Gene Predictors | University of Quebec\" ]\r\n\r\nAuthors: University of Quebec\r\nSpeedup: 43X\r\n\r\nComputerized approaches to studying the human genome are challenged by the exploding amount of data, which doubles roughly every 6 months. In order to deal with this burgeoning datasets, demands for faster processing power continue to arise. This work focuses on predicting genes using frequency analysis with FFTs and with an equivalent technique known as Goertzel\'s algorithm. In these applications, the emphasis of this paper is to propose tools to geneticists and molecular biologists for the prediction or identification of new genes using existing complementary strategies. The criteria for these tools are speed, reliability, accuracy and ease of use, thus requiring little training.\r\n[/accordion_item]\r\n[accordion_item title=\"Pathology Advances with GPUs | Northeastern University\" ]\r\n\r\nAuthors: Laboratory for Spectral Diagnosis at Northeastern University\r\nSpeedup: 100X+\r\n\r\nOne element of the hyperspectral image analysis workflow that requires more than a traditional desktop workstation or personal computer is Hierarchical Cluster analysis (HCA). HCA requires a large amount of data space and substantial computation time (~11 hours) for typical datasets using a single processor personal computer. Rather than following the traditional approach of moving to a lower level programming language like C or C++ and complex parallel programming paradigms such as OpenMP or the Massage Passing Interface (MPI), the lab utilized graphics processing units, or GPUs, and the ArrayFire software platform. The solution allowed the lab to dramatically increase the performance of the analysis while substantially decreasing the amount of calendar time to reach the desired results.\r\n[/accordion_item]\r\n[accordion_item title=\"Hepatitis C Virus - Mutation Modeling | Centers for Disease Control and Prevention\" ]\r\n\r\nAuthors: CDC Research and Development Team\r\nSpeedup: ~20X\r\n\r\nThis case study provides a look at biological research regarding coordinated mutations of the Hepatitis C Virus (HCV). ArrayFire provided collaborative R&amp;D resources and greatly improved the speed of this HCV research with the use of parallelization, reducing the computing time from 40 days to less than 1 day. Most importantly, the conclusion of the case study illustrates the the relative price-performance of personal supercomputers that leverage GPUs and ArrayFire software provides a compelling solution versus other architectures and approaches.\r\n[/accordion_item]\r\n[accordion_item title=\"Accelerating the SPM Package for Neuroimaging | Georgia Institute of Technology\" ]\r\n\r\nAuthors: Georgia Institute of Technology\r\nSpeedup: 3.5X\r\n\r\nThe Georgia Tech team explores the value of ArrayFire software and GPUs for fMRI workflows within the popular SPM - Statistical Parametric Mapping software widely used in neuroscience research.\r\n[/accordion_item]\r\n[accordion_item title=\"Medical Image Compression | Indian Institute of Technology, Roorkee, India\" ]\r\n\r\nAuthors: Jaideep Singh, Ipseeta Aruni, R. Balasubramanian - IIT - Roorkee, India\r\nSpeedup: 38X\r\n\r\nThis study presents the acceleration of Haar wavelet-based image compression algorithm for medical imaging on the Graphics Processing Unit (GPU) using ArrayFire software. Due to bandwidth and image size constraints of medical imaging systems, image compression plays a vital role in reducing the bit rate of transmission or storage. Wavelet-based image compression provides the most promising approach for high quality image compression.\r\n[/accordion_item]\r\n[accordion_item title=\"Brain Displacement | Spencer Technologies\"]\r\n\r\nAuthors: Spencer Technologies\r\nSpeedup: 12X\r\n\r\nSpencer describes how ArrayFire software facilitates the development of fast algorithms enabling observation of brain displacement across depth with sampling density that far surpasses previous benchmarks.\r\n[/accordion_item]\r\n[accordion_item title=\"Multidimensional Scaling for Genomics | Leibniz Institute of Plant Genetics and Crop Plant Research\" ]\r\n\r\nAuthors: Leibniz Institute of Plant Genetics and Crop Plant Research\r\nSpeedup: 20-35X\r\n\r\nMultidimensional scaling (MDS) is a general computing technique to turn a distance matrix into a set of reconstructed points with pair-wise relationships approximating the original distances by points located in a usually low-dimensional space. ArrayFire software is used to enhance execution of the HiT-MDS procedure and delivers considerable performance improvement.\r\n[/accordion_item]\r\n[accordion_item title=\"Drug Delivery Model | Georgia Institute of Technology\"]\r\n\r\nAuthors: Georgia Institute of Technology\r\nSpeedup: 70X\r\n\r\nIn this work, the researchers simulate the delivery of a novel nanoparticle chemotherapy drug to cancerous tissue. Simulation allows scientists to predict experimental outcomes and thus reduce the cost of development and time to clinical relevance. The simulation model includes blood vessels, tumor cells, and healthy cells and an engine to calculate the spatial distributions of both drug and oxygen. ArrayFire software is used to speed up the diffusion calculations for the drug and oxygen within the tissue.\r\n[/accordion_item]\r\n[accordion_item title=\"Biomedical Infrared Spectroscopy | University of Manchester and Nofima Mat, Norway\" ]\r\n\r\nAuthors: University of Manchester and Nofima Mat, Norway\r\nSpeedup: Hours of runtime reduction\r\n\r\nThe authors present an iterative algorithm that applies full Mie scattering theory and avoids noise accumulation in their iterative algorithm by integrating a curve-fitting step. ArrayFire software along with NVIDIA GPUs are leveraged to reduce the time added by the curve-fitting step.\r\n[/accordion_item][/accordion]\r\n<h5>Manufacturing</h5>\r\n[accordion][accordion_item title=\"Feature Learning on Images | Stanford\" ]\r\n\r\nAuthors: Andrew Ng, Stanford University\r\nSpeedup: Ability to process many images in parallel\r\n\r\nStanford researchers in Andrew Ng\'s group used GPUs and ArrayFire software to speed up their work on Feature Learning Architectures. They decided to use ArrayFire software for this study because of the need to quickly evaluate many architectures on thousands of images. ArrayFire software taps into the immense computing power of GPUs and speeds up research utilizing many images.\r\n[/accordion_item]\r\n[accordion_item title=\"Tomography of Vegetation - Filtered Back-Projection and Non-Uniform FFTs | Universita di Napoli Federico II\" ]\r\n\r\nAuthors: Drs. Capozzoli, Curcio, di Vico, and Liseno, Universita di Napoli Federico II\r\nSpeedup: 10X\r\n\r\nIn order to investigate changes of forest biomass, scientists use microwave tomography to image the vegetation. At the smallest scale, individual plants can be imaged to investigate branching and growth, but even synthetic aperture radar can reveal large-scale changes in regional ecology. To the right, you can see the experimental setup to image an individual plant.\r\n[/accordion_item]\r\n[accordion_item title=\"Action Recognition with Independent Subspace Analysis | Stanford University\" ]\r\n\r\nAuthors: Quoc Le, Will Zou, Serena Yeung, Andrew Ng, Stanford University\r\nSpeedup: 4.4X\r\n\r\nIn a paper at this year\'s CVPR 2011, entitled \"Learning hierarchical invariant spatio-temporal features for action recognition with independent subspace analysis\", the authors explain how their unsupervised feature learning algorithm competes with other algorithms that are hand crafted or use learned features. For their training purposes, they used a multi-layered stacked convolutional ISA (Independent subspace analysis) network. An ISA is used for learning features from image patches without supervision.\r\n[/accordion_item][/accordion]\r\n<h5>Media and Computer Vision</h5>\r\n[accordion][accordion_item title=\"Fast Computer Vision with OpenCV and ArrayFire | OpenCV Blogger\" ]\r\n\r\nAuthors: OpenCV Blogger\r\nSpeedup: ~10X\r\n\r\nThe OpenCV library is the defacto standard for doing computer vision and image processing research projects. OpenCV includes several hundreds of computer vision algorithms, aimed for use in realtime vision applications. This case study shows how to use both libraries together. There is a simple example application that demonstrates using OpenCV for webcam access and ArrayFire for some basic processing routines and displaying results.\r\n[/accordion_item]\r\n[accordion_item title=\"Video Processing | Google\" ]\r\n\r\nAuthors: Google and Stanford\r\nSpeedup: 10-20X\r\n\r\nVideo content analysis is the basis for categorizing videos and enabling search by content. Growing interest in using sparse-coding methods to extract motion features in video in support of video content analysis led to the application of ArrayFire software to improve performance by substantially accelerating the solution of the L1-regularized least-squares optimization problem.\r\n[/accordion_item]\r\n[accordion_item title=\"Action Recognition with Independent Subspace Analysis | Stanford University\"]\r\n\r\nAuthors: Quoc Le, Will Zou, Serena Yeung, Andrew Ng, Stanford University\r\nSpeedup: 4.4X\r\n\r\nIn a paper at this year\'s CVPR 2011, entitled \"Learning hierarchical invariant spatio-temporal features for action recognition with independent subspace analysis\", the authors explain how their unsupervised feature learning algorithm competes with other algorithms that are hand crafted or use learned features. For their training purposes, they used a multi-layered stacked convolutional ISA (Independent subspace analysis) network. An ISA is used for learning features from image patches without supervision.\r\n[/accordion_item]\r\n[accordion_item title=\"Music Beat Analysis | Georgia Tech\"]\r\n\r\nAuthors: Vidhur Vohra - Georgia Tech\r\nSpeedup: 15X\r\n\r\nDid you ever wonder how the music visualizer in your media player works? Watching it pulsate in synchrony with the beats of the song is almost as entertaining as listening to the song itself! Researchers have been attempting to detect beats in audio signals for many years, and there are many techniques available, from the simplest (and least accurate) to more complicated algorithms that are highly accurate. All algorithms, though, perform some form of signal processing and frequency analysis, applications highly suited to GPU Computing.\r\n[/accordion_item]\r\n[accordion_item title=\"Optimization Methods for Deep Learning | Stanford Artificial Intelligence Laboratory\" ]\r\n\r\nAuthors: Stanford Artificial Intelligence Laboratory\r\nSpeedup: Improved accuracy\r\n\r\nResearchers at SAIL (Stanford Artificial Intelligence Laboratory), have done it again. They have successfully used ArrayFire software to speed up the training part of Deep Learning algorithms. In their paper titled .On Optimization Methods for Deep Learning., they experiment with some of the well known training algorithms and demostrate their scalability across parallel architectures (GPUs as well as multi-machine networks). The algorithms include SGDs (Stochastic Gradient Descent) L-BFGS (Limited BFGS used for solving non-linear problems), CG (Conjugate Gradient).\r\n[/accordion_item]\r\n[accordion_item title=\"Feature Learning on Images | Stanford University\" ]\r\n\r\nAuthors: Andrew Ng, Stanford University\r\nSpeedup: Ability to process many images in parallel\r\n\r\nStanford researchers in Andrew Ng’s group used ArrayFire software to speed up their work on Feature Learning Architectures. They decided to use ArrayFire software for this study because of the need to quickly evaluate many architectures on thousands of images. ArrayFire software taps into the immense computing power of GPUs and speeds up research utilizing many images.\r\n[/accordion_item]\r\n[accordion_item title=\"Digital Holography for Imaging | National University of Ireland, Maynooth\" ]\r\n\r\nAuthors: Nitesh Pandey, Damien Kelly, Bryan Hennelly and Thomas Naughton from the National University of Ireland, Maynooth\r\nSpeedup: 17X\r\n\r\nDigital holography is a powerful imaging technique with many new applications like true 3D display. It allows the capture of both amplitude and phase information of the light reflected off the surface of 3D objects. Researchers at the National University of Ireland, Maynooth are developing techniques based on digital holography for 3D display applications.\r\nReconstruction of large digital holograms can be computationally intensive to generate on CPUs, but GPUs running ArrayFire software offer amazing possibilities.\r\n[/accordion_item][/accordion]\r\n<h5>Oil and Gas</h5>\r\n[accordion][accordion_item title=\"3D Mantle Convection - Geodynamics | Boise State, University of Colorado, University of Minnesota\" ]\r\n\r\nAuthors: Boise State, University of Colorado, University of Minnesota\r\nSpeedup: 2.5-4.5X\r\n\r\nThe authors introduce a GPU implementation of a three-dimensional mantle convection modeling at a high Rayleigh number to the solid earth geophysics community. They outline code development time, compare performance of CPUs versus GPUs, and deliver powerful visualizations.\r\n[/accordion_item]\r\n[accordion_item title=\"Ground Water Simulations | Louisiana State University\" ]\r\n\r\nAuthors: Kevin R. Tubbs and Frank T-C. Tsai at Louisiana State University\r\nSpeedup: &gt;20X\r\n\r\nA lattice Boltzmann method for solving the shallow water equations and the advection-dispersion equation is developed and implemented on graphics processing unit (GPU)-based architectures. The proposed LBM is implemented to an NVIDIA Computing Processor in a single GPU workstation. GPU computing is performed using ArrayFire software. Mass transport with velocity-dependent dispersion in shallow water flow is simulated by combining the MRT-LBM model and the TRT-LBM model. The GPU parallel performance increases as the grid size increases. The results indicate the promise of the GPU-accelerated LBM for modeling mass transport phenomena in shallow water flows.\r\n[/accordion_item]\r\n[accordion_item title=\"Shallow Water Fluid Flow | Louisiana State University\" ]\r\n\r\nAuthors: Louisiana State University\r\nSpeedup: &gt;10X\r\n\r\nA lattice Boltzmann method (LBM) on high performance computing (HPC) environments for three-dimensional shallow water flow fields coupled to mass transport is developed. LBM is an attractive method for solving the multilayered shallow water equations because the extension to multilayer is straight forward with all of the simplicities and advantages of the LBM in mass transport in shallow water flows and the LBM performance on central processing unit (CPU)-based and graphics processing unit (GPU)-based HPC environments.\r\n[/accordion_item][/accordion]\r\n<div id=\"consulting\"></div>\r\n[/content_band]\r\n<div id=\"services\"></div>\r\n[content_band inner_container=\"true\" no_margin=\"true\" border=\"top\" padding_top=\"40px\" padding_bottom=\"40px\"][column type=\"one-half\"][custom_headline type=\"left\" level=\"h3\"]Hire our acceleration gang[/custom_headline]\r\n\r\nHire us to accelerate your code. Or to train your pros. Or even to write new code for your organization!\r\n\r\nWe’ve already helped thousands of organizations speedup their code. We’ve accelerated algorithms, data sets, and challenging problems of all types in the past, and we’re confident that we can accelerate your code too.\r\n\r\n[gap size=\"10%\"][button  type=\"flat\" shape=\"rounded\" href=\"http://meetme.so/arrayfire\" size=\"x-large\" ]Schedule a consultation[/button][/column][column type=\"one-half\" last=\"true\" class=\"center-text\"][gap size=\"5%\"][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/Bat-signal-e1391790016951.png\"][/column] [gap size=\"7%\"]\r\n\r\n[column type=\"one-third\" class=\"center-text\"][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/04/LFG-B-HORZ_202_K-e1396448935778.jpg\"][line]Lincoln Financial Group ported their CPU code (C/C++) to CUDA, and this enabled them to speed up the necessary financial calculations. Their primary objective was to reduce the time taken to run this code. Before porting to CUDA, they required 10-12 hours to run the entire code. After porting to CUDA, they were able to do the same work in about 30 minutes.[/column][column type=\"one-third\" class=\"center-text\"][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/02/reveal_logo-e1396449044651.jpg\"][line]Reveal Imaging, an SAIC company, uses ArrayFire in developing threat-detection products for transportation systems—such as cargo and baggage screening in airports—and in securing facilities and public events.[/column][column type=\"one-third\" last=\"true\" class=\"center-text\"][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/04/1800contactlogo.png\"][line]The Glasses.com app relies on computer vision to recognize the features of a user’s face. The application then generates an accurate, high-fidelity, three-dimensional model of that face, and virtually places selected frames on the image.[/column]\r\n<div id=\"starterpackage\"></div>\r\n[/content_band]\r\n\r\n[content_band inner_container=\"true\" no_margin=\"true\" border=\"top\" padding_top=\"40px\" padding_bottom=\"40px\"]\r\n\r\n[column type=\"one-half\" last=\"false\" fade=\"true\" fade_animation=\"in-from-left\" ][gap size=\"10%\"][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/comingatyou.png\"][/column][column type=\"one-half\" last=\"true\"] [custom_headline type=\"left\" level=\"h3\"]Starter Package ($500)* [/custom_headline] Hire us for 1-day. We set you up with one engineer dedicated for a full day, as well as support from senior and test engineers throughout the day. Here\'s how it works:\r\n\r\n[icon_list] [icon_list_item type=\"angle-double-right\"]Initial phone call[/icon_list_item] [icon_list_item type=\"angle-double-right\"]You send us your code or algorithm [/icon_list_item] [icon_list_item type=\"angle-double-right\"]We analyze your code for potential GPU benefit[/icon_list_item][icon_list_item type=\"angle-double-right\"]We accelerate as much of the code as is possible within the 1-day effort, applying our extensive GPU software libraries[/icon_list_item][icon_list_item type=\"angle-double-right\"]We produce a final report, along with code[/icon_list_item] [/icon_list] The final report outlines the best approach to follow for full GPU-acceleration of your code.\r\n\r\n&nbsp;\r\n\r\n[button type=\"flat\" shape=\"rounded\" size=\"regular\" href=\"http://sandbox.arrayfire.com/product/consulting-starter-package/\" title=\"Starter Package\"]Buy the Starter Package[/button]\r\n\r\n&nbsp;\r\n\r\n*Limit one (1) per customer.\r\n\r\n[/column]\r\n<div id=\"customcode\"></div>\r\n[/content_band] [content_band inner_container=\"true\" no_margin=\"true\" border=\"top\" padding_top=\"40px\" padding_bottom=\"40px\" ]\r\n\r\n[column type=\"one-half\"][custom_headline type=\"left\" level=\"h3\" ]Custom Coding Work[/custom_headline]\r\n\r\n[custom_headline type=\"left\" level=\"h6\" ]Why Choose Us?[/custom_headline] [icon_list] [icon_list_item type=\"angle-double-right\"]Deep experience, already servicing thousands of customers[/icon_list_item] [icon_list_item type=\"angle-double-right\"]Quality work, with leading GPU software [/icon_list_item] [icon_list_item type=\"angle-double-right\"]Efficient delivery, with ArrayFire\'s code base we can deliver results fast[/icon_list_item][icon_list_item type=\"angle-double-right\"]Proven, we make customers happy through faster code[/icon_list_item][/icon_list] [custom_headline type=\"left\" level=\"h6\" ]Our Strengths[/custom_headline] [icon_list] [icon_list_item type=\"angle-double-right\"]Excellence in GPU code[/icon_list_item] [icon_list_item type=\"angle-double-right\"]Well-written, efficient C, C++, Fortran, Java, or .NET [/icon_list_item] [icon_list_item type=\"angle-double-right\"]Application porting and integration[/icon_list_item][icon_list_item type=\"angle-double-right\"]Tuning software to peak hardware performance[/icon_list_item][icon_list_item type=\"angle-double-right\"]Scalability of algorithms to handle enterprise-level programs[/icon_list_item] [/icon_list][button type=\"flat\" shape=\"rounded\" size=\"regular\" href=\"http://meetme.so/arrayfire\" title=\"Tech Consultation\"]Schedule a consultation[/button] [/column][column type=\"one-half\"  fade=\"true\" fade_animation=\"in-from-right\" last=\"true\" ][gap size=\"25%\"][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/02/Holoham.png\"][/column]\r\n<div id=\"training\"></div>\r\n[/content_band] [content_band inner_container=\"true\" no_margin=\"true\" border=\"top\" padding_top=\"40px\" padding_bottom=\"40px\" ]\r\n\r\n[column type=\"one-half\"][custom_headline type=\"left\" level=\"h3\" ]Training[/custom_headline] Attendees will receive the latest industry knowledge and techniques for GPU computing in CUDA and OpenCL.\r\n\r\nArrayFire offers up to four days of specialized GPU training in CUDA and OpenCL programming. We provide customized on-site training courses for customers that have 3 or more attendees from their organization. We can travel to your location and provide a CUDA or OpenCL training course tailored to meet your application-specific needs. We also offer individual trainings at our Atlanta office. Please <a href=\"mailto:sales@arrayfire.com\">contact us</a> to learn more about our training offerings.\r\n\r\nWe recommend that attendees have a working knowledge of C/C++ in order to gain the most from the training courses. For more information about the content of our training lectures and hands-on practicums, please see the following training course syllabus.\r\n\r\n[/column]\r\n\r\n[column type=\"one-half\" last=\"true\" fade=\"true\" fade_animation=\"in-from-right\" class=\"center-text\"][gap size=\"15%\"][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/02/Professor-AF_Exported-e1395436350363.png\" ][/column]\r\n\r\n[column type=\"one-half\" class=\"center-text\"] [gap size=\"17%\"]\r\n<div>[button type=\"flat\" shape=\"rounded\" size=\"jumbo\" href=\"mailto:sales@arrayfire.com?Subject=Training%20Inquiry\"] Register for Training[/button]</div>\r\n[/column][column type=\"one-half\" last=\"true\"][custom_headline type=\"left\" level=\"h3\"]Included in Course[/custom_headline]\r\n\r\n[icon_list] [icon_list_item type=\"angle-double-right\"]Instruction by an excellent and interesting expert, with hands-on exercises[/icon_list_item] [icon_list_item type=\"angle-double-right\"]Use of a laptop with CUDA and OpenCL capable GPUs and CPUs [/icon_list_item] [icon_list_item type=\"angle-double-right\"]Choice of Linux or Windows operating system[/icon_list_item][icon_list_item type=\"angle-double-right\"]Printed manual of lecture material[/icon_list_item][icon_list_item type=\"angle-double-right\"]Electronic copy of programming exercises[/icon_list_item][/icon_list]\r\n\r\n[/column]\r\n\r\n<span style=\"line-height: 1.5em;\">[gap size=\"5%\"]</span>\r\n\r\n[custom_headline type=\"left\" level=\"h3\"]Training Course Syllabus[/custom_headline] [column type=\"one-half\"] [custom_headline type=\"left\" level=\"h5\"  accent=\"false\"]Day 1, Introduction[/custom_headline] Lectures:\r\nGPU Computing Overview\r\nThe Programming Model\r\nBasic Dataset Mapping Techniques\r\nLibraries, ArrayFire\r\nProfiling Tools\r\n\r\nPractice:\r\nA Simple Kernel\r\nEquivalent ArrayFire Example\r\nUsing Libraries\r\nMonte Carlo Pi Estimation\r\nTiming and ArrayFire\r\nDebugging Code\r\n\r\n[custom_headline type=\"left\" level=\"h5\" accent=\"false\"]Day 3, Multi-GPU[/custom_headline] Lectures:\r\nMulti-GPU Use Cases\r\nMulti-GPUs: Contexts\r\nExisting Libraries\r\nScaling Across Multiple GPUs\r\n\r\nPractice:\r\nOut of Core Problems: Matrix Multiply\r\nTask Level Parallelism: Optimization\r\nArrayFire Multi-GPU[/column]\r\n\r\n[column type=\"one-half\" last=\"true\"] [custom_headline type=\"left\" level=\"h5\" accent=\"false\"]Day 2, Optimization[/custom_headline] Lectures:\r\nArchitecture: Grids, Blocks, and Threads\r\nMemory Model: Global, Shared, and Constant Memory\r\nAdvanced Mapping Techniques\r\nStreams: Asynchronos Launches and Concurrent Execution\r\nArrayFire: Lazy Evaluation and Code Vectorization\r\n\r\nPractice:\r\nMatrix Transpose\r\nOptimization Using Shared Memory\r\nMedian Filter\r\nOptimization Using Constant Memory\r\nStream Example\r\nArrayFire Example: Nearest Neighbor Algorithm\r\n\r\n[custom_headline type=\"left\" level=\"h5\" accent=\"false\"]Day 4, Algorithm Problems[/custom_headline]\r\n\r\nLectures and Practice:\r\nReductions\r\nScan Algorithms\r\nSort\r\nConvolution\r\nCustomer-Specific Problem [/column][/content_band]','Home','','inherit','open','closed','','245-revision-v1','','','2014-05-29 16:07:38','2014-05-29 16:07:38','',245,'http://sandbox.arrayfire.com/245-revision-v1/',0,'revision','',0),(5724,17795,'2014-05-29 18:09:06','2014-05-29 18:09:06','In the upcoming months we will be adding a lot of new Computer Vision functionality to ArrayFire. This means dozens of new functions specifically targeted for the most commonly used applications in this field, like feature tracking, object classification, scene segmentation, optical flow, stereo-vision, among others, will be added to take full advantage of <abbr title=\"Graphics Processing Unit\">GPU</abbr> devices.\r\n\r\nFeature tracking consists of three basic steps:\r\n<ol>\r\n	<li>Detecting good or unique features, normally they are corners or blobs of an object</li>\r\n	<li>Extracting a descriptor for each feature, understanding the texture of a small patch around each feature</li>\r\n	<li>Descriptor matching, finding out the best match for each pair of descriptors (one from the object being tracked, another from a scene that potentially contains that object), if any.</li>\r\n</ol>\r\n<h3>Harris corner detector</h3>\r\nIn this article we will be using ArrayFire to dive deeper into the first step of feature tracking: detecting good features. Through a step-by-step guide, we will develop a simple corner detector, known as the Harris corner detector [1].\r\n\r\nThe Harris corner detector is very simple to implement, especially when you have so many good tools and libraries out there to do the core matrix manipulation. What we specifically need for Harris are some convolutions, together with a few element-wise matrix addition and multiplication operations, all of these operations are present in most scientific tools and libraries that work with matrix manipulation. I will try to avoid going into the mathematical details in this post and go directly to the implementation.\r\n<h5>Loading an image</h5>\r\nBefore starting writing the code for the corner detector, we need to load an image. The image can be either color or gray-scale, but it will only work on the gray-scale version, so if it is a color image, we have to convert it before proceeding.\r\n<pre>// Load a color image\r\narray img_color = loadimage(\"lena.jpg\", true);\r\n// Convert the image from RGB to gray-scale\r\narray img_gray = colorspace(img_color, af_gray, af_rgb);\r\n// For visualization in ArrayFire, color images must be in the [0.0f-1.0f] interval\r\nimg_color /= 255.f;\r\n</pre>\r\n<h5>Compute first-order derivatives</h5>\r\nThe first step in the Harris corner detector is to determine first order derivatives of an image, in both horizontal and vertical directions. This can be achieved by one convolution for each direction, with the kernel (-1, 0, 1)  for horizontal derivative and its transpose for vertical derivative. ArrayFire contains a function called <a href=\"http://www.accelereyes.com/arrayfire/c/group__math__func__cpp__grad.htm\">grad</a>, it calculates gradients in both directions and will perform faster than the two convolutions. The only difference is <a href=\"http://www.accelereyes.com/arrayfire/c/group__math__func__cpp__grad.htm\">grad</a> divides the result by 2, thus, the response factor will change, but this can be compensated by using a smaller response, while computation performance is improved, so <a href=\"http://www.accelereyes.com/arrayfire/c/group__math__func__cpp__grad.htm\">grad</a> be used instead.\r\n<pre>// Calculate image gradients\r\narray ix, iy;\r\ngrad(ix, iy, img_gray);\r\n</pre>\r\n<h5>Compute second-order derivatives</h5>\r\nAt this point, we have both horizontal and vertical first order derivatives of our image, but Harris corner detector is processed with second-order derivatives, which can be easily computed in ArrayFire with simple element-wise multiplications of the first-order derivatives.\r\n<pre>// Compute second-order derivatives\r\narray ixx = ix * ix;\r\narray ixy = ix * iy;\r\narray iyy = iy * iy;\r\n</pre>\r\n<h5>Compute an isotropic window</h5>\r\nTo check the cornerness of each pixel of an image, it\'s not enough to check the pixel value itself, but a small window around that pixel. To reduce noise sensitivity and have an isotropic response, Harris claims that a smooth circular window should be used, and it can be achieved by filtering of all three second-order derivatives with a Gaussian kernel.\r\n<pre>// Compute a Gaussian kernel with standard deviation of 1.0 and length of 5 pixels\r\n// These values can be changed to use a smaller or larger window\r\narray gauss_filt = gaussiankernel(5, 5, 1.0, 1.0);\r\n\r\n// Filter second-order derivatives with Gaussian kernel computed previously\r\nixx = convolve(ixx, gauss_filt);\r\nixy = convolve(ixy, gauss_filt);\r\niyy = convolve(iyy, gauss_filt);\r\n</pre>\r\n<h5>Compute trace and determinant</h5>\r\nFrom a second-order Hessian matrix, we then compute the values of its trace and determinant. These are the values we will need later to calculate the Harris response for each pixel in the image.\r\n<pre>// Calculate trace\r\narray tr = ixx + iyy;\r\n// Calculate determinant\r\narray det = ixx * iyy - ixy * ixy;\r\n</pre>\r\n<h5>Compute Harris response</h5>\r\nNext, we calculate the Harris response for each pixel. For this calculation, Harris uses an empirically defined constant <code>k</code>. This constant is usually very small, normally ranging from <code>0.04</code> to <code>0.06</code>. In our case, we will use <code>k = 0.04</code>, but we encourage you to play with this value and see how the result is affected.\r\n<pre>// Calculate Harris response\r\narray response = det - 0.04f * (tr * tr);\r\n</pre>\r\n<h5>Selection of good corners</h5>\r\nNow we already have our Harris responses for each pixel in the image. This value is used to determine whether a pixel is a corner or not. The standard way is to perform a non-maximal suppression, meaning that for each pixel it can only be a corner if it is a maximum compared to its 8 adjacent pixels. At the moment we do not have a direct way to compute a non-maximal suppression with ArrayFire, we have to write our own kernel for that. Non-maximal suppression is only one of the cool things we will be able to do with our new computer vision toolset for ArrayFire.\r\n\r\nAn alternative is to do the non-maximal suppression in a naive way. To do this, we will use ArrayFire\'s <a href=\"http://www.accelereyes.com/arrayfire/c/group__image__func__cpp__maxfilt.htm\">maxfilt</a> function, that filters the image with a mask of <code>NxM</code> pixel and returns the maximum value of the neighborhood to the pixel centered within the mask. In this case we will use a <code>3x3</code> pixel mask to return the maximum of the 8-neighborhood, including the central pixel itself.\r\n\r\nThe <a href=\"http://www.accelereyes.com/arrayfire/c/group__image__func__cpp__maxfilt.htm\">maxfilt</a> function alone will not perform a non-maximal suppression, but combining with a few other steps, we can get the proper responses.\r\n\r\nThe nature of a pixel can be determined by the Harris responses, a negative response means that a pixel corresponds to the segment of an edge. If the response is small but positive, it corresponds to a flat region. Only a large response corresponds to a corner. By thresholding the response array with the minimum desired Harris response, that for our example will be 10<sup>5</sup>, we can calculate a binary response array for which only pixels with a value greater than this threshold will be true. We then multiply it to the original response array to get a new array containing only responses greater that 10<sup>5</sup>.\r\n\r\nHere, we will use a threshold of 10<sup>5</sup>. For the implementation presented in this article, we found that corners seem to be better for responses larger than 10<sup>4</sup>, but you can and should play with these values to see how it will affect the image you are working on.\r\n\r\nThe last step for this is testing whether each pixel is equal to the maximum Harris response of the neighborhood. If it is equal, then we keep it, else, the response is not a local maximum and we discard it.\r\n<pre>// Gets maximum response for each 3x3 neighborhood\r\narray max_resp = maxfilt(response, 3, 3);\r\n\r\n// Discard responses that are not greater than threshold\r\narray corners = response > 1e5f;\r\ncorners = corners * response;\r\n\r\n// Discard responses that are not equal to maximum neighborhood response,\r\n// scale them to original response value\r\ncorners = (corners == max_resp) * corners;\r\n</pre>\r\nIf you still think you want a non-maximal suppression kernel for yourself, you can write it instead of using the last piece of code above. If you have never written your own kernel to work with an ArrayFire array, check out the <a href=\"http://sandbox.arrayfire.com/custom-kernels-with-arrayfire/\">Custom Kernels with ArrayFire</a> post. Writing the non-maximal suppression kernel itself will not take more than 20 or 30 lines of code.\r\n<h5>Plotting corners</h5>\r\nThis last step is done on the <abbr title=\"Central Processing Unit\">CPU</abbr> side, we only do this to show the corners that are detected. Most likely, you will not need to do this unless you want to visualize, but for the sake of clarity, we include this part to show the result.\r\n<pre>// Gets host pointer to response data\r\nfloat* h_corners = corners.host<float>();\r\n\r\n// Draw draw_len x draw_len crosshairs where the corners are\r\nconst int draw_len = 3;\r\nfor (int y = draw_len; y < img_color.dims(0) - draw_len; y++) {\r\n    for (int x = draw_len; x < img_color.dims(1) - draw_len; x++) {\r\n        // Only draws crosshair if is a corner\r\n        if (h_corners[x * corners.dims(0) + y] > 1e5f) {\r\n            // Draw horizontal line of (draw_len * 2 + 1) pixels centered on the corner\r\n            // Set only the first channel to 1 (green lines)\r\n            img_color(y, seq(x-draw_len, x+draw_len), 0) = 0.f;\r\n            img_color(y, seq(x-draw_len, x+draw_len), 1) = 1.f;\r\n            img_color(y, seq(x-draw_len, x+draw_len), 2) = 0.f;\r\n\r\n            // Draw vertical line of (draw_len * 2 + 1) pixels centered on  the corner\r\n            // Set only the first channel to 1 (green lines)\r\n            img_color(seq(y-draw_len, y+draw_len), x, 0) = 0.f;\r\n            img_color(seq(y-draw_len, y+draw_len), x, 1) = 1.f;\r\n            img_color(seq(y-draw_len, y+draw_len), x, 2) = 0.f;\r\n        }\r\n    }\r\n}</pre>\r\n<h5>Visualize results</h5>\r\nFinally, the image can be visualized.\r\n<pre>// Previews color image with green crosshairs\r\nimage(img_color);\r\n</pre>\r\nBelow you can see Lena\'s picture after the Harris corner detection and plotting. The green crosshairs indicate where corners are.\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_lena.png\"><img class=\"alignnone size-full wp-image-5710\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_lena.png\" alt=\"Harris Corners - Lena\" width=\"1024\" height=\"600\" /></a>\r\n\r\nTo test for correctness of the algorithm, nothing better than a picture with well-defined corners. Below you can see the picture of a white square on a black background and the corners marked by green crosshairs.\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_square.png\"><img class=\"alignnone size-full wp-image-5711\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_square.png\" alt=\"Harris Corners - Square\" width=\"1024\" height=\"600\" /></a>\r\n\r\nAll our example sources can be found in our <a href=\"https://github.com/arrayfire/arrayfire_examples\">ArrayFire examples project</a> on GitHub, and the complete code for this article can be access directly <a href=\"https://github.com/arrayfire/arrayfire_examples/blob/master/image_processing/harris_demo.cpp\">here</a>.\r\n\r\nWe would like to hear from you, what you are working on the computer vision field and which features you would like to see in ArrayFire. Please share your thoughts and requests below or contact us at <a href=\"mailto:sales@arrayfire.com\">sales@arrayfire.com</a>.\r\n<h5>References</h5>\r\n[1] Harris, Chris, and Mike Stephens. \"A combined corner and edge detector.\" <em>Alvey vision conference</em>. Vol. 15. 1988.','Writing a Simple Corner Detector with ArrayFire','','inherit','open','closed','','5659-revision-v1','','','2014-05-29 18:09:06','2014-05-29 18:09:06','',5659,'http://sandbox.arrayfire.com/5659-revision-v1/',0,'revision','',0),(5725,17795,'2014-05-29 18:09:50','2014-05-29 18:09:50','In the upcoming months we will be adding a lot of new Computer Vision functionality to ArrayFire. This means dozens of new functions specifically targeted for the most commonly used applications in this field, like feature tracking, object classification, scene segmentation, optical flow, stereo-vision, among others, will be added to take full advantage of <abbr title=\"Graphics Processing Unit\">GPU</abbr> devices.\r\n\r\nFeature tracking consists of three basic steps:\r\n<ol>\r\n	<li>Detecting good or unique features, normally they are corners or blobs of an object</li>\r\n	<li>Extracting a descriptor for each feature, understanding the texture of a small patch around each feature</li>\r\n	<li>Descriptor matching, finding out the best match for each pair of descriptors (one from the object being tracked, another from a scene that potentially contains that object), if any.</li>\r\n</ol>\r\n<h3>Harris corner detector</h3>\r\nIn this article we will be using ArrayFire to dive deeper into the first step of feature tracking: detecting good features. Through a step-by-step guide, we will develop a simple corner detector, known as the Harris corner detector [1].\r\n\r\nThe Harris corner detector is very simple to implement, especially when you have so many good tools and libraries out there to do the core matrix manipulation. What we specifically need for Harris are some convolutions, together with a few element-wise matrix addition and multiplication operations, all of these operations are present in most scientific tools and libraries that work with matrix manipulation. I will try to avoid going into the mathematical details in this post and go directly to the implementation.\r\n<h5>Loading an image</h5>\r\nBefore starting writing the code for the corner detector, we need to load an image. The image can be either color or gray-scale, but it will only work on the gray-scale version, so if it is a color image, we have to convert it before proceeding.\r\n<pre>// Load a color image\r\narray img_color = loadimage(\"lena.jpg\", true);\r\n// Convert the image from RGB to gray-scale\r\narray img_gray = colorspace(img_color, af_gray, af_rgb);\r\n// For visualization in ArrayFire, color images must be in the [0.0f-1.0f] interval\r\nimg_color /= 255.f;\r\n</pre>\r\n<h5>Compute first-order derivatives</h5>\r\nThe first step in the Harris corner detector is to determine first order derivatives of an image, in both horizontal and vertical directions. This can be achieved by one convolution for each direction, with the kernel (-1, 0, 1)  for horizontal derivative and its transpose for vertical derivative. ArrayFire contains a function called <a href=\"http://www.accelereyes.com/arrayfire/c/group__math__func__cpp__grad.htm\">grad</a>, it calculates gradients in both directions and will perform faster than the two convolutions. The only difference is <a href=\"http://www.accelereyes.com/arrayfire/c/group__math__func__cpp__grad.htm\">grad</a> divides the result by 2, thus, the response factor will change, but this can be compensated by using a smaller response, while computation performance is improved, so <a href=\"http://www.accelereyes.com/arrayfire/c/group__math__func__cpp__grad.htm\">grad</a> be used instead.\r\n<pre>// Calculate image gradients\r\narray ix, iy;\r\ngrad(ix, iy, img_gray);\r\n</pre>\r\n<h5>Compute second-order derivatives</h5>\r\nAt this point, we have both horizontal and vertical first order derivatives of our image, but Harris corner detector is processed with second-order derivatives, which can be easily computed in ArrayFire with simple element-wise multiplications of the first-order derivatives.\r\n<pre>// Compute second-order derivatives\r\narray ixx = ix * ix;\r\narray ixy = ix * iy;\r\narray iyy = iy * iy;\r\n</pre>\r\n<h5>Compute an isotropic window</h5>\r\nTo check the cornerness of each pixel of an image, it\'s not enough to check the pixel value itself, but a small window around that pixel. To reduce noise sensitivity and have an isotropic response, Harris claims that a smooth circular window should be used, and it can be achieved by filtering of all three second-order derivatives with a Gaussian kernel.\r\n<pre>// Compute a Gaussian kernel with standard deviation of 1.0 and length of 5 pixels\r\n// These values can be changed to use a smaller or larger window\r\narray gauss_filt = gaussiankernel(5, 5, 1.0, 1.0);\r\n\r\n// Filter second-order derivatives with Gaussian kernel computed previously\r\nixx = convolve(ixx, gauss_filt);\r\nixy = convolve(ixy, gauss_filt);\r\niyy = convolve(iyy, gauss_filt);\r\n</pre>\r\n<h5>Compute trace and determinant</h5>\r\nFrom a second-order Hessian matrix, we then compute the values of its trace and determinant. These are the values we will need later to calculate the Harris response for each pixel in the image.\r\n<pre>// Calculate trace\r\narray tr = ixx + iyy;\r\n// Calculate determinant\r\narray det = ixx * iyy - ixy * ixy;\r\n</pre>\r\n<h5>Compute Harris response</h5>\r\nNext, we calculate the Harris response for each pixel. For this calculation, Harris uses an empirically defined constant <code>k</code>. This constant is usually very small, normally ranging from <code>0.04</code> to <code>0.06</code>. In our case, we will use <code>k = 0.04</code>, but we encourage you to play with this value and see how the result is affected.\r\n<pre>// Calculate Harris response\r\narray response = det - 0.04f * (tr * tr);\r\n</pre>\r\n<h5>Selection of good corners</h5>\r\nNow we already have our Harris responses for each pixel in the image. This value is used to determine whether a pixel is a corner or not. The standard way is to perform a non-maximal suppression, meaning that for each pixel it can only be a corner if it is a maximum compared to its 8 adjacent pixels. At the moment we do not have a direct way to compute a non-maximal suppression with ArrayFire, we have to write our own kernel for that. Non-maximal suppression is only one of the cool things we will be able to do with our new computer vision toolset for ArrayFire.\r\n\r\nAn alternative is to do the non-maximal suppression in a naive way. To do this, we will use ArrayFire\'s <a href=\"http://www.accelereyes.com/arrayfire/c/group__image__func__cpp__maxfilt.htm\">maxfilt</a> function, that filters the image with a mask of <code>NxM</code> pixel and returns the maximum value of the neighborhood to the pixel centered within the mask. In this case we will use a <code>3x3</code> pixel mask to return the maximum of the 8-neighborhood, including the central pixel itself.\r\n\r\nThe <a href=\"http://www.accelereyes.com/arrayfire/c/group__image__func__cpp__maxfilt.htm\">maxfilt</a> function alone will not perform a non-maximal suppression, but combining with a few other steps, we can get the proper responses.\r\n\r\nThe nature of a pixel can be determined by the Harris responses, a negative response means that a pixel corresponds to the segment of an edge. If the response is small but positive, it corresponds to a flat region. Only a large response corresponds to a corner. By thresholding the response array with the minimum desired Harris response, that for our example will be 10<sup>5</sup>, we can calculate a binary response array for which only pixels with a value greater than this threshold will be true. We then multiply it to the original response array to get a new array containing only responses greater that 10<sup>5</sup>.\r\n\r\nHere, we will use a threshold of 10<sup>5</sup>. For the implementation presented in this article, we found that corners seem to be better for responses larger than 10<sup>4</sup>, but you can and should play with these values to see how it will affect the image you are working on.\r\n\r\nThe last step for this is testing whether each pixel is equal to the maximum Harris response of the neighborhood. If it is equal, then we keep it, else, the response is not a local maximum and we discard it.\r\n<pre>// Gets maximum response for each 3x3 neighborhood\r\narray max_resp = maxfilt(response, 3, 3);\r\n\r\n// Discard responses that are not greater than threshold\r\narray corners = response > 1e5f;\r\ncorners = corners * response;\r\n\r\n// Discard responses that are not equal to maximum neighborhood response,\r\n// scale them to original response value\r\ncorners = (corners == max_resp) * corners;\r\n</pre>\r\nIf you still think you want a non-maximal suppression kernel for yourself, you can write it instead of using the last piece of code above. If you have never written your own kernel to work with an ArrayFire array, check out the <a href=\"http://sandbox.arrayfire.com/custom-kernels-with-arrayfire/\">Custom Kernels with ArrayFire</a> post. Writing the non-maximal suppression kernel itself will not take more than 20 or 30 lines of code.\r\n<h5>Plotting corners</h5>\r\nThis last step is done on the <abbr title=\"Central Processing Unit\">CPU</abbr> side, we only do this to show the corners that are detected. Most likely, you will not need to do this unless you want to visualize, but for the sake of clarity, we include this part to show the result.\r\n<pre>// Gets host pointer to response data\r\nfloat* h_corners = corners.host<float>();\r\n\r\n// Draw draw_len x draw_len crosshairs where the corners are\r\nconst int draw_len = 3;\r\nfor (int y = draw_len; y < img_color.dims(0) - draw_len; y++) {\r\n    for (int x = draw_len; x < img_color.dims(1) - draw_len; x++) {\r\n        // Only draws crosshair if is a corner\r\n        if (h_corners[x * corners.dims(0) + y] > 1e5f) {\r\n            // Draw horizontal line of (draw_len * 2 + 1) pixels centered on the corner\r\n            // Set only the first channel to 1 (green lines)\r\n            img_color(y, seq(x-draw_len, x+draw_len), 0) = 0.f;\r\n            img_color(y, seq(x-draw_len, x+draw_len), 1) = 1.f;\r\n            img_color(y, seq(x-draw_len, x+draw_len), 2) = 0.f;\r\n\r\n            // Draw vertical line of (draw_len * 2 + 1) pixels centered on  the corner\r\n            // Set only the first channel to 1 (green lines)\r\n            img_color(seq(y-draw_len, y+draw_len), x, 0) = 0.f;\r\n            img_color(seq(y-draw_len, y+draw_len), x, 1) = 1.f;\r\n            img_color(seq(y-draw_len, y+draw_len), x, 2) = 0.f;\r\n        }\r\n    }\r\n}</pre>\r\n<h5>Visualize results</h5>\r\nFinally, the image can be visualized.\r\n<pre>// Previews color image with green crosshairs\r\nimage(img_color);\r\n</pre>\r\nBelow you can see Lena\'s picture after the Harris corner detection and plotting. The green crosshairs indicate where corners are.\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_lena.png\"><img class=\"alignnone size-full wp-image-5710\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_lena.png\" alt=\"Harris Corners - Lena\" width=\"1024\" height=\"600\" /></a>\r\n\r\nTo test for correctness of the algorithm, nothing better than a picture with well-defined corners. Below you can see the picture of a white square on a black background and the corners marked by green crosshairs.\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_square.png\"><img class=\"alignnone size-full wp-image-5711\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_square.png\" alt=\"Harris Corners - Square\" width=\"1024\" height=\"600\" /></a>\r\n\r\nAll sources to our examples can be found in our <a href=\"https://github.com/arrayfire/arrayfire_examples\">ArrayFire examples project</a> on GitHub, and the complete code for this article can be directly viewed <a href=\"https://github.com/arrayfire/arrayfire_examples/blob/master/image_processing/harris_demo.cpp\">here</a>.\r\n\r\nWe would like to hear from you, what you are working on the computer vision field and which features you would like to see in ArrayFire. Please share your thoughts and requests below or contact us at <a href=\"mailto:sales@arrayfire.com\">sales@arrayfire.com</a>.\r\n<h5>References</h5>\r\n[1] Harris, Chris, and Mike Stephens. \"A combined corner and edge detector.\" <em>Alvey vision conference</em>. Vol. 15. 1988.','Writing a Simple Corner Detector with ArrayFire','','inherit','open','closed','','5659-revision-v1','','','2014-05-29 18:09:50','2014-05-29 18:09:50','',5659,'http://sandbox.arrayfire.com/5659-revision-v1/',0,'revision','',0),(5726,17795,'2014-05-29 18:11:08','2014-05-29 18:11:08','In the upcoming months we will be adding a lot of new Computer Vision functionality to ArrayFire. This means dozens of new functions specifically targeted for the most commonly used applications in this field, like feature tracking, object classification, scene segmentation, optical flow, stereo-vision, among others, will be added to take full advantage of <abbr title=\"Graphics Processing Unit\">GPU</abbr> devices.\r\n\r\nFeature tracking consists of three basic steps:\r\n<ol>\r\n	<li>Detecting good or unique features, normally they are corners or blobs of an object</li>\r\n	<li>Extracting a descriptor for each feature, understanding the texture of a small patch around each feature</li>\r\n	<li>Descriptor matching, finding out the best match for each pair of descriptors (one from the object being tracked, another from a scene that potentially contains that object), if any.</li>\r\n</ol>\r\n<h3>Harris corner detector</h3>\r\nIn this article we will be using ArrayFire to dive deeper into the first step of feature tracking: detecting good features. Through a step-by-step guide, we will develop a simple corner detector, known as the Harris corner detector [1].\r\n\r\nThe Harris corner detector is very simple to implement, especially when you have so many good tools and libraries out there to do the core matrix manipulation. What we specifically need for Harris are some convolutions, together with a few element-wise matrix addition and multiplication operations, all of these operations are present in most scientific tools and libraries that work with matrix manipulation. I will try to avoid going into the mathematical details in this post and go directly to the implementation.\r\n<h5>Loading an image</h5>\r\nBefore starting writing the code for the corner detector, we need to load an image. The image can be either color or gray-scale, but it will only work on the gray-scale version, so if it is a color image, we have to convert it before proceeding.\r\n<pre>// Load a color image\r\narray img_color = loadimage(\"lena.jpg\", true);\r\n// Convert the image from RGB to gray-scale\r\narray img_gray = colorspace(img_color, af_gray, af_rgb);\r\n// For visualization in ArrayFire, color images must be in the [0.0f-1.0f] interval\r\nimg_color /= 255.f;\r\n</pre>\r\n<h5>Compute first-order derivatives</h5>\r\nThe first step in the Harris corner detector is to determine first order derivatives of an image, in both horizontal and vertical directions. This can be achieved by one convolution for each direction, with the kernel (-1, 0, 1)  for horizontal derivative and its transpose for vertical derivative. ArrayFire contains a function called <a href=\"http://www.accelereyes.com/arrayfire/c/group__math__func__cpp__grad.htm\">grad</a>, it calculates gradients in both directions and will perform faster than the two convolutions. The only difference is <a href=\"http://www.accelereyes.com/arrayfire/c/group__math__func__cpp__grad.htm\">grad</a> divides the result by 2, thus, the response factor will change, but this can be compensated by using a smaller response, while computation performance is improved, so <a href=\"http://www.accelereyes.com/arrayfire/c/group__math__func__cpp__grad.htm\">grad</a> be used instead.\r\n<pre>// Calculate image gradients\r\narray ix, iy;\r\ngrad(ix, iy, img_gray);\r\n</pre>\r\n<h5>Compute second-order derivatives</h5>\r\nAt this point, we have both horizontal and vertical first order derivatives of our image, but Harris corner detector is processed with second-order derivatives, which can be easily computed in ArrayFire with simple element-wise multiplications of the first-order derivatives.\r\n<pre>// Compute second-order derivatives\r\narray ixx = ix * ix;\r\narray ixy = ix * iy;\r\narray iyy = iy * iy;\r\n</pre>\r\n<h5>Compute an isotropic window</h5>\r\nTo check the cornerness of each pixel of an image, it\'s not enough to check the pixel value itself, but a small window around that pixel. To reduce noise sensitivity and have an isotropic response, Harris claims that a smooth circular window should be used, and it can be achieved by filtering of all three second-order derivatives with a Gaussian kernel.\r\n<pre>// Compute a Gaussian kernel with standard deviation of 1.0 and length of 5 pixels\r\n// These values can be changed to use a smaller or larger window\r\narray gauss_filt = gaussiankernel(5, 5, 1.0, 1.0);\r\n\r\n// Filter second-order derivatives with Gaussian kernel computed previously\r\nixx = convolve(ixx, gauss_filt);\r\nixy = convolve(ixy, gauss_filt);\r\niyy = convolve(iyy, gauss_filt);\r\n</pre>\r\n<h5>Compute trace and determinant</h5>\r\nFrom a second-order Hessian matrix, we then compute the values of its trace and determinant. These are the values we will need later to calculate the Harris response for each pixel in the image.\r\n<pre>// Calculate trace\r\narray tr = ixx + iyy;\r\n// Calculate determinant\r\narray det = ixx * iyy - ixy * ixy;\r\n</pre>\r\n<h5>Compute Harris response</h5>\r\nNext, we calculate the Harris response for each pixel. For this calculation, Harris uses an empirically defined constant <code>k</code>. This constant is usually very small, normally ranging from <code>0.04</code> to <code>0.06</code>. In our case, we will use <code>k = 0.04</code>, but we encourage you to play with this value and see how the result is affected.\r\n<pre>// Calculate Harris response\r\narray response = det - 0.04f * (tr * tr);\r\n</pre>\r\n<h5>Selection of good corners</h5>\r\nNow we already have our Harris responses for each pixel in the image. This value is used to determine whether a pixel is a corner or not. The standard way is to perform a non-maximal suppression, meaning that for each pixel it can only be a corner if it is a maximum compared to its 8 adjacent pixels. At the moment we do not have a direct way to compute a non-maximal suppression with ArrayFire, we have to write our own kernel for that. Non-maximal suppression is only one of the cool things we will be able to do with our new computer vision toolset for ArrayFire.\r\n\r\nAn alternative is to do the non-maximal suppression in a naive way. To do this, we will use ArrayFire\'s <a href=\"http://www.accelereyes.com/arrayfire/c/group__image__func__cpp__maxfilt.htm\">maxfilt</a> function, that filters the image with a mask of <code>NxM</code> pixel and returns the maximum value of the neighborhood to the pixel centered within the mask. In this case we will use a <code>3x3</code> pixel mask to return the maximum of the 8-neighborhood, including the central pixel itself.\r\n\r\nThe <a href=\"http://www.accelereyes.com/arrayfire/c/group__image__func__cpp__maxfilt.htm\">maxfilt</a> function alone will not perform a non-maximal suppression, but combining with a few other steps, we can get the proper responses.\r\n\r\nThe nature of a pixel can be determined by the Harris responses, a negative response means that a pixel corresponds to the segment of an edge. If the response is small but positive, it corresponds to a flat region. Only a large response corresponds to a corner. By thresholding the response array with the minimum desired Harris response, that for our example will be 10<sup>5</sup>, we can calculate a binary response array for which only pixels with a value greater than this threshold will be true. We then multiply it to the original response array to get a new array containing only responses greater that 10<sup>5</sup>.\r\n\r\nHere, we will use a threshold of 10<sup>5</sup>. For the implementation presented in this article, we found that corners seem to be better for responses larger than 10<sup>4</sup>, but you can and should play with these values to see how it will affect the image you are working on.\r\n\r\nThe last step for this is testing whether each pixel is equal to the maximum Harris response of the neighborhood. If it is equal, then we keep it, else, the response is not a local maximum and we discard it.\r\n<pre>// Gets maximum response for each 3x3 neighborhood\r\narray max_resp = maxfilt(response, 3, 3);\r\n\r\n// Discard responses that are not greater than threshold\r\narray corners = response > 1e5f;\r\ncorners = corners * response;\r\n\r\n// Discard responses that are not equal to maximum neighborhood response,\r\n// scale them to original response value\r\ncorners = (corners == max_resp) * corners;\r\n</pre>\r\nIf you still think you want a non-maximal suppression kernel for yourself, you can write it instead of using the last piece of code above. If you have never written your own kernel to work with an ArrayFire array, check out the <a href=\"http://sandbox.arrayfire.com/custom-kernels-with-arrayfire/\">Custom Kernels with ArrayFire</a> post. Writing the non-maximal suppression kernel itself will not take more than 20 or 30 lines of code.\r\n<h5>Plotting corners</h5>\r\nThis last step is done on the <abbr title=\"Central Processing Unit\">CPU</abbr> side, we only do this to show the corners that are detected. Most likely, you will not need to do this unless you want to visualize, but for the sake of clarity, we include this part to show the result.\r\n<pre>// Gets host pointer to response data\r\nfloat* h_corners = corners.host<float>();\r\n\r\n// Draw draw_len x draw_len crosshairs where the corners are\r\nconst int draw_len = 3;\r\nfor (int y = draw_len; y < img_color.dims(0) - draw_len; y++) {\r\n    for (int x = draw_len; x < img_color.dims(1) - draw_len; x++) {\r\n        // Only draws crosshair if is a corner\r\n        if (h_corners[x * corners.dims(0) + y] > 1e5f) {\r\n            // Draw horizontal line of (draw_len * 2 + 1) pixels centered on the corner\r\n            // Set only the first channel to 1 (green lines)\r\n            img_color(y, seq(x-draw_len, x+draw_len), 0) = 0.f;\r\n            img_color(y, seq(x-draw_len, x+draw_len), 1) = 1.f;\r\n            img_color(y, seq(x-draw_len, x+draw_len), 2) = 0.f;\r\n\r\n            // Draw vertical line of (draw_len * 2 + 1) pixels centered on  the corner\r\n            // Set only the first channel to 1 (green lines)\r\n            img_color(seq(y-draw_len, y+draw_len), x, 0) = 0.f;\r\n            img_color(seq(y-draw_len, y+draw_len), x, 1) = 1.f;\r\n            img_color(seq(y-draw_len, y+draw_len), x, 2) = 0.f;\r\n        }\r\n    }\r\n}</pre>\r\n<h5>Visualize results</h5>\r\nFinally, the image can be visualized.\r\n<pre>// Previews color image with green crosshairs\r\nimage(img_color);\r\n</pre>\r\nBelow you can see Lena\'s picture after the Harris corner detection and plotting. The green crosshairs indicate where corners are.\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_lena.png\"><img class=\"alignnone size-full wp-image-5710\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_lena.png\" alt=\"Harris Corners - Lena\" width=\"1024\" height=\"600\" /></a>\r\n\r\nTo test for correctness of the algorithm, nothing better than a picture with well-defined corners. Below you can see the picture of a white square on a black background and the corners marked by green crosshairs.\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_square.png\"><img class=\"alignnone size-full wp-image-5711\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_square.png\" alt=\"Harris Corners - Square\" width=\"1024\" height=\"600\" /></a>\r\n\r\nAll sources to our examples can be found in our <a href=\"https://github.com/arrayfire/arrayfire_examples\">ArrayFire examples project</a> on GitHub, and the complete code for this article can be viewed via this direct <a href=\"https://github.com/arrayfire/arrayfire_examples/blob/master/image_processing/harris_demo.cpp\">link</a>.\r\n\r\nWe would like to hear from you, what you are working on the computer vision field and which features you would like to see in ArrayFire. Please share your thoughts and requests below or contact us at <a href=\"mailto:sales@arrayfire.com\">sales@arrayfire.com</a>.\r\n<h5>References</h5>\r\n[1] Harris, Chris, and Mike Stephens. \"A combined corner and edge detector.\" <em>Alvey vision conference</em>. Vol. 15. 1988.','Writing a Simple Corner Detector with ArrayFire','','inherit','open','closed','','5659-revision-v1','','','2014-05-29 18:11:08','2014-05-29 18:11:08','',5659,'http://sandbox.arrayfire.com/5659-revision-v1/',0,'revision','',0),(5727,7,'2014-05-30 18:35:10','2014-05-30 18:35:10','In the upcoming months we\'ll be adding a lot of new Computer Vision functionality to ArrayFire, <span style=\"color: #333333;\">specifically targeting the most commonly used applications in this field. New functions include</span> feature tracking, object classification, scene segmentation, optical flow, and stereo-vision.\r\n\r\nFeature tracking consists of three basic steps:\r\n<ol>\r\n	<li>Detecting good or unique features; normally they are corners or blobs of an object.</li>\r\n	<li>Extracting a descriptor for each feature—understanding the texture of a small patch around each feature.</li>\r\n	<li>Descriptor matching—finding out the best match for each pair of descriptors (one from the object being tracked, another from a scene that potentially contains that object), if any.</li>\r\n</ol>\r\n<h3>Harris corner detector</h3>\r\nIn this article we will be using ArrayFire to dive deeper into the first step of feature tracking: detecting good features. Through a step-by-step guide we will develop a simple corner detector, known as the Harris corner detector [1].\r\n\r\nThe Harris corner detector is very simple to implement, especially when you have so many good tools and libraries out there to do the core matrix manipulation. What we specifically need for Harris are some convolutions, together with a few element-wise matrix addition and multiplication operations; all of these operations are present in most scientific tools and libraries that work with matrix manipulation. I will try to avoid going into the mathematical details in this post and go directly to the implementation.\r\n<h5>Loading an image</h5>\r\nBefore writing the code for the corner detector, we need to load an image. The image can be either color or grayscale, but it will only work on the grayscale version; if we upload a color image, we have to convert it before proceeding.\r\n<pre>// Load a color image\r\narray img_color = loadimage(\"lena.jpg\", true);\r\n// Convert the image from RGB to gray-scale\r\narray img_gray = colorspace(img_color, af_gray, af_rgb);\r\n// For visualization in ArrayFire, color images must be in the [0.0f-1.0f] interval\r\nimg_color /= 255.f;\r\n</pre>\r\n<h5>Compute first-order derivatives</h5>\r\nThe first step in the Harris corner detector is to determine first order derivatives of an image, in both horizontal and vertical directions. This can be achieved by one convolution for each direction, with the kernel (-1, 0, 1)  for horizontal derivative and its transpose for vertical derivative. ArrayFire contains a function called <a href=\"http://www.accelereyes.com/arrayfire/c/group__math__func__cpp__grad.htm\">grad</a>, which calculates gradients in both directions and will perform faster than the two convolutions. The only difference  is that <a href=\"http://www.accelereyes.com/arrayfire/c/group__math__func__cpp__grad.htm\">grad</a> divides the result by 2, thus, the response factor will change. The use of grad will improve the performance, and factor change can be easily compensated by using a smaller response.\r\n<pre>// Calculate image gradients\r\narray ix, iy;\r\ngrad(ix, iy, img_gray);\r\n</pre>\r\n<h5>Compute second-order derivatives</h5>\r\nAt this point we have both horizontal and vertical first order derivatives of our image, but Harris corner detector is processed with second-order derivatives, which can be easily computed in ArrayFire with simple element-wise multiplications of the first-order derivatives.\r\n<pre>// Compute second-order derivatives\r\narray ixx = ix * ix;\r\narray ixy = ix * iy;\r\narray iyy = iy * iy;\r\n</pre>\r\n<h5>Compute an isotropic window</h5>\r\nTo check the cornerness of each pixel of an image, it\'s not enough to check the pixel value itself. We must also check a small window around that pixel. To reduce noise sensitivity and have an isotropic response, Harris claims that a smooth circular window should be used. This can be achieved by filtering of all three second-order derivatives with a Gaussian kernel.\r\n<pre>// Compute a Gaussian kernel with standard deviation of 1.0 and length of 5 pixels\r\n// These values can be changed to use a smaller or larger window\r\narray gauss_filt = gaussiankernel(5, 5, 1.0, 1.0);\r\n\r\n// Filter second-order derivatives with Gaussian kernel computed previously\r\nixx = convolve(ixx, gauss_filt);\r\nixy = convolve(ixy, gauss_filt);\r\niyy = convolve(iyy, gauss_filt);\r\n</pre>\r\n<h5>Compute trace and determinant</h5>\r\nFrom a second-order Hessian matrix, we then compute the values of its trace and determinant. These are the values we will need later to calculate the Harris response for each pixel in the image.\r\n<pre>// Calculate trace\r\narray tr = ixx + iyy;\r\n// Calculate determinant\r\narray det = ixx * iyy - ixy * ixy;\r\n</pre>\r\n<h5>Compute Harris response</h5>\r\nNext, we calculate the Harris response for each pixel. For this calculation, Harris uses an empirically defined constant <code>k</code>. This constant is usually very small, normally ranging from <code>0.04</code> to <code>0.06</code>. In our case, we will use <code>k = 0.04</code>, but we encourage you to play with this value and see how the result is affected.\r\n<pre>// Calculate Harris response\r\narray response = det - 0.04f * (tr * tr);\r\n</pre>\r\n<h5>Selection of good corners</h5>\r\nNow we already have our Harris responses for each pixel in the image. This value is used to determine whether a pixel is a corner or not. The standard way is to perform a non-maximal suppression, meaning that each pixel can only be a corner if it is a maximum compared to its 8 adjacent pixels. At the moment we do not have a direct way to compute a non-maximal suppression with ArrayFire; we have to write our own kernel for that. Non-maximal suppression is  just one of the cool things we will be able to do with our new computer vision toolset for ArrayFire.\r\n\r\nAn alternative is to do the non-maximal suppression in a naive way. To do this, we will use ArrayFire\'s <a href=\"http://www.accelereyes.com/arrayfire/c/group__image__func__cpp__maxfilt.htm\">maxfilt</a> function, which filters the image with a mask of <code>NxM</code> pixel and returns the maximum value of the neighborhood to the pixel centered within the mask. In this case we will use a <code>3x3</code> pixel mask to return the maximum of the 8-neighborhood, including the central pixel itself.\r\n\r\nThe <a href=\"http://www.accelereyes.com/arrayfire/c/group__image__func__cpp__maxfilt.htm\">maxfilt</a> function alone will not perform a non-maximal suppression, but by combining the function with a few other steps we can get the proper responses.\r\n\r\nThe nature of a pixel can be determined by the Harris responses; a negative response means that a pixel corresponds to the segment of an edge. If the response is small but positive, it corresponds to a flat region. Only a large response corresponds to a corner. By thresholding the response array with the minimum desired Harris response, which, for our example, will be 10<sup>5</sup>, we can calculate a binary response array for which only pixels with a value greater than this threshold will be true. We then multiply it to the original response array to get a new array containing only responses greater that 10<sup>5</sup>.\r\n\r\nHere we will use a threshold of 10<sup>5</sup>. For the implementation presented in this article, we found that corners seem to be better for responses larger than 10<sup>4</sup>, but you can and should play with these values to see how it will affect the image you are working on.\r\n\r\nThe last step for this is testing whether each pixel is equal to the maximum Harris response of the neighborhood. If it is equal, then we keep it, else, the response is not a local maximum and we discard it.\r\n<pre>// Gets maximum response for each 3x3 neighborhood\r\narray max_resp = maxfilt(response, 3, 3);\r\n\r\n// Discard responses that are not greater than threshold\r\narray corners = response &gt; 1e5f;\r\ncorners = corners * response;\r\n\r\n// Discard responses that are not equal to maximum neighborhood response,\r\n// scale them to original response value\r\ncorners = (corners == max_resp) * corners;\r\n</pre>\r\nIf you still think you want a non-maximal suppression kernel for yourself, you can write it instead of using the last piece of code above. If you have never written your own kernel to work with an ArrayFire array, check out the <a href=\"http://sandbox.arrayfire.com/custom-kernels-with-arrayfire/\">Custom Kernels with ArrayFire</a> post. Writing the non-maximal suppression kernel itself will not take more than 20 or 30 lines of code.\r\n<h5>Plotting corners</h5>\r\nThis last step is done on the <abbr title=\"Central Processing Unit\">CPU</abbr> side; we only do this to show the corners that are detected. This will most likely be unnecessary unless you want to visualize, but, for the sake of clarity, we will include this part to show the result.\r\n<pre>// Gets host pointer to response data\r\nfloat* h_corners = corners.host();\r\n\r\n// Draw draw_len x draw_len crosshairs where the corners are\r\nconst int draw_len = 3;\r\nfor (int y = draw_len; y &lt; img_color.dims(0) - draw_len; y++) {\r\n    for (int x = draw_len; x &lt; img_color.dims(1) - draw_len; x++) {\r\n        // Only draws crosshair if is a corner\r\n        if (h_corners[x * corners.dims(0) + y] &gt; 1e5f) {\r\n            // Draw horizontal line of (draw_len * 2 + 1) pixels centered on the corner\r\n            // Set only the first channel to 1 (green lines)\r\n            img_color(y, seq(x-draw_len, x+draw_len), 0) = 0.f;\r\n            img_color(y, seq(x-draw_len, x+draw_len), 1) = 1.f;\r\n            img_color(y, seq(x-draw_len, x+draw_len), 2) = 0.f;\r\n\r\n            // Draw vertical line of (draw_len * 2 + 1) pixels centered on  the corner\r\n            // Set only the first channel to 1 (green lines)\r\n            img_color(seq(y-draw_len, y+draw_len), x, 0) = 0.f;\r\n            img_color(seq(y-draw_len, y+draw_len), x, 1) = 1.f;\r\n            img_color(seq(y-draw_len, y+draw_len), x, 2) = 0.f;\r\n        }\r\n    }\r\n}</pre>\r\n<h5>Visualize results</h5>\r\nFinally, the image can be visualized.\r\n<pre>// Previews color image with green crosshairs\r\nimage(img_color);\r\n</pre>\r\nBelow you can see Lena\'s picture after the Harris corner detection and plotting. The green crosshairs indicate where corners are.\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_lena.png\"><img class=\"alignnone size-full wp-image-5710\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_lena.png\" alt=\"Harris Corners - Lena\" width=\"1024\" height=\"600\" /></a>\r\n\r\nTo test for correctness of the algorithm, nothing better than a picture with well-defined corners. Below you can see the picture of a white square on a black background and the corners marked by green crosshairs.\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_square.png\"><img class=\"alignnone size-full wp-image-5711\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_square.png\" alt=\"Harris Corners - Square\" width=\"1024\" height=\"600\" /></a>\r\n\r\nAll sources to our examples can be found in our <a href=\"https://github.com/arrayfire/arrayfire_examples\">ArrayFire examples project</a> on GitHub, and the complete code for this article can be viewed via this direct <a href=\"https://github.com/arrayfire/arrayfire_examples/blob/master/image_processing/harris_demo.cpp\">link</a>.\r\n\r\nWe would like to hear from you! What you are working on the computer vision field and what features would you like to see in ArrayFire? Please share your thoughts and requests below or contact us at <a href=\"mailto:sales@arrayfire.com\">sales@arrayfire.com</a>.\r\n<h5>References</h5>\r\n[1] Harris, Chris, and Mike Stephens. \"A combined corner and edge detector.\" <em>Alvey vision conference</em>. Vol. 15. 1988.','Writing a Simple Corner Detector with ArrayFire','','inherit','open','closed','','5659-autosave-v1','','','2014-05-30 18:35:10','2014-05-30 18:35:10','',5659,'http://sandbox.arrayfire.com/5659-autosave-v1/',0,'revision','',0),(5728,7,'2014-05-30 16:05:22','2014-05-30 16:05:22','In the upcoming months we will be adding a lot of new Computer Vision functionality to ArrayFire. This means dozens of new functions specifically targeted for the most commonly used applications in this field, such as feature tracking, object classification, scene segmentation, optical flow, stereo-vision, among others, will be added to take full advantage of <abbr title=\"Graphics Processing Unit\">GPU</abbr> devices.\r\n<div>[In the upcoming months we\'ll be adding a lot of new Computer Vision functionality to ArrayFire, <span style=\"color: #333333;\">specifically targeting the most commonly used applications in this field. New functions include</span> feature tracking, object classification, scene segmentation, optical flow, and stereo-vision.]</div>\r\nFeature tracking consists of three basic steps:\r\n<ol>\r\n	<li>Detecting good or unique features<del>,</del>; normally they are corners or blobs of an object.</li>\r\n	<li>Extracting a descriptor for each feature<del>,</del>--understanding the texture of a small patch around each feature.</li>\r\n	<li>Descriptor matching<del>,</del>--finding out the best match for each pair of descriptors (one from the object being tracked, another from a scene that potentially contains that object), if any.</li>\r\n</ol>\r\n<h3>Harris corner detector</h3>\r\nIn this article we will be using ArrayFire to dive deeper into the first step of feature tracking: detecting good features. Through a step-by-step guide<del>,</del> we will develop a simple corner detector, known as the Harris corner detector [1].\r\n\r\nThe Harris corner detector is very simple to implement, especially when you have so many good tools and libraries out there to do the core matrix manipulation. What we specifically need for Harris are some convolutions, together with a few element-wise matrix addition and multiplication operations<del>,</del>; all of these operations are present in most scientific tools and libraries that work with matrix manipulation. I will try to avoid going into the mathematical details in this post and go directly to the implementation.\r\n<h5>Loading an image</h5>\r\nBefore <del>starting</del> writing the code for the corner detector, we need to load an image. The image can be either color or <del>gray-scale</del> grayscale, but it [what is this pronoun referring to--the Harris corner detector?] will only work on the gray-scale version<del>, so</del>; if <del>it is</del> we upload a color image, we have to convert it before proceeding.\r\n<pre>// Load a color image\r\narray img_color = loadimage(\"lena.jpg\", true);\r\n// Convert the image from RGB to gray-scale\r\narray img_gray = colorspace(img_color, af_gray, af_rgb);\r\n// For visualization in ArrayFire, color images must be in the [0.0f-1.0f] interval\r\nimg_color /= 255.f;\r\n</pre>\r\n<h5>Compute first-order derivatives</h5>\r\nThe first step in the Harris corner detector is to determine first order derivatives of an image, in both horizontal and vertical directions. This can be achieved by one convolution for each direction, with the kernel (-1, 0, 1)  for horizontal derivative and its transpose for vertical derivative. ArrayFire contains a function called <a href=\"http://www.accelereyes.com/arrayfire/c/group__math__func__cpp__grad.htm\">grad</a>, <del>it</del> which calculates gradients in both directions and will perform faster than the two convolutions. <span style=\"color: rgb(0, 128, 0);\">The only difference [between what?] is [that] <a href=\"http://www.accelereyes.com/arrayfire/c/group__math__func__cpp__grad.htm\"><span style=\"color: rgb(0, 128, 0);\">grad</span></a> divides the result by 2, thus, the response factor will change, but this can be compensated for by using a smaller response, while computation performance is improved, so <a href=\"http://www.accelereyes.com/arrayfire/c/group__math__func__cpp__grad.htm\"><span style=\"color: rgb(0, 128, 0);\">grad</span></a> [can?] be used instead.</span> &lt;--This sentence is confusing and long. Split it up to improve clarity.\r\n<pre>// Calculate image gradients\r\narray ix, iy;\r\ngrad(ix, iy, img_gray);\r\n</pre>\r\n<h5>Compute second-order derivatives</h5>\r\nAt this point<del>,</del> we have both horizontal and vertical first order derivatives of our image, but Harris corner detector is processed with second-order derivatives, which can be easily computed in ArrayFire with simple element-wise multiplications of the first-order derivatives.\r\n<pre>// Compute second-order derivatives\r\narray ixx = ix * ix;\r\narray ixy = ix * iy;\r\narray iyy = iy * iy;\r\n</pre>\r\n<h5>Compute an isotropic window</h5>\r\nTo check the cornerness of each pixel of an image, it\'s not enough to check the pixel value itself. We must also check a small window around that pixel. To reduce noise sensitivity and have an isotropic response, Harris claims that a smooth circular window should be used<del>, and it</del>. This can be achieved by filtering of all three second-order derivatives with a Gaussian kernel.\r\n<pre>// Compute a Gaussian kernel with standard deviation of 1.0 and length of 5 pixels\r\n// These values can be changed to use a smaller or larger window\r\narray gauss_filt = gaussiankernel(5, 5, 1.0, 1.0);\r\n\r\n// Filter second-order derivatives with Gaussian kernel computed previously\r\nixx = convolve(ixx, gauss_filt);\r\nixy = convolve(ixy, gauss_filt);\r\niyy = convolve(iyy, gauss_filt);\r\n</pre>\r\n<h5>Compute trace and determinant</h5>\r\nFrom a second-order Hessian matrix, we then compute the values of its trace and determinant. These are the values we will need later to calculate the Harris response for each pixel in the image.\r\n<pre>// Calculate trace\r\narray tr = ixx + iyy;\r\n// Calculate determinant\r\narray det = ixx * iyy - ixy * ixy;\r\n</pre>\r\n<h5>Compute Harris response</h5>\r\nNext, we calculate the Harris response for each pixel. For this calculation, Harris uses an empirically defined constant <code>k</code>. This constant is usually very small, normally ranging from <code>0.04</code> to <code>0.06</code>. In our case, we will use <code>k = 0.04</code>, but we encourage you to play with this value and see how the result is affected.\r\n<pre>// Calculate Harris response\r\narray response = det - 0.04f * (tr * tr);\r\n</pre>\r\n<h5>Selection of good corners</h5>\r\nNow we already have our Harris responses for each pixel in the image. This value is used to determine whether a pixel is a corner or not. The standard way is to perform a non-maximal suppression, meaning that for each pixel it can only be a corner if it is a maximum compared to its 8 adjacent pixels. At the moment we do not have a direct way to compute a non-maximal suppression with ArrayFire, we have to write our own kernel for that. Non-maximal suppression is <del>only</del> just one of the cool things we will be able to do with our new computer vision toolset for ArrayFire.\r\n\r\nAn alternative is to do the non-maximal suppression in a naive way. To do this, we will use ArrayFire\'s <a href=\"http://www.accelereyes.com/arrayfire/c/group__image__func__cpp__maxfilt.htm\">maxfilt</a> function, <del>that</del> which filters the image with a mask of <code>NxM</code> pixel and returns the maximum value of the neighborhood to the pixel centered within the mask. In this case we will use a <code>3x3</code> pixel mask to return the maximum of the 8-neighborhood, including the central pixel itself.\r\n\r\nThe <a href=\"http://www.accelereyes.com/arrayfire/c/group__image__func__cpp__maxfilt.htm\">maxfilt</a> function alone will not perform a non-maximal suppression, but by combining the function with a few other steps<del>,</del> we can get the proper responses.\r\n\r\nThe nature of a pixel can be determined by the Harris responses<del>,</del>; a negative response means that a pixel corresponds to the segment of an edge. If the response is small but positive, it corresponds to a flat region. Only a large response corresponds to a corner. By thresholding the response array with the minimum desired Harris response, <del>that</del> which, for our example, will be 10<sup>5</sup>, we can calculate a binary response array for which only pixels with a value greater than this threshold will be true. We then multiply it to the original response array to get a new array containing only responses greater that 10<sup>5</sup>.\r\n\r\nHere<del>,</del> we will use a threshold of 10<sup>5</sup>. For the implementation presented in this article, we found that corners seem to be better for responses larger than 10<sup>4</sup>, but you can and should play with these values to see how it will affect the image you are working on.\r\n\r\nThe last step for this is testing whether each pixel is equal to the maximum Harris response of the neighborhood. If it is equal, then we keep it, else, the response is not a local maximum and we discard it.\r\n<pre>// Gets maximum response for each 3x3 neighborhood\r\narray max_resp = maxfilt(response, 3, 3);\r\n\r\n// Discard responses that are not greater than threshold\r\narray corners = response &gt; 1e5f;\r\ncorners = corners * response;\r\n\r\n// Discard responses that are not equal to maximum neighborhood response,\r\n// scale them to original response value\r\ncorners = (corners == max_resp) * corners;\r\n</pre>\r\nIf you still think you want a non-maximal suppression kernel for yourself, you can write it instead of using the last piece of code above. If you have never written your own kernel to work with an ArrayFire array, check out the <a href=\"http://sandbox.arrayfire.com/custom-kernels-with-arrayfire/\">Custom Kernels with ArrayFire</a> post. Writing the non-maximal suppression kernel itself will not take more than 20 or 30 lines of code.\r\n<h5>Plotting corners</h5>\r\nThis last step is done on the <abbr title=\"Central Processing Unit\">CPU</abbr> side<del>,</del>; we only do this to show the corners that are detected. This will most likely be unnecessary <del>Most likely, you will not need to do this</del> unless you want to visualize, but, for the sake of clarity, we will include this part to show the result.\r\n<pre>// Gets host pointer to response data\r\nfloat* h_corners = corners.host();\r\n\r\n// Draw draw_len x draw_len crosshairs where the corners are\r\nconst int draw_len = 3;\r\nfor (int y = draw_len; y &lt; img_color.dims(0) - draw_len; y++) {\r\n    for (int x = draw_len; x &lt; img_color.dims(1) - draw_len; x++) {\r\n        // Only draws crosshair if is a corner\r\n        if (h_corners[x * corners.dims(0) + y] &gt; 1e5f) {\r\n            // Draw horizontal line of (draw_len * 2 + 1) pixels centered on the corner\r\n            // Set only the first channel to 1 (green lines)\r\n            img_color(y, seq(x-draw_len, x+draw_len), 0) = 0.f;\r\n            img_color(y, seq(x-draw_len, x+draw_len), 1) = 1.f;\r\n            img_color(y, seq(x-draw_len, x+draw_len), 2) = 0.f;\r\n\r\n            // Draw vertical line of (draw_len * 2 + 1) pixels centered on  the corner\r\n            // Set only the first channel to 1 (green lines)\r\n            img_color(seq(y-draw_len, y+draw_len), x, 0) = 0.f;\r\n            img_color(seq(y-draw_len, y+draw_len), x, 1) = 1.f;\r\n            img_color(seq(y-draw_len, y+draw_len), x, 2) = 0.f;\r\n        }\r\n    }\r\n}</pre>\r\n<h5>Visualize results</h5>\r\nFinally, the image can be visualized.\r\n<pre>// Previews color image with green crosshairs\r\nimage(img_color);\r\n</pre>\r\nBelow you can see Lena\'s picture after the Harris corner detection and plotting. The green crosshairs indicate where corners are.\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_lena.png\"><img class=\"alignnone size-full wp-image-5710\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_lena.png\" alt=\"Harris Corners - Lena\" width=\"1024\" height=\"600\" /></a>\r\n\r\nTo test for correctness of the algorithm, nothing better than a picture with well-defined corners. Below you can see the picture of a white square on a black background and the corners marked by green crosshairs.\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_square.png\"><img class=\"alignnone size-full wp-image-5711\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_square.png\" alt=\"Harris Corners - Square\" width=\"1024\" height=\"600\" /></a>\r\n\r\nAll sources to our examples can be found in our <a href=\"https://github.com/arrayfire/arrayfire_examples\">ArrayFire examples project</a> on GitHub, and the complete code for this article can be viewed via this direct <a href=\"https://github.com/arrayfire/arrayfire_examples/blob/master/image_processing/harris_demo.cpp\">link</a>.\r\n\r\nWe would like to hear from you, what you are working on the computer vision field and which features you would like to see in ArrayFire. Please share your thoughts and requests below or contact us at <a href=\"mailto:sales@arrayfire.com\">sales@arrayfire.com</a>.\r\n<h5>References</h5>\r\n[1] Harris, Chris, and Mike Stephens. \"A combined corner and edge detector.\" <em>Alvey vision conference</em>. Vol. 15. 1988.','Writing a Simple Corner Detector with ArrayFire','','inherit','open','closed','','5659-revision-v1','','','2014-05-30 16:05:22','2014-05-30 16:05:22','',5659,'http://sandbox.arrayfire.com/5659-revision-v1/',0,'revision','',0),(5730,7,'2014-05-30 18:25:50','2014-05-30 18:25:50','In the upcoming months we\'ll be adding a lot of new Computer Vision functionality to ArrayFire, <span style=\"color: #333333;\">specifically targeting the most commonly used applications in this field. New functions include</span> feature tracking, object classification, scene segmentation, optical flow, and stereo-vision.\r\n\r\nFeature tracking consists of three basic steps:\r\n<ol>\r\n	<li>Detecting good or unique features; normally they are corners or blobs of an object.</li>\r\n	<li>Extracting a descriptor for each feature—understanding the texture of a small patch around each feature.</li>\r\n	<li>Descriptor matching—finding out the best match for each pair of descriptors (one from the object being tracked, another from a scene that potentially contains that object), if any.</li>\r\n</ol>\r\n<h3>Harris corner detector</h3>\r\nIn this article we will be using ArrayFire to dive deeper into the first step of feature tracking: detecting good features. Through a step-by-step guide we will develop a simple corner detector, known as the Harris corner detector [1].\r\n\r\nThe Harris corner detector is very simple to implement, especially when you have so many good tools and libraries out there to do the core matrix manipulation. What we specifically need for Harris are some convolutions, together with a few element-wise matrix addition and multiplication operations; all of these operations are present in most scientific tools and libraries that work with matrix manipulation. I will try to avoid going into the mathematical details in this post and go directly to the implementation.\r\n<h5>Loading an image</h5>\r\nBefore writing the code for the corner detector, we need to load an image. The image can be either color or grayscale, but it will only work on the grayscale version; if we upload a color image, we have to convert it before proceeding.\r\n<pre>// Load a color image\r\narray img_color = loadimage(\"lena.jpg\", true);\r\n// Convert the image from RGB to gray-scale\r\narray img_gray = colorspace(img_color, af_gray, af_rgb);\r\n// For visualization in ArrayFire, color images must be in the [0.0f-1.0f] interval\r\nimg_color /= 255.f;\r\n</pre>\r\n<h5>Compute first-order derivatives</h5>\r\nThe first step in the Harris corner detector is to determine first order derivatives of an image, in both horizontal and vertical directions. This can be achieved by one convolution for each direction, with the kernel (-1, 0, 1)  for horizontal derivative and its transpose for vertical derivative. ArrayFire contains a function called <a href=\"http://www.accelereyes.com/arrayfire/c/group__math__func__cpp__grad.htm\">grad</a>, which calculates gradients in both directions and will perform faster than the two convolutions. <span style=\"color: #008000;\">The only difference  is that <a href=\"http://www.accelereyes.com/arrayfire/c/group__math__func__cpp__grad.htm\"><span style=\"color: #008000;\">grad</span></a> divides the result by 2, thus, the response factor will change, but this can be compensated for by using a smaller response, while computation performance is improved, so <a href=\"http://www.accelereyes.com/arrayfire/c/group__math__func__cpp__grad.htm\"><span style=\"color: #008000;\">grad</span></a> can be used instead.</span> &lt;--This sentence is confusing and long. Split it up to improve clarity.\r\n<pre>// Calculate image gradients\r\narray ix, iy;\r\ngrad(ix, iy, img_gray);\r\n</pre>\r\n<h5>Compute second-order derivatives</h5>\r\nAt this point we have both horizontal and vertical first order derivatives of our image, but Harris corner detector is processed with second-order derivatives, which can be easily computed in ArrayFire with simple element-wise multiplications of the first-order derivatives.\r\n<pre>// Compute second-order derivatives\r\narray ixx = ix * ix;\r\narray ixy = ix * iy;\r\narray iyy = iy * iy;\r\n</pre>\r\n<h5>Compute an isotropic window</h5>\r\nTo check the cornerness of each pixel of an image, it\'s not enough to check the pixel value itself. We must also check a small window around that pixel. To reduce noise sensitivity and have an isotropic response, Harris claims that a smooth circular window should be used. This can be achieved by filtering of all three second-order derivatives with a Gaussian kernel.\r\n<pre>// Compute a Gaussian kernel with standard deviation of 1.0 and length of 5 pixels\r\n// These values can be changed to use a smaller or larger window\r\narray gauss_filt = gaussiankernel(5, 5, 1.0, 1.0);\r\n\r\n// Filter second-order derivatives with Gaussian kernel computed previously\r\nixx = convolve(ixx, gauss_filt);\r\nixy = convolve(ixy, gauss_filt);\r\niyy = convolve(iyy, gauss_filt);\r\n</pre>\r\n<h5>Compute trace and determinant</h5>\r\nFrom a second-order Hessian matrix, we then compute the values of its trace and determinant. These are the values we will need later to calculate the Harris response for each pixel in the image.\r\n<pre>// Calculate trace\r\narray tr = ixx + iyy;\r\n// Calculate determinant\r\narray det = ixx * iyy - ixy * ixy;\r\n</pre>\r\n<h5>Compute Harris response</h5>\r\nNext, we calculate the Harris response for each pixel. For this calculation, Harris uses an empirically defined constant <code>k</code>. This constant is usually very small, normally ranging from <code>0.04</code> to <code>0.06</code>. In our case, we will use <code>k = 0.04</code>, but we encourage you to play with this value and see how the result is affected.\r\n<pre>// Calculate Harris response\r\narray response = det - 0.04f * (tr * tr);\r\n</pre>\r\n<h5>Selection of good corners</h5>\r\nNow we already have our Harris responses for each pixel in the image. This value is used to determine whether a pixel is a corner or not. The standard way is to perform a non-maximal suppression, meaning that each pixel can only be a corner if it is a maximum compared to its 8 adjacent pixels. At the moment we do not have a direct way to compute a non-maximal suppression with ArrayFire; we have to write our own kernel for that. Non-maximal suppression is  just one of the cool things we will be able to do with our new computer vision toolset for ArrayFire.\r\n\r\nAn alternative is to do the non-maximal suppression in a naive way. To do this, we will use ArrayFire\'s <a href=\"http://www.accelereyes.com/arrayfire/c/group__image__func__cpp__maxfilt.htm\">maxfilt</a> function, which filters the image with a mask of <code>NxM</code> pixel and returns the maximum value of the neighborhood to the pixel centered within the mask. In this case we will use a <code>3x3</code> pixel mask to return the maximum of the 8-neighborhood, including the central pixel itself.\r\n\r\nThe <a href=\"http://www.accelereyes.com/arrayfire/c/group__image__func__cpp__maxfilt.htm\">maxfilt</a> function alone will not perform a non-maximal suppression, but by combining the function with a few other steps we can get the proper responses.\r\n\r\nThe nature of a pixel can be determined by the Harris responses; a negative response means that a pixel corresponds to the segment of an edge. If the response is small but positive, it corresponds to a flat region. Only a large response corresponds to a corner. By thresholding the response array with the minimum desired Harris response, which, for our example, will be 10<sup>5</sup>, we can calculate a binary response array for which only pixels with a value greater than this threshold will be true. We then multiply it to the original response array to get a new array containing only responses greater that 10<sup>5</sup>.\r\n\r\nHere we will use a threshold of 10<sup>5</sup>. For the implementation presented in this article, we found that corners seem to be better for responses larger than 10<sup>4</sup>, but you can and should play with these values to see how it will affect the image you are working on.\r\n\r\nThe last step for this is testing whether each pixel is equal to the maximum Harris response of the neighborhood. If it is equal, then we keep it, else, the response is not a local maximum and we discard it.\r\n<pre>// Gets maximum response for each 3x3 neighborhood\r\narray max_resp = maxfilt(response, 3, 3);\r\n\r\n// Discard responses that are not greater than threshold\r\narray corners = response &gt; 1e5f;\r\ncorners = corners * response;\r\n\r\n// Discard responses that are not equal to maximum neighborhood response,\r\n// scale them to original response value\r\ncorners = (corners == max_resp) * corners;\r\n</pre>\r\nIf you still think you want a non-maximal suppression kernel for yourself, you can write it instead of using the last piece of code above. If you have never written your own kernel to work with an ArrayFire array, check out the <a href=\"http://sandbox.arrayfire.com/custom-kernels-with-arrayfire/\">Custom Kernels with ArrayFire</a> post. Writing the non-maximal suppression kernel itself will not take more than 20 or 30 lines of code.\r\n<h5>Plotting corners</h5>\r\nThis last step is done on the <abbr title=\"Central Processing Unit\">CPU</abbr> side; we only do this to show the corners that are detected. This will most likely be unnecessary unless you want to visualize, but, for the sake of clarity, we will include this part to show the result.\r\n<pre>// Gets host pointer to response data\r\nfloat* h_corners = corners.host();\r\n\r\n// Draw draw_len x draw_len crosshairs where the corners are\r\nconst int draw_len = 3;\r\nfor (int y = draw_len; y &lt; img_color.dims(0) - draw_len; y++) {\r\n    for (int x = draw_len; x &lt; img_color.dims(1) - draw_len; x++) {\r\n        // Only draws crosshair if is a corner\r\n        if (h_corners[x * corners.dims(0) + y] &gt; 1e5f) {\r\n            // Draw horizontal line of (draw_len * 2 + 1) pixels centered on the corner\r\n            // Set only the first channel to 1 (green lines)\r\n            img_color(y, seq(x-draw_len, x+draw_len), 0) = 0.f;\r\n            img_color(y, seq(x-draw_len, x+draw_len), 1) = 1.f;\r\n            img_color(y, seq(x-draw_len, x+draw_len), 2) = 0.f;\r\n\r\n            // Draw vertical line of (draw_len * 2 + 1) pixels centered on  the corner\r\n            // Set only the first channel to 1 (green lines)\r\n            img_color(seq(y-draw_len, y+draw_len), x, 0) = 0.f;\r\n            img_color(seq(y-draw_len, y+draw_len), x, 1) = 1.f;\r\n            img_color(seq(y-draw_len, y+draw_len), x, 2) = 0.f;\r\n        }\r\n    }\r\n}</pre>\r\n<h5>Visualize results</h5>\r\nFinally, the image can be visualized.\r\n<pre>// Previews color image with green crosshairs\r\nimage(img_color);\r\n</pre>\r\nBelow you can see Lena\'s picture after the Harris corner detection and plotting. The green crosshairs indicate where corners are.\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_lena.png\"><img class=\"alignnone size-full wp-image-5710\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_lena.png\" alt=\"Harris Corners - Lena\" width=\"1024\" height=\"600\" /></a>\r\n\r\nTo test for correctness of the algorithm, nothing better than a picture with well-defined corners. Below you can see the picture of a white square on a black background and the corners marked by green crosshairs.\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_square.png\"><img class=\"alignnone size-full wp-image-5711\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_square.png\" alt=\"Harris Corners - Square\" width=\"1024\" height=\"600\" /></a>\r\n\r\nAll sources to our examples can be found in our <a href=\"https://github.com/arrayfire/arrayfire_examples\">ArrayFire examples project</a> on GitHub, and the complete code for this article can be viewed via this direct <a href=\"https://github.com/arrayfire/arrayfire_examples/blob/master/image_processing/harris_demo.cpp\">link</a>.\r\n\r\nWe would like to hear from you! What you are working on the computer vision field and what features would you like to see in ArrayFire? Please share your thoughts and requests below or contact us at <a href=\"mailto:sales@arrayfire.com\">sales@arrayfire.com</a>.\r\n<h5>References</h5>\r\n[1] Harris, Chris, and Mike Stephens. \"A combined corner and edge detector.\" <em>Alvey vision conference</em>. Vol. 15. 1988.','Writing a Simple Corner Detector with ArrayFire','','inherit','open','closed','','5659-revision-v1','','','2014-05-30 18:25:50','2014-05-30 18:25:50','',5659,'http://sandbox.arrayfire.com/5659-revision-v1/',0,'revision','',0),(5731,7,'2014-05-30 18:37:39','2014-05-30 18:37:39','In the upcoming months we\'ll be adding a lot of new Computer Vision functionality to ArrayFire, <span style=\"color: #333333;\">specifically targeting the most commonly used applications in this field. New functions include</span> feature tracking, object classification, scene segmentation, optical flow, and stereo-vision.\r\n\r\nFeature tracking consists of three basic steps:\r\n<ol>\r\n	<li>Detecting good or unique features; normally they are corners or blobs of an object.</li>\r\n	<li>Extracting a descriptor for each feature—understanding the texture of a small patch around each feature.</li>\r\n	<li>Descriptor matching—finding out the best match for each pair of descriptors (one from the object being tracked, another from a scene that potentially contains that object), if any.</li>\r\n</ol>\r\n<h3>Harris corner detector</h3>\r\nIn this article we will be using ArrayFire to dive deeper into the first step of feature tracking: detecting good features. Through a step-by-step guide we will develop a simple corner detector, known as the Harris corner detector [1].\r\n\r\nThe Harris corner detector is very simple to implement, especially when you have so many good tools and libraries out there to do the core matrix manipulation. What we specifically need for Harris are some convolutions, together with a few element-wise matrix addition and multiplication operations; all of these operations are present in most scientific tools and libraries that work with matrix manipulation. I will try to avoid going into the mathematical details in this post and go directly to the implementation.\r\n<h5>Loading an image</h5>\r\nBefore writing the code for the corner detector, we need to load an image. The image can be either color or grayscale, but it will only work on the grayscale version; if we upload a color image, we have to convert it before proceeding.\r\n<pre>// Load a color image\r\narray img_color = loadimage(\"lena.jpg\", true);\r\n// Convert the image from RGB to gray-scale\r\narray img_gray = colorspace(img_color, af_gray, af_rgb);\r\n// For visualization in ArrayFire, color images must be in the [0.0f-1.0f] interval\r\nimg_color /= 255.f;\r\n</pre>\r\n<h5>Compute first-order derivatives</h5>\r\nThe first step in the Harris corner detector is to determine first order derivatives of an image, in both horizontal and vertical directions. This can be achieved by one convolution for each direction, with the kernel (-1, 0, 1)  for horizontal derivative and its transpose for vertical derivative. ArrayFire contains a function called <a href=\"http://www.accelereyes.com/arrayfire/c/group__math__func__cpp__grad.htm\">grad</a>, which calculates gradients in both directions and will perform faster than the two convolutions. The only difference  is that <a href=\"http://www.accelereyes.com/arrayfire/c/group__math__func__cpp__grad.htm\">grad</a> divides the result by 2, thus, the response factor will change. The use of grad will improve the performance, and factor change can be easily compensated by using a smaller response.\r\n<pre>// Calculate image gradients\r\narray ix, iy;\r\ngrad(ix, iy, img_gray);\r\n</pre>\r\n<h5>Compute second-order derivatives</h5>\r\nAt this point we have both horizontal and vertical first order derivatives of our image, but Harris corner detector is processed with second-order derivatives, which can be easily computed in ArrayFire with simple element-wise multiplications of the first-order derivatives.\r\n<pre>// Compute second-order derivatives\r\narray ixx = ix * ix;\r\narray ixy = ix * iy;\r\narray iyy = iy * iy;\r\n</pre>\r\n<h5>Compute an isotropic window</h5>\r\nTo check the cornerness of each pixel of an image, it\'s not enough to check the pixel value itself. We must also check a small window around that pixel. To reduce noise sensitivity and have an isotropic response, Harris claims that a smooth circular window should be used. This can be achieved by filtering of all three second-order derivatives with a Gaussian kernel.\r\n<pre>// Compute a Gaussian kernel with standard deviation of 1.0 and length of 5 pixels\r\n// These values can be changed to use a smaller or larger window\r\narray gauss_filt = gaussiankernel(5, 5, 1.0, 1.0);\r\n\r\n// Filter second-order derivatives with Gaussian kernel computed previously\r\nixx = convolve(ixx, gauss_filt);\r\nixy = convolve(ixy, gauss_filt);\r\niyy = convolve(iyy, gauss_filt);\r\n</pre>\r\n<h5>Compute trace and determinant</h5>\r\nFrom a second-order Hessian matrix, we then compute the values of its trace and determinant. These are the values we will need later to calculate the Harris response for each pixel in the image.\r\n<pre>// Calculate trace\r\narray tr = ixx + iyy;\r\n// Calculate determinant\r\narray det = ixx * iyy - ixy * ixy;\r\n</pre>\r\n<h5>Compute Harris response</h5>\r\nNext, we calculate the Harris response for each pixel. For this calculation, Harris uses an empirically defined constant <code>k</code>. This constant is usually very small, normally ranging from <code>0.04</code> to <code>0.06</code>. In our case, we will use <code>k = 0.04</code>, but we encourage you to play with this value and see how the result is affected.\r\n<pre>// Calculate Harris response\r\narray response = det - 0.04f * (tr * tr);\r\n</pre>\r\n<h5>Selection of good corners</h5>\r\nNow we already have our Harris responses for each pixel in the image. This value is used to determine whether a pixel is a corner or not. The standard way is to perform a non-maximal suppression, meaning that each pixel can only be a corner if it is a maximum compared to its 8 adjacent pixels. At the moment we do not have a direct way to compute a non-maximal suppression with ArrayFire; we have to write our own kernel for that. Non-maximal suppression is  just one of the cool things we will be able to do with our new computer vision toolset for ArrayFire.\r\n\r\nAn alternative is to do the non-maximal suppression in a naive way. To do this, we will use ArrayFire\'s <a href=\"http://www.accelereyes.com/arrayfire/c/group__image__func__cpp__maxfilt.htm\">maxfilt</a> function, which filters the image with a mask of <code>NxM</code> pixel and returns the maximum value of the neighborhood to the pixel centered within the mask. In this case we will use a <code>3x3</code> pixel mask to return the maximum of the 8-neighborhood, including the central pixel itself.\r\n\r\nThe <a href=\"http://www.accelereyes.com/arrayfire/c/group__image__func__cpp__maxfilt.htm\">maxfilt</a> function alone will not perform a non-maximal suppression, but by combining the function with a few other steps we can get the proper responses.\r\n\r\nThe nature of a pixel can be determined by the Harris responses; a negative response means that a pixel corresponds to the segment of an edge. If the response is small but positive, it corresponds to a flat region. Only a large response corresponds to a corner. By thresholding the response array with the minimum desired Harris response, which, for our example, will be 10<sup>5</sup>, we can calculate a binary response array for which only pixels with a value greater than this threshold will be true. We then multiply it to the original response array to get a new array containing only responses greater that 10<sup>5</sup>.\r\n\r\nHere we will use a threshold of 10<sup>5</sup>. For the implementation presented in this article, we found that corners seem to be better for responses larger than 10<sup>4</sup>, but you can and should play with these values to see how it will affect the image you are working on.\r\n\r\nThe last step for this is testing whether each pixel is equal to the maximum Harris response of the neighborhood. If it is equal, then we keep it, else, the response is not a local maximum and we discard it.\r\n<pre>// Gets maximum response for each 3x3 neighborhood\r\narray max_resp = maxfilt(response, 3, 3);\r\n\r\n// Discard responses that are not greater than threshold\r\narray corners = response &gt; 1e5f;\r\ncorners = corners * response;\r\n\r\n// Discard responses that are not equal to maximum neighborhood response,\r\n// scale them to original response value\r\ncorners = (corners == max_resp) * corners;\r\n</pre>\r\nIf you still think you want a non-maximal suppression kernel for yourself, you can write it instead of using the last piece of code above. If you have never written your own kernel to work with an ArrayFire array, check out the <a href=\"http://sandbox.arrayfire.com/custom-kernels-with-arrayfire/\">Custom Kernels with ArrayFire</a> post. Writing the non-maximal suppression kernel itself will not take more than 20 or 30 lines of code.\r\n<h5>Plotting corners</h5>\r\nThis last step is done on the <abbr title=\"Central Processing Unit\">CPU</abbr> side; we only do this to show the corners that are detected. This will most likely be unnecessary unless you want to visualize, but, for the sake of clarity, we will include this part to show the result.\r\n<pre>// Gets host pointer to response data\r\nfloat* h_corners = corners.host();\r\n\r\n// Draw draw_len x draw_len crosshairs where the corners are\r\nconst int draw_len = 3;\r\nfor (int y = draw_len; y &lt; img_color.dims(0) - draw_len; y++) {\r\n    for (int x = draw_len; x &lt; img_color.dims(1) - draw_len; x++) {\r\n        // Only draws crosshair if is a corner\r\n        if (h_corners[x * corners.dims(0) + y] &gt; 1e5f) {\r\n            // Draw horizontal line of (draw_len * 2 + 1) pixels centered on the corner\r\n            // Set only the first channel to 1 (green lines)\r\n            img_color(y, seq(x-draw_len, x+draw_len), 0) = 0.f;\r\n            img_color(y, seq(x-draw_len, x+draw_len), 1) = 1.f;\r\n            img_color(y, seq(x-draw_len, x+draw_len), 2) = 0.f;\r\n\r\n            // Draw vertical line of (draw_len * 2 + 1) pixels centered on  the corner\r\n            // Set only the first channel to 1 (green lines)\r\n            img_color(seq(y-draw_len, y+draw_len), x, 0) = 0.f;\r\n            img_color(seq(y-draw_len, y+draw_len), x, 1) = 1.f;\r\n            img_color(seq(y-draw_len, y+draw_len), x, 2) = 0.f;\r\n        }\r\n    }\r\n}</pre>\r\n<h5>Visualize results</h5>\r\nFinally, the image can be visualized.\r\n<pre>// Previews color image with green crosshairs\r\nimage(img_color);\r\n</pre>\r\nBelow you can see Lena\'s picture after the Harris corner detection and plotting. The green crosshairs indicate where corners are.\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_lena.png\"><img class=\"alignnone size-full wp-image-5710\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_lena.png\" alt=\"Harris Corners - Lena\" width=\"1024\" height=\"600\" /></a>\r\n\r\nTo test for correctness of the algorithm, nothing better than a picture with well-defined corners. Below you can see the picture of a white square on a black background and the corners marked by green crosshairs.\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_square.png\"><img class=\"alignnone size-full wp-image-5711\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_square.png\" alt=\"Harris Corners - Square\" width=\"1024\" height=\"600\" /></a>\r\n\r\nAll sources to our examples can be found in our <a href=\"https://github.com/arrayfire/arrayfire_examples\">ArrayFire examples project</a> on GitHub, and the complete code for this article can be viewed via this direct <a href=\"https://github.com/arrayfire/arrayfire_examples/blob/master/image_processing/harris_demo.cpp\">link</a>.\r\n\r\nWe would like to hear from you! What you are working on the computer vision field and what features would you like to see in ArrayFire? Please share your thoughts and requests below or contact us at <a href=\"mailto:sales@arrayfire.com\">sales@arrayfire.com</a>.\r\n<h5>References</h5>\r\n[1] Harris, Chris, and Mike Stephens. \"A combined corner and edge detector.\" <em>Alvey vision conference</em>. Vol. 15. 1988.','Writing a Simple Corner Detector with ArrayFire','','inherit','open','closed','','5659-revision-v1','','','2014-05-30 18:37:39','2014-05-30 18:37:39','',5659,'http://sandbox.arrayfire.com/5659-revision-v1/',0,'revision','',0),(5732,7,'2014-05-30 18:39:38','2014-05-30 18:39:38','In the upcoming months we\'ll be adding a lot of new Computer Vision functionality to ArrayFire, specifically targeting the most commonly used applications in this field. New functions include feature tracking, object classification, scene segmentation, optical flow, and stereo-vision.\r\n\r\nFeature tracking consists of three basic steps:\r\n<ol>\r\n	<li>Detecting good or unique features; normally they are corners or blobs of an object.</li>\r\n	<li>Extracting a descriptor for each feature—understanding the texture of a small patch around each feature.</li>\r\n	<li>Descriptor matching—finding out the best match for each pair of descriptors (one from the object being tracked, another from a scene that potentially contains that object), if any.</li>\r\n</ol>\r\n<h3>Harris corner detector</h3>\r\nIn this article we will be using ArrayFire to dive deeper into the first step of feature tracking: detecting good features. Through a step-by-step guide we will develop a simple corner detector, known as the Harris corner detector [1].\r\n\r\nThe Harris corner detector is very simple to implement, especially when you have so many good tools and libraries out there to do the core matrix manipulation. What we specifically need for Harris are some convolutions, together with a few element-wise matrix addition and multiplication operations; all of these operations are present in most scientific tools and libraries that work with matrix manipulation. I will try to avoid going into the mathematical details in this post and go directly to the implementation.\r\n<h5>Loading an image</h5>\r\nBefore writing the code for the corner detector, we need to load an image. The image can be either color or grayscale, but it will only work on the grayscale version; if we upload a color image, we have to convert it before proceeding.\r\n<pre>// Load a color image\r\narray img_color = loadimage(\"lena.jpg\", true);\r\n// Convert the image from RGB to gray-scale\r\narray img_gray = colorspace(img_color, af_gray, af_rgb);\r\n// For visualization in ArrayFire, color images must be in the [0.0f-1.0f] interval\r\nimg_color /= 255.f;\r\n</pre>\r\n<h5>Compute first-order derivatives</h5>\r\nThe first step in the Harris corner detector is to determine first order derivatives of an image, in both horizontal and vertical directions. This can be achieved by one convolution for each direction, with the kernel (-1, 0, 1)  for horizontal derivative and its transpose for vertical derivative. ArrayFire contains a function called <a href=\"http://www.accelereyes.com/arrayfire/c/group__math__func__cpp__grad.htm\">grad</a>, which calculates gradients in both directions and will perform faster than the two convolutions. The only difference  is that <a href=\"http://www.accelereyes.com/arrayfire/c/group__math__func__cpp__grad.htm\">grad</a> divides the result by 2, thus, the response factor will change. The use of grad will improve the performance, and factor change can be easily compensated by using a smaller response.\r\n<pre>// Calculate image gradients\r\narray ix, iy;\r\ngrad(ix, iy, img_gray);\r\n</pre>\r\n<h5>Compute second-order derivatives</h5>\r\nAt this point we have both horizontal and vertical first order derivatives of our image, but Harris corner detector is processed with second-order derivatives, which can be easily computed in ArrayFire with simple element-wise multiplications of the first-order derivatives.\r\n<pre>// Compute second-order derivatives\r\narray ixx = ix * ix;\r\narray ixy = ix * iy;\r\narray iyy = iy * iy;\r\n</pre>\r\n<h5>Compute an isotropic window</h5>\r\nTo check the cornerness of each pixel of an image, it\'s not enough to check the pixel value itself. We must also check a small window around that pixel. To reduce noise sensitivity and have an isotropic response, Harris claims that a smooth circular window should be used. This can be achieved by filtering of all three second-order derivatives with a Gaussian kernel.\r\n<pre>// Compute a Gaussian kernel with standard deviation of 1.0 and length of 5 pixels\r\n// These values can be changed to use a smaller or larger window\r\narray gauss_filt = gaussiankernel(5, 5, 1.0, 1.0);\r\n\r\n// Filter second-order derivatives with Gaussian kernel computed previously\r\nixx = convolve(ixx, gauss_filt);\r\nixy = convolve(ixy, gauss_filt);\r\niyy = convolve(iyy, gauss_filt);\r\n</pre>\r\n<h5>Compute trace and determinant</h5>\r\nFrom a second-order Hessian matrix, we then compute the values of its trace and determinant. These are the values we will need later to calculate the Harris response for each pixel in the image.\r\n<pre>// Calculate trace\r\narray tr = ixx + iyy;\r\n// Calculate determinant\r\narray det = ixx * iyy - ixy * ixy;\r\n</pre>\r\n<h5>Compute Harris response</h5>\r\nNext, we calculate the Harris response for each pixel. For this calculation, Harris uses an empirically defined constant <code>k</code>. This constant is usually very small, normally ranging from <code>0.04</code> to <code>0.06</code>. In our case, we will use <code>k = 0.04</code>, but we encourage you to play with this value and see how the result is affected.\r\n<pre>// Calculate Harris response\r\narray response = det - 0.04f * (tr * tr);\r\n</pre>\r\n<h5>Selection of good corners</h5>\r\nNow we already have our Harris responses for each pixel in the image. This value is used to determine whether a pixel is a corner or not. The standard way is to perform a non-maximal suppression, meaning that each pixel can only be a corner if it is a maximum compared to its 8 adjacent pixels. At the moment we do not have a direct way to compute a non-maximal suppression with ArrayFire; we have to write our own kernel for that. Non-maximal suppression is  just one of the cool things we will be able to do with our new computer vision toolset for ArrayFire.\r\n\r\nAn alternative is to do the non-maximal suppression in a naive way. To do this, we will use ArrayFire\'s <a href=\"http://www.accelereyes.com/arrayfire/c/group__image__func__cpp__maxfilt.htm\">maxfilt</a> function, which filters the image with a mask of <code>NxM</code> pixel and returns the maximum value of the neighborhood to the pixel centered within the mask. In this case we will use a <code>3x3</code> pixel mask to return the maximum of the 8-neighborhood, including the central pixel itself.\r\n\r\nThe <a href=\"http://www.accelereyes.com/arrayfire/c/group__image__func__cpp__maxfilt.htm\">maxfilt</a> function alone will not perform a non-maximal suppression, but by combining the function with a few other steps we can get the proper responses.\r\n\r\nThe nature of a pixel can be determined by the Harris responses; a negative response means that a pixel corresponds to the segment of an edge. If the response is small but positive, it corresponds to a flat region. Only a large response corresponds to a corner. By thresholding the response array with the minimum desired Harris response, which, for our example, will be 10<sup>5</sup>, we can calculate a binary response array for which only pixels with a value greater than this threshold will be true. We then multiply it to the original response array to get a new array containing only responses greater that 10<sup>5</sup>.\r\n\r\nHere we will use a threshold of 10<sup>5</sup>. For the implementation presented in this article, we found that corners seem to be better for responses larger than 10<sup>4</sup>, but you can and should play with these values to see how it will affect the image you are working on.\r\n\r\nThe last step for this is testing whether each pixel is equal to the maximum Harris response of the neighborhood. If it is equal, then we keep it, else, the response is not a local maximum and we discard it.\r\n<pre>// Gets maximum response for each 3x3 neighborhood\r\narray max_resp = maxfilt(response, 3, 3);\r\n\r\n// Discard responses that are not greater than threshold\r\narray corners = response &gt; 1e5f;\r\ncorners = corners * response;\r\n\r\n// Discard responses that are not equal to maximum neighborhood response,\r\n// scale them to original response value\r\ncorners = (corners == max_resp) * corners;\r\n</pre>\r\nIf you still think you want a non-maximal suppression kernel for yourself, you can write it instead of using the last piece of code above. If you have never written your own kernel to work with an ArrayFire array, check out the <a href=\"http://sandbox.arrayfire.com/custom-kernels-with-arrayfire/\">Custom Kernels with ArrayFire</a> post. Writing the non-maximal suppression kernel itself will not take more than 20 or 30 lines of code.\r\n<h5>Plotting corners</h5>\r\nThis last step is done on the <abbr title=\"Central Processing Unit\">CPU</abbr> side; we only do this to show the corners that are detected. This will most likely be unnecessary unless you want to visualize, but, for the sake of clarity, we will include this part to show the result.\r\n<pre>// Gets host pointer to response data\r\nfloat* h_corners = corners.host();\r\n\r\n// Draw draw_len x draw_len crosshairs where the corners are\r\nconst int draw_len = 3;\r\nfor (int y = draw_len; y &lt; img_color.dims(0) - draw_len; y++) {\r\n    for (int x = draw_len; x &lt; img_color.dims(1) - draw_len; x++) {\r\n        // Only draws crosshair if is a corner\r\n        if (h_corners[x * corners.dims(0) + y] &gt; 1e5f) {\r\n            // Draw horizontal line of (draw_len * 2 + 1) pixels centered on the corner\r\n            // Set only the first channel to 1 (green lines)\r\n            img_color(y, seq(x-draw_len, x+draw_len), 0) = 0.f;\r\n            img_color(y, seq(x-draw_len, x+draw_len), 1) = 1.f;\r\n            img_color(y, seq(x-draw_len, x+draw_len), 2) = 0.f;\r\n\r\n            // Draw vertical line of (draw_len * 2 + 1) pixels centered on  the corner\r\n            // Set only the first channel to 1 (green lines)\r\n            img_color(seq(y-draw_len, y+draw_len), x, 0) = 0.f;\r\n            img_color(seq(y-draw_len, y+draw_len), x, 1) = 1.f;\r\n            img_color(seq(y-draw_len, y+draw_len), x, 2) = 0.f;\r\n        }\r\n    }\r\n}</pre>\r\n<h5>Visualize results</h5>\r\nFinally, the image can be visualized.\r\n<pre>// Previews color image with green crosshairs\r\nimage(img_color);\r\n</pre>\r\nBelow you can see Lena\'s picture after the Harris corner detection and plotting. The green crosshairs indicate where corners are.\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_lena.png\"><img class=\"alignnone size-full wp-image-5710\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_lena.png\" alt=\"Harris Corners - Lena\" width=\"1024\" height=\"600\" /></a>\r\n\r\nTo test for correctness of the algorithm, nothing better than a picture with well-defined corners. Below you can see the picture of a white square on a black background and the corners marked by green crosshairs.\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_square.png\"><img class=\"alignnone size-full wp-image-5711\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_square.png\" alt=\"Harris Corners - Square\" width=\"1024\" height=\"600\" /></a>\r\n\r\nAll sources to our examples can be found in our <a href=\"https://github.com/arrayfire/arrayfire_examples\">ArrayFire examples project</a> on GitHub, and the complete code for this article can be viewed via this direct <a href=\"https://github.com/arrayfire/arrayfire_examples/blob/master/image_processing/harris_demo.cpp\">link</a>.\r\n\r\nWe would like to hear from you! What you are working on the computer vision field and what features would you like to see in ArrayFire? Please share your thoughts and requests below or contact us at <a href=\"mailto:sales@arrayfire.com\">sales@arrayfire.com</a>.\r\n<h5>References</h5>\r\n[1] Harris, Chris, and Mike Stephens. \"A combined corner and edge detector.\" <em>Alvey vision conference</em>. Vol. 15. 1988.','Writing a Simple Corner Detector with ArrayFire','','inherit','open','closed','','5659-revision-v1','','','2014-05-30 18:39:38','2014-05-30 18:39:38','',5659,'http://sandbox.arrayfire.com/5659-revision-v1/',0,'revision','',0),(5733,7,'2014-05-30 19:24:44','2014-05-30 19:24:44','[content_band inner_container=\"true\" no_margin=\"true\" border=\"none\" padding_top=\"40px\" padding_bottom=\"40px\"][column type=\"two-fifths\"]\r\n\r\n[custom_headline type=\"left\" level=\"h3\"]If you want faster code, you\'ve come to the right place.[/custom_headline][gap size=\"15%\"][button  type=\"flat\" shape=\"rounded\" href=\"http://www.sandbox.arrayfire.com/docs/installation.htm\" size=\"x-large\" block=\"true\"]Download ArrayFire[/button]\r\n\r\n[gap size=\"10%\"]\r\n\r\n[button  type=\"flat\" block=\"true\" shape=\"rounded\" href=\"http://www.meetme.so/arrayfire\" size=\"x-large\" ]Schedule a consultation[/button]\r\n\r\n[/column][column type=\"three-fifths\" last=\"true\"][gap size=\"7%\"]\r\n<div id=\"wistia_rj2bar3xxp\" class=\"wistia_embed\" style=\"width: 640px; height: 388px;\"></div>\r\n<script src=\"//fast.wistia.com/assets/external/E-v1.js\" charset=\"ISO-8859-1\"></script><script>// <![CDATA[\r\nwistiaEmbed = Wistia.embed(\"rj2bar3xxp\");\r\n// ]]></script>[/column]\r\n<div id=\"arrayfire\"></div>\r\n[/content_band]\r\n\r\n[content_band inner_container=\"true\" no_margin=\"true\" border=\"top\" padding_top=\"40px\" padding_bottom=\"40px\"][column type=\"one-half\"][custom_headline type=\"left\" level=\"h3\"]Faster code[/custom_headline]\r\n\r\nArrayFire is a fast, hardware-neutral software library for GPU computing with an easy-to-use API. Its array-based function set makes GPU programming simple. A few lines of code in ArrayFire can replace dozens of lines of raw GPU code, saving you valuable time and lowering development costs.\r\n\r\n[gap size=\"10%\"][button  type=\"flat\" shape=\"rounded\" href=\"http://www.sandbox.arrayfire.com/docs/installation.htm\" size=\"x-large\" ]Download ArrayFire[/button][/column][column type=\"one-half\" last=\"true\" class=\"center-text\"][gap size=\"5%\"][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/Triumvirate_Exported.png\"][/column] [gap size=\"5%\"]\r\n\r\n[column type=\"one-third\" class=\"center-text\"][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/04/Googlelogo-e1396387097279.png\"][line]Video content analysis is the basis for categorizing videos and enabling search by content. Google used ArrayFire to extract motion features in video, improving performance by substantially accelerating the solution of the L1-regularized least-squares optimization problem.[/column][column type=\"one-third\" class=\"center-text\"][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/04/Koch-Industries-e1396387359637.jpg\"][line]Andrew Shin, Market Risk Manager of Koch Supply &amp; Trading, achieves significant performance increases on option pricing algorithms using ArrayFire software, \"My buddy and I are, at best, novice programmers and we couldn\'t imagine having to figure out how to code all this in CUDA.\"[/column][column type=\"one-third\" last=\"true\" class=\"center-text\"][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/04/nasa-e1396387230473.png\"][line]The main thrust of this research was improving Mars rover image compression via GPUs and genetic algorithms. With ArrayFire software and GPUs, the researchers were able to achieve 5X speedups on the larger data sizes.[/column]\r\n<div id=\"hardware\"></div>\r\n[/content_band]\r\n[content_band inner_container=\"true\" no_margin=\"true\" border=\"top\" padding_top=\"40px\" padding_bottom=\"40px\"]\r\n\r\n[column type=\"one-half\"][gap size=\"15%\"]\r\n\r\n<img class=\"aligncenter\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/CUDA-logo.jpg\" alt=\"CUDA logo\" width=\"231\" height=\"140\" />\r\n\r\n<img class=\"aligncenter\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/OpenCLLogo_678x452.png\" alt=\"OpenCL\" width=\"326\" height=\"217\" />\r\n\r\n[/column][column type=\"one-half\" last=\"true\"][gap size=\"10%\"]\r\n\r\n[custom_headline type=\"left\" level=\"h3\"] ArrayFire for CUDA and OpenCL[/custom_headline]\r\n\r\nArrayFire supports CUDA-capable NVIDIA GPUs and most OpenCL devices, including AMD GPUs/APUs and Intel Xeon Phi co-processors. It also supports mobile OpenCL devices from ARM, Qualcomm, and others.\r\n\r\nArrayFire is a high-performance software library designed for maximum productivity and speed without the hassle of writing difficult low-level device code. Each of ArrayFire\'s functions has been hand-tuned by our CUDA and OpenCL experts.\r\n\r\n[/column]\r\n<div id=\"mobile\"></div>\r\n[/content_band]\r\n\r\n[content_band inner_container=\"true\" no_margin=\"true\" border=\"top\" padding_top=\"40px\" padding_bottom=\"40px\"]\r\n[column type=\"one-half\"][custom_headline type=\"left\" level=\"h3\"  ]Mobile GPU Computing[/custom_headline]\r\n\r\nMobile GPUs offer accelerated performance. If you would like to use ArrayFire in a mobile application or if you would like to hire our mobile acceleration services, email us at <a href=\"mailto:sales@arrayfire.com\" target=\"_blank\">sales@arrayfire.com</a> and include a description of your application.\r\n\r\nOur clients have achieved between 5X to 30X speed boosts for convolutions and other compute functions on mobile devices. It enables:[icon_list][icon_list_item type=\"angle-double-right\"]Real-time video processing[/icon_list_item][icon_list_item type=\"angle-double-right\"]Better augmented reality [/icon_list_item][icon_list_item type=\"angle-double-right\"]Better computational photograph[/icon_list_item][icon_list_item type=\"angle-double-right\"]Faster data processing[/icon_list_item][/icon_list]\r\n\r\nAll mobile devices have a GPU which can deliver greater compute throughput than the CPU. Why not use the GPU to make your app faster?[/column][column type=\"one-half\" fade=\"true\" last=\"true\" fade_animation=\"in-from-right\" class=\"center-text\"][gap size=\"10%\"][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/02/mobile_Exported1-e1395437261846.png\"][/column]\r\n<div id=\"documentation\"></div>\r\n[/content_band]\r\n\r\n[content_band inner_container=\"true\" no_margin=\"true\" border=\"top\" padding_top=\"40px\" padding_bottom=\"40px\"][column type=\"one-half\"][custom_headline type=\"left\" level=\"h3\"]Documentation[/custom_headline]\r\n<h5>ArrayFire for C, C++, and Fortran</h5>\r\nOpen the hood—take a look at the beautiful nitty-gritty.\r\n\r\n[icon type=\"angle-double-right\"] <a href=\"http://www.sandbox.arrayfire.com/docs/\" target=\"_blank\">CUDA &amp; OpenCL C/C++</a>\r\n<h5>Functions</h5>\r\nHundreds of functions, hand-tuned and optimized by our engineers.\r\n\r\n[icon type=\"angle-double-right\"] <a title=\"ArrayFire Functions\" href=\"http://www.sandbox.arrayfire.com/docs/modules.htm\">ArrayFire Functions</a>\r\n<h5>User Forums</h5>\r\nEvery post gets a response from ArrayFire engineers.\r\n\r\n[icon type=\"angle-double-right\"] <a href=\"http://forums.accelereyes.com/\" target=\"_blank\">User Forums</a>\r\n\r\n[/column][column class=\"center-text\" type=\"one-half\" last=\"true\" fade=\"true\" fade_animation=\"in-from-right\" ][gap size=\"5%\"][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/gears1.png\"][/column]\r\n<div id=\"benchmarks\"></div>\r\n[/content_band]\r\n\r\n[content_band inner_container=\"true\" no_margin=\"true\" border=\"top\" padding_top=\"40px\" padding_bottom=\"40px\"]\r\n[column type=\"one-half\" fade=\"true\" fade_animation=\"in-from-left\" ][gap size=\"5%\"][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/02/Benchmark-guy-torso-opposite-e1392155948298.png\"][/column]\r\n\r\n[column type=\"one-half\" last=\"true\"][custom_headline type=\"left\" level=\"h3\" ]Benchmarks[/custom_headline]\r\n\r\nAll benchmarks were performed on a NVIDIA Tesla C2050 with an Intel i7-950 processor. The benchmarks compare ArrayFire with several popular CPU-based acceleration libraries, including <a href=\"http://software.intel.com/en-us/articles/intel-mkl/\" target=\"_new\">Intel Math Kernel Library</a>, <a href=\"http://software.intel.com/en-us/articles/intel-ipp/\" target=\"_new\">Intel Integrated Performance Primitives</a>, <a href=\"http://eigen.tuxfamily.org/index.php?title=Main_Page\" target=\"_new\">Eigen</a>, and <a href=\"http://arma.sourceforge.net/\" target=\"_new\">Armadillo</a>.[/column]\r\n\r\n[column type=\"one-fifth\"].[/column][column type=\"three-fifths\"][tab_nav type=\"four-up\"][tab_nav_item title=\"Base\" active=\"true\"][tab_nav_item title=\"Linear Algebra\" active=\"\"][tab_nav_item title=\"Convolution\" active=\"\"][tab_nav_item title=\"Utility\" active=\"\"][/tab_nav][tabs][tab active=\"true\"]<img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/matrix_multiply-1024x730.png\" alt=\"Matrix Multiply\" width=\"491\" height=\"350\" />[line]<img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/matrix_transpose-1024x730.png\" alt=\"Matrix Transpose\" width=\"491\" height=\"350\" />[line]<img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/fft-1024x730.png\" alt=\"FFT\" width=\"491\" height=\"350\" />[/tab][tab]<img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/lu-1024x730.png\" alt=\"LU\" width=\"491\" height=\"350\" />[line]<img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/svd-1024x730.png\" alt=\"SVD\" width=\"491\" height=\"350\" />[line]<img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/solve-1024x730.png\" alt=\"Solve\" width=\"491\" height=\"350\" />[/tab][tab]<img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/convs-1024x730.png\" alt=\"Convs\" width=\"491\" height=\"350\" />[line]<img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/conv-1024x730.png\" alt=\"Conv\" width=\"491\" height=\"350\" />[/tab][tab]<img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/sum-1024x730.png\" alt=\"sum\" width=\"491\" height=\"350\" />[line]<img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/sort-1024x730.png\" alt=\"sort\" width=\"491\" height=\"350\" />[line]<img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/scan-1024x730.png\" alt=\"scan\" width=\"491\" height=\"350\" />[/tab][/tabs][/column][column type=\"one-fifth\" last=\"true\"].[/column]\r\n<div id=\"free\"></div>\r\n[/content_band]\r\n\r\n[content_band inner_container=\"true\" no_margin=\"true\" border=\"top\" padding_top=\"40px\" padding_bottom=\"40px\" ]\r\n\r\n[column type=\"one-half\"].[/column][column type=\"one-fourth\"].[custom_headline type=\"center\"  level=\"h3\" class=\"mtn\"]ArrayFire Free[/custom_headline][/column][column type=\"one-fourth\" last=\"true\"].[/column][column type=\"one-fourth\"  fade=\"true\" fade_animation=\"in-from-left\" ][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/right-leaning-e1391788779101.png\"][/column][column type=\"one-fourth\"]\r\n<table>\r\n<tbody>\r\n<tr>\r\n<td>[custom_headline type=\"center\" level=\"h5\"]Functions[/custom_headline]</td>\r\n</tr>\r\n<tr>\r\n<td>[icon type=\"check-circle\" style=\"color: #8cc540;\"] Basic Operations</td>\r\n</tr>\r\n<tr>\r\n<td>[icon type=\"check-circle\" style=\"color: #8cc540;\"] Arithmetic</td>\r\n</tr>\r\n<tr>\r\n<td>[icon type=\"check-circle\" style=\"color: #8cc540;\"] Signal Processing</td>\r\n</tr>\r\n<tr>\r\n<td>[icon type=\"check-circle\" style=\"color: #8cc540;\"] Image Processing</td>\r\n</tr>\r\n<tr>\r\n<td>[icon type=\"check-circle\" style=\"color: #8cc540;\"] Statistics</td>\r\n</tr>\r\n<tr>\r\n<td>[icon type=\"check-circle\" style=\"color: #8cc540;\"] Visualization</td>\r\n</tr>\r\n</tbody>\r\n</table>\r\n[gap size=\"17%\"][button type=\"flat\" block=\"true\" shape=\"rounded\" size=\"large\"  href=\"http://www.sandbox.arrayfire.com/docs/installation.htm\"]Download ArrayFire[/button] [/column][column type=\"one-fourth\"]\r\n<table>\r\n<tbody>\r\n<tr>\r\n<td>[custom_headline type=\"center\" level=\"h5\"]Hardware[/custom_headline]</td>\r\n</tr>\r\n<tr>\r\n<td>[icon type=\"check-circle\" style=\"color: #8cc540;\"] CUDA</td>\r\n</tr>\r\n<tr>\r\n<td>[icon type=\"check-circle\" style=\"color: #8cc540;\"] OpenCL</td>\r\n</tr>\r\n<tr>\r\n<td>[custom_headline type=\"center\" level=\"h5\"]Languages[/custom_headline]</td>\r\n</tr>\r\n<tr>\r\n<td>[icon type=\"check-circle\" style=\"color: #8cc540;\"] C/C++</td>\r\n</tr>\r\n<tr>\r\n<td>[icon type=\"check-circle\" style=\"color: #8cc540;\"] Fortran</td>\r\n</tr>\r\n<tr>\r\n<td>[custom_headline type=\"center\" level=\"h5\"]Advanced[/custom_headline]</td>\r\n</tr>\r\n<tr>\r\n<td> [icon type=\"check-circle\" style=\"color: #8cc540;\"] GFOR Loop</td>\r\n</tr>\r\n</tbody>\r\n</table>\r\n[/column][column type=\"one-fourth\" last=\"true\"]\r\n<table>\r\n<tbody>\r\n<tr>\r\n<td>[custom_headline type=\"center\" level=\"h5\"]Platforms[/custom_headline]</td>\r\n</tr>\r\n<tr>\r\n<td>[icon type=\"check-circle\" style=\"color: #8cc540;\"] Windows</td>\r\n</tr>\r\n<tr>\r\n<td>[icon type=\"check-circle\" style=\"color: #8cc540;\"] Linux</td>\r\n</tr>\r\n<tr>\r\n<td>[icon type=\"check-circle\" style=\"color: #8cc540;\"] Mac</td>\r\n</tr>\r\n<tr>\r\n<td>[custom_headline type=\"center\" level=\"h5\"]Data Types[/custom_headline]</td>\r\n</tr>\r\n<tr>\r\n<td>[icon type=\"check-circle\" style=\"color: #8cc540;\"] All types</td>\r\n</tr>\r\n<tr>\r\n<td>[custom_headline type=\"center\" level=\"h5\"]Support[/custom_headline]</td>\r\n</tr>\r\n<tr>\r\n<td> [icon type=\"check-circle\" style=\"color: #8cc540;\"] Forums</td>\r\n</tr>\r\n</tbody>\r\n</table>\r\n<div id=\"licensing\"></div>\r\n[/column][gap size=\"8%\"]\r\n\r\n[pricing_table id=\"pricing\" columns=\"3\"][pricing_table_column  featured=\"false\" title=\"ArrayFire Developer\" currency=\"$\" price=\"499 / year\" interval=\"$149 / year (Academic)\"] [icon_list] [icon_list_item type=\"star\" ]Dedicated license [/icon_list_item] [icon_list_item  type=\"times-circle\"] Starts at 2 GPUs or devices [/icon_list_item] [icon_list_item type=\"times-circle\"] Linear algebra [/icon_list_item] [icon_list_item type=\"times-circle\"] Sparse matrices [/icon_list_item][icon_list_item type=\"times-circle\"] Phone support [/icon_list_item][icon_list_item type=\"times-circle\"] Premium support &amp; consulting [/icon_list_item][/icon_list] [button href=\"http://sandbox.arrayfire.com/shop\"] Purchase [/button] [/pricing_table_column] [pricing_table_column featured=\"true\" featured_sub=\"Most Popular\" title=\"ArrayFire Pro\" currency=\"$\" price=\"1,499 / year\" interval=\"$525 / year (Academic)\"] [icon_list] [icon_list_item type=\"star\"] Dedicated license [/icon_list_item] [icon_list_item type=\"star\"] Starts at 2 GPUs or devices [/icon_list_item] [icon_list_item type=\"star\"] Linear algebra [/icon_list_item][icon_list_item type=\"star\"] Sparse matrices [/icon_list_item][icon_list_item type=\"times-circle\"] Phone support [/icon_list_item][icon_list_item type=\"times-circle\"] Premium support &amp; consulting [/icon_list_item] [/icon_list] [button href=\"http://sandbox.arrayfire.com/shop\"]Purchase [/button] [/pricing_table_column] [pricing_table_column featured=\"false\" title=\"ArrayFire Enterprise\" currency=\"$\" price=\"2,999 / year\" interval=\"$1,049 / year (Academic)\"] [icon_list] [icon_list_item type=\"star\"] Dedicated license [/icon_list_item] [icon_list_item type=\"star\"] Starts at 2 GPUs or devices [/icon_list_item] [icon_list_item type=\"star\"] Linear algebra [/icon_list_item][icon_list_item type=\"star\"]Sparse matrices [/icon_list_item][icon_list_item type=\"star\"] Phone support[/icon_list_item][icon_list_item type=\"star\"]Premium support &amp; consulting [/icon_list_item][/icon_list] [button href=\"http://sandbox.arrayfire.com/shop\"] Purchase [/button] [/pricing_table_column] [/pricing_table]\r\n<div id=\"whitepapers\"></div>\r\n[/content_band]\r\n\r\n[content_band inner_container=\"true\" no_margin=\"true\" border=\"top\" padding_top=\"40px\" padding_bottom=\"40px\" ]\r\n\r\n[column type=\"one-half\"][gap size=\"20%\"][image type=\"thumbnail\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/02/wp2.jpg\"][button href=\"http://go.sandbox.arrayfire.com/l/37882/2014-05-29/dw83/37882/18534/arrayfire_matrix_computations_chrzeszczyk.pdf\" shape=\"rounded\" size=\"regular\" block=\"true\"]Download <em>Matrix Computations on the GPU with ArrayFire for C/C++</em>[/button][/column][column type=\"one-half\" last=\"true\"]\r\n\r\n[custom_headline type=\"left\" level=\"h3\" ]Whitepapers[/custom_headline]\r\n\r\n<img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/02/Whitepaper-1.png\" alt=\"Whitepaper 1\" width=\"466\" height=\"374\" />\r\n\r\n&nbsp;\r\n\r\n[/column][gap size=\"10%\"]\r\n\r\n[column type=\"one-half\"]<img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/02/Whitepaper-2.png\" alt=\"Whitepaper 2\" width=\"442\" height=\"304\" />[/column][column type=\"one-half\" last=\"true\"][image type=\"thumbnail\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/02/wp1.jpg\"][button href=\"http://go.sandbox.arrayfire.com/l/37882/2014-05-29/dw81/37882/18532/arrayfire_whitepaper.pdf\" shape=\"rounded\" size=\"regular\"  block=\"true\" float=\"right\"]Download <em>High-level GPU Computing in C, C++, and Fortran</em>[/button][/column]\r\n<div id=\"casestudies\"></div>\r\n[/content_band]\r\n\r\n[content_band inner_container=\"true\" no_margin=\"true\" border=\"top\" padding_top=\"40px\" padding_bottom=\"40px\" ]\r\n\r\n[column type=\"one-half\"][gap size=\"12%\"][custom_headline type=\"left\" level=\"h3\" ]Case Studies[/custom_headline]\r\n\r\nLearn how ArrayFire has worked in real code, including applications in academia, finance, government, life sciences, manufacturing, media, and oil &amp; gas.[/column][column type=\"one-half\" last=\"true\" fade=\"true\" fade_animation=\"in-from right\"][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/02/model-A.png\"][/column][custom_headline type=\"left\" level=\"h5\"]Academia [/custom_headline][accordion][accordion_item title=\"Accelerating LTE Simulation | Tsinghua University\"]\r\n\r\nAuthors: Yuan Gao, Yin Sun, Chun Hui Zhou, Xin Su, Xi Bin Xu, Shi Dong Zhou, Tsinghua University\r\nSpeedup: 3X\r\n\r\nFast simulations are a driving force in several research projects. However, the accompanying long simulation times can tend to be a drag in many of these projects. In this article, we shall bring up the example of the work on 3GPP LTE System Simulation by Yuan Gao et al (from Tsinghua University, Beijing) and demonstrate how the use of ArrayFire software can significantly improve the simulator performance and lead to faster validation times in simulation projects.[/accordion_item]\r\n\r\n[accordion_item title=\"High Performance Compressive Sensing | Rice University\"]\r\n\r\nAuthors: Nabor Reyna and Wotao Yin from Rice University\r\nSpeedup: 5X\r\n\r\nThis work deals with reconstruction of signals using partial Fourier matrices (RecPF). The major computational components of the algorithm involve shrinkage and FFTs. ArrayFire software is employed to accelerate this compute-heavy code.[/accordion_item]\r\n\r\n[accordion_item title=\"Power System Simulations | Indian Institute of Technology, Roorkee, India\"]\r\nAuthors: Indian Institute of Technology, Roorkee\r\nSpeedup: 35X\r\n\r\nPower flow studies are one of the most important aspects of power system planning and operation. The power flow reveals the sinusoidal steady state characteristics of the entire system - voltages, real and reactive power generated, and absorbed and line losses- elucidating the voltage magnitudes and angles at each bus, the generation of each generating unit, and real and reactive power losses in the system. All this is necessary to ensure the security, economy, and control of electrical energy distribution. Learn how ArrayFire software can deliver magnitudes of performance improvement over CPU-based solutions.[/accordion_item]\r\n\r\n[accordion_item title=\"Antenna Array Simulations | University of Naples Federico II\"]\r\n\r\nAuthors: A. Capozzoli, C. Cucio, A. Liseno at University of Naples Federico II\r\nSpeedup: 24X\r\n\r\nAntenna array design involves repeated simulation to tune the many parameters involved, and waiting around for simulations to finish is no fun. Offloading the optimization problem onto the GPU cuts that time down significantly. In their recent paper, Capozzoli, Curcio, and Liseno of University of Naples Federico II demonstrated how a simple modification to their echo generator array simulation took advantage of the GPU to bring immediate speedups.[/accordion_item]\r\n\r\n[accordion_item title=\"Laplace Transform Inversion | Acunum Algorithms and Simulations\"]\r\n\r\nAuthors: Patrick Kano and Moysey Brio at Acunum Algorithms and Simulations\r\nSpeedup: 3.8X\r\n\r\nThe numerical inversion of the Laplace transform is a long standing problem due its implicit ill-posedness. Patrick Kano and Moysey Brio of Acunum Algorithms and Simulations, with their experience in computational methods and algorithm development, found a solution that not only works, but is very fast.[/accordion_item]\r\n\r\n[accordion_item title=\"Compressed Sensing for Image Reconstruction | College of Engineering, Roorkee, India\"]\r\n\r\nAuthors: Kuldeep Yadav, Ankush Mittal, M. A. Ansar, and Avi Srivastava, College of Engineering, Roorkee, India\r\nSpeedup: 8X\r\n\r\nCompressed sensing is very critical in the areas of medical image reconstruction, image acquisition or sensor networks. An algorithm for compressed sensing developed using a Basis Pursuit Algorithm shows over 8X speedup when run on an NVIDIA GPU.[/accordion_item]\r\n\r\n[accordion_item title=\"Fat/Water Reconstruction for Medical Images | Case Western Reserve University\"]\r\n\r\nAuthors: D. H. Johnson, S. Narayan, C. A. Flask, and D. L. Wilson, Case Western Reserve University\r\nSpeedup: 11.6X\r\n\r\nCase Western Reserve University researchers turned to GPUs running ArrayFire software to develop a fast and robust version of the \"Iterative Decomposition of water and fat with an Echo Asymmetry and Least-squares\" (IDEAL) reconstruction algorithm. This algorithm uses a lot of Image Processing algorithms for reconstruction, and was shown to achieve very high speedups.\r\n[/accordion_item]\r\n\r\n[/accordion]\r\n<h5>Finance</h5>\r\n[accordion][accordion_item title=\"Option Pricing | Koch Supply and Trading\"]\r\n\r\nAuthors: Koch Supply &amp; Trading\r\nSpeedup: 51.8X\r\n\r\nAndrew Shin, Market Risk Manager of Koch Supply &amp; Trading, achieves significant performance increases on option pricing algorithms using ArrayFire software to accelerate his code with GPUs. Andrew says, \"My buddy and I are, at best, novice programmers and we couldn\'t imagine having to figure out how to code all this in CUDA.\" But he found ArrayFire software to be straight-forward. With these results, he says he can see ArrayFire software and GPUs populating Koch\'s mark-to-futures cube, which contains its assets, simulations, and simulated asset prices.[/accordion_item]\r\n\r\n[accordion_item title=\"GPU Computing in Automated Trader | Automated Trader\"]\r\n\r\nAuthors: Automated Trader\r\nSpeedup: 37.5X\r\n\r\nThe Q1 2012 issue of Automated Trader contains an excellent Mashup piece reviewing software for algorithmic trading. The article provides a wonderful glimpse into the 1-2 month adventure of Andy Webb, Automated Trader.s Founder, and Wrecking Crew building a fast trading platform from several technologies. The full trading platform they built was quite extensive. The part that caught our eye was the core computational component of the pipeline. That component involved permuting 1,000 potential pairs with cointegration tests for 350 time windows on each potential pair.\r\n[/accordion_item]\r\n[accordion_item title=\"GPUs in Quantitative Analytics and Finance | Private Bank\"]\r\n\r\nThe world of Quantitative finance is all about getting accurate results really, really fast. ArrayFire is working with one of the largest banks in Spain to maximize their output using GPUs. Click the link below for an overview of the uses of GPU computing in finance.[/accordion_item][/accordion]\r\n<h5>Government</h5>\r\n[accordion][accordion_item title=\"Powering Mars Research | NASA and UAA in Anchorage\" ]\r\n\r\nAuthors: NASA and UAA in Anchorage\r\nSpeedup: 5X\r\n\r\nThe main thrust of this research is improving mars rover image compression via GPUs and genetic algorithms. With ArrayFire software and GPUs, the researchers were able to achieve 5X speedups on the larger data sizes. The algorithm works by pairing neighboring pixels with a random one and then adjusting the random pixel based on whether it incrementally improves the original image. Babb described the algorithm as an embarrassingly parallel process, ideally suited to GPU acceleration. He estimates he has been able to achieve a 20 to 30 percent error reduction in subjects like fingerprints and satellite imagery.[/accordion_item]\r\n\r\n[accordion_item title=\"Radar Image Formation | System Planning Corporation\"]\r\n\r\nAuthors: Gary Rubin and Earl Sager - System Planning Corporation\r\nSpeedup: ~45X\r\n\r\nRadar imaging is computationally intensive. As a result, many imaging algorithms apply FFT-based approximations. While efficient, these algorithms sacrifice data fidelity for speed. Other algorithms better preserve information, but are often too slow for many applications. At System Planning Corporation (SPC) , we have implemented a SAR/ISAR imaging routine based on the Backprojection algorithm. Using ArrayFire software, we have demonstrated speedups of roughly 45x for large datasets.[/accordion_item]\r\n\r\n[accordion_item title=\"Radar Clutter Reduction | System Planning Corporation\"]\r\n\r\nAuthors: David Berger and Gary Rubin - System Planning Corporation\r\nSpeedup: 5-10X\r\n\r\nSystem Planning Corporation (SPC) uses ArrayFire software to accelerate radar processing algorithms. The system processes raw data from marine navigation radars using a variety of thresholding techniques to extract real targets from clutter. This involves highly data-parallel processing in which each radar pulse is subjected to the same computations; very few operations occur across multiple pulses. Using ArrayFire software, SPC has achieved 10x speed improvements relative to a Core i7-920 CPU and 5x improvements relative to a realtime DSP implementation.[/accordion_item]\r\n\r\n[accordion_item title=\"Novel Algorithms for Linear Algebra | SAIC\" ]\r\n\r\nAuthors: Nolan Davis and Daniel Redig, SAIC\r\nSpeedup: 3.5X\r\n\r\nNolan Davis and Daniel Redig at SAIC recently presented work on Hybrid GPU/Multicore Solutions for Large Linear Algebra Problems where they developed a novel algorithm for LU decomposition, one of the most important routines in linear algebra. They presented a Hybrid CPU/GPU computing approach, where problems too large to fit in GPU memory can also be solved faster than using only the CPU.\r\n[/accordion_item]\r\n[accordion_item title=\"Geolocation | BAE Systems\"]\r\n\r\nAuthors: BAE Systems\r\nSpeedup: 17X\r\n\r\nGeolocation is the identification of the real-world geographic location of a target of interest. In this application, the system receives the signal with an array of several antennas and computes the direction of arrival of the radio energy by measuring the time difference of arrival (or the phase difference) at the different antennas.\r\n[/accordion_item]\r\n[accordion_item title=\"Tsunami Modeling | University of Minnesota, Boise State, Saint Scholastica, and NCAR\"]\r\n\r\nAuthors: University of Minnesota, Boise State, Saint Scholastica, and NCAR\r\nSpeedup: 3-5X\r\n\r\nNatural catastrophic disasters like tsunamis commonly strike with little warning. For most people, tsunamis are underrated as major hazards. People sometimes wrongly believe that they occur infrequently and only along distant coasts. Tsunamis are usually caused by earthquakes. Seismic signals can give some margin of warning since the speed of tsunami waves travels at 1/30 the speed of seismic waves. Still there is little time between the creation of the tsunami and its impact making fast processing critical to producing effective warning systems. ArrayFire software was used to run an RBF simulation on the GPU with a time to solution not available by other alternatives.\r\n[/accordion_item][/accordion]\r\n<h5>Life Sciences</h5>\r\n[accordion][accordion_item title=\"Parallelized Gene Predictors | University of Quebec\" ]\r\n\r\nAuthors: University of Quebec\r\nSpeedup: 43X\r\n\r\nComputerized approaches to studying the human genome are challenged by the exploding amount of data, which doubles roughly every 6 months. In order to deal with this burgeoning datasets, demands for faster processing power continue to arise. This work focuses on predicting genes using frequency analysis with FFTs and with an equivalent technique known as Goertzel\'s algorithm. In these applications, the emphasis of this paper is to propose tools to geneticists and molecular biologists for the prediction or identification of new genes using existing complementary strategies. The criteria for these tools are speed, reliability, accuracy and ease of use, thus requiring little training.\r\n[/accordion_item]\r\n[accordion_item title=\"Pathology Advances with GPUs | Northeastern University\" ]\r\n\r\nAuthors: Laboratory for Spectral Diagnosis at Northeastern University\r\nSpeedup: 100X+\r\n\r\nOne element of the hyperspectral image analysis workflow that requires more than a traditional desktop workstation or personal computer is Hierarchical Cluster analysis (HCA). HCA requires a large amount of data space and substantial computation time (~11 hours) for typical datasets using a single processor personal computer. Rather than following the traditional approach of moving to a lower level programming language like C or C++ and complex parallel programming paradigms such as OpenMP or the Massage Passing Interface (MPI), the lab utilized graphics processing units, or GPUs, and the ArrayFire software platform. The solution allowed the lab to dramatically increase the performance of the analysis while substantially decreasing the amount of calendar time to reach the desired results.\r\n[/accordion_item]\r\n[accordion_item title=\"Hepatitis C Virus - Mutation Modeling | Centers for Disease Control and Prevention\" ]\r\n\r\nAuthors: CDC Research and Development Team\r\nSpeedup: ~20X\r\n\r\nThis case study provides a look at biological research regarding coordinated mutations of the Hepatitis C Virus (HCV). ArrayFire provided collaborative R&amp;D resources and greatly improved the speed of this HCV research with the use of parallelization, reducing the computing time from 40 days to less than 1 day. Most importantly, the conclusion of the case study illustrates the the relative price-performance of personal supercomputers that leverage GPUs and ArrayFire software provides a compelling solution versus other architectures and approaches.\r\n[/accordion_item]\r\n[accordion_item title=\"Accelerating the SPM Package for Neuroimaging | Georgia Institute of Technology\" ]\r\n\r\nAuthors: Georgia Institute of Technology\r\nSpeedup: 3.5X\r\n\r\nThe Georgia Tech team explores the value of ArrayFire software and GPUs for fMRI workflows within the popular SPM - Statistical Parametric Mapping software widely used in neuroscience research.\r\n[/accordion_item]\r\n[accordion_item title=\"Medical Image Compression | Indian Institute of Technology, Roorkee, India\" ]\r\n\r\nAuthors: Jaideep Singh, Ipseeta Aruni, R. Balasubramanian - IIT - Roorkee, India\r\nSpeedup: 38X\r\n\r\nThis study presents the acceleration of Haar wavelet-based image compression algorithm for medical imaging on the Graphics Processing Unit (GPU) using ArrayFire software. Due to bandwidth and image size constraints of medical imaging systems, image compression plays a vital role in reducing the bit rate of transmission or storage. Wavelet-based image compression provides the most promising approach for high quality image compression.\r\n[/accordion_item]\r\n[accordion_item title=\"Brain Displacement | Spencer Technologies\"]\r\n\r\nAuthors: Spencer Technologies\r\nSpeedup: 12X\r\n\r\nSpencer describes how ArrayFire software facilitates the development of fast algorithms enabling observation of brain displacement across depth with sampling density that far surpasses previous benchmarks.\r\n[/accordion_item]\r\n[accordion_item title=\"Multidimensional Scaling for Genomics | Leibniz Institute of Plant Genetics and Crop Plant Research\" ]\r\n\r\nAuthors: Leibniz Institute of Plant Genetics and Crop Plant Research\r\nSpeedup: 20-35X\r\n\r\nMultidimensional scaling (MDS) is a general computing technique to turn a distance matrix into a set of reconstructed points with pair-wise relationships approximating the original distances by points located in a usually low-dimensional space. ArrayFire software is used to enhance execution of the HiT-MDS procedure and delivers considerable performance improvement.\r\n[/accordion_item]\r\n[accordion_item title=\"Drug Delivery Model | Georgia Institute of Technology\"]\r\n\r\nAuthors: Georgia Institute of Technology\r\nSpeedup: 70X\r\n\r\nIn this work, the researchers simulate the delivery of a novel nanoparticle chemotherapy drug to cancerous tissue. Simulation allows scientists to predict experimental outcomes and thus reduce the cost of development and time to clinical relevance. The simulation model includes blood vessels, tumor cells, and healthy cells and an engine to calculate the spatial distributions of both drug and oxygen. ArrayFire software is used to speed up the diffusion calculations for the drug and oxygen within the tissue.\r\n[/accordion_item]\r\n[accordion_item title=\"Biomedical Infrared Spectroscopy | University of Manchester and Nofima Mat, Norway\" ]\r\n\r\nAuthors: University of Manchester and Nofima Mat, Norway\r\nSpeedup: Hours of runtime reduction\r\n\r\nThe authors present an iterative algorithm that applies full Mie scattering theory and avoids noise accumulation in their iterative algorithm by integrating a curve-fitting step. ArrayFire software along with NVIDIA GPUs are leveraged to reduce the time added by the curve-fitting step.\r\n[/accordion_item][/accordion]\r\n<h5>Manufacturing</h5>\r\n[accordion][accordion_item title=\"Feature Learning on Images | Stanford\" ]\r\n\r\nAuthors: Andrew Ng, Stanford University\r\nSpeedup: Ability to process many images in parallel\r\n\r\nStanford researchers in Andrew Ng\'s group used GPUs and ArrayFire software to speed up their work on Feature Learning Architectures. They decided to use ArrayFire software for this study because of the need to quickly evaluate many architectures on thousands of images. ArrayFire software taps into the immense computing power of GPUs and speeds up research utilizing many images.\r\n[/accordion_item]\r\n[accordion_item title=\"Tomography of Vegetation - Filtered Back-Projection and Non-Uniform FFTs | Universita di Napoli Federico II\" ]\r\n\r\nAuthors: Drs. Capozzoli, Curcio, di Vico, and Liseno, Universita di Napoli Federico II\r\nSpeedup: 10X\r\n\r\nIn order to investigate changes of forest biomass, scientists use microwave tomography to image the vegetation. At the smallest scale, individual plants can be imaged to investigate branching and growth, but even synthetic aperture radar can reveal large-scale changes in regional ecology. To the right, you can see the experimental setup to image an individual plant.\r\n[/accordion_item]\r\n[accordion_item title=\"Action Recognition with Independent Subspace Analysis | Stanford University\" ]\r\n\r\nAuthors: Quoc Le, Will Zou, Serena Yeung, Andrew Ng, Stanford University\r\nSpeedup: 4.4X\r\n\r\nIn a paper at this year\'s CVPR 2011, entitled \"Learning hierarchical invariant spatio-temporal features for action recognition with independent subspace analysis\", the authors explain how their unsupervised feature learning algorithm competes with other algorithms that are hand crafted or use learned features. For their training purposes, they used a multi-layered stacked convolutional ISA (Independent subspace analysis) network. An ISA is used for learning features from image patches without supervision.\r\n[/accordion_item][/accordion]\r\n<h5>Media and Computer Vision</h5>\r\n[accordion][accordion_item title=\"Fast Computer Vision with OpenCV and ArrayFire | OpenCV Blogger\" ]\r\n\r\nAuthors: OpenCV Blogger\r\nSpeedup: ~10X\r\n\r\nThe OpenCV library is the defacto standard for doing computer vision and image processing research projects. OpenCV includes several hundreds of computer vision algorithms, aimed for use in realtime vision applications. This case study shows how to use both libraries together. There is a simple example application that demonstrates using OpenCV for webcam access and ArrayFire for some basic processing routines and displaying results.\r\n[/accordion_item]\r\n[accordion_item title=\"Video Processing | Google\" ]\r\n\r\nAuthors: Google and Stanford\r\nSpeedup: 10-20X\r\n\r\nVideo content analysis is the basis for categorizing videos and enabling search by content. Growing interest in using sparse-coding methods to extract motion features in video in support of video content analysis led to the application of ArrayFire software to improve performance by substantially accelerating the solution of the L1-regularized least-squares optimization problem.\r\n[/accordion_item]\r\n[accordion_item title=\"Action Recognition with Independent Subspace Analysis | Stanford University\"]\r\n\r\nAuthors: Quoc Le, Will Zou, Serena Yeung, Andrew Ng, Stanford University\r\nSpeedup: 4.4X\r\n\r\nIn a paper at this year\'s CVPR 2011, entitled \"Learning hierarchical invariant spatio-temporal features for action recognition with independent subspace analysis\", the authors explain how their unsupervised feature learning algorithm competes with other algorithms that are hand crafted or use learned features. For their training purposes, they used a multi-layered stacked convolutional ISA (Independent subspace analysis) network. An ISA is used for learning features from image patches without supervision.\r\n[/accordion_item]\r\n[accordion_item title=\"Music Beat Analysis | Georgia Tech\"]\r\n\r\nAuthors: Vidhur Vohra - Georgia Tech\r\nSpeedup: 15X\r\n\r\nDid you ever wonder how the music visualizer in your media player works? Watching it pulsate in synchrony with the beats of the song is almost as entertaining as listening to the song itself! Researchers have been attempting to detect beats in audio signals for many years, and there are many techniques available, from the simplest (and least accurate) to more complicated algorithms that are highly accurate. All algorithms, though, perform some form of signal processing and frequency analysis, applications highly suited to GPU Computing.\r\n[/accordion_item]\r\n[accordion_item title=\"Optimization Methods for Deep Learning | Stanford Artificial Intelligence Laboratory\" ]\r\n\r\nAuthors: Stanford Artificial Intelligence Laboratory\r\nSpeedup: Improved accuracy\r\n\r\nResearchers at SAIL (Stanford Artificial Intelligence Laboratory), have done it again. They have successfully used ArrayFire software to speed up the training part of Deep Learning algorithms. In their paper titled .On Optimization Methods for Deep Learning., they experiment with some of the well known training algorithms and demostrate their scalability across parallel architectures (GPUs as well as multi-machine networks). The algorithms include SGDs (Stochastic Gradient Descent) L-BFGS (Limited BFGS used for solving non-linear problems), CG (Conjugate Gradient).\r\n[/accordion_item]\r\n[accordion_item title=\"Feature Learning on Images | Stanford University\" ]\r\n\r\nAuthors: Andrew Ng, Stanford University\r\nSpeedup: Ability to process many images in parallel\r\n\r\nStanford researchers in Andrew Ng’s group used ArrayFire software to speed up their work on Feature Learning Architectures. They decided to use ArrayFire software for this study because of the need to quickly evaluate many architectures on thousands of images. ArrayFire software taps into the immense computing power of GPUs and speeds up research utilizing many images.\r\n[/accordion_item]\r\n[accordion_item title=\"Digital Holography for Imaging | National University of Ireland, Maynooth\" ]\r\n\r\nAuthors: Nitesh Pandey, Damien Kelly, Bryan Hennelly and Thomas Naughton from the National University of Ireland, Maynooth\r\nSpeedup: 17X\r\n\r\nDigital holography is a powerful imaging technique with many new applications like true 3D display. It allows the capture of both amplitude and phase information of the light reflected off the surface of 3D objects. Researchers at the National University of Ireland, Maynooth are developing techniques based on digital holography for 3D display applications.\r\nReconstruction of large digital holograms can be computationally intensive to generate on CPUs, but GPUs running ArrayFire software offer amazing possibilities.\r\n[/accordion_item][/accordion]\r\n<h5>Oil and Gas</h5>\r\n[accordion][accordion_item title=\"3D Mantle Convection - Geodynamics | Boise State, University of Colorado, University of Minnesota\" ]\r\n\r\nAuthors: Boise State, University of Colorado, University of Minnesota\r\nSpeedup: 2.5-4.5X\r\n\r\nThe authors introduce a GPU implementation of a three-dimensional mantle convection modeling at a high Rayleigh number to the solid earth geophysics community. They outline code development time, compare performance of CPUs versus GPUs, and deliver powerful visualizations.\r\n[/accordion_item]\r\n[accordion_item title=\"Ground Water Simulations | Louisiana State University\" ]\r\n\r\nAuthors: Kevin R. Tubbs and Frank T-C. Tsai at Louisiana State University\r\nSpeedup: &gt;20X\r\n\r\nA lattice Boltzmann method for solving the shallow water equations and the advection-dispersion equation is developed and implemented on graphics processing unit (GPU)-based architectures. The proposed LBM is implemented to an NVIDIA Computing Processor in a single GPU workstation. GPU computing is performed using ArrayFire software. Mass transport with velocity-dependent dispersion in shallow water flow is simulated by combining the MRT-LBM model and the TRT-LBM model. The GPU parallel performance increases as the grid size increases. The results indicate the promise of the GPU-accelerated LBM for modeling mass transport phenomena in shallow water flows.\r\n[/accordion_item]\r\n[accordion_item title=\"Shallow Water Fluid Flow | Louisiana State University\" ]\r\n\r\nAuthors: Louisiana State University\r\nSpeedup: &gt;10X\r\n\r\nA lattice Boltzmann method (LBM) on high performance computing (HPC) environments for three-dimensional shallow water flow fields coupled to mass transport is developed. LBM is an attractive method for solving the multilayered shallow water equations because the extension to multilayer is straight forward with all of the simplicities and advantages of the LBM in mass transport in shallow water flows and the LBM performance on central processing unit (CPU)-based and graphics processing unit (GPU)-based HPC environments.\r\n[/accordion_item][/accordion]\r\n<div id=\"consulting\"></div>\r\n[/content_band]\r\n<div id=\"services\"></div>\r\n[content_band inner_container=\"true\" no_margin=\"true\" border=\"top\" padding_top=\"40px\" padding_bottom=\"40px\"][column type=\"one-half\"][custom_headline type=\"left\" level=\"h3\"]Hire our acceleration gang[/custom_headline]\r\n\r\nHire us to accelerate your code. Or to train your pros. Or even to write new code for your organization!\r\n\r\nWe’ve already helped thousands of organizations speedup their code. We’ve accelerated algorithms, data sets, and challenging problems of all types in the past, and we’re confident that we can accelerate your code too.\r\n\r\n[gap size=\"10%\"][button  type=\"flat\" shape=\"rounded\" href=\"http://meetme.so/arrayfire\" size=\"x-large\" ]Schedule a consultation[/button][/column][column type=\"one-half\" last=\"true\" class=\"center-text\"][gap size=\"5%\"][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/Bat-signal-e1391790016951.png\"][/column] [gap size=\"7%\"]\r\n\r\n[column type=\"one-third\" class=\"center-text\"][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/04/LFG-B-HORZ_202_K-e1396448935778.jpg\"][line]Lincoln Financial Group ported their CPU code (C/C++) to CUDA, and this enabled them to speed up the necessary financial calculations. Their primary objective was to reduce the time taken to run this code. Before porting to CUDA, they required 10-12 hours to run the entire code. After porting to CUDA, they were able to do the same work in about 30 minutes.[/column][column type=\"one-third\" class=\"center-text\"][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/02/reveal_logo-e1396449044651.jpg\"][line]Reveal Imaging, an SAIC company, uses ArrayFire in developing threat-detection products for transportation systems—such as cargo and baggage screening in airports—and in securing facilities and public events.[/column][column type=\"one-third\" last=\"true\" class=\"center-text\"][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/04/1800contactlogo.png\"][line]The Glasses.com app relies on computer vision to recognize the features of a user’s face. The application then generates an accurate, high-fidelity, three-dimensional model of that face, and virtually places selected frames on the image.[/column]\r\n<div id=\"starterpackage\"></div>\r\n[/content_band]\r\n\r\n[content_band inner_container=\"true\" no_margin=\"true\" border=\"top\" padding_top=\"40px\" padding_bottom=\"40px\"]\r\n\r\n[column type=\"one-half\" last=\"false\" fade=\"true\" fade_animation=\"in-from-left\" ][gap size=\"10%\"][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/comingatyou.png\"][/column][column type=\"one-half\" last=\"true\"] [custom_headline type=\"left\" level=\"h3\"]Starter Package ($500)* [/custom_headline] Hire us for 1-day. We set you up with one engineer dedicated for a full day, as well as support from senior and test engineers throughout the day. Here\'s how it works:\r\n\r\n[icon_list] [icon_list_item type=\"angle-double-right\"]Initial phone call[/icon_list_item] [icon_list_item type=\"angle-double-right\"]You send us your code or algorithm [/icon_list_item] [icon_list_item type=\"angle-double-right\"]We analyze your code for potential GPU benefit[/icon_list_item][icon_list_item type=\"angle-double-right\"]We accelerate as much of the code as is possible within the 1-day effort, applying our extensive GPU software libraries[/icon_list_item][icon_list_item type=\"angle-double-right\"]We produce a final report, along with code[/icon_list_item] [/icon_list] The final report outlines the best approach to follow for full GPU-acceleration of your code.\r\n\r\n&nbsp;\r\n\r\n[button type=\"flat\" shape=\"rounded\" size=\"regular\" href=\"http://sandbox.arrayfire.com/product/consulting-starter-package/\" title=\"Starter Package\"]Buy the Starter Package[/button]\r\n\r\n&nbsp;\r\n\r\n*Limit one (1) per customer.\r\n\r\n[/column]\r\n<div id=\"customcode\"></div>\r\n[/content_band] [content_band inner_container=\"true\" no_margin=\"true\" border=\"top\" padding_top=\"40px\" padding_bottom=\"40px\" ]\r\n\r\n[column type=\"one-half\"][custom_headline type=\"left\" level=\"h3\" ]Custom Coding Work[/custom_headline]\r\n\r\n[custom_headline type=\"left\" level=\"h6\" ]Why Choose Us?[/custom_headline] [icon_list] [icon_list_item type=\"angle-double-right\"]Deep experience, already servicing thousands of customers[/icon_list_item] [icon_list_item type=\"angle-double-right\"]Quality work, with leading GPU software [/icon_list_item] [icon_list_item type=\"angle-double-right\"]Efficient delivery, with ArrayFire\'s code base we can deliver results fast[/icon_list_item][icon_list_item type=\"angle-double-right\"]Proven, we make customers happy through faster code[/icon_list_item][/icon_list] [custom_headline type=\"left\" level=\"h6\" ]Our Strengths[/custom_headline] [icon_list] [icon_list_item type=\"angle-double-right\"]Excellence in GPU code[/icon_list_item] [icon_list_item type=\"angle-double-right\"]Well-written, efficient C, C++, Fortran, Java, or .NET [/icon_list_item] [icon_list_item type=\"angle-double-right\"]Application porting and integration[/icon_list_item][icon_list_item type=\"angle-double-right\"]Tuning software to peak hardware performance[/icon_list_item][icon_list_item type=\"angle-double-right\"]Scalability of algorithms to handle enterprise-level programs[/icon_list_item] [/icon_list][button type=\"flat\" shape=\"rounded\" size=\"regular\" href=\"http://meetme.so/arrayfire\" title=\"Tech Consultation\"]Schedule a consultation[/button] [/column][column type=\"one-half\"  fade=\"true\" fade_animation=\"in-from-right\" last=\"true\" ][gap size=\"25%\"][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/02/Holoham.png\"][/column]\r\n<div id=\"training\"></div>\r\n[/content_band] [content_band inner_container=\"true\" no_margin=\"true\" border=\"top\" padding_top=\"40px\" padding_bottom=\"40px\" ]\r\n\r\n[column type=\"one-half\"][custom_headline type=\"left\" level=\"h3\" ]Training[/custom_headline] Attendees will receive the latest industry knowledge and techniques for GPU computing in CUDA and OpenCL.\r\n\r\nArrayFire offers up to four days of specialized GPU training in CUDA and OpenCL programming. We provide customized on-site training courses for customers that have 3 or more attendees from their organization. We can travel to your location and provide a CUDA or OpenCL training course tailored to meet your application-specific needs. We also offer individual trainings at our Atlanta office. Please <a href=\"mailto:sales@arrayfire.com\">contact us</a> to learn more about our training offerings.\r\n\r\nWe recommend that attendees have a working knowledge of C/C++ in order to gain the most from the training courses. For more information about the content of our training lectures and hands-on practicums, please see the following training course syllabus.\r\n\r\n[/column]\r\n\r\n[column type=\"one-half\" last=\"true\" fade=\"true\" fade_animation=\"in-from-right\" class=\"center-text\"][gap size=\"15%\"][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/02/Professor-AF_Exported-e1395436350363.png\" ][/column]\r\n\r\n[column type=\"one-half\" class=\"center-text\"] [gap size=\"17%\"]\r\n<div>[button type=\"flat\" shape=\"rounded\" size=\"jumbo\" href=\"mailto:sales@arrayfire.com?Subject=Training%20Inquiry\"] Register for Training[/button]</div>\r\n[/column][column type=\"one-half\" last=\"true\"][custom_headline type=\"left\" level=\"h3\"]Included in Course[/custom_headline]\r\n\r\n[icon_list] [icon_list_item type=\"angle-double-right\"]Instruction by an excellent and interesting expert, with hands-on exercises[/icon_list_item] [icon_list_item type=\"angle-double-right\"]Use of a laptop with CUDA and OpenCL capable GPUs and CPUs [/icon_list_item] [icon_list_item type=\"angle-double-right\"]Choice of Linux or Windows operating system[/icon_list_item][icon_list_item type=\"angle-double-right\"]Printed manual of lecture material[/icon_list_item][icon_list_item type=\"angle-double-right\"]Electronic copy of programming exercises[/icon_list_item][/icon_list]\r\n\r\n[/column]\r\n\r\n<span style=\"line-height: 1.5em;\">[gap size=\"5%\"]</span>\r\n\r\n[custom_headline type=\"left\" level=\"h3\"]Training Course Syllabus[/custom_headline] [column type=\"one-half\"] [custom_headline type=\"left\" level=\"h5\"  accent=\"false\"]Day 1, Introduction[/custom_headline] Lectures:\r\nGPU Computing Overview\r\nThe Programming Model\r\nBasic Dataset Mapping Techniques\r\nLibraries, ArrayFire\r\nProfiling Tools\r\n\r\nPractice:\r\nA Simple Kernel\r\nEquivalent ArrayFire Example\r\nUsing Libraries\r\nMonte Carlo Pi Estimation\r\nTiming and ArrayFire\r\nDebugging Code\r\n\r\n[custom_headline type=\"left\" level=\"h5\" accent=\"false\"]Day 3, Multi-GPU[/custom_headline] Lectures:\r\nMulti-GPU Use Cases\r\nMulti-GPUs: Contexts\r\nExisting Libraries\r\nScaling Across Multiple GPUs\r\n\r\nPractice:\r\nOut of Core Problems: Matrix Multiply\r\nTask Level Parallelism: Optimization\r\nArrayFire Multi-GPU[/column]\r\n\r\n[column type=\"one-half\" last=\"true\"] [custom_headline type=\"left\" level=\"h5\" accent=\"false\"]Day 2, Optimization[/custom_headline] Lectures:\r\nArchitecture: Grids, Blocks, and Threads\r\nMemory Model: Global, Shared, and Constant Memory\r\nAdvanced Mapping Techniques\r\nStreams: Asynchronos Launches and Concurrent Execution\r\nArrayFire: Lazy Evaluation and Code Vectorization\r\n\r\nPractice:\r\nMatrix Transpose\r\nOptimization Using Shared Memory\r\nMedian Filter\r\nOptimization Using Constant Memory\r\nStream Example\r\nArrayFire Example: Nearest Neighbor Algorithm\r\n\r\n[custom_headline type=\"left\" level=\"h5\" accent=\"false\"]Day 4, Algorithm Problems[/custom_headline]\r\n\r\nLectures and Practice:\r\nReductions\r\nScan Algorithms\r\nSort\r\nConvolution\r\nCustomer-Specific Problem [/column][/content_band]','Home','','inherit','open','closed','','245-revision-v1','','','2014-05-30 19:24:44','2014-05-30 19:24:44','',245,'http://sandbox.arrayfire.com/245-revision-v1/',0,'revision','',0),(5736,11,'2014-06-02 22:10:54','2014-06-02 22:10:54','One of the reasons for ArrayFire\'s usefulness is the various performance oriented function from many domains. What many people don\'t realize is that ArrayFire also includes many utilities for image loading and visualization.\r\n\r\nIn many cases, setting up a test harness is a ton of work. This is where ArrayFire can come in handy.\r\n\r\nRecently we worked on a project for one of our customers that involved image processing. As a part of development we wanted to make sure the quality is not compromised. They did not have a sufficient test framework in place. One option was to do this was the old fashioned way by reading two images and comparing them on CPU. Given that we needed to compare hundreds of images and we wanted to have a fast dev-loop, this was not a viable option. We decided to use ArrayFire to verify the results.\r\n\r\nThis particular project was an OpenGL application and they did not have a dependency on ArrayFire or CUDA/OpenCL. Because ArrayFire was only used in testing we wanted to isolate it from the rest of the production code.\r\n\r\nWe started to write the tests. A simple function that would read images from the respective folders and then perform various comparisons on them. This is where ArrayFire excels. In just a few lines of code and everything is set for loading and comparing images. Some of the function we used included subtraction, min, mean, max, stats etc. ArrayFire has an excellent visualization functionality. It allows us to visualize the differences between the current and the gold versions.\r\n<pre>std::string goldPath = std::string(gold)      + path;\r\nstd::string testPath = std::string(\"output/\") + path;\r\n\r\naf::array goldImage = af::loadimage(goldPath.c_str(), true) / 255.0f;\r\naf::array testImage = af::loadimage(testPath.c_str(), true) / 255.0f;\r\n\r\naf::array diffImage = af::abs(goldImage - testImage);\r\n\r\nfloat mean = af::mean<float>(diffImage);\r\n\r\nif(mean < 0.001f) {\r\n    fprintf ( stderr, \"FOUND MISMATCH\\n\" ) ;\r\n    result = false;\r\n    printf(\"!!!***FAILED***!!!: %s\\n\", path);\r\n    stats(diffImage);\r\n\r\n    if(visualize) {\r\n        // colormap\r\n        af::fig(\"color\", \"default\");\r\n\r\n        // image operations\r\n        af::fig(\"sub\", 3, 1, 1); af::image(goldImage); af::fig(\"title\", \"GOLD\");\r\n        af::fig(\"sub\", 3, 1, 2); af::image(testImage); af::fig(\"title\", \"TEST\");\r\n        af::fig(\"sub\", 3, 1, 3); af::image(diffImage); af::fig(\"title\", \"DIFF\");\r\n\r\n        // Force screen refresh (optional)\r\n        af::fig(\"draw\");\r\n        getchar();\r\n    }\r\n}</pre>\r\nAs you can see, the ArrayFire syntax is simple and easy to use. We didn\'t have to use a library to load the image, a library to verify the results, and a library to visualize the output. This can all be done using ArrayFire.Once the test was in place, all we had to do was include it in the make file and run the tests.\r\n\r\nArrayFire is a fantastic library for high performance applications but it can also be used for everyday tasks like testing. We would love you hear how you use ArrayFire in your projects.','Q/A Using ArrayFire','','publish','open','closed','','qa-using-arrayfire','','','2014-06-03 18:34:03','2014-06-03 18:34:03','',0,'http://sandbox.arrayfire.com/?p=5736',0,'post','',0),(5737,11,'2014-06-02 21:59:05','2014-06-02 21:59:05','One of the reasons ArrayFire has become so useful is attributed to it integrating various performance oriented function from many domains with utility functions such as image loading and visualization.\r\n\r\nIn a lot of cases, developers write a ton of code with multiple iterations but do not have a way to check the quality of the results. That\'s where ArrayFire can be used very well.\r\n\r\nIn one of our recent projects that involved image processing, we did a lot of development but faced a speed bump when we had to make sure the quality is not compromised. As a part of making code faster, we do tend to take acceptable detours. Hence it becomes absolutely crucial that we test code from time to time and especially before commits. In this particular case, it was an OpenGL project without any ArrayFire or CUDA/OpenCL as a part of it. Anything that we would do with ArrayFire would be kept separate from the production code. We needed code that would compare and analyse the result from our development branch against a \"Gold\" data set generated by the code received by us.\r\n\r\nThe first option to do this was the old fashioned way by reading two images and comparing them on CPU. But given that we needed to compare images (in the 100s), this was not a viable option. It would simply be too slow.\r\n\r\nThe preferred option was to use ArrayFire but keep it separate from the production code. So we decided to go this route.\r\n\r\nThe first thing we did was to write our testing code. A simple function that would read images from the respective folders and then perform various comparisons on then. This is where ArrayFire excels. Just about 10 lines of code and everything is set for loading and comparing images. Some of the function we used included subtraction, min, mean, max, stats etc. We also included visualization using fig if the user chose to visualize the differences.\r\n\r\n&lt;pre&gt;\r\n\r\nstd::string goldPath = std::string(gold)          + path;\r\nstd::string testPath   = std::string(\"output/\") + path;\r\n\r\naf::array goldImage = af::loadimage(goldPath.c_str(), true) / 255.0f;\r\naf::array testImage   = af::loadimage(testPath.c_str(), true) / 255.0f;\r\n\r\naf::array diffImage = af::abs(goldImage - testImage);\r\n\r\nfloat mean = af::mean&lt;float&gt;(diffImage);\r\n\r\nif(mean &gt; 0.001f) {\r\nfprintf ( stderr, \"FOUND MISMATCH\\n\" ) ;\r\nresult = false;\r\nprintf(\"!!!***FAILED***!!!: %s\\n\", path);\r\n\r\nstats(diffImage);\r\nif(visualize) {\r\n// colormap\r\naf::fig(\"color\", \"default\");\r\n\r\n// image operations\r\naf::fig(\"sub\", 3, 1, 1); af::image(goldImage); af::fig(\"title\", \"GOLD\");\r\naf::fig(\"sub\", 3, 1, 2); af::image(testImage);   af::fig(\"title\", \"TEST\");\r\naf::fig(\"sub\", 3, 1, 3); af::image(diffImage);   af::fig(\"title\", \"DIFF\");\r\n\r\n// Force screen refresh (optional)\r\naf::fig(\"draw\");\r\ngetchar();\r\n}\r\n}\r\n\r\n&lt;/pre&gt;\r\n\r\nOnce the code was in place, we had to integrate it into the main function of the code. Again, it was required that this must not mess with the production code. So we put two lines in the main function. The first line includes the file containing the test function and the second line calls the test function. Both these lines were wrapped in a #ifdef TEST which would be defined in the makefile. That way, if TEST is not defined, the file isn\'t included and ArrayFire is not required for compilation and running of the code. For all of this, we created a makefile goal called \"test\" which would define the flag, include and link ArrayFire.','Q&A Using ArrayFire','','inherit','open','closed','','5736-revision-v1','','','2014-06-02 21:59:05','2014-06-02 21:59:05','',5736,'http://sandbox.arrayfire.com/5736-revision-v1/',0,'revision','',0),(5738,11,'2014-06-02 22:01:49','2014-06-02 22:01:49','One of the reasons ArrayFire has become so useful is attributed to it integrating various performance oriented function from many domains with utility functions such as image loading and visualization.\r\n\r\nIn a lot of cases, developers write a ton of code with multiple iterations but do not have a way to check the quality of the results. That\'s where ArrayFire can be used very well.\r\n\r\nIn one of our recent projects that involved image processing, we did a lot of development but faced a speed bump when we had to make sure the quality is not compromised. As a part of making code faster, we do tend to take acceptable detours. Hence it becomes absolutely crucial that we test code from time to time and especially before commits. In this particular case, it was an OpenGL project without any ArrayFire or CUDA/OpenCL as a part of it. Anything that we would do with ArrayFire would be kept separate from the production code. We needed code that would compare and analyse the result from our development branch against a \"Gold\" data set generated by the code received by us.\r\n\r\nThe first option to do this was the old fashioned way by reading two images and comparing them on CPU. But given that we needed to compare images (in the 100s), this was not a viable option. It would simply be too slow.\r\n\r\nThe preferred option was to use ArrayFire but keep it separate from the production code. So we decided to go this route.\r\n\r\nThe first thing we did was to write our testing code. A simple function that would read images from the respective folders and then perform various comparisons on then. This is where ArrayFire excels. Just about 10 lines of code and everything is set for loading and comparing images. Some of the function we used included subtraction, min, mean, max, stats etc. We also included visualization using fig if the user chose to visualize the differences.\r\n\r\n&nbsp;\r\n\r\nOnce the code was in place, we had to integrate it into the main function of the code. Again, it was required that this must not mess with the production code. So we put two lines in the main function. The first line includes the file containing the test function and the second line calls the test function. Both these lines were wrapped in a #ifdef TEST which would be defined in the makefile. That way, if TEST is not defined, the file isn\'t included and ArrayFire is not required for compilation and running of the code. For all of this, we created a makefile goal called \"test\" which would define the flag, include and link ArrayFire.','Q&A Using ArrayFire','','inherit','open','closed','','5736-revision-v1','','','2014-06-02 22:01:49','2014-06-02 22:01:49','',5736,'http://sandbox.arrayfire.com/5736-revision-v1/',0,'revision','',0),(5739,11,'2014-06-02 22:02:47','2014-06-02 22:02:47','One of the reasons ArrayFire has become so useful is attributed to it integrating various performance oriented function from many domains with utility functions such as image loading and visualization.\r\n\r\nIn a lot of cases, developers write a ton of code with multiple iterations but do not have a way to check the quality of the results. That\'s where ArrayFire can be used very well.\r\n\r\nIn one of our recent projects that involved image processing, we did a lot of development but faced a speed bump when we had to make sure the quality is not compromised. As a part of making code faster, we do tend to take acceptable detours. Hence it becomes absolutely crucial that we test code from time to time and especially before commits. In this particular case, it was an OpenGL project without any ArrayFire or CUDA/OpenCL as a part of it. Anything that we would do with ArrayFire would be kept separate from the production code. We needed code that would compare and analyse the result from our development branch against a \"Gold\" data set generated by the code received by us.\r\n\r\nThe first option to do this was the old fashioned way by reading two images and comparing them on CPU. But given that we needed to compare images (in the 100s), this was not a viable option. It would simply be too slow.\r\n\r\nThe preferred option was to use ArrayFire but keep it separate from the production code. So we decided to go this route.\r\n\r\nThe first thing we did was to write our testing code. A simple function that would read images from the respective folders and then perform various comparisons on then. This is where ArrayFire excels. Just about 10 lines of code and everything is set for loading and comparing images. Some of the function we used included subtraction, min, mean, max, stats etc. We also included visualization using fig if the user chose to visualize the differences.\r\n\r\n&lt;pre&gt;\r\n\r\nstd::string goldPath = std::string(gold)          + path;\r\nstd::string testPath   = std::string(\"output/\") + path;\r\n\r\naf::array goldImage = af::loadimage(goldPath.c_str(), true) / 255.0f;\r\naf::array testImage   = af::loadimage(testPath.c_str(), true) / 255.0f;\r\n\r\naf::array diffImage = af::abs(goldImage - testImage);\r\n\r\nfloat mean = af::mean&lt;float&gt;(diffImage);\r\n\r\nif(mean &gt; 0.001f) {\r\nfprintf ( stderr, \"FOUND MISMATCH\\n\" ) ;\r\nresult = false;\r\nprintf(\"!!!***FAILED***!!!: %s\\n\", path);\r\n\r\nstats(diffImage);\r\nif(visualize) {\r\n// colormap\r\naf::fig(\"color\", \"default\");\r\n\r\n// image operations\r\naf::fig(\"sub\", 3, 1, 1); af::image(goldImage); af::fig(\"title\", \"GOLD\");\r\naf::fig(\"sub\", 3, 1, 2); af::image(testImage);   af::fig(\"title\", \"TEST\");\r\naf::fig(\"sub\", 3, 1, 3); af::image(diffImage);   af::fig(\"title\", \"DIFF\");\r\n\r\n// Force screen refresh (optional)\r\naf::fig(\"draw\");\r\ngetchar();\r\n}\r\n}\r\n\r\n&lt;/pre&gt;\r\n\r\nOnce the code was in place, we had to integrate it into the main function of the code. Again, it was required that this must not mess with the production code. So we put two lines in the main function. The first line includes the file containing the test function and the second line calls the test function. Both these lines were wrapped in a #ifdef TEST which would be defined in the makefile. That way, if TEST is not defined, the file isn\'t included and ArrayFire is not required for compilation and running of the code. For all of this, we created a makefile goal called \"test\" which would define the flag, include and link ArrayFire.','Q&A Using ArrayFire','','inherit','open','closed','','5736-revision-v1','','','2014-06-02 22:02:47','2014-06-02 22:02:47','',5736,'http://sandbox.arrayfire.com/5736-revision-v1/',0,'revision','',0),(5740,11,'2014-06-02 22:07:05','2014-06-02 22:07:05','One of the reasons ArrayFire has become so useful is attributed to it integrating various performance oriented function from many domains with utility functions such as image loading and visualization.\r\n\r\nIn a lot of cases, developers write a ton of code with multiple iterations but do not have a way to check the quality of the results. That\'s where ArrayFire can be used very well.\r\n\r\nIn one of our recent projects that involved image processing, we did a lot of development but faced a speed bump when we had to make sure the quality is not compromised. As a part of making code faster, we do tend to take acceptable detours. Hence it becomes absolutely crucial that we test code from time to time and especially before commits. In this particular case, it was an OpenGL project without any ArrayFire or CUDA/OpenCL as a part of it. Anything that we would do with ArrayFire would be kept separate from the production code. We needed code that would compare and analyse the result from our development branch against a \"Gold\" data set generated by the code received by us.\r\n\r\nThe first option to do this was the old fashioned way by reading two images and comparing them on CPU. But given that we needed to compare images (in the 100s), this was not a viable option. It would simply be too slow.\r\n\r\nThe preferred option was to use ArrayFire but keep it separate from the production code. So we decided to go this route.\r\n\r\nThe first thing we did was to write our testing code. A simple function that would read images from the respective folders and then perform various comparisons on then. This is where ArrayFire excels. Just about 10 lines of code and everything is set for loading and comparing images. Some of the function we used included subtraction, min, mean, max, stats etc. We also included visualization using fig if the user chose to visualize the differences.\r\n<pre>std::string goldPath = std::string(gold)      + path;\r\nstd::string testPath = std::string(\"output/\") + path;</pre>\r\n<pre>af::array goldImage = af::loadimage(goldPath.c_str(), true) / 255.0f;\r\naf::array testImage = af::loadimage(testPath.c_str(), true) / 255.0f;</pre>\r\n<pre>af::array diffImage = af::abs(goldImage - testImage);</pre>\r\n<pre>float mean = af::mean&lt;float&gt;(diffImage);</pre>\r\n<pre>if(mean &gt; 0.001f) {\r\n    fprintf ( stderr, \"FOUND MISMATCH\\n\" ) ;\r\n    result = false;\r\n    printf(\"!!!***FAILED***!!!: %s\\n\", path);</pre>\r\n<pre>    stats(diffImage);\r\n    if(visualize) {\r\n        // colormap\r\n        af::fig(\"color\", \"default\");</pre>\r\n<pre>        // image operations\r\n        af::fig(\"sub\", 3, 1, 1); af::image(goldImage); af::fig(\"title\", \"GOLD\");\r\n        af::fig(\"sub\", 3, 1, 2); af::image(testImage); af::fig(\"title\", \"TEST\");\r\n        af::fig(\"sub\", 3, 1, 3); af::image(diffImage); af::fig(\"title\", \"DIFF\");</pre>\r\n<pre>        // Force screen refresh (optional)\r\n        af::fig(\"draw\");\r\n        getchar();\r\n    }\r\n}</pre>\r\nOnce the code was in place, we had to integrate it into the main function of the code. Again, it was required that this must not mess with the production code. So we put two lines in the main function. The first line includes the file containing the test function and the second line calls the test function. Both these lines were wrapped in a #ifdef TEST which would be defined in the makefile. That way, if TEST is not defined, the file isn\'t included and ArrayFire is not required for compilation and running of the code. For all of this, we created a makefile goal called \"test\" which would define the flag, include and link ArrayFire.','Q&A Using ArrayFire','','inherit','open','closed','','5736-revision-v1','','','2014-06-02 22:07:05','2014-06-02 22:07:05','',5736,'http://sandbox.arrayfire.com/5736-revision-v1/',0,'revision','',0),(5741,11,'2014-06-02 22:07:21','2014-06-02 22:07:21','One of the reasons ArrayFire has become so useful is attributed to it integrating various performance oriented function from many domains with utility functions such as image loading and visualization.\r\n\r\nIn a lot of cases, developers write a ton of code with multiple iterations but do not have a way to check the quality of the results. That\'s where ArrayFire can be used very well.\r\n\r\nIn one of our recent projects that involved image processing, we did a lot of development but faced a speed bump when we had to make sure the quality is not compromised. As a part of making code faster, we do tend to take acceptable detours. Hence it becomes absolutely crucial that we test code from time to time and especially before commits. In this particular case, it was an OpenGL project without any ArrayFire or CUDA/OpenCL as a part of it. Anything that we would do with ArrayFire would be kept separate from the production code. We needed code that would compare and analyse the result from our development branch against a \"Gold\" data set generated by the code received by us.\r\n\r\nThe first option to do this was the old fashioned way by reading two images and comparing them on CPU. But given that we needed to compare images (in the 100s), this was not a viable option. It would simply be too slow.\r\n\r\nThe preferred option was to use ArrayFire but keep it separate from the production code. So we decided to go this route.\r\n\r\nThe first thing we did was to write our testing code. A simple function that would read images from the respective folders and then perform various comparisons on then. This is where ArrayFire excels. Just a few lines of code and everything is set for loading and comparing images. Some of the function we used included subtraction, min, mean, max, stats etc. We also included visualization using fig if the user chose to visualize the differences.\r\n<pre>std::string goldPath = std::string(gold)      + path;\r\nstd::string testPath = std::string(\"output/\") + path;</pre>\r\n<pre>af::array goldImage = af::loadimage(goldPath.c_str(), true) / 255.0f;\r\naf::array testImage = af::loadimage(testPath.c_str(), true) / 255.0f;</pre>\r\n<pre>af::array diffImage = af::abs(goldImage - testImage);</pre>\r\n<pre>float mean = af::mean&lt;float&gt;(diffImage);</pre>\r\n<pre>if(mean &gt; 0.001f) {\r\n    fprintf ( stderr, \"FOUND MISMATCH\\n\" ) ;\r\n    result = false;\r\n    printf(\"!!!***FAILED***!!!: %s\\n\", path);</pre>\r\n<pre>    stats(diffImage);\r\n    if(visualize) {\r\n        // colormap\r\n        af::fig(\"color\", \"default\");</pre>\r\n<pre>        // image operations\r\n        af::fig(\"sub\", 3, 1, 1); af::image(goldImage); af::fig(\"title\", \"GOLD\");\r\n        af::fig(\"sub\", 3, 1, 2); af::image(testImage); af::fig(\"title\", \"TEST\");\r\n        af::fig(\"sub\", 3, 1, 3); af::image(diffImage); af::fig(\"title\", \"DIFF\");</pre>\r\n<pre>        // Force screen refresh (optional)\r\n        af::fig(\"draw\");\r\n        getchar();\r\n    }\r\n}</pre>\r\nOnce the code was in place, we had to integrate it into the main function of the code. Again, it was required that this must not mess with the production code. So we put two lines in the main function. The first line includes the file containing the test function and the second line calls the test function. Both these lines were wrapped in a #ifdef TEST which would be defined in the makefile. That way, if TEST is not defined, the file isn\'t included and ArrayFire is not required for compilation and running of the code. For all of this, we created a makefile goal called \"test\" which would define the flag, include and link ArrayFire.','Q&A Using ArrayFire','','inherit','open','closed','','5736-revision-v1','','','2014-06-02 22:07:21','2014-06-02 22:07:21','',5736,'http://sandbox.arrayfire.com/5736-revision-v1/',0,'revision','',0),(5742,11,'2014-06-02 22:07:39','2014-06-02 22:07:39','One of the reasons ArrayFire has become so useful is attributed to it integrating various performance oriented function from many domains with utility functions such as image loading and visualization.\r\n\r\nIn a lot of cases, developers write a ton of code with multiple iterations but do not have a way to check the quality of the results. That\'s where ArrayFire can be used very well.\r\n\r\nIn one of our recent projects that involved image processing, we did a lot of development but faced a speed bump when we had to make sure the quality is not compromised. As a part of making code faster, we do tend to take acceptable detours. Hence it becomes absolutely crucial that we test code from time to time and especially before commits. In this particular case, it was an OpenGL project without any ArrayFire or CUDA/OpenCL as a part of it. Anything that we would do with ArrayFire would be kept separate from the production code. We needed code that would compare and analyse the result from our development branch against a \"Gold\" data set generated by the code received by us.\r\n\r\nThe first option to do this was the old fashioned way by reading two images and comparing them on CPU. But given that we needed to compare images (in the 100s), this was not a viable option. It would simply be too slow.\r\n\r\nThe preferred option was to use ArrayFire but keep it separate from the production code. So we decided to go this route.\r\n\r\nThe first thing we did was to write our testing code. A simple function that would read images from the respective folders and then perform various comparisons on then. This is where ArrayFire excels. Just a few lines of code and everything is set for loading and comparing images. Some of the function we used included subtraction, min, mean, max, stats etc. We also included visualization using fig if the user chose to visualize the differences.\r\n<pre>std::string goldPath = std::string(gold)      + path;\r\nstd::string testPath = std::string(\"output/\") + path;\r\n\r\naf::array goldImage = af::loadimage(goldPath.c_str(), true) / 255.0f;\r\naf::array testImage = af::loadimage(testPath.c_str(), true) / 255.0f;</pre>\r\n<pre>af::array diffImage = af::abs(goldImage - testImage);</pre>\r\n<pre>float mean = af::mean&lt;float&gt;(diffImage);</pre>\r\n<pre>if(mean &gt; 0.001f) {\r\n    fprintf ( stderr, \"FOUND MISMATCH\\n\" ) ;\r\n    result = false;\r\n    printf(\"!!!***FAILED***!!!: %s\\n\", path);</pre>\r\n<pre>    stats(diffImage);\r\n    if(visualize) {\r\n        // colormap\r\n        af::fig(\"color\", \"default\");</pre>\r\n<pre>        // image operations\r\n        af::fig(\"sub\", 3, 1, 1); af::image(goldImage); af::fig(\"title\", \"GOLD\");\r\n        af::fig(\"sub\", 3, 1, 2); af::image(testImage); af::fig(\"title\", \"TEST\");\r\n        af::fig(\"sub\", 3, 1, 3); af::image(diffImage); af::fig(\"title\", \"DIFF\");</pre>\r\n<pre>        // Force screen refresh (optional)\r\n        af::fig(\"draw\");\r\n        getchar();\r\n    }\r\n}</pre>\r\nOnce the code was in place, we had to integrate it into the main function of the code. Again, it was required that this must not mess with the production code. So we put two lines in the main function. The first line includes the file containing the test function and the second line calls the test function. Both these lines were wrapped in a #ifdef TEST which would be defined in the makefile. That way, if TEST is not defined, the file isn\'t included and ArrayFire is not required for compilation and running of the code. For all of this, we created a makefile goal called \"test\" which would define the flag, include and link ArrayFire.','Q&A Using ArrayFire','','inherit','open','closed','','5736-revision-v1','','','2014-06-02 22:07:39','2014-06-02 22:07:39','',5736,'http://sandbox.arrayfire.com/5736-revision-v1/',0,'revision','',0),(5743,11,'2014-06-02 22:08:22','2014-06-02 22:08:22','One of the reasons ArrayFire has become so useful is attributed to it integrating various performance oriented function from many domains with utility functions such as image loading and visualization.\r\n\r\nIn a lot of cases, developers write a ton of code with multiple iterations but do not have a way to check the quality of the results. That\'s where ArrayFire can be used very well.\r\n\r\nIn one of our recent projects that involved image processing, we did a lot of development but faced a speed bump when we had to make sure the quality is not compromised. As a part of making code faster, we do tend to take acceptable detours. Hence it becomes absolutely crucial that we test code from time to time and especially before commits. In this particular case, it was an OpenGL project without any ArrayFire or CUDA/OpenCL as a part of it. Anything that we would do with ArrayFire would be kept separate from the production code. We needed code that would compare and analyse the result from our development branch against a \"Gold\" data set generated by the code received by us.\r\n\r\nThe first option to do this was the old fashioned way by reading two images and comparing them on CPU. But given that we needed to compare images (in the 100s), this was not a viable option. It would simply be too slow.\r\n\r\nThe preferred option was to use ArrayFire but keep it separate from the production code. So we decided to go this route.\r\n\r\nThe first thing we did was to write our testing code. A simple function that would read images from the respective folders and then perform various comparisons on then. This is where ArrayFire excels. Just a few lines of code and everything is set for loading and comparing images. Some of the function we used included subtraction, min, mean, max, stats etc. We also included visualization using fig if the user chose to visualize the differences.\r\n<pre>std::string goldPath = std::string(gold)      + path;\r\nstd::string testPath = std::string(\"output/\") + path;\r\n\r\naf::array goldImage = af::loadimage(goldPath.c_str(), true) / 255.0f;\r\naf::array testImage = af::loadimage(testPath.c_str(), true) / 255.0f;\r\n\r\naf::array diffImage = af::abs(goldImage - testImage);\r\n\r\nfloat mean = af::mean&lt;float&gt;(diffImage);\r\n\r\nif(mean &gt; 0.001f) {\r\n    fprintf ( stderr, \"FOUND MISMATCH\\n\" ) ;\r\n    result = false;\r\n    printf(\"!!!***FAILED***!!!: %s\\n\", path);\r\n    stats(diffImage);\r\n\r\n    if(visualize) {</pre>\r\n<pre>        // colormap\r\n        af::fig(\"color\", \"default\");</pre>\r\n<pre>        // image operations\r\n        af::fig(\"sub\", 3, 1, 1); af::image(goldImage); af::fig(\"title\", \"GOLD\");\r\n        af::fig(\"sub\", 3, 1, 2); af::image(testImage); af::fig(\"title\", \"TEST\");\r\n        af::fig(\"sub\", 3, 1, 3); af::image(diffImage); af::fig(\"title\", \"DIFF\");</pre>\r\n<pre>        // Force screen refresh (optional)\r\n        af::fig(\"draw\");\r\n        getchar();\r\n    }\r\n}</pre>\r\nOnce the code was in place, we had to integrate it into the main function of the code. Again, it was required that this must not mess with the production code. So we put two lines in the main function. The first line includes the file containing the test function and the second line calls the test function. Both these lines were wrapped in a #ifdef TEST which would be defined in the makefile. That way, if TEST is not defined, the file isn\'t included and ArrayFire is not required for compilation and running of the code. For all of this, we created a makefile goal called \"test\" which would define the flag, include and link ArrayFire.','Q&A Using ArrayFire','','inherit','open','closed','','5736-revision-v1','','','2014-06-02 22:08:22','2014-06-02 22:08:22','',5736,'http://sandbox.arrayfire.com/5736-revision-v1/',0,'revision','',0),(5744,11,'2014-06-02 22:09:25','2014-06-02 22:09:25','One of the reasons ArrayFire has become so useful is attributed to it integrating various performance oriented function from many domains with utility functions such as image loading and visualization.\r\n\r\nIn a lot of cases, developers write a ton of code with multiple iterations but do not have a way to check the quality of the results. That\'s where ArrayFire can be used very well.\r\n\r\nIn one of our recent projects that involved image processing, we did a lot of development but faced a speed bump when we had to make sure the quality is not compromised. As a part of making code faster, we do tend to take acceptable detours. Hence it becomes absolutely crucial that we test code from time to time and especially before commits. In this particular case, it was an OpenGL project without any ArrayFire or CUDA/OpenCL as a part of it. Anything that we would do with ArrayFire would be kept separate from the production code. We needed code that would compare and analyse the result from our development branch against a \"Gold\" data set generated by the code received by us.\r\n\r\nThe first option to do this was the old fashioned way by reading two images and comparing them on CPU. But given that we needed to compare images (in the 100s), this was not a viable option. It would simply be too slow.\r\n\r\nThe preferred option was to use ArrayFire but keep it separate from the production code. So we decided to go this route.\r\n\r\nThe first thing we did was to write our testing code. A simple function that would read images from the respective folders and then perform various comparisons on then. This is where ArrayFire excels. Just a few lines of code and everything is set for loading and comparing images. Some of the function we used included subtraction, min, mean, max, stats etc. We also included visualization using fig if the user chose to visualize the differences.\r\n<pre>std::string goldPath = std::string(gold)      + path;\r\nstd::string testPath = std::string(\"output/\") + path;\r\n\r\naf::array goldImage = af::loadimage(goldPath.c_str(), true) / 255.0f;\r\naf::array testImage = af::loadimage(testPath.c_str(), true) / 255.0f;\r\n\r\naf::array diffImage = af::abs(goldImage - testImage);\r\n\r\nfloat mean = af::mean&lt;float&gt;(diffImage);\r\n\r\nif(mean &gt; 0.001f) {\r\n    fprintf ( stderr, \"FOUND MISMATCH\\n\" ) ;\r\n    result = false;\r\n    printf(\"!!!***FAILED***!!!: %s\\n\", path);\r\n    stats(diffImage);\r\n\r\n    if(visualize) {\r\n        // colormap\r\n        af::fig(\"color\", \"default\");\r\n\r\n        // image operations\r\n        af::fig(\"sub\", 3, 1, 1); af::image(goldImage); af::fig(\"title\", \"GOLD\");\r\n        af::fig(\"sub\", 3, 1, 2); af::image(testImage); af::fig(\"title\", \"TEST\");\r\n        af::fig(\"sub\", 3, 1, 3); af::image(diffImage); af::fig(\"title\", \"DIFF\");\r\n\r\n        // Force screen refresh (optional)\r\n        af::fig(\"draw\");\r\n        getchar();\r\n    }\r\n}</pre>\r\nOnce the code was in place, we had to integrate it into the main function of the code. Again, it was required that this must not mess with the production code. So we put two lines in the main function. The first line includes the file containing the test function and the second line calls the test function. Both these lines were wrapped in a #ifdef TEST which would be defined in the makefile. That way, if TEST is not defined, the file isn\'t included and ArrayFire is not required for compilation and running of the code. For all of this, we created a makefile goal called \"test\" which would define the flag, include and link ArrayFire.','Q&A Using ArrayFire','','inherit','open','closed','','5736-revision-v1','','','2014-06-02 22:09:25','2014-06-02 22:09:25','',5736,'http://sandbox.arrayfire.com/5736-revision-v1/',0,'revision','',0),(5745,11,'2014-06-02 22:10:54','2014-06-02 22:10:54','One of the reasons ArrayFire has become so useful is attributed to it integrating various performance oriented function from many domains with utility functions such as image loading and visualization.\r\n\r\nIn a lot of cases, developers write a ton of code with multiple iterations but do not have a way to check the quality of the results. That\'s where ArrayFire can be used very well.\r\n\r\nIn one of our recent projects that involved image processing, we did a lot of development but faced a speed bump when we had to make sure the quality is not compromised. As a part of making code faster, we do tend to take acceptable detours. Hence it becomes absolutely crucial that we test code from time to time and especially before commits. In this particular case, it was an OpenGL project without any ArrayFire or CUDA/OpenCL as a part of it. Anything that we would do with ArrayFire would be kept separate from the production code. We needed code that would compare and analyse the result from our development branch against a \"Gold\" data set generated by the code received by us.\r\n\r\nThe first option to do this was the old fashioned way by reading two images and comparing them on CPU. But given that we needed to compare images (in the 100s), this was not a viable option. It would simply be too slow.\r\n\r\nThe preferred option was to use ArrayFire but keep it separate from the production code. So we decided to go this route.\r\n\r\nThe first thing we did was to write our testing code. A simple function that would read images from the respective folders and then perform various comparisons on then. This is where ArrayFire excels. Just a few lines of code and everything is set for loading and comparing images. Some of the function we used included subtraction, min, mean, max, stats etc. We also included visualization using fig if the user chose to visualize the differences.\r\n<pre>std::string goldPath = std::string(gold)      + path;\r\nstd::string testPath = std::string(\"output/\") + path;\r\n\r\naf::array goldImage = af::loadimage(goldPath.c_str(), true) / 255.0f;\r\naf::array testImage = af::loadimage(testPath.c_str(), true) / 255.0f;\r\n\r\naf::array diffImage = af::abs(goldImage - testImage);\r\n\r\nfloat mean = af::mean\\&lt;float&amp;gt(diffImage);\r\n\r\nif(mean &gt; 0.001f) {\r\n    fprintf ( stderr, \"FOUND MISMATCH\\n\" ) ;\r\n    result = false;\r\n    printf(\"!!!***FAILED***!!!: %s\\n\", path);\r\n    stats(diffImage);\r\n\r\n    if(visualize) {\r\n        // colormap\r\n        af::fig(\"color\", \"default\");\r\n\r\n        // image operations\r\n        af::fig(\"sub\", 3, 1, 1); af::image(goldImage); af::fig(\"title\", \"GOLD\");\r\n        af::fig(\"sub\", 3, 1, 2); af::image(testImage); af::fig(\"title\", \"TEST\");\r\n        af::fig(\"sub\", 3, 1, 3); af::image(diffImage); af::fig(\"title\", \"DIFF\");\r\n\r\n        // Force screen refresh (optional)\r\n        af::fig(\"draw\");\r\n        getchar();\r\n    }\r\n}</pre>\r\nOnce the code was in place, we had to integrate it into the main function of the code. Again, it was required that this must not mess with the production code. So we put two lines in the main function. The first line includes the file containing the test function and the second line calls the test function. Both these lines were wrapped in a #ifdef TEST which would be defined in the makefile. That way, if TEST is not defined, the file isn\'t included and ArrayFire is not required for compilation and running of the code. For all of this, we created a makefile goal called \"test\" which would define the flag, include and link ArrayFire.','Q&A Using ArrayFire','','inherit','open','closed','','5736-revision-v1','','','2014-06-02 22:10:54','2014-06-02 22:10:54','',5736,'http://sandbox.arrayfire.com/5736-revision-v1/',0,'revision','',0),(5746,11,'2014-06-02 22:29:48','2014-06-02 22:29:48','One of the reasons ArrayFire has become so useful is attributed to it integrating various performance oriented function from many domains with utility functions such as image loading and visualization.\r\n\r\nIn a lot of cases, developers write a ton of code with multiple iterations but do not have a way to check the quality of the results. That\'s where ArrayFire can be used very well.\r\n\r\nIn one of our recent projects that involved image processing, we did a lot of development but faced a speed bump when we had to make sure the quality is not compromised. As a part of making code faster, we do tend to take acceptable detours. Hence it becomes absolutely crucial that we test code from time to time and especially before commits. In this particular case, it was an OpenGL project without any ArrayFire or CUDA/OpenCL as a part of it. Anything that we would do with ArrayFire would be kept separate from the production code. We needed code that would compare and analyse the result from our development branch against a \"Gold\" data set generated by the code received by us.\r\n\r\nThe first option to do this was the old fashioned way by reading two images and comparing them on CPU. But given that we needed to compare images (in the 100s), this was not a viable option. It would simply be too slow.\r\n\r\nThe preferred option was to use ArrayFire but keep it separate from the production code. So we decided to go this route.\r\n\r\nThe first thing we did was to write our testing code. A simple function that would read images from the respective folders and then perform various comparisons on then. This is where ArrayFire excels. Just a few lines of code and everything is set for loading and comparing images. Some of the function we used included subtraction, min, mean, max, stats etc. We also included visualization using fig if the user chose to visualize the differences.\r\n<pre>std::string goldPath = std::string(gold)      + path;\r\nstd::string testPath = std::string(\"output/\") + path;\r\n\r\naf::array goldImage = af::loadimage(goldPath.c_str(), true) / 255.0f;\r\naf::array testImage = af::loadimage(testPath.c_str(), true) / 255.0f;\r\n\r\naf::array diffImage = af::abs(goldImage - testImage);\r\n\r\nfloat mean = af::mean<float>(diffImage);\r\n\r\nif(mean < 0.001f) {\r\n    fprintf ( stderr, \"FOUND MISMATCH\\n\" ) ;\r\n    result = false;\r\n    printf(\"!!!***FAILED***!!!: %s\\n\", path);\r\n    stats(diffImage);\r\n\r\n    if(visualize) {\r\n        // colormap\r\n        af::fig(\"color\", \"default\");\r\n\r\n        // image operations\r\n        af::fig(\"sub\", 3, 1, 1); af::image(goldImage); af::fig(\"title\", \"GOLD\");\r\n        af::fig(\"sub\", 3, 1, 2); af::image(testImage); af::fig(\"title\", \"TEST\");\r\n        af::fig(\"sub\", 3, 1, 3); af::image(diffImage); af::fig(\"title\", \"DIFF\");\r\n\r\n        // Force screen refresh (optional)\r\n        af::fig(\"draw\");\r\n        getchar();\r\n    }\r\n}</pre>\r\nOnce the code was in place, we had to integrate it into the main function of the code. Again, it was required that this must not mess with the production code. So we put two lines in the main function. The first line includes the file containing the test function and the second line calls the test function. Both these lines were wrapped in a #ifdef TEST which would be defined in the makefile. That way, if TEST is not defined, the file isn\'t included and ArrayFire is not required for compilation and running of the code. For all of this, we created a makefile goal called \"test\" which would define the flag, include and link ArrayFire.','Q&A Using ArrayFire','','inherit','open','closed','','5736-autosave-v1','','','2014-06-02 22:29:48','2014-06-02 22:29:48','',5736,'http://sandbox.arrayfire.com/5736-autosave-v1/',0,'revision','',0),(5747,11,'2014-06-02 22:15:18','2014-06-02 22:15:18','In the upcoming months we\'ll be adding a lot of new Computer Vision functionality to ArrayFire, specifically targeting the most commonly used applications in this field. New functions include feature tracking, object classification, scene segmentation, optical flow, and stereo-vision.\r\n\r\nFeature tracking consists of three basic steps:\r\n<ol>\r\n	<li>Detecting good or unique features; normally they are corners or blobs of an object.</li>\r\n	<li>Extracting a descriptor for each feature—understanding the texture of a small patch around each feature.</li>\r\n	<li>Descriptor matching—finding out the best match for each pair of descriptors (one from the object being tracked, another from a scene that potentially contains that object), if any.</li>\r\n</ol>\r\n<h3>Harris corner detector</h3>\r\nIn this article we will be using ArrayFire to dive deeper into the first step of feature tracking: detecting good features. Through a step-by-step guide we will develop a simple corner detector, known as the Harris corner detector [1].\r\n\r\nThe Harris corner detector is very simple to implement, especially when you have so many good tools and libraries out there to do the core matrix manipulation. What we specifically need for Harris are some convolutions, together with a few element-wise matrix addition and multiplication operations; all of these operations are present in most scientific tools and libraries that work with matrix manipulation. I will try to avoid going into the mathematical details in this post and go directly to the implementation.\r\n<h5>Loading an image</h5>\r\nBefore writing the code for the corner detector, we need to load an image. The image can be either color or grayscale, but it will only work on the grayscale version; if we upload a color image, we have to convert it before proceeding.\r\n<pre>// Load a color image\r\narray img_color = loadimage(\"lena.jpg\", true);\r\n// Convert the image from RGB to gray-scale\r\narray img_gray = colorspace(img_color, af_gray, af_rgb);\r\n// For visualization in ArrayFire, color images must be in the [0.0f-1.0f] interval\r\nimg_color /= 255.f;\r\n</pre>\r\n<h5>Compute first-order derivatives</h5>\r\nThe first step in the Harris corner detector is to determine first order derivatives of an image, in both horizontal and vertical directions. This can be achieved by one convolution for each direction, with the kernel (-1, 0, 1)  for horizontal derivative and its transpose for vertical derivative. ArrayFire contains a function called <a href=\"http://www.accelereyes.com/arrayfire/c/group__math__func__cpp__grad.htm\">grad</a>, which calculates gradients in both directions and will perform faster than the two convolutions. The only difference  is that <a href=\"http://www.accelereyes.com/arrayfire/c/group__math__func__cpp__grad.htm\">grad</a> divides the result by 2, thus, the response factor will change. The use of grad will improve the performance, and factor change can be easily compensated by using a smaller response.\r\n<pre>// Calculate image gradients\r\narray ix, iy;\r\ngrad(ix, iy, img_gray);\r\n</pre>\r\n<h5>Compute second-order derivatives</h5>\r\nAt this point we have both horizontal and vertical first order derivatives of our image, but Harris corner detector is processed with second-order derivatives, which can be easily computed in ArrayFire with simple element-wise multiplications of the first-order derivatives.\r\n<pre>// Compute second-order derivatives\r\narray ixx = ix * ix;\r\narray ixy = ix * iy;\r\narray iyy = iy * iy;\r\n</pre>\r\n<h5>Compute an isotropic window</h5>\r\nTo check the cornerness of each pixel of an image, it\'s not enough to check the pixel value itself. We must also check a small window around that pixel. To reduce noise sensitivity and have an isotropic response, Harris claims that a smooth circular window should be used. This can be achieved by filtering of all three second-order derivatives with a Gaussian kernel.\r\n<pre>// Compute a Gaussian kernel with standard deviation of 1.0 and length of 5 pixels\r\n// These values can be changed to use a smaller or larger window\r\narray gauss_filt = gaussiankernel(5, 5, 1.0, 1.0);\r\n\r\n// Filter second-order derivatives with Gaussian kernel computed previously\r\nixx = convolve(ixx, gauss_filt);\r\nixy = convolve(ixy, gauss_filt);\r\niyy = convolve(iyy, gauss_filt);\r\n</pre>\r\n<h5>Compute trace and determinant</h5>\r\nFrom a second-order Hessian matrix, we then compute the values of its trace and determinant. These are the values we will need later to calculate the Harris response for each pixel in the image.\r\n<pre>// Calculate trace\r\narray tr = ixx + iyy;\r\n// Calculate determinant\r\narray det = ixx * iyy - ixy * ixy;\r\n</pre>\r\n<h5>Compute Harris response</h5>\r\nNext, we calculate the Harris response for each pixel. For this calculation, Harris uses an empirically defined constant <code>k</code>. This constant is usually very small, normally ranging from <code>0.04</code> to <code>0.06</code>. In our case, we will use <code>k = 0.04</code>, but we encourage you to play with this value and see how the result is affected.\r\n<pre>// Calculate Harris response\r\narray response = det - 0.04f * (tr * tr);\r\n</pre>\r\n<h5>Selection of good corners</h5>\r\nNow we already have our Harris responses for each pixel in the image. This value is used to determine whether a pixel is a corner or not. The standard way is to perform a non-maximal suppression, meaning that each pixel can only be a corner if it is a maximum compared to its 8 adjacent pixels. At the moment we do not have a direct way to compute a non-maximal suppression with ArrayFire; we have to write our own kernel for that. Non-maximal suppression is  just one of the cool things we will be able to do with our new computer vision toolset for ArrayFire.\r\n\r\nAn alternative is to do the non-maximal suppression in a naive way. To do this, we will use ArrayFire\'s <a href=\"http://www.accelereyes.com/arrayfire/c/group__image__func__cpp__maxfilt.htm\">maxfilt</a> function, which filters the image with a mask of <code>NxM</code> pixel and returns the maximum value of the neighborhood to the pixel centered within the mask. In this case we will use a <code>3x3</code> pixel mask to return the maximum of the 8-neighborhood, including the central pixel itself.\r\n\r\nThe <a href=\"http://www.accelereyes.com/arrayfire/c/group__image__func__cpp__maxfilt.htm\">maxfilt</a> function alone will not perform a non-maximal suppression, but by combining the function with a few other steps we can get the proper responses.\r\n\r\nThe nature of a pixel can be determined by the Harris responses; a negative response means that a pixel corresponds to the segment of an edge. If the response is small but positive, it corresponds to a flat region. Only a large response corresponds to a corner. By thresholding the response array with the minimum desired Harris response, which, for our example, will be 10<sup>5</sup>, we can calculate a binary response array for which only pixels with a value greater than this threshold will be true. We then multiply it to the original response array to get a new array containing only responses greater that 10<sup>5</sup>.\r\n\r\nHere we will use a threshold of 10<sup>5</sup>. For the implementation presented in this article, we found that corners seem to be better for responses larger than 10<sup>4</sup>, but you can and should play with these values to see how it will affect the image you are working on.\r\n\r\nThe last step for this is testing whether each pixel is equal to the maximum Harris response of the neighborhood. If it is equal, then we keep it, else, the response is not a local maximum and we discard it.\r\n<pre>// Gets maximum response for each 3x3 neighborhood\r\narray max_resp = maxfilt(response, 3, 3);\r\n\r\n// Discard responses that are not greater than threshold\r\narray corners = response &gt; 1e5f;\r\ncorners = corners * response;\r\n\r\n// Discard responses that are not equal to maximum neighborhood response,\r\n// scale them to original response value\r\ncorners = (corners == max_resp) * corners;\r\n</pre>\r\nIf you still think you want a non-maximal suppression kernel for yourself, you can write it instead of using the last piece of code above. If you have never written your own kernel to work with an ArrayFire array, check out the <a href=\"http://sandbox.arrayfire.com/custom-kernels-with-arrayfire/\">Custom Kernels with ArrayFire</a> post. Writing the non-maximal suppression kernel itself will not take more than 20 or 30 lines of code.\r\n<h5>Plotting corners</h5>\r\nThis last step is done on the <abbr title=\"Central Processing Unit\">CPU</abbr> side; we only do this to show the corners that are detected. This will most likely be unnecessary unless you want to visualize, but, for the sake of clarity, we will include this part to show the result.\r\n<pre>// Gets host pointer to response data\r\nfloat* h_corners = corners.host();\r\n\r\n// Draw draw_len x draw_len crosshairs where the corners are\r\nconst int draw_len = 3;\r\nfor (int y = draw_len; y &lt; img_color.dims(0) - draw_len; y++) {\r\n    for (int x = draw_len; x &lt; img_color.dims(1) - draw_len; x++) {\r\n        // Only draws crosshair if is a corner\r\n        if (h_corners[x * corners.dims(0) + y] &gt; 1e5f) {\r\n            // Draw horizontal line of (draw_len * 2 + 1) pixels centered on the corner\r\n            // Set only the first channel to 1 (green lines)\r\n            img_color(y, seq(x-draw_len, x+draw_len), 0) = 0.f;\r\n            img_color(y, seq(x-draw_len, x+draw_len), 1) = 1.f;\r\n            img_color(y, seq(x-draw_len, x+draw_len), 2) = 0.f;\r\n\r\n            // Draw vertical line of (draw_len * 2 + 1) pixels centered on  the corner\r\n            // Set only the first channel to 1 (green lines)\r\n            img_color(seq(y-draw_len, y+draw_len), x, 0) = 0.f;\r\n            img_color(seq(y-draw_len, y+draw_len), x, 1) = 1.f;\r\n            img_color(seq(y-draw_len, y+draw_len), x, 2) = 0.f;\r\n        }\r\n    }\r\n}</pre>\r\n<h5>Visualize results</h5>\r\nFinally, the image can be visualized.\r\n<pre>// Previews color image with green crosshairs\r\nimage(img_color);\r\n</pre>\r\nBelow you can see Lena\'s picture after the Harris corner detection and plotting. The green crosshairs indicate where corners are.\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_lena.png\"><img class=\"alignnone size-full wp-image-5710\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_lena.png\" alt=\"Harris Corners - Lena\" width=\"1024\" height=\"600\" /></a>\r\n\r\nTo test for correctness of the algorithm, nothing better than a picture with well-defined corners. Below you can see the picture of a white square on a black background and the corners marked by green crosshairs.\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_square.png\"><img class=\"alignnone size-full wp-image-5711\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_square.png\" alt=\"Harris Corners - Square\" width=\"1024\" height=\"600\" /></a>\r\n\r\nAll sources to our examples can be found in our <a href=\"https://github.com/arrayfire/arrayfire_examples\">ArrayFire examples project</a> on GitHub, and the complete code for this article can be viewed via this direct <a href=\"https://github.com/arrayfire/arrayfire_examples/blob/master/image_processing/harris_demo.cpp\">link</a>.\r\n\r\nWe would like to hear from you! What you are working on the computer vision field and what features would you like to see in ArrayFire? Please share your thoughts and requests below or contact us at <a href=\"mailto:sales@arrayfire.com\">sales@arrayfire.com</a>.\r\n<h5>References</h5>\r\n[1] Harris, Chris, and Mike Stephens. \"A combined corner and edge detector.\" <em>Alvey vision conference</em>. Vol. 15. 1988.','Writing a Simple Corner Detector with ArrayFire','','inherit','open','closed','','5659-autosave-v1','','','2014-06-02 22:15:18','2014-06-02 22:15:18','',5659,'http://sandbox.arrayfire.com/5659-autosave-v1/',0,'revision','',0),(5749,11,'2014-06-02 22:22:31','2014-06-02 22:22:31','Mobile devices are carving their niche into the world of computing with more processing power day by day. GPUs on mobile devices have been around for a while, but using them for accelerating computation is still quite new. Until recently, the only way to access the GPU was through OpenGL. Around december 2008, Khronos released OpenCL, a generic API for accelerating non-graphics tasks. OpenCL enables us to take advantage of acceleration hardware. Since it is an open standard, many hardware vendors provide support on their devices. With the recent release of Adreno and Mali SDKs, you can now run OpenCL code on mobile GPUs.\r\n\r\nToday\'s post is going to be about how to do image processing on camera feed on Android devices using OpenCL. To successfully complete this tutorial, you need to have basic knowledge of how to write OpenCL kernels and native code for Android.\r\n<h3 id=\"opencl\">OpenCL</h3>\r\nTo use OpenCL on your mobile device\'s GPU, you must obtain the compatible libOpenCL.so library and the corresponding OpenCL headers.\r\n\r\nI initially thought I could just use the C++ OpenCL header available from Khronos website for development, however that didn\'t work. I faced compilation errors because of incompatible OpenGL headers. There are couple of ways to get the compatible headers. You can either use the <a href=\"https://github.com/arrayfire/androidcl/tree/master/jni/include\">headers</a> provided along with the example application or extract them from Adreno/Mali SDK. For Adreno SDK, you can find the headers at <code>&lt;Adreno_SDK&gt;/Development/Inc/CL</code>. For Mali SDK, you can find the headers at <code>&lt;MALI_SDK&gt;/include/CL</code>.\r\n\r\nFor newer devices such as Samsung Galaxy Note 3 and Samsung Galaxy S5, it is very likely the library is already present on the mobile device. My test device is a Note 3 for which i found the library under <code>/system/vendor/lib</code>. You can do <code>adb pull /system/vendor/lib/libOpenCL.so ./</code> to get the file to your desktop machine. In these kind of cases, you might be able to use the library out of the box without any issues. For any other scenario, please use the directions in following sections to get the library and make it work if available.\r\n<h4 id=\"adreno-gpu\">Adreno GPU</h4>\r\nIf you do not find the library on your device, check if your device has OpenCL support on the corresponding vendor\'s website. If your GPU does have OpenCL support, you might have to update your OS in order to get the recent updates. If you don\'t find the library even after OS update, you might want to email the vendor. However, if your GPU does not have OpenCL support, there isn\'t much we can do.\r\n\r\nIf you do find the library and can\'t use for some reason. Try to update your device drivers using the ones provided by Qualcomm. You can download them from <a href=\"https://developer.qualcomm.com/mobile-development/maximize-hardware/mobile-gaming-graphics-adreno/tools-and-resources\">here</a>. Ensure that you are downloading the Adreno driver but not the Adreno SDK. Follow the instructions in the package and update the drivers on your device. This should resolve any issues you have.\r\n<h4 id=\"mali-gpu\">Mali GPU</h4>\r\nDownload the SDK from <a href=\"http://malideveloper.arm.com/develop-for-mali/sdks/mali-opencl-sdk/\">here</a>. Follow the instructions in the package and build the shared library and copy it on to your device.\r\n<h4 id=\"kernels\">Kernels</h4>\r\nI needed to do two things to achieve my target.\r\n<ul>\r\n	<li>Convert frame data provided by Android camera from NV21 format to RGBA8888 format.</li>\r\n	<li>Run laplacian operator on the RGBA8888 image data.</li>\r\n</ul>\r\nGetting a grayscale image from NV21 format is cake walk, just read the first width*height bytes and you are done. As per the format of <a href=\"http://www.fourcc.org/yuv.php#NV21\">NV21</a>, for each 2x2 sub-matrix of pixels, there will be a pair (v,u). Since 4 pixels are reading same (v,u), i decided to use shared memory to reduce reading latency. The code below is the core of this conversion kernel, that is expected to speed up the conversion if compared to a pure C code.\r\n<pre>#define BLK_SIZE 16\r\n//prefix D for decoding\r\n#define DSHRD_LEN (BLK_SIZE/2)\r\n#define DSHRD_SIZE (2*DSHRD_LEN*DSHRD_LEN)\r\n// ...\r\n// ...\r\n// kernel signature\r\n{\r\n    __local uchar uvShrd[DSHRD_SIZE];\r\n    int gx = get_global_id(0);\r\n    int gy = get_global_id(1);\r\n    int lx = get_local_id(0);\r\n    int ly = get_local_id(1);\r\n    int off = im_width*im_height;\r\n    int inIdx= gy*im_width+gx;\r\n    int uvIdx= off + (gy/2)*im_width + (gx &amp; ~1); // took me a while to figure out this formula\r\n    int shlx = lx/2;\r\n    int shly = ly/2;\r\n    int shIdx= 2*(shlx+shly*DSHRD_LEN);\r\n    if( gx%2==0 &amp;&amp; gy%2==0 ) {\r\n        uvShrd[shIdx+0] = in[uvIdx+0];\r\n        uvShrd[shIdx+1] = in[uvIdx+1];\r\n    }\r\n    int y = (0xFF &amp; ((int)in[inIdx]));\r\n    int y = (0xFF &amp; ((int)in[inIdx]));\r\n    if( y &lt; 16 ) y=16;\r\n    barrier(CLK_LOCAL_MEM_FENCE);\r\n    //..... rest of code that does color space conversion\r\n}\r\n</pre>\r\nLaplacian kernel is pretty straightforward, read all eight neighbors pixel values using shared memory and compute the convolution result. You can find kernels source code <a href=\"https://github.com/arrayfire/androidcl/blob/master/assets/kernels.cl\">here</a>.\r\n<h4 id=\"auxilary-code\">Auxilary Code</h4>\r\nThe JNI native function declarations can be seen in the file <a href=\"https://github.com/arrayfire/androidcl/blob/master/jni/processor.h\">processor.h</a>. I have included couple of extra Android related headers which are required to read bitmap files and print debug messages from JNI routines. The C-string pointed by macro <code>app_name</code> can be used to prune the output of the command <code>adb logcat</code> to get only messages that are associated with our JNI routines. To do that, you need to pass the value of <code>app_name</code> to adb command as an option as shown below.\r\n<pre>adb logcat -s \"JNIProcessor\"</pre>\r\nThis is quite useful when you are debugging problems that are related to accuracy of results.\r\n\r\nThe full source code for JNI native functions can be seen in the file <a href=\"https://github.com/arrayfire/androidcl/blob/master/jni/processor.cpp\">processor.cpp</a>. Following are brief descriptions of the Android/JNI functions I have used in this project.\r\n<ul>\r\n	<li><code>AndroidBitmap_getInfo</code> - provides details like width, height, stride, format.</li>\r\n	<li><code>AndroidBitmap_lockPixels</code> - gives us a pointer to the memory location of image data. Once lockPixels is called, it has to be followed by a unlockPixels at some point later in the code.</li>\r\n	<li><code>GetPrimitiveArrayCritical</code> - as the name suggets, this is some kind of performance critical call. Hence, we should take care that the code amid a GetPrimitiveArrayCritical call and the corresponding ReleasePrimitiveArrayCritical call doesn\'t stall execution for extended periods of time. As per <a href=\"http://docs.oracle.com/javase/6/docs/technotes/guides/jni/spec/functions.html\">Oracle\'s Java documentation</a>, a VM may temporarily disable garbage collection when the native code is holding a pointer to an array obtained via GetPrimitiveArrayCritical. So, just be careful when you use this function.</li>\r\n	<li><code>ReleasePrimitiveArrayCritical</code> - used to release the memory space requested by previous GetPrimitiveArrayCritical. call.</li>\r\n	<li><code>AndroidBitmap_unlockPixels</code> - used to release memory space used by a previous lockPixels call.</li>\r\n</ul>\r\nListed below are some of the other auxilary functions that i needed to make the code look clean.\r\n<ul>\r\n	<li><code>throwJavaException</code> - convenience function used to throw Java exceptions from JNI routines.</li>\r\n	<li><code>cb</code> - callback function provided when OpenCL kernels are built. When you actually look at this, you might wonder why did i do this part alone using C-interface of OpenCL. I just wanted to try it out, hence it happened so.</li>\r\n	<li><code>Java_com_example_LiveFeatureActivity_compileKernels</code> - as you might have noticed, this is a JNI routine i used to compile the OpenCL kernels only once during the app start up.</li>\r\n</ul>\r\n<h3 id=\"build-on-linux\">Build (on Linux)</h3>\r\nAndroid-NDK provides a very useful tool <code>ndk-build</code> to build native code for Android.\r\n<ol>\r\n	<li>Clone the git repo <code>git clone https://github.com/arrayfire/androidcl</code></li>\r\n	<li><code>cd androidcl</code></li>\r\n	<li>Ensure android-ndk installed and environment variable <code>ANDROID_NDK</code> is pointing to ndk installation root.</li>\r\n	<li>Ensure environment variable <code>PATH</code> has the path <code>$ANDROID_NDK</code> appended to it.</li>\r\n	<li>Run <code>ndk-build</code> from project root.</li>\r\n	<li>If you have <code>eclipse</code> installed, then import the project from eclipse and build it as usually.</li>\r\n	<li>If you do not have eclipse or don\'t want to use it, then I assume you might already know about apache-ant tool. Run <code>ant debug</code></li>\r\n</ol>\r\n<h4 id=\"android.mk\">Android.mk</h4>\r\nThere are couple of things that you need to do to use OpenCL on Android apart from standard JNI makefile instructions.\r\n<ul>\r\n	<li>Ensure that you set <code>LOCAL_ARM_MODE</code> to <code>arm</code>, which enables you to build for 32-bit ARM architecture instead of the default 16-bit.</li>\r\n	<li>Ensure that the variable <code>LOCAL_CPPFLAGS</code> has been set to point to OpenCL headers.</li>\r\n	<li>Add <code>libOpenCL.so</code> dependency to <code>LOCAL_LDLIBS</code> variable.</li>\r\n</ul>\r\nClick <a href=\"https://github.com/arrayfire/androidcl/blob/master/jni/Android.mk\">here</a> to see full content of Android.mk.\r\n\r\nNote: In case you want a static library, replace <code>include $(BUILD_SHARED_LIBRARY)</code> with <code>include $(BUILD_STATIC_LIBRARY)</code>.\r\n<h4 id=\"application.mk\">Application.mk</h4>\r\nThis file is not mandatory, but you may need it in cases where you want specify your requirements about the system libraries you want to use in your application. In this project i have set <code>APP_STL</code> to <code>gnustl_static</code> to declare that i want to use the static version of gnustl. I have also set the Android API target version as 14 by setting <code>APP_PLATFORM</code> to <code>android-14</code>.\r\nClick <a href=\"https://github.com/arrayfire/androidcl/blob/master/jni/Application.mk\">here</a> to see full content of Application.mk.\r\n<h3 id=\"app-installation\">App Installation</h3>\r\n<h4 id=\"ant-users\">ant-users</h4>\r\nFor installing the app in your mobile device do <code>ant debug install</code>. Should you choose to remove it after you are done playing with it, just do <code>ant debug uninstall</code>.\r\n<h4 id=\"eclipse-users\">eclipse-users</h4>\r\nRight click the project in workspace and click the menu item \"Run As -&gt; Android Application\".\r\n\r\nYou can see below the video of the app running live.\r\n\r\n[video width=\"1280\" height=\"720\" mp4=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/05/ocl_demo.mp4\"]Screen capture of the live app[/video]\r\n\r\n&nbsp;\r\n\r\nStay tuned for more exciting developments as we continue to add more examples of OpenCL on Andriod!','Getting Started with OpenCL on Android','','inherit','open','closed','','5574-autosave-v1','','','2014-06-02 22:22:31','2014-06-02 22:22:31','',5574,'http://sandbox.arrayfire.com/5574-autosave-v1/',0,'revision','',0),(5750,17729,'2014-06-02 22:26:22','2014-06-02 22:26:22','One of the reasons ArrayFire has become so useful is attributed to it integrating various performance oriented function from many domains with utility functions such as image loading and visualization.\r\n\r\nIn a lot of cases, developers write a ton of code with multiple iterations but do not have a way to check the quality of the results. That\'s where ArrayFire can be used very well.\r\n\r\nIn one of our recent projects that involved image processing, we did a lot of development but faced a speed bump when we had to make sure the quality is not compromised. As a part of making code faster, we do tend to take acceptable detours. Hence it becomes absolutely crucial that we test code from time to time and especially before commits. In this particular case, it was an OpenGL project without any ArrayFire or CUDA/OpenCL as a part of it. Anything that we would do with ArrayFire would be kept separate from the production code. We needed code that would compare and analyse the result from our development branch against a \"Gold\" data set generated by the code received by us.\r\n\r\nThe first option to do this was the old fashioned way by reading two images and comparing them on CPU. But given that we needed to compare images (in the 100s), this was not a viable option. It would simply be too slow.\r\n\r\nThe preferred option was to use ArrayFire but keep it separate from the production code. So we decided to go this route.\r\n\r\nThe first thing we did was to write our testing code. A simple function that would read images from the respective folders and then perform various comparisons on then. This is where ArrayFire excels. Just a few lines of code and everything is set for loading and comparing images. Some of the function we used included subtraction, min, mean, max, stats etc. We also included visualization using fig if the user chose to visualize the differences.\r\n<pre>std::string goldPath = std::string(gold)      + path;\r\nstd::string testPath = std::string(\"output/\") + path;\r\n\r\naf::array goldImage = af::loadimage(goldPath.c_str(), true) / 255.0f;\r\naf::array testImage = af::loadimage(testPath.c_str(), true) / 255.0f;\r\n\r\naf::array diffImage = af::abs(goldImage - testImage);\r\n\r\nfloat mean = af::mean<float>(diffImage);\r\n\r\nif(mean &gt; 0.001f) {\r\n    fprintf ( stderr, \"FOUND MISMATCH\\n\" ) ;\r\n    result = false;\r\n    printf(\"!!!***FAILED***!!!: %s\\n\", path);\r\n    stats(diffImage);\r\n\r\n    if(visualize) {\r\n        // colormap\r\n        af::fig(\"color\", \"default\");\r\n\r\n        // image operations\r\n        af::fig(\"sub\", 3, 1, 1); af::image(goldImage); af::fig(\"title\", \"GOLD\");\r\n        af::fig(\"sub\", 3, 1, 2); af::image(testImage); af::fig(\"title\", \"TEST\");\r\n        af::fig(\"sub\", 3, 1, 3); af::image(diffImage); af::fig(\"title\", \"DIFF\");\r\n\r\n        // Force screen refresh (optional)\r\n        af::fig(\"draw\");\r\n        getchar();\r\n    }\r\n}</pre>\r\nOnce the code was in place, we had to integrate it into the main function of the code. Again, it was required that this must not mess with the production code. So we put two lines in the main function. The first line includes the file containing the test function and the second line calls the test function. Both these lines were wrapped in a #ifdef TEST which would be defined in the makefile. That way, if TEST is not defined, the file isn\'t included and ArrayFire is not required for compilation and running of the code. For all of this, we created a makefile goal called \"test\" which would define the flag, include and link ArrayFire.','Q&A Using ArrayFire','','inherit','open','closed','','5736-autosave-v1','','','2014-06-02 22:26:22','2014-06-02 22:26:22','',5736,'http://sandbox.arrayfire.com/5736-autosave-v1/',0,'revision','',0),(5751,11,'2014-06-02 22:29:36','2014-06-02 22:29:36','One of the reasons ArrayFire has become so useful is attributed to it integrating various performance oriented function from many domains with utility functions such as image loading and visualization.\r\n\r\nIn a lot of cases, developers write a ton of code with multiple iterations but do not have a way to check the quality of the results. That\'s where ArrayFire can be used very well.\r\n\r\nIn one of our recent projects that involved image processing, we did a lot of development but faced a speed bump when we had to make sure the quality is not compromised. As a part of making code faster, we do tend to take acceptable detours. Hence it becomes absolutely crucial that we test code from time to time and especially before commits. In this particular case, it was an OpenGL project without any ArrayFire or CUDA/OpenCL as a part of it. Anything that we would do with ArrayFire would be kept separate from the production code. We needed code that would compare and analyse the result from our development branch against a \"Gold\" data set generated by the code received by us.\r\n\r\nThe first option to do this was the old fashioned way by reading two images and comparing them on CPU. But given that we needed to compare images (in the 100s), this was not a viable option. It would simply be too slow.\r\n\r\nThe preferred option was to use ArrayFire but keep it separate from the production code. So we decided to go this route.\r\n\r\nThe first thing we did was to write our testing code. A simple function that would read images from the respective folders and then perform various comparisons on then. This is where ArrayFire excels. Just a few lines of code and everything is set for loading and comparing images. Some of the function we used included subtraction, min, mean, max, stats etc. We also included visualization using fig if the user chose to visualize the differences.\r\n<pre>std::string goldPath = std::string(gold)      + path;\r\nstd::string testPath = std::string(\"output/\") + path;\r\n\r\naf::array goldImage = af::loadimage(goldPath.c_str(), true) / 255.0f;\r\naf::array testImage = af::loadimage(testPath.c_str(), true) / 255.0f;\r\n\r\naf::array diffImage = af::abs(goldImage - testImage);\r\n\r\nfloat mean = af::mean<float>(diffImage);\r\n\r\nif(mean < 0.001f) {\r\n    fprintf ( stderr, \"FOUND MISMATCH\\n\" ) ;\r\n    result = false;\r\n    printf(\"!!!***FAILED***!!!: %s\\n\", path);\r\n    stats(diffImage);\r\n\r\n    if(visualize) {\r\n        // colormap\r\n        af::fig(\"color\", \"default\");\r\n\r\n        // image operations\r\n        af::fig(\"sub\", 3, 1, 1); af::image(goldImage); af::fig(\"title\", \"GOLD\");\r\n        af::fig(\"sub\", 3, 1, 2); af::image(testImage); af::fig(\"title\", \"TEST\");\r\n        af::fig(\"sub\", 3, 1, 3); af::image(diffImage); af::fig(\"title\", \"DIFF\");\r\n\r\n        // Force screen refresh (optional)\r\n        af::fig(\"draw\");\r\n        getchar();\r\n    }\r\n}</pre>\r\nOnce the code was in place, we had to integrate it into the main function of the code. Again, it was required that this must not mess with the production code. So we put two lines in the main function. The first line includes the file containing the test function and the second line calls the test function. Both these lines were wrapped in a #ifdef TEST which would be defined in the makefile. That way, if TEST is not defined, the file isn\'t included and ArrayFire is not required for compilation and running of the code. For all of this, we created a makefile goal called \"test\" which would define the flag, include and link ArrayFire.','Q&A Using ArrayFire','','inherit','open','closed','','5736-revision-v1','','','2014-06-02 22:29:36','2014-06-02 22:29:36','',5736,'http://sandbox.arrayfire.com/5736-revision-v1/',0,'revision','',0),(5753,17795,'2014-08-24 22:37:58','2014-08-24 22:37:58','In the upcoming months we\'ll be adding a lot of new Computer Vision functionality to ArrayFire, specifically targeting the most commonly used applications in this field. New functions include feature tracking, object classification, scene segmentation, optical flow, and stereo-vision.\r\n\r\nFeature tracking consists of three basic steps:\r\n<ol>\r\n	<li>Detecting good or unique features; normally they are corners or blobs of an object.</li>\r\n	<li>Extracting a descriptor for each feature—understanding the texture of a small patch around each feature.</li>\r\n	<li>Descriptor matching—finding out the best match for each pair of descriptors (one from the object being tracked, another from a scene that potentially contains that object), if any.</li>\r\n</ol>\r\n<h3>Harris corner detector</h3>\r\nIn this article we will be using ArrayFire to dive deeper into the first step of feature tracking: detecting good features. Through a step-by-step guide we will develop a simple corner detector, known as the Harris corner detector [1].\r\n\r\nThe Harris corner detector is very simple to implement, especially when you have so many good tools and libraries out there to do the core matrix manipulation. What we specifically need for Harris are some convolutions, together with a few element-wise matrix addition and multiplication operations; all of these operations are present in most scientific tools and libraries that work with matrix manipulation. I will try to avoid going into the mathematical details in this post and go directly to the implementation.\r\n<h5>Loading an image</h5>\r\nBefore writing the code for the corner detector, we need to load an image. The image can be either color or grayscale, but it will only work on the grayscale version; if we upload a color image, we have to convert it before proceeding.\r\n<pre>// Load a color image\r\narray img_color = loadimage(\"lena.jpg\", true);\r\n// Convert the image from RGB to gray-scale\r\narray img_gray = colorspace(img_color, af_gray, af_rgb);\r\n// For visualization in ArrayFire, color images must be in the [0.0f-1.0f] interval\r\nimg_color /= 255.f;\r\n</pre>\r\n<h5>Compute first-order derivatives</h5>\r\nThe first step in the Harris corner detector is to determine first order derivatives of an image, in both horizontal and vertical directions. This can be achieved by one convolution for each direction, with the kernel (-1, 0, 1)  for horizontal derivative and its transpose for vertical derivative. ArrayFire contains a function called <a href=\"http://www.accelereyes.com/arrayfire/c/group__math__func__cpp__grad.htm\">grad</a>, which calculates gradients in both directions and will perform faster than the two convolutions. The only difference  is that <a href=\"http://www.accelereyes.com/arrayfire/c/group__math__func__cpp__grad.htm\">grad</a> divides the result by 2, thus, the response factor will change. The use of grad will improve the performance, and factor change can be easily compensated by using a smaller response.\r\n<pre>// Calculate image gradients\r\narray ix, iy;\r\ngrad(ix, iy, img_gray);\r\n</pre>\r\n<h5>Compute second-order derivatives</h5>\r\nAt this point we have both horizontal and vertical first order derivatives of our image, but Harris corner detector is processed with second-order derivatives, which can be easily computed in ArrayFire with simple element-wise multiplications of the first-order derivatives.\r\n<pre>// Compute second-order derivatives\r\narray ixx = ix * ix;\r\narray ixy = ix * iy;\r\narray iyy = iy * iy;\r\n</pre>\r\n<h5>Compute an isotropic window</h5>\r\nTo check the cornerness of each pixel of an image, it\'s not enough to check the pixel value itself. We must also check a small window around that pixel. To reduce noise sensitivity and have an isotropic response, Harris claims that a smooth circular window should be used. This can be achieved by filtering of all three second-order derivatives with a Gaussian kernel.\r\n<pre>// Compute a Gaussian kernel with standard deviation of 1.0 and length of 5 pixels\r\n// These values can be changed to use a smaller or larger window\r\narray gauss_filt = gaussiankernel(5, 5, 1.0, 1.0);\r\n\r\n// Filter second-order derivatives with Gaussian kernel computed previously\r\nixx = convolve(ixx, gauss_filt);\r\nixy = convolve(ixy, gauss_filt);\r\niyy = convolve(iyy, gauss_filt);\r\n</pre>\r\n<h5>Compute trace and determinant</h5>\r\nFrom a second-order Hessian matrix, we then compute the values of its trace and determinant. These are the values we will need later to calculate the Harris response for each pixel in the image.\r\n<pre>// Calculate trace\r\narray tr = ixx + iyy;\r\n// Calculate determinant\r\narray det = ixx * iyy - ixy * ixy;\r\n</pre>\r\n<h5>Compute Harris response</h5>\r\nNext, we calculate the Harris response for each pixel. For this calculation, Harris uses an empirically defined constant <code>k</code>. This constant is usually very small, normally ranging from <code>0.04</code> to <code>0.06</code>. In our case, we will use <code>k = 0.04</code>, but we encourage you to play with this value and see how the result is affected.\r\n<pre>// Calculate Harris response\r\narray response = det - 0.04f * (tr * tr);\r\n</pre>\r\n<h5>Selection of good corners</h5>\r\nNow we already have our Harris responses for each pixel in the image. This value is used to determine whether a pixel is a corner or not. The standard way is to perform a non-maximal suppression, meaning that each pixel can only be a corner if it is a maximum compared to its 8 adjacent pixels. At the moment we do not have a direct way to compute a non-maximal suppression with ArrayFire; we have to write our own kernel for that. Non-maximal suppression is  just one of the cool things we will be able to do with our new computer vision toolset for ArrayFire.\r\n\r\nAn alternative is to do the non-maximal suppression in a naive way. To do this, we will use ArrayFire\'s <a href=\"http://www.accelereyes.com/arrayfire/c/group__image__func__cpp__maxfilt.htm\">maxfilt</a> function, which filters the image with a mask of <code>NxM</code> pixel and returns the maximum value of the neighborhood to the pixel centered within the mask. In this case we will use a <code>3x3</code> pixel mask to return the maximum of the 8-neighborhood, including the central pixel itself.\r\n\r\nThe <a href=\"http://www.accelereyes.com/arrayfire/c/group__image__func__cpp__maxfilt.htm\">maxfilt</a> function alone will not perform a non-maximal suppression, but by combining the function with a few other steps we can get the proper responses.\r\n\r\nThe nature of a pixel can be determined by the Harris responses; a negative response means that a pixel corresponds to the segment of an edge. If the response is small but positive, it corresponds to a flat region. Only a large response corresponds to a corner. By thresholding the response array with the minimum desired Harris response, which, for our example, will be 10<sup>5</sup>, we can calculate a binary response array for which only pixels with a value greater than this threshold will be true. We then multiply it to the original response array to get a new array containing only responses greater that 10<sup>5</sup>.\r\n\r\nHere we will use a threshold of 10<sup>5</sup>. For the implementation presented in this article, we found that corners seem to be better for responses larger than 10<sup>4</sup>, but you can and should play with these values to see how it will affect the image you are working on.\r\n\r\nThe last step for this is testing whether each pixel is equal to the maximum Harris response of the neighborhood. If it is equal, then we keep it, else, the response is not a local maximum and we discard it.\r\n<pre>// Gets maximum response for each 3x3 neighborhood\r\narray max_resp = maxfilt(response, 3, 3);\r\n\r\n// Discard responses that are not greater than threshold\r\narray corners = response &gt; 1e5f;\r\ncorners = corners * response;\r\n\r\n// Discard responses that are not equal to maximum neighborhood response,\r\n// scale them to original response value\r\ncorners = (corners == max_resp) * corners;\r\n</pre>\r\nIf you still think you want a non-maximal suppression kernel for yourself, you can write it instead of using the last piece of code above. If you have never written your own kernel to work with an ArrayFire array, check out the <a href=\"http://sandbox.arrayfire.com/custom-kernels-with-arrayfire/\">Custom Kernels with ArrayFire</a> post. Writing the non-maximal suppression kernel itself will not take more than 20 or 30 lines of code.\r\n<h5>Plotting corners</h5>\r\nThis last step is done on the <abbr title=\"Central Processing Unit\">CPU</abbr> side; we only do this to show the corners that are detected. This will most likely be unnecessary unless you want to visualize, but, for the sake of clarity, we will include this part to show the result.\r\n<pre>// Gets host pointer to response data\r\nfloat* h_corners = corners.host();\r\n\r\n// Draw draw_len x draw_len crosshairs where the corners are\r\nconst int draw_len = 3;\r\nfor (int y = draw_len; y &lt; img_color.dims(0) - draw_len; y++) {\r\n    for (int x = draw_len; x &lt; img_color.dims(1) - draw_len; x++) {\r\n        // Only draws crosshair if is a corner\r\n        if (h_corners[x * corners.dims(0) + y] &gt; 1e5f) {\r\n            // Draw horizontal line of (draw_len * 2 + 1) pixels centered on the corner\r\n            // Set only the first channel to 1 (green lines)\r\n            img_color(y, seq(x-draw_len, x+draw_len), 0) = 0.f;\r\n            img_color(y, seq(x-draw_len, x+draw_len), 1) = 1.f;\r\n            img_color(y, seq(x-draw_len, x+draw_len), 2) = 0.f;\r\n\r\n            // Draw vertical line of (draw_len * 2 + 1) pixels centered on  the corner\r\n            // Set only the first channel to 1 (green lines)\r\n            img_color(seq(y-draw_len, y+draw_len), x, 0) = 0.f;\r\n            img_color(seq(y-draw_len, y+draw_len), x, 1) = 1.f;\r\n            img_color(seq(y-draw_len, y+draw_len), x, 2) = 0.f;\r\n        }\r\n    }\r\n}</pre>\r\n<h5>Visualize results</h5>\r\nFinally, the image can be visualized.\r\n<pre>// Previews color image with green crosshairs\r\nimage(img_color);\r\n</pre>\r\nBelow you can see Lena\'s picture after the Harris corner detection and plotting. The green crosshairs indicate where corners are.\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_lena.png\"><img class=\"alignnone size-full wp-image-5710\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_lena.png\" alt=\"Harris Corners - Lena\" width=\"1024\" height=\"600\" /></a>\r\n\r\nTo test for correctness of the algorithm, nothing better than a picture with well-defined corners. Below you can see the picture of a white square on a black background and the corners marked by green crosshairs.\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_square.png\"><img class=\"alignnone size-full wp-image-5711\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_square.png\" alt=\"Harris Corners - Square\" width=\"1024\" height=\"600\" /></a>\r\n\r\nAll sources to our examples can be found in our <a href=\"https://github.com/arrayfire/arrayfire_examples\">ArrayFire examples project</a> on GitHub, and the complete code for this article can be viewed via this direct <a href=\"https://github.com/arrayfire/arrayfire_examples/blob/master/image_processing/harris_demo.cpp\">link</a>.\r\n\r\nWe would like to hear from you! What you are working on the computer vision field and what features would you like to see in ArrayFire? Please share your thoughts and requests below or contact us at <a href=\"mailto:sales@arrayfire.com\">sales@arrayfire.com</a>.\r\n<h5>References</h5>\r\n[1] Harris, Chris, and Mike Stephens. \"A combined corner and edge detector.\" <em>Alvey vision conference</em>. Vol. 15. 1988.','Writing a Simple Corner Detector with ArrayFire','','inherit','open','closed','','5659-autosave-v1','','','2014-08-24 22:37:58','2014-08-24 22:37:58','',5659,'http://sandbox.arrayfire.com/5659-autosave-v1/',0,'revision','',0),(5754,17795,'2014-06-02 22:44:46','2014-06-02 22:44:46','In the upcoming months we\'ll be adding a lot of new Computer Vision functionality to ArrayFire, specifically targeting the most commonly used applications in this field. New functions include feature tracking, object classification, scene segmentation, optical flow, and stereo-vision.\r\n\r\nFeature tracking consists of three basic steps:\r\n<ol>\r\n	<li>Detecting good or unique features; normally they are corners or blobs of an object.</li>\r\n	<li>Extracting a descriptor for each feature—understanding the texture of a small patch around each feature.</li>\r\n	<li>Descriptor matching—finding out the best match for each pair of descriptors (one from the object being tracked, another from a scene that potentially contains that object), if any.</li>\r\n</ol>\r\n<h3>Harris corner detector</h3>\r\nIn this article we will be using ArrayFire to dive deeper into the first step of feature tracking: detecting good features. Through a step-by-step guide we will develop a simple corner detector, known as the Harris corner detector [1].\r\n\r\nThe Harris corner detector is very simple to implement, especially when you have so many good tools and libraries out there to do the core matrix manipulation. What we specifically need for Harris are some convolutions, together with a few element-wise matrix addition and multiplication operations; all of these operations are present in most scientific tools and libraries that work with matrix manipulation. I will try to avoid going into the mathematical details in this post and go directly to the implementation.\r\n<h5>Loading an image</h5>\r\nBefore writing the code for the corner detector, we need to load an image. The image can be either color or grayscale, but it will only work on the grayscale version; if we upload a color image, we have to convert it before proceeding.\r\n<pre>// Load a color image\r\narray img_color = loadimage(\"lena.jpg\", true);\r\n// Convert the image from RGB to gray-scale\r\narray img_gray = colorspace(img_color, af_gray, af_rgb);\r\n// For visualization in ArrayFire, color images must be in the [0.0f-1.0f] interval\r\nimg_color /= 255.f;\r\n</pre>\r\n<h5>Compute first-order derivatives</h5>\r\nThe first step in the Harris corner detector is to determine first order derivatives of an image, in both horizontal and vertical directions. This can be achieved by one convolution for each direction, with the kernel (-1, 0, 1)  for horizontal derivative and its transpose for vertical derivative. ArrayFire contains a function called <a href=\"http://www.accelereyes.com/arrayfire/c/group__math__func__cpp__grad.htm\">grad</a>, which calculates gradients in both directions and will perform faster than the two convolutions. The only difference  is that <a href=\"http://www.accelereyes.com/arrayfire/c/group__math__func__cpp__grad.htm\">grad</a> divides the result by 2, thus, the response factor will change. The use of grad will improve the performance, and factor change can be easily compensated by using a smaller response.\r\n<pre>// Calculate image gradients\r\narray ix, iy;\r\ngrad(ix, iy, img_gray);\r\n</pre>\r\n<h5>Compute second-order derivatives</h5>\r\nAt this point we have both horizontal and vertical first order derivatives of our image, but Harris corner detector is processed with second-order derivatives, which can be easily computed in ArrayFire with simple element-wise multiplications of the first-order derivatives.\r\n<pre>// Compute second-order derivatives\r\narray ixx = ix * ix;\r\narray ixy = ix * iy;\r\narray iyy = iy * iy;\r\n</pre>\r\n<h5>Compute an isotropic window</h5>\r\nTo check the cornerness of each pixel of an image, it\'s not enough to check the pixel value itself. We must also check a small window around that pixel. To reduce noise sensitivity and have an isotropic response, Harris claims that a smooth circular window should be used. This can be achieved by filtering of all three second-order derivatives with a Gaussian kernel.\r\n<pre>// Compute a Gaussian kernel with standard deviation of 1.0 and length of 5 pixels\r\n// These values can be changed to use a smaller or larger window\r\narray gauss_filt = gaussiankernel(5, 5, 1.0, 1.0);\r\n\r\n// Filter second-order derivatives with Gaussian kernel computed previously\r\nixx = convolve(ixx, gauss_filt);\r\nixy = convolve(ixy, gauss_filt);\r\niyy = convolve(iyy, gauss_filt);\r\n</pre>\r\n<h5>Compute trace and determinant</h5>\r\nFrom a second-order Hessian matrix, we then compute the values of its trace and determinant. These are the values we will need later to calculate the Harris response for each pixel in the image.\r\n<pre>// Calculate trace\r\narray tr = ixx + iyy;\r\n// Calculate determinant\r\narray det = ixx * iyy - ixy * ixy;\r\n</pre>\r\n<h5>Compute Harris response</h5>\r\nNext, we calculate the Harris response for each pixel. For this calculation, Harris uses an empirically defined constant <code>k</code>. This constant is usually very small, normally ranging from <code>0.04</code> to <code>0.06</code>. In our case, we will use <code>k = 0.04</code>, but we encourage you to play with this value and see how the result is affected.\r\n<pre>// Calculate Harris response\r\narray response = det - 0.04f * (tr * tr);\r\n</pre>\r\n<h5>Selection of good corners</h5>\r\nNow we already have our Harris responses for each pixel in the image. This value is used to determine whether a pixel is a corner or not. The standard way is to perform a non-maximal suppression, meaning that each pixel can only be a corner if it is a maximum compared to its 8 adjacent pixels. At the moment we do not have a direct way to compute a non-maximal suppression with ArrayFire; we have to write our own kernel for that. Non-maximal suppression is  just one of the cool things we will be able to do with our new computer vision toolset for ArrayFire.\r\n\r\nAn alternative is to do the non-maximal suppression in a naive way. To do this, we will use ArrayFire\'s <a href=\"http://www.accelereyes.com/arrayfire/c/group__image__func__cpp__maxfilt.htm\">maxfilt</a> function, which filters the image with a mask of <code>NxM</code> pixel and returns the maximum value of the neighborhood to the pixel centered within the mask. In this case we will use a <code>3x3</code> pixel mask to return the maximum of the 8-neighborhood, including the central pixel itself.\r\n\r\nThe <a href=\"http://www.accelereyes.com/arrayfire/c/group__image__func__cpp__maxfilt.htm\">maxfilt</a> function alone will not perform a non-maximal suppression, but by combining the function with a few other steps we can get the proper responses.\r\n\r\nThe nature of a pixel can be determined by the Harris responses; a negative response means that a pixel corresponds to the segment of an edge. If the response is small but positive, it corresponds to a flat region. Only a large response corresponds to a corner. By thresholding the response array with the minimum desired Harris response, which, for our example, will be 10<sup>5</sup>, we can calculate a binary response array for which only pixels with a value greater than this threshold will be true. We then multiply it to the original response array to get a new array containing only responses greater that 10<sup>5</sup>.\r\n\r\nHere we will use a threshold of 10<sup>5</sup>. For the implementation presented in this article, we found that corners seem to be better for responses larger than 10<sup>4</sup>, but you can and should play with these values to see how it will affect the image you are working on.\r\n\r\nThe last step for this is testing whether each pixel is equal to the maximum Harris response of the neighborhood. If it is equal, then we keep it, else, the response is not a local maximum and we discard it.\r\n<pre>// Gets maximum response for each 3x3 neighborhood\r\narray max_resp = maxfilt(response, 3, 3);\r\n\r\n// Discard responses that are not greater than threshold\r\narray corners = response > 1e5f;\r\ncorners = corners * response;\r\n\r\n// Discard responses that are not equal to maximum neighborhood response,\r\n// scale them to original response value\r\ncorners = (corners == max_resp) * corners;\r\n</pre>\r\nIf you still think you want a non-maximal suppression kernel for yourself, you can write it instead of using the last piece of code above. If you have never written your own kernel to work with an ArrayFire array, check out the <a href=\"http://sandbox.arrayfire.com/custom-kernels-with-arrayfire/\">Custom Kernels with ArrayFire</a> post. Writing the non-maximal suppression kernel itself will not take more than 20 or 30 lines of code.\r\n<h5>Plotting corners</h5>\r\nThis last step is done on the <abbr title=\"Central Processing Unit\">CPU</abbr> side; we only do this to show the corners that are detected. This will most likely be unnecessary unless you want to visualize, but, for the sake of clarity, we will include this part to show the result.\r\n<pre>// Gets host pointer to response data\r\nfloat* h_corners = corners.host();\r\n\r\n// Draw draw_len x draw_len crosshairs where the corners are\r\nconst int draw_len = 3;\r\nfor (int y = draw_len; y < img_color.dims(0) - draw_len; y++) {\r\n    for (int x = draw_len; x < img_color.dims(1) - draw_len; x++) {\r\n        // Only draws crosshair if is a corner\r\n        if (h_corners[x * corners.dims(0) + y] > 1e5f) {\r\n            // Draw horizontal line of (draw_len * 2 + 1) pixels centered on the corner\r\n            // Set only the first channel to 1 (green lines)\r\n            img_color(y, seq(x-draw_len, x+draw_len), 0) = 0.f;\r\n            img_color(y, seq(x-draw_len, x+draw_len), 1) = 1.f;\r\n            img_color(y, seq(x-draw_len, x+draw_len), 2) = 0.f;\r\n\r\n            // Draw vertical line of (draw_len * 2 + 1) pixels centered on  the corner\r\n            // Set only the first channel to 1 (green lines)\r\n            img_color(seq(y-draw_len, y+draw_len), x, 0) = 0.f;\r\n            img_color(seq(y-draw_len, y+draw_len), x, 1) = 1.f;\r\n            img_color(seq(y-draw_len, y+draw_len), x, 2) = 0.f;\r\n        }\r\n    }\r\n}</pre>\r\n<h5>Visualize results</h5>\r\nFinally, the image can be visualized.\r\n<pre>// Previews color image with green crosshairs\r\nimage(img_color);\r\n</pre>\r\nBelow you can see Lena\'s picture after the Harris corner detection and plotting. The green crosshairs indicate where corners are.\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_lena.png\"><img class=\"alignnone size-full wp-image-5710\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_lena.png\" alt=\"Harris Corners - Lena\" width=\"1024\" height=\"600\" /></a>\r\n\r\nTo test for correctness of the algorithm, nothing better than a picture with well-defined corners. Below you can see the picture of a white square on a black background and the corners marked by green crosshairs.\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_square.png\"><img class=\"alignnone size-full wp-image-5711\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/12/harris_square.png\" alt=\"Harris Corners - Square\" width=\"1024\" height=\"600\" /></a>\r\n\r\nAll sources to our examples can be found in our <a href=\"https://github.com/arrayfire/arrayfire_examples\">ArrayFire examples project</a> on GitHub, and the complete code for this article can be viewed via this direct <a href=\"https://github.com/arrayfire/arrayfire_examples/blob/master/image_processing/harris_demo.cpp\">link</a>.\r\n\r\nWe would like to hear from you! What you are working on the computer vision field and what features would you like to see in ArrayFire? Please share your thoughts and requests below or contact us at <a href=\"mailto:sales@arrayfire.com\">sales@arrayfire.com</a>.\r\n<h5>References</h5>\r\n[1] Harris, Chris, and Mike Stephens. \"A combined corner and edge detector.\" <em>Alvey vision conference</em>. Vol. 15. 1988.','Writing a Simple Corner Detector with ArrayFire','','inherit','open','closed','','5659-revision-v1','','','2014-06-02 22:44:46','2014-06-02 22:44:46','',5659,'http://sandbox.arrayfire.com/5659-revision-v1/',0,'revision','',0),(5756,17794,'2014-06-03 18:07:24','2014-06-03 18:07:24','One of the reasons for ArrayFire\'s usefulness is the various performance oriented function from many domains. What many people don\'t realize is that ArrayFire also includes many utilities for image loading and visualization.\n\nIn many cases, setting up a test harness is a ton of work. This is where ArrayFire can come in handy.\n\nRecently we worked on a project for one of our customers that involved image processing. As a part of development we wanted to make sure the quality is not compromised. They did not have a sufficient test framework in place. One option was to do this was the old fashioned way by reading two images and comparing them on CPU. Given that we needed to compare hundreds of images and we wanted to have a fast dev-loop, this was not a viable option. We decided to use ArrayFire to verify the results.\n\nThis particular project was an OpenGL application and they did not have a dependency on ArrayFire or CUDA/OpenCL. Because ArrayFire was only used in testing we wanted to isolate it from the rest of the production code.\n\nWe started to write the tests. A simple function that would read images from the respective folders and then perform various comparisons on them. This is where ArrayFire excels. In just a few lines of code and everything is set for loading and comparing images. Some of the function we used included subtraction, min, mean, max, stats etc. ArrayFire has an excellent visualization functionality. It allows us to visualize the differences between the current and the gold versions.\n<pre>std::string goldPath = std::string(gold)      + path;\nstd::string testPath = std::string(\"output/\") + path;\n\naf::array goldImage = af::loadimage(goldPath.c_str(), true) / 255.0f;\naf::array testImage = af::loadimage(testPath.c_str(), true) / 255.0f;\n\naf::array diffImage = af::abs(goldImage - testImage);\n\nfloat mean = af::mean(diffImage);\n\nif(mean &lt; 0.001f) {\n    fprintf ( stderr, \"FOUND MISMATCH\\n\" ) ;\n    result = false;\n    printf(\"!!!***FAILED***!!!: %s\\n\", path);\n    stats(diffImage);\n\n    if(visualize) {\n        // colormap\n        af::fig(\"color\", \"default\");\n\n        // image operations\n        af::fig(\"sub\", 3, 1, 1); af::image(goldImage); af::fig(\"title\", \"GOLD\");\n        af::fig(\"sub\", 3, 1, 2); af::image(testImage); af::fig(\"title\", \"TEST\");\n        af::fig(\"sub\", 3, 1, 3); af::image(diffImage); af::fig(\"title\", \"DIFF\");\n\n        // Force screen refresh (optional)\n        af::fig(\"draw\");\n        getchar();\n    }\n}</pre>\nAs you can see, the ArrayFire syntax is simple and easy to use. We didn\'t have to use a library to load the image, a library to verify the results, and a library to visualize the output. This can all be done using ArrayFire.Once the test was in place, all we had to do was include it in the make file and run the tests.\n\nArrayFire is a fantastic library for high performance applications but it can also be used for everyday tasks like testing. We would love you hear how you use ArrayFire in your environment.','Q&A Using ArrayFire','','inherit','open','closed','','5736-autosave-v1','','','2014-06-03 18:07:24','2014-06-03 18:07:24','',5736,'http://sandbox.arrayfire.com/5736-autosave-v1/',0,'revision','',0),(5757,17794,'2014-06-03 18:08:22','2014-06-03 18:08:22','One of the reasons for ArrayFire\'s usefulness is the various performance oriented function from many domains. What many people don\'t realize is that ArrayFire also includes many utilities for image loading and visualization.\r\n\r\nIn many cases, setting up a test harness is a ton of work. This is where ArrayFire can come in handy.\r\n\r\nRecently we worked on a project for one of our customers that involved image processing. As a part of development we wanted to make sure the quality is not compromised. They did not have a sufficient test framework in place. One option was to do this was the old fashioned way by reading two images and comparing them on CPU. Given that we needed to compare hundreds of images and we wanted to have a fast dev-loop, this was not a viable option. We decided to use ArrayFire to verify the results.\r\n\r\nThis particular project was an OpenGL application and they did not have a dependency on ArrayFire or CUDA/OpenCL. Because ArrayFire was only used in testing we wanted to isolate it from the rest of the production code.\r\n\r\nWe started to write the tests. A simple function that would read images from the respective folders and then perform various comparisons on them. This is where ArrayFire excels. In just a few lines of code and everything is set for loading and comparing images. Some of the function we used included subtraction, min, mean, max, stats etc. ArrayFire has an excellent visualization functionality. It allows us to visualize the differences between the current and the gold versions.\r\n<pre>std::string goldPath = std::string(gold)      + path;\r\nstd::string testPath = std::string(\"output/\") + path;\r\n\r\naf::array goldImage = af::loadimage(goldPath.c_str(), true) / 255.0f;\r\naf::array testImage = af::loadimage(testPath.c_str(), true) / 255.0f;\r\n\r\naf::array diffImage = af::abs(goldImage - testImage);\r\n\r\nfloat mean = af::mean(diffImage);\r\n\r\nif(mean &lt; 0.001f) {\r\n    fprintf ( stderr, \"FOUND MISMATCH\\n\" ) ;\r\n    result = false;\r\n    printf(\"!!!***FAILED***!!!: %s\\n\", path);\r\n    stats(diffImage);\r\n\r\n    if(visualize) {\r\n        // colormap\r\n        af::fig(\"color\", \"default\");\r\n\r\n        // image operations\r\n        af::fig(\"sub\", 3, 1, 1); af::image(goldImage); af::fig(\"title\", \"GOLD\");\r\n        af::fig(\"sub\", 3, 1, 2); af::image(testImage); af::fig(\"title\", \"TEST\");\r\n        af::fig(\"sub\", 3, 1, 3); af::image(diffImage); af::fig(\"title\", \"DIFF\");\r\n\r\n        // Force screen refresh (optional)\r\n        af::fig(\"draw\");\r\n        getchar();\r\n    }\r\n}</pre>\r\nAs you can see, the ArrayFire syntax is simple and easy to use. We didn\'t have to use a library to load the image, a library to verify the results, and a library to visualize the output. This can all be done using ArrayFire.Once the test was in place, all we had to do was include it in the make file and run the tests.\r\n\r\nArrayFire is a fantastic library for high performance applications but it can also be used for everyday tasks like testing. We would love you hear how you use ArrayFire in your projects.','Q&A Using ArrayFire','','inherit','open','closed','','5736-revision-v1','','','2014-06-03 18:08:22','2014-06-03 18:08:22','',5736,'http://sandbox.arrayfire.com/5736-revision-v1/',0,'revision','',0),(5758,11,'2014-06-03 18:10:46','2014-06-03 18:10:46','One of the reasons for ArrayFire\'s usefulness is the various performance oriented function from many domains. What many people don\'t realize is that ArrayFire also includes many utilities for image loading and visualization.\r\n\r\nIn many cases, setting up a test harness is a ton of work. This is where ArrayFire can come in handy.\r\n\r\nRecently we worked on a project for one of our customers that involved image processing. As a part of development we wanted to make sure the quality is not compromised. They did not have a sufficient test framework in place. One option was to do this was the old fashioned way by reading two images and comparing them on CPU. Given that we needed to compare hundreds of images and we wanted to have a fast dev-loop, this was not a viable option. We decided to use ArrayFire to verify the results.\r\n\r\nThis particular project was an OpenGL application and they did not have a dependency on ArrayFire or CUDA/OpenCL. Because ArrayFire was only used in testing we wanted to isolate it from the rest of the production code.\r\n\r\nWe started to write the tests. A simple function that would read images from the respective folders and then perform various comparisons on them. This is where ArrayFire excels. In just a few lines of code and everything is set for loading and comparing images. Some of the function we used included subtraction, min, mean, max, stats etc. ArrayFire has an excellent visualization functionality. It allows us to visualize the differences between the current and the gold versions.\r\n<pre>std::string goldPath = std::string(gold)      + path;\r\nstd::string testPath = std::string(\"output/\") + path;\r\n\r\naf::array goldImage = af::loadimage(goldPath.c_str(), true) / 255.0f;\r\naf::array testImage = af::loadimage(testPath.c_str(), true) / 255.0f;\r\n\r\naf::array diffImage = af::abs(goldImage - testImage);\r\n\r\nfloat mean = af::mean<float>(diffImage);\r\n\r\nif(mean < 0.001f) {\r\n    fprintf ( stderr, \"FOUND MISMATCH\\n\" ) ;\r\n    result = false;\r\n    printf(\"!!!***FAILED***!!!: %s\\n\", path);\r\n    stats(diffImage);\r\n\r\n    if(visualize) {\r\n        // colormap\r\n        af::fig(\"color\", \"default\");\r\n\r\n        // image operations\r\n        af::fig(\"sub\", 3, 1, 1); af::image(goldImage); af::fig(\"title\", \"GOLD\");\r\n        af::fig(\"sub\", 3, 1, 2); af::image(testImage); af::fig(\"title\", \"TEST\");\r\n        af::fig(\"sub\", 3, 1, 3); af::image(diffImage); af::fig(\"title\", \"DIFF\");\r\n\r\n        // Force screen refresh (optional)\r\n        af::fig(\"draw\");\r\n        getchar();\r\n    }\r\n}</pre>\r\nAs you can see, the ArrayFire syntax is simple and easy to use. We didn\'t have to use a library to load the image, a library to verify the results, and a library to visualize the output. This can all be done using ArrayFire.Once the test was in place, all we had to do was include it in the make file and run the tests.\r\n\r\nArrayFire is a fantastic library for high performance applications but it can also be used for everyday tasks like testing. We would love you hear how you use ArrayFire in your projects.','Q&A Using ArrayFire','','inherit','open','closed','','5736-revision-v1','','','2014-06-03 18:10:46','2014-06-03 18:10:46','',5736,'http://sandbox.arrayfire.com/5736-revision-v1/',0,'revision','',0),(5759,11,'2014-06-03 18:34:03','2014-06-03 18:34:03','One of the reasons for ArrayFire\'s usefulness is the various performance oriented function from many domains. What many people don\'t realize is that ArrayFire also includes many utilities for image loading and visualization.\r\n\r\nIn many cases, setting up a test harness is a ton of work. This is where ArrayFire can come in handy.\r\n\r\nRecently we worked on a project for one of our customers that involved image processing. As a part of development we wanted to make sure the quality is not compromised. They did not have a sufficient test framework in place. One option was to do this was the old fashioned way by reading two images and comparing them on CPU. Given that we needed to compare hundreds of images and we wanted to have a fast dev-loop, this was not a viable option. We decided to use ArrayFire to verify the results.\r\n\r\nThis particular project was an OpenGL application and they did not have a dependency on ArrayFire or CUDA/OpenCL. Because ArrayFire was only used in testing we wanted to isolate it from the rest of the production code.\r\n\r\nWe started to write the tests. A simple function that would read images from the respective folders and then perform various comparisons on them. This is where ArrayFire excels. In just a few lines of code and everything is set for loading and comparing images. Some of the function we used included subtraction, min, mean, max, stats etc. ArrayFire has an excellent visualization functionality. It allows us to visualize the differences between the current and the gold versions.\r\n<pre>std::string goldPath = std::string(gold)      + path;\r\nstd::string testPath = std::string(\"output/\") + path;\r\n\r\naf::array goldImage = af::loadimage(goldPath.c_str(), true) / 255.0f;\r\naf::array testImage = af::loadimage(testPath.c_str(), true) / 255.0f;\r\n\r\naf::array diffImage = af::abs(goldImage - testImage);\r\n\r\nfloat mean = af::mean<float>(diffImage);\r\n\r\nif(mean < 0.001f) {\r\n    fprintf ( stderr, \"FOUND MISMATCH\\n\" ) ;\r\n    result = false;\r\n    printf(\"!!!***FAILED***!!!: %s\\n\", path);\r\n    stats(diffImage);\r\n\r\n    if(visualize) {\r\n        // colormap\r\n        af::fig(\"color\", \"default\");\r\n\r\n        // image operations\r\n        af::fig(\"sub\", 3, 1, 1); af::image(goldImage); af::fig(\"title\", \"GOLD\");\r\n        af::fig(\"sub\", 3, 1, 2); af::image(testImage); af::fig(\"title\", \"TEST\");\r\n        af::fig(\"sub\", 3, 1, 3); af::image(diffImage); af::fig(\"title\", \"DIFF\");\r\n\r\n        // Force screen refresh (optional)\r\n        af::fig(\"draw\");\r\n        getchar();\r\n    }\r\n}</pre>\r\nAs you can see, the ArrayFire syntax is simple and easy to use. We didn\'t have to use a library to load the image, a library to verify the results, and a library to visualize the output. This can all be done using ArrayFire.Once the test was in place, all we had to do was include it in the make file and run the tests.\r\n\r\nArrayFire is a fantastic library for high performance applications but it can also be used for everyday tasks like testing. We would love you hear how you use ArrayFire in your projects.','Q/A Using ArrayFire','','inherit','open','closed','','5736-revision-v1','','','2014-06-03 18:34:03','2014-06-03 18:34:03','',5736,'http://sandbox.arrayfire.com/5736-revision-v1/',0,'revision','',0),(5760,17794,'2014-06-03 18:59:38','2014-06-03 18:59:38','<a href=\"http://blog.accelereyes.com/blog/wp-content/uploads/2013/12/arrayfire_logo_whitebkgnd.png\"><img class=\"aligncenter size-medium wp-image-4605\" src=\"http://blog.accelereyes.com/blog/wp-content/uploads/2013/12/arrayfire_logo_whitebkgnd-300x42.png\" alt=\"arrayfire_logo_whitebkgnd\" width=\"300\" height=\"42\" /></a> We are thrilled to announce the official release ArrayFire v2.0, our biggest and best product ever!\r\n<p style=\"text-align: justify;\">ArrayFire v2.0 adds full commercial support for OpenCL devices including all AMD APUs and AMD FireProTM graphics, CUDA GPUs from NVIDIA, and other OpenCL devices from Imagination, Freescale, ARM, Intel, and Apple.</p>\r\n\r\n<div>\r\n<p style=\"text-align: justify;\">ArrayFire is a CUDA and OpenCL library designed for maximum speed without the hassle of writing time-consuming CUDA and OpenCL device code.  With ArrayFire’s library functions, developers can maximize productivity and performance. Each of ArrayFire’s functions has been hand-tuned by CUDA and OpenCL experts.</p>\r\n<strong>Announcing ArrayFire for OpenCL</strong>\r\n<div>\r\n<ul>\r\n	<li>Support for all of ArrayFire\'s function library (with a few exceptions)</li>\r\n	<li>Same API as ArrayFire for CUDA enabling seamless interoperability</li>\r\n	<li>Just-In-Time (JIT) compilation of kernels for top performance</li>\r\n	<li>Specific tuning for Intel Xeon Phi coprocessors</li>\r\n	<li>Accelerated algorithms for image processing, signal processing, visualization, and more</li>\r\n</ul>\r\n<strong>Updates to ArrayFire for CUDA</strong>\r\n<div>\r\n<ul>\r\n	<li>New signal and image processing functions</li>\r\n	<li>Faster transpose and matrix multiplication</li>\r\n	<li>Enhanced debugging support for GDB and Visual Studio</li>\r\n	<li>Better examples and documentation</li>\r\n</ul>\r\n<p style=\"text-align: justify;\">Maybe the upgrade you wanted isn\'t mentioned here. Don\'t despair! Check out our <a href=\"http://www.accelereyes.com/arrayfire/c/releasenotes.htm\">release notes</a>, as well as our new and improved <a href=\"http://www.accelereyes.com/arrayfire/c/\">documentation</a>, for a complete list of the many ArrayFire v2.0 enhancements available.</p>\r\n<p style=\"text-align: justify;\">To learn more about which licensing option would be the best for your needs, visit our ArrayFire <a href=\"http://www.accelereyes.com/products/arrayfire_licensing\">licensing page</a>.</p>\r\n<p style=\"text-align: justify;\"><span style=\"line-height: 1.5em;\">Just getting started with GPU computing? Need an extra hand on a project? Tap into our deep parallel computing expertise and vast code base by setting up a free <a href=\"http://www.meetme.so/accelereyes\">technical consultation</a> today.</span><span style=\"line-height: 1.5em;\"> </span></p>\r\n\r\n</div>\r\n<div>\r\n<p style=\"text-align: justify;\">We\'re always looking to make ArrayFire even better—let us know your thoughts through this short <a href=\"https://www.surveymonkey.com/s/arrayfire-new-feature\">survey</a>. We promise it\'ll be worth your while!</p>\r\nStay tuned for more exciting news from the ArrayFire gang coming soon...\r\n\r\n</div>\r\n</div>\r\n</div>','ArrayFire v2.0 Official Release','','inherit','open','closed','','4604-autosave-v1','','','2014-06-03 18:59:38','2014-06-03 18:59:38','',4604,'http://sandbox.arrayfire.com/4604-autosave-v1/',0,'revision','',0),(5762,17728,'2014-06-09 17:05:12','2014-06-09 17:05:12','Programmers and Data Scientists want to take advantage of fast and parallel computational devices. Writing vectorized code is becoming a necessity to get the best performance out of the current generation parallel hardware and scientific computing software. However, writing vectorized code may not be intuitive immediately. There are many ways you can vectorize a given code segment. Each method has its own benefits and drawbacks. Hence, writing vectorized code involves analyzing the pros and cons of the available methods and choosing the right one to solve your problem.\r\n\r\nIn this post, I present various ways to vectorize your code using ArrayFire. ArrayFire is chosen because of my familiarity with the software. The same methods can be easily used in numpy, octave, julia or other scientific computing software.\r\n<h3>The problem</h3>\r\nThe problem we will be looking at is the calculation of distances from every point in a set <code>A</code> to every point in set <code>B</code>. For example, if <code> A </code> has <code> 200 </code> points and <code> B </code> has <code> 300 </code> points, the distance matrix will be of size <code>200 x 300</code>. Each point has coordinates in 3 dimensional space. We can generate the necessary data in the following manner.\r\n<pre>A = randu(3, 200);\r\nB = randu(3, 300);\r\n</pre>\r\n<h3>Naive implementation</h3>\r\nThe naive method would be to have three loops. The outer most loop iterating through points in A. The second loop iterating through points in B. The inner most loop iterating through the three dimensions. You can find difference in coordinates between the two points and find the distance between the two points.\r\n\r\nThis can be implemented in the following manner. <em> The code is shown for reference. This is extremely slow on GPUs </em>\r\n<pre>// CODE SHOWN FOR REFERENCE. DO NOT USE. IT IS EXTREMELY SLOW.\r\nstatic array dist_naive(array a, array b)\r\n{\r\n    array dist_mat = constant(0, a.dims(1), b.dims(1));\r\n\r\n    // Iterate through columns a\r\n    for (int ii = 0; ii < a.dims(1); ii++) {\r\n\r\n        // Iterate through columns of b\r\n        for (int jj = 0; jj < b.dims(1); jj++) {\r\n\r\n            // Get the sum of absolute differences\r\n            for (int kk = 0; kk < a.dims(0); kk++) {\r\n                dist_mat(ii, jj) += abs(a(kk, ii) - b(kk, jj));\r\n            }\r\n        }\r\n    }\r\n\r\n    return dist_mat;\r\n}\r\n</pre>\r\n<h3>Vectorizing along one dimension</h3>\r\nKeeping the outer two loops the same, you can improve the performance by treating the set of three coordinates as a single vector. You can perform the difference between these vectors in parallel. A reduction operation after getting the absolute differences will give us the distance without the need of a third loop.\r\n<pre>static array dist_vec(array a, array b)\r\n{\r\n    array dist_mat = constant(0, a.dims(1), b.dims(1));\r\n\r\n    // Iterate through columns a\r\n    for (int ii = 0; ii < a.dims(1); ii++) {\r\n        array avec = a(span, ii);\r\n\r\n        // Iterate through columns of b\r\n        for (int jj = 0; jj < b.dims(1); jj++) {\r\n            array bvec = b(span, jj);\r\n\r\n            // get SAD using sum on the vector\r\n            dist_mat(ii, jj) = sum(abs(avec - bvec));\r\n        }\r\n    }\r\n\r\n    return dist_mat;\r\n}\r\n</pre>\r\n<h3>Using GFOR</h3>\r\n<a href=\"http://sandbox.arrayfire.com/docs/page_gfor.htm\">GFOR</a> is a parallel version of the for loop in ArrayFire. Since GFOR\'s cannot be nested, we can replace one of the for loops using GFOR. This can be done in the following manners.\r\n<pre>static array dist_gfor1(array a, array b)\r\n{\r\n    array dist_mat = constant(0, a.dims(1), b.dims(1));\r\n\r\n    // GFOR along columns of a\r\n    gfor (array ii, a.dims(1)) {\r\n        array avec = a(span, ii);\r\n\r\n        // Itere through columns of b\r\n        for (int jj = 0; jj < b.dims(1); jj++) {\r\n            array bvec = b(span, jj);\r\n\r\n            // get SAD using sum on the vector\r\n            dist_mat(ii, jj) = sum(abs(avec - bvec));\r\n        }\r\n    }\r\n\r\n    return dist_mat;\r\n}\r\n\r\nstatic array dist_gfor2(array a, array b)\r\n{\r\n    array dist_mat = constant(0, a.dims(1), b.dims(1));\r\n\r\n    // GFOR along columns of b\r\n    gfor (array jj, b.dims(1)) {\r\n        array bvec = b(span, jj);\r\n\r\n        // Iterate through columns of A\r\n        for (int ii = 0; ii < a.dims(1); ii++) {\r\n            array avec = a(span, ii);\r\n\r\n            // get SAD using sum on the vector\r\n            dist_mat(ii, jj) = sum(abs(avec - bvec));\r\n        }\r\n    }\r\n\r\n    return dist_mat;\r\n}\r\n</pre>\r\n<h3>Vectorizing along two dimensions</h3>\r\nWe can get rid of another FOR loop to have 2-D vectorized code. You can get a single point from set <code>A </code>and replicate it to create a matrix that is the same size as <code>B</code>. You can now find distance of a <code><em>single</em></code> point in <code>A </code>from <code><em>all </em></code>points in <code>B</code>. The code can be seen below.\r\n<pre>static array dist_tile1(array a, array b)\r\n{\r\n    // int feat_len = a.dims(0); // Same as b.dims(0);\r\n    int alen = a.dims(1);\r\n    int blen = b.dims(1);\r\n\r\n    array dist_mat = constant(0, alen, blen);\r\n\r\n    // Iterate through columns of b\r\n    for (int jj = 0; jj < blen; jj++) {\r\n\r\n        // Get the column vector of b\r\n        // shape of bvec is (feat_len, 1)\r\n        array bvec = b(span, jj);\r\n\r\n        // Tile avec to be same size as a\r\n        // shape of bvec_tiled is (feat_len, alen)\r\n        array bvec_tiled = tile(bvec, 1, alen);\r\n\r\n        // Get the sum of absolute differences\r\n        array sad = sum(abs(bvec_tiled - a));\r\n\r\n        // sad is row vector, dist_mat needs column vector\r\n        // transpose sad and fill in dist_mat\r\n        dist_mat(span, jj) = sad.T();\r\n    }\r\n\r\n    return dist_mat;\r\n}\r\n</pre>\r\n<h3>Vectorizing along three dimensions</h3>\r\nThe previous method can be further extended. This would involve getting the differences between every point in <code>A<em> </em></code> and every point in <code>B </code> in parallel. This can be achieved by modifying and tiling <code>A</code>, <code>B </code>to get matrices of size <code>[3, Alen, Blen]</code>.\r\n\r\nFor <code>A, </code>we need to tile it for each point present in <code>B</code>.<code> </code>This generates a 3D array of the desired dimensions. For <code>B, </code>we need to first modify it such that each point in <code>B</code> is represented in the 3rd dimension rather than the second. This is followed up by a tiling operation in the second dimension to generate a 3D array of the desired dimensions.\r\n\r\nA simple illustration of what tiling does to the data can be seen below.\r\n<pre>Original\r\nA [2 4] =\r\n       10.0000    11.0000    12.0000    13.0000\r\n       14.0000    15.0000    16.0000    17.0000\r\n\r\nB [2 3] =\r\n       20.0000    21.0000    22.0000\r\n       23.0000    24.0000    25.0000\r\n\r\nModified\r\nA_mod [2 4] =\r\n       10.0000    11.0000    12.0000    13.0000\r\n       14.0000    15.0000    16.0000    17.0000\r\n\r\nB_mod [2 1 3] =\r\n       20.0000\r\n       23.0000\r\n\r\n       21.0000\r\n       24.0000\r\n\r\n       22.0000\r\n       25.0000\r\n\r\nTiled\r\nA_tiled [2 4 3] =\r\n       10.0000    11.0000    12.0000    13.0000\r\n       14.0000    15.0000    16.0000    17.0000\r\n\r\n       10.0000    11.0000    12.0000    13.0000\r\n       14.0000    15.0000    16.0000    17.0000\r\n\r\n       10.0000    11.0000    12.0000    13.0000\r\n       14.0000    15.0000    16.0000    17.0000\r\n\r\nB_tiled [2 4 3] =\r\n       20.0000    20.0000    20.0000    20.0000\r\n       23.0000    23.0000    23.0000    23.0000\r\n\r\n       21.0000    21.0000    21.0000    21.0000\r\n       24.0000    24.0000    24.0000    24.0000\r\n\r\n       22.0000    22.0000    22.0000    22.0000\r\n       25.0000    25.0000    25.0000    25.0000\r\n</pre>\r\nOnce we have the tiled versions of the matrices, a single reduction generates the desired results in a single step. The code for this optimization can be seen below.\r\n<pre>static array dist_tile2(array a, array b)\r\n{\r\n    int feat_len = a.dims(0);\r\n    int alen = a.dims(1);\r\n    int blen = b.dims(1);\r\n\r\n    // Shape of a is (feat_len, alen, 1)\r\n    array a_mod = a;\r\n    // Reshape b from (feat_len, blen) to (feat_len, 1, blen)\r\n    array b_mod = moddims(b, feat_len, 1, blen);\r\n\r\n    // Tile both matrices to be (feat_len, alen, blen)\r\n    array a_tiled = tile(a_mod, 1, 1, blen);\r\n    array b_tiled = tile(b_mod, 1, alen, 1);\r\n\r\n    // Do The sum operation along first dimension\r\n    // Output is of shape (1, alen, blen)\r\n    array dist_mod = sum(abs(a_tiled - b_tiled));\r\n\r\n    // Reshape dist_mat from (1, alen, blen) to (alen, blen)\r\n    array dist_mat = moddims(dist_mod, alen, blen);\r\n    return dist_mat;\r\n}\r\n</pre>\r\n<h3>Results</h3>\r\nThe following results have been generated on a NVIDIA Quadro K5000.\r\n<pre>Time for dist_vec  : 2177.73ms\r\nTime for dist_gfor1: 10.80ms\r\nTime for dist_gfor2: 7.35ms\r\nTime for dist_tile1: 7.23ms\r\nTime for dist_tile2: 0.25ms\r\n</pre>\r\n<ul>\r\n	<li>As you can see the final code is about <em><code>8,700 </code><code>times</code><code> faster</code></em> than the 1D vectorized code. It is also <em><code>29 times faster</code></em> than the next fastest methods.</li>\r\n	<li><code>gfor2</code> (GFOR over B) is faster than <code>gfor1</code> (GFOR over A) because <em><code>B</code></em> has more points than <em><code>A. </code></em></li>\r\n	<li><code>tile1</code> and <code>gfor2 </code>have similar performance because they employ similar mechanisms internally.</li>\r\n</ul>\r\n<h3>Considerations</h3>\r\n<ul>\r\n	<li><code>tile2 </code>is the fastest method, but it also uses up the most memory as scratch space. It requires two temporary matrices of sizes <code>[feat_len, Alen, Blen]. </code>In this particular case, <code>feat_len</code> was 3, <code>Alen</code> was 200 and <code>Blen</code> was 300. However, it is easy for the scratch space requirements to grow to a few gigabytes when the number for points is much higher (as is the case with most machine learning algorithms).</li>\r\n	<li>Though <code>gfor2 </code>and <code>tile1 </code>give the same performance, <code>tile1 </code>should be preferred. This is because <code>GFOR </code>can not be nested. However using the <code>tile1 </code>method enables us to use GFOR at a higher level in the program.</li>\r\n	<li>Of the functions presented here, <code>tile1</code> is perhaps the best compromise when constrained by memory.</li>\r\n	<li>Hybrid algorithms, which combine one or two of the methods shown here, can provide better performance than <code>tile1. </code>We will talk about such algorithms at a later date.</li>\r\n</ul>\r\nThe relevant code for this post can be found on <a href=\"http://github.com/arrayfire\">our github</a> page over <a href=\"https://github.com/arrayfire/arrayfire_examples/blob/master/getting_started/vectorize.cpp\">here</a>.','How to write vectorized code','','publish','open','open','','how-to-write-vectorized-code','','','2014-06-09 18:05:20','2014-06-09 18:05:20','',0,'http://sandbox.arrayfire.com/?p=5762',0,'post','',0),(5764,17728,'2014-06-06 19:16:41','2014-06-06 19:16:41','A lot of scientists and programmers want to take advantage of fast and parallel computational devices. Writing vectorized code is becoming a necessity to get the best performance out of the current generation parallel hardware and scientific computing software. However writing vectorized code may not be intuitive immediately. There are many ways you can vectorize a given code segment. Each method has its own benefits and drawbacks. Hence writing vectorized code involves analyzing the pros and cons of the available methods and choosing the right one to solve your problem.\r\n\r\nIn this post we present various ways to vectorize your code using ArrayFire. ArrayFire is chosen because of my familiarity with the software. The same methods can be easily used in numpy, octave, julia or other scientific computing software.\r\n<h3>The problem</h3>\r\nIn this post we will be looking to speed up the calculation of distances from every point in a set <strong>A</strong> to every point in set <strong>B</strong>. i.e. if <strong> A </strong> has <strong> 200 </strong> points and <strong> B </strong> has <strong> 300 </strong> points, the distance matrix will be of size <strong>200 x 300</strong>. Each point has co-ordinates in 3 dimensional space. We can generate the necessary data in the following manner.\r\n\r\nCODE HERE\r\n<h3>Naive implementation</h3>\r\nThe naive method would be to have three loops. The outer most loop iterating through points in A. The second loop iterating through points in B. The inner most loop iterating through the three dimensions. You can find difference in co-ordinates between the two points and find the distance between the two points.\r\n\r\nThis can be implemented in the following manner.\r\n\r\nCODE HERE\r\n<h3>Vectorizing along one dimension</h3>\r\nKeeping the outer two loops the same, you can improve the performance by treating the set of three co-ordinates as a single vector. You can perform the difference between these vectors in parallel. A reduction operation after getting the absolute differences will give us the distance without having to use the third loop.\r\n\r\n<strong><em>addition + loop = sum</em></strong>\r\n\r\nCODE HERE\r\n<h3>Using GFOR</h3>\r\nGFOR is a parallel version of the for loop in ArrayFire. Since GFOR\'s can not be nested, we can replace one of the for loops using GFOR. This can be done in the following manners.\r\n\r\n<b><i>parallel for loops</i></b>\r\n\r\nCODE HERE 1\r\n\r\nCODE HERE 2\r\n<h3>Vectorizing along two dimensions</h3>\r\nWe can get rid of another FOR loop to have 2-D vectorized code. You can get a single point from set <strong>A </strong>and replicate it to create a matrix that is the same size as <strong>B</strong>. You can now find distance of a <strong><em>single</em></strong> point in <strong>A </strong>from <strong><em>all </em></strong>points in <strong>B</strong>. The code can be seen below.\r\n\r\n<strong><em>getting rid of for loops</em></strong>\r\n\r\nCODE HERE\r\n<h3><strong>Vectorizing along three dimensions</strong></h3>\r\nThe previous method can be further extended. This would involve getting the differences between every point in <strong>A<em> </em></strong> from every point in <strong>B </strong> in parallel. This can be achieved by modifying and tiling <strong>A</strong>, <strong>B </strong>to get matrices of size [<strong>3, Alen, Blen]</strong>.\r\n\r\nFor <strong>A, </strong>we need to tile it for each point present in <strong>B</strong>.<strong> </strong>This generates a 3D array of the desired dimensions. For <strong>B, </strong>we need to first modify it such that each point in <strong>B</strong> is represented in the 3rd dimension rather than the second. This is followed up by a tiling operation in the second dimension to generate a 3D array of the desired dimensions. A simple illustration of what is happening can be seen below.\r\n\r\nRESULTS HERE\r\n\r\nOnce we have the tiled versions of the matrices, a single reduction generates the desired results in a single step. The code for this optimization can be seen below.\r\n\r\nCODE HERE\r\n<h3>Results</h3>\r\nThe following results have been generated on a NVIDIA Quadro K5000.\r\n\r\nRESULTS HERE\r\n<ul>\r\n	<li>As you can see the final performance improvements are about <em><strong>20,000 </strong><strong>times</strong><strong> faster</strong></em> than the <em><strong>naive implementation</strong></em>. It is also <em><strong>29 times faster</strong></em> than the next fastest methods.</li>\r\n	<li><strong>gfor2</strong> (GFOR over B) is faster than <b>gfor2</b> (GFOR over A) because <em><strong>B</strong></em><strong> </strong>has more points than <em><strong>A. </strong></em></li>\r\n	<li><strong>tile1</strong> and <strong>gfor2 </strong>have similar performance because they employ similar mechanisms internally.</li>\r\n</ul>\r\n<h3>Considerations</h3>\r\n<ul>\r\n	<li><strong>tile2 </strong>is the fastest method, but it also uses up the most memory as scratch space. It requires two temporary matrices of sizes <strong>[feat_len, Alen, Blen]. </strong>In this particular case, feat_len was 3, Alen was 200 and Blen was 300. However it is easy for the scratch space requirements to grow to a few gigabytes when the number for points is much higher (as is the case with most machine learning algorithms).</li>\r\n	<li>Though <strong>gfor2 </strong>and <strong>tile1 </strong>give the same performance, <strong>tile1 </strong>should be preferred. This is because <strong>GFOR </strong>can not be nested. However using the <strong>tile1 </strong>method enables us to use GFOR at a higher level in the program.</li>\r\n	<li>Of the functions presented here, <strong>tile1</strong> is perhaps the best compromise when constrained by memory.</li>\r\n	<li>Hybrid algorithms which combine one or two of the method shown here can provide better performance than <strong>tile1.  </strong>We will talk about such algorithms at a later date.</li>\r\n</ul>','How to write vectorized code','','inherit','open','open','','5762-revision-v1','','','2014-06-06 19:16:41','2014-06-06 19:16:41','',5762,'http://sandbox.arrayfire.com/5762-revision-v1/',0,'revision','',0),(5765,17728,'2014-06-06 19:17:14','2014-06-06 19:17:14','A lot of scientists and programmers want to take advantage of fast and parallel computational devices. Writing vectorized code is becoming a necessity to get the best performance out of the current generation parallel hardware and scientific computing software. However writing vectorized code may not be intuitive immediately. There are many ways you can vectorize a given code segment. Each method has its own benefits and drawbacks. Hence writing vectorized code involves analyzing the pros and cons of the available methods and choosing the right one to solve your problem.\r\n\r\nIn this post we present various ways to vectorize your code using ArrayFire. ArrayFire is chosen because of my familiarity with the software. The same methods can be easily used in numpy, octave, julia or other scientific computing software.\r\n<h3>The problem</h3>\r\nIn this post we will be looking to speed up the calculation of distances from every point in a set <strong>A</strong> to every point in set <strong>B</strong>. i.e. if <strong> A </strong> has <strong> 200 </strong> points and <strong> B </strong> has <strong> 300 </strong> points, the distance matrix will be of size <strong>200 x 300</strong>. Each point has co-ordinates in 3 dimensional space. We can generate the necessary data in the following manner.\r\n\r\nCODE HERE\r\n<h3>Naive implementation</h3>\r\nThe naive method would be to have three loops. The outer most loop iterating through points in A. The second loop iterating through points in B. The inner most loop iterating through the three dimensions. You can find difference in co-ordinates between the two points and find the distance between the two points.\r\n\r\nThis can be implemented in the following manner.\r\n\r\nCODE HERE\r\n<h3>Vectorizing along one dimension</h3>\r\nKeeping the outer two loops the same, you can improve the performance by treating the set of three co-ordinates as a single vector. You can perform the difference between these vectors in parallel. A reduction operation after getting the absolute differences will give us the distance without having to use the third loop.\r\n\r\n<strong><em>addition + loop = sum</em></strong>\r\n\r\nCODE HERE\r\n<h3>Using GFOR</h3>\r\nGFOR is a parallel version of the for loop in ArrayFire. Since GFOR\'s can not be nested, we can replace one of the for loops using GFOR. This can be done in the following manners.\r\n\r\n<b><i>parallel for loops</i></b>\r\n\r\nCODE HERE 1\r\n\r\nCODE HERE 2\r\n<h3>Vectorizing along two dimensions</h3>\r\nWe can get rid of another FOR loop to have 2-D vectorized code. You can get a single point from set <strong>A </strong>and replicate it to create a matrix that is the same size as <strong>B</strong>. You can now find distance of a <strong><em>single</em></strong> point in <strong>A </strong>from <strong><em>all </em></strong>points in <strong>B</strong>. The code can be seen below.\r\n\r\n<strong><em>getting rid of for loops</em></strong>\r\n\r\nCODE HERE\r\n<h3><strong>Vectorizing along three dimensions</strong></h3>\r\nThe previous method can be further extended. This would involve getting the differences between every point in <strong>A<em> </em></strong> from every point in <strong>B </strong> in parallel. This can be achieved by modifying and tiling <strong>A</strong>, <strong>B </strong>to get matrices of size <strong>[3, Alen, Blen]</strong>.\r\n\r\nFor <strong>A, </strong>we need to tile it for each point present in <strong>B</strong>.<strong> </strong>This generates a 3D array of the desired dimensions. For <strong>B, </strong>we need to first modify it such that each point in <strong>B</strong> is represented in the 3rd dimension rather than the second. This is followed up by a tiling operation in the second dimension to generate a 3D array of the desired dimensions. A simple illustration of what is happening can be seen below.\r\n\r\nRESULTS HERE\r\n\r\nOnce we have the tiled versions of the matrices, a single reduction generates the desired results in a single step. The code for this optimization can be seen below.\r\n\r\nCODE HERE\r\n<h3>Results</h3>\r\nThe following results have been generated on a NVIDIA Quadro K5000.\r\n\r\nRESULTS HERE\r\n<ul>\r\n	<li>As you can see the final performance improvements are about <em><strong>20,000 </strong><strong>times</strong><strong> faster</strong></em> than the <em><strong>naive implementation</strong></em>. It is also <em><strong>29 times faster</strong></em> than the next fastest methods.</li>\r\n	<li><strong>gfor2</strong> (GFOR over B) is faster than <b>gfor2</b> (GFOR over A) because <em><strong>B</strong></em><strong> </strong>has more points than <em><strong>A. </strong></em></li>\r\n	<li><strong>tile1</strong> and <strong>gfor2 </strong>have similar performance because they employ similar mechanisms internally.</li>\r\n</ul>\r\n<h3>Considerations</h3>\r\n<ul>\r\n	<li><strong>tile2 </strong>is the fastest method, but it also uses up the most memory as scratch space. It requires two temporary matrices of sizes <strong>[feat_len, Alen, Blen]. </strong>In this particular case, feat_len was 3, Alen was 200 and Blen was 300. However it is easy for the scratch space requirements to grow to a few gigabytes when the number for points is much higher (as is the case with most machine learning algorithms).</li>\r\n	<li>Though <strong>gfor2 </strong>and <strong>tile1 </strong>give the same performance, <strong>tile1 </strong>should be preferred. This is because <strong>GFOR </strong>can not be nested. However using the <strong>tile1 </strong>method enables us to use GFOR at a higher level in the program.</li>\r\n	<li>Of the functions presented here, <strong>tile1</strong> is perhaps the best compromise when constrained by memory.</li>\r\n	<li>Hybrid algorithms which combine one or two of the method shown here can provide better performance than <strong>tile1.  </strong>We will talk about such algorithms at a later date.</li>\r\n</ul>','How to write vectorized code','','inherit','open','open','','5762-revision-v1','','','2014-06-06 19:17:14','2014-06-06 19:17:14','',5762,'http://sandbox.arrayfire.com/5762-revision-v1/',0,'revision','',0),(5766,17728,'2014-06-06 19:17:58','2014-06-06 19:17:58','A lot of scientists and programmers want to take advantage of fast and parallel computational devices. Writing vectorized code is becoming a necessity to get the best performance out of the current generation parallel hardware and scientific computing software. However writing vectorized code may not be intuitive immediately. There are many ways you can vectorize a given code segment. Each method has its own benefits and drawbacks. Hence writing vectorized code involves analyzing the pros and cons of the available methods and choosing the right one to solve your problem.\r\n\r\nIn this post we present various ways to vectorize your code using ArrayFire. ArrayFire is chosen because of my familiarity with the software. The same methods can be easily used in numpy, octave, julia or other scientific computing software.\r\n<h3>The problem</h3>\r\nIn this post we will be looking to speed up the calculation of distances from every point in a set <strong>A</strong> to every point in set <strong>B</strong>. i.e. if <strong> A </strong> has <strong> 200 </strong> points and <strong> B </strong> has <strong> 300 </strong> points, the distance matrix will be of size <strong>200 x 300</strong>. Each point has co-ordinates in 3 dimensional space. We can generate the necessary data in the following manner.\r\n\r\nCODE HERE\r\n<h3>Naive implementation</h3>\r\nThe naive method would be to have three loops. The outer most loop iterating through points in A. The second loop iterating through points in B. The inner most loop iterating through the three dimensions. You can find difference in co-ordinates between the two points and find the distance between the two points.\r\n\r\nThis can be implemented in the following manner.\r\n\r\nCODE HERE\r\n<h3>Vectorizing along one dimension</h3>\r\nKeeping the outer two loops the same, you can improve the performance by treating the set of three co-ordinates as a single vector. You can perform the difference between these vectors in parallel. A reduction operation after getting the absolute differences will give us the distance without having to use the third loop.\r\n<blockquote><strong><em>addition + loop = sum</em></strong></blockquote>\r\nCODE HERE\r\n<h3>Using GFOR</h3>\r\nGFOR is a parallel version of the for loop in ArrayFire. Since GFOR\'s can not be nested, we can replace one of the for loops using GFOR. This can be done in the following manners.\r\n\r\n<b><i>parallel for loops</i></b>\r\n\r\nCODE HERE 1\r\n\r\nCODE HERE 2\r\n<h3>Vectorizing along two dimensions</h3>\r\nWe can get rid of another FOR loop to have 2-D vectorized code. You can get a single point from set <strong>A </strong>and replicate it to create a matrix that is the same size as <strong>B</strong>. You can now find distance of a <strong><em>single</em></strong> point in <strong>A </strong>from <strong><em>all </em></strong>points in <strong>B</strong>. The code can be seen below.\r\n\r\n<strong><em>getting rid of for loops</em></strong>\r\n\r\nCODE HERE\r\n<h3><strong>Vectorizing along three dimensions</strong></h3>\r\nThe previous method can be further extended. This would involve getting the differences between every point in <strong>A<em> </em></strong> from every point in <strong>B </strong> in parallel. This can be achieved by modifying and tiling <strong>A</strong>, <strong>B </strong>to get matrices of size <strong>[3, Alen, Blen]</strong>.\r\n\r\nFor <strong>A, </strong>we need to tile it for each point present in <strong>B</strong>.<strong> </strong>This generates a 3D array of the desired dimensions. For <strong>B, </strong>we need to first modify it such that each point in <strong>B</strong> is represented in the 3rd dimension rather than the second. This is followed up by a tiling operation in the second dimension to generate a 3D array of the desired dimensions. A simple illustration of what is happening can be seen below.\r\n\r\nRESULTS HERE\r\n\r\nOnce we have the tiled versions of the matrices, a single reduction generates the desired results in a single step. The code for this optimization can be seen below.\r\n\r\nCODE HERE\r\n<h3>Results</h3>\r\nThe following results have been generated on a NVIDIA Quadro K5000.\r\n\r\nRESULTS HERE\r\n<ul>\r\n	<li>As you can see the final performance improvements are about <em><strong>20,000 </strong><strong>times</strong><strong> faster</strong></em> than the <em><strong>naive implementation</strong></em>. It is also <em><strong>29 times faster</strong></em> than the next fastest methods.</li>\r\n	<li><strong>gfor2</strong> (GFOR over B) is faster than <b>gfor2</b> (GFOR over A) because <em><strong>B</strong></em><strong> </strong>has more points than <em><strong>A. </strong></em></li>\r\n	<li><strong>tile1</strong> and <strong>gfor2 </strong>have similar performance because they employ similar mechanisms internally.</li>\r\n</ul>\r\n<h3>Considerations</h3>\r\n<ul>\r\n	<li><strong>tile2 </strong>is the fastest method, but it also uses up the most memory as scratch space. It requires two temporary matrices of sizes <strong>[feat_len, Alen, Blen]. </strong>In this particular case, feat_len was 3, Alen was 200 and Blen was 300. However it is easy for the scratch space requirements to grow to a few gigabytes when the number for points is much higher (as is the case with most machine learning algorithms).</li>\r\n	<li>Though <strong>gfor2 </strong>and <strong>tile1 </strong>give the same performance, <strong>tile1 </strong>should be preferred. This is because <strong>GFOR </strong>can not be nested. However using the <strong>tile1 </strong>method enables us to use GFOR at a higher level in the program.</li>\r\n	<li>Of the functions presented here, <strong>tile1</strong> is perhaps the best compromise when constrained by memory.</li>\r\n	<li>Hybrid algorithms which combine one or two of the method shown here can provide better performance than <strong>tile1.  </strong>We will talk about such algorithms at a later date.</li>\r\n</ul>','How to write vectorized code','','inherit','open','open','','5762-revision-v1','','','2014-06-06 19:17:58','2014-06-06 19:17:58','',5762,'http://sandbox.arrayfire.com/5762-revision-v1/',0,'revision','',0),(5767,17728,'2014-06-06 19:18:34','2014-06-06 19:18:34','A lot of scientists and programmers want to take advantage of fast and parallel computational devices. Writing vectorized code is becoming a necessity to get the best performance out of the current generation parallel hardware and scientific computing software. However writing vectorized code may not be intuitive immediately. There are many ways you can vectorize a given code segment. Each method has its own benefits and drawbacks. Hence writing vectorized code involves analyzing the pros and cons of the available methods and choosing the right one to solve your problem.\r\n\r\nIn this post we present various ways to vectorize your code using ArrayFire. ArrayFire is chosen because of my familiarity with the software. The same methods can be easily used in numpy, octave, julia or other scientific computing software.\r\n<h3>The problem</h3>\r\nIn this post we will be looking to speed up the calculation of distances from every point in a set <strong>A</strong> to every point in set <strong>B</strong>. i.e. if <strong> A </strong> has <strong> 200 </strong> points and <strong> B </strong> has <strong> 300 </strong> points, the distance matrix will be of size <strong>200 x 300</strong>. Each point has co-ordinates in 3 dimensional space. We can generate the necessary data in the following manner.\r\n\r\nCODE HERE\r\n<h3>Naive implementation</h3>\r\nThe naive method would be to have three loops. The outer most loop iterating through points in A. The second loop iterating through points in B. The inner most loop iterating through the three dimensions. You can find difference in co-ordinates between the two points and find the distance between the two points.\r\n\r\nThis can be implemented in the following manner.\r\n\r\nCODE HERE\r\n<h3>Vectorizing along one dimension</h3>\r\nKeeping the outer two loops the same, you can improve the performance by treating the set of three co-ordinates as a single vector. You can perform the difference between these vectors in parallel. A reduction operation after getting the absolute differences will give us the distance without having to use the third loop.\r\n\r\nCODE HERE\r\n<h3>Using GFOR</h3>\r\nGFOR is a parallel version of the for loop in ArrayFire. Since GFOR\'s can not be nested, we can replace one of the for loops using GFOR. This can be done in the following manners.\r\n\r\nCODE HERE 1\r\n\r\nCODE HERE 2\r\n<h3>Vectorizing along two dimensions</h3>\r\nWe can get rid of another FOR loop to have 2-D vectorized code. You can get a single point from set <strong>A </strong>and replicate it to create a matrix that is the same size as <strong>B</strong>. You can now find distance of a <strong><em>single</em></strong> point in <strong>A </strong>from <strong><em>all </em></strong>points in <strong>B</strong>. The code can be seen below.\r\n\r\nCODE HERE\r\n<h3><strong>Vectorizing along three dimensions</strong></h3>\r\nThe previous method can be further extended. This would involve getting the differences between every point in <strong>A<em> </em></strong> from every point in <strong>B </strong> in parallel. This can be achieved by modifying and tiling <strong>A</strong>, <strong>B </strong>to get matrices of size <strong>[3, Alen, Blen]</strong>.\r\n\r\nFor <strong>A, </strong>we need to tile it for each point present in <strong>B</strong>.<strong> </strong>This generates a 3D array of the desired dimensions. For <strong>B, </strong>we need to first modify it such that each point in <strong>B</strong> is represented in the 3rd dimension rather than the second. This is followed up by a tiling operation in the second dimension to generate a 3D array of the desired dimensions. A simple illustration of what is happening can be seen below.\r\n\r\nRESULTS HERE\r\n\r\nOnce we have the tiled versions of the matrices, a single reduction generates the desired results in a single step. The code for this optimization can be seen below.\r\n\r\nCODE HERE\r\n<h3>Results</h3>\r\nThe following results have been generated on a NVIDIA Quadro K5000.\r\n\r\nRESULTS HERE\r\n<ul>\r\n	<li>As you can see the final performance improvements are about <em><strong>20,000 </strong><strong>times</strong><strong> faster</strong></em> than the <em><strong>naive implementation</strong></em>. It is also <em><strong>29 times faster</strong></em> than the next fastest methods.</li>\r\n	<li><strong>gfor2</strong> (GFOR over B) is faster than <b>gfor2</b> (GFOR over A) because <em><strong>B</strong></em><strong> </strong>has more points than <em><strong>A. </strong></em></li>\r\n	<li><strong>tile1</strong> and <strong>gfor2 </strong>have similar performance because they employ similar mechanisms internally.</li>\r\n</ul>\r\n<h3>Considerations</h3>\r\n<ul>\r\n	<li><strong>tile2 </strong>is the fastest method, but it also uses up the most memory as scratch space. It requires two temporary matrices of sizes <strong>[feat_len, Alen, Blen]. </strong>In this particular case, feat_len was 3, Alen was 200 and Blen was 300. However it is easy for the scratch space requirements to grow to a few gigabytes when the number for points is much higher (as is the case with most machine learning algorithms).</li>\r\n	<li>Though <strong>gfor2 </strong>and <strong>tile1 </strong>give the same performance, <strong>tile1 </strong>should be preferred. This is because <strong>GFOR </strong>can not be nested. However using the <strong>tile1 </strong>method enables us to use GFOR at a higher level in the program.</li>\r\n	<li>Of the functions presented here, <strong>tile1</strong> is perhaps the best compromise when constrained by memory.</li>\r\n	<li>Hybrid algorithms which combine one or two of the method shown here can provide better performance than <strong>tile1.  </strong>We will talk about such algorithms at a later date.</li>\r\n</ul>','How to write vectorized code','','inherit','open','open','','5762-revision-v1','','','2014-06-06 19:18:34','2014-06-06 19:18:34','',5762,'http://sandbox.arrayfire.com/5762-revision-v1/',0,'revision','',0),(5768,17728,'2014-06-06 19:19:38','2014-06-06 19:19:38','A lot of scientists and programmers want to take advantage of fast and parallel computational devices. Writing vectorized code is becoming a necessity to get the best performance out of the current generation parallel hardware and scientific computing software. However writing vectorized code may not be intuitive immediately. There are many ways you can vectorize a given code segment. Each method has its own benefits and drawbacks. Hence writing vectorized code involves analyzing the pros and cons of the available methods and choosing the right one to solve your problem.\r\n\r\nIn this post we present various ways to vectorize your code using ArrayFire. ArrayFire is chosen because of my familiarity with the software. The same methods can be easily used in numpy, octave, julia or other scientific computing software.\r\n<h3>The problem</h3>\r\nIn this post we will be looking to speed up the calculation of distances from every point in a set <strong>A</strong> to every point in set <strong>B</strong>. i.e. if <strong> A </strong> has <strong> 200 </strong> points and <strong> B </strong> has <strong> 300 </strong> points, the distance matrix will be of size <strong>200 x 300</strong>. Each point has co-ordinates in 3 dimensional space. We can generate the necessary data in the following manner.\r\n\r\n<pre>\r\nA = randu(3, 200);\r\nB = randu(3, 300);\r\n</pre>\r\n<h3>Naive implementation</h3>\r\nThe naive method would be to have three loops. The outer most loop iterating through points in A. The second loop iterating through points in B. The inner most loop iterating through the three dimensions. You can find difference in co-ordinates between the two points and find the distance between the two points.\r\n\r\nThis can be implemented in the following manner.\r\n\r\nCODE HERE\r\n<h3>Vectorizing along one dimension</h3>\r\nKeeping the outer two loops the same, you can improve the performance by treating the set of three co-ordinates as a single vector. You can perform the difference between these vectors in parallel. A reduction operation after getting the absolute differences will give us the distance without having to use the third loop.\r\n\r\nCODE HERE\r\n<h3>Using GFOR</h3>\r\nGFOR is a parallel version of the for loop in ArrayFire. Since GFOR\'s can not be nested, we can replace one of the for loops using GFOR. This can be done in the following manners.\r\n\r\nCODE HERE 1\r\n\r\nCODE HERE 2\r\n<h3>Vectorizing along two dimensions</h3>\r\nWe can get rid of another FOR loop to have 2-D vectorized code. You can get a single point from set <strong>A </strong>and replicate it to create a matrix that is the same size as <strong>B</strong>. You can now find distance of a <strong><em>single</em></strong> point in <strong>A </strong>from <strong><em>all </em></strong>points in <strong>B</strong>. The code can be seen below.\r\n\r\nCODE HERE\r\n<h3><strong>Vectorizing along three dimensions</strong></h3>\r\nThe previous method can be further extended. This would involve getting the differences between every point in <strong>A<em> </em></strong> from every point in <strong>B </strong> in parallel. This can be achieved by modifying and tiling <strong>A</strong>, <strong>B </strong>to get matrices of size <strong>[3, Alen, Blen]</strong>.\r\n\r\nFor <strong>A, </strong>we need to tile it for each point present in <strong>B</strong>.<strong> </strong>This generates a 3D array of the desired dimensions. For <strong>B, </strong>we need to first modify it such that each point in <strong>B</strong> is represented in the 3rd dimension rather than the second. This is followed up by a tiling operation in the second dimension to generate a 3D array of the desired dimensions. A simple illustration of what is happening can be seen below.\r\n\r\nRESULTS HERE\r\n\r\nOnce we have the tiled versions of the matrices, a single reduction generates the desired results in a single step. The code for this optimization can be seen below.\r\n\r\nCODE HERE\r\n<h3>Results</h3>\r\nThe following results have been generated on a NVIDIA Quadro K5000.\r\n\r\nRESULTS HERE\r\n<ul>\r\n	<li>As you can see the final performance improvements are about <em><strong>20,000 </strong><strong>times</strong><strong> faster</strong></em> than the <em><strong>naive implementation</strong></em>. It is also <em><strong>29 times faster</strong></em> than the next fastest methods.</li>\r\n	<li><strong>gfor2</strong> (GFOR over B) is faster than <b>gfor2</b> (GFOR over A) because <em><strong>B</strong></em><strong> </strong>has more points than <em><strong>A. </strong></em></li>\r\n	<li><strong>tile1</strong> and <strong>gfor2 </strong>have similar performance because they employ similar mechanisms internally.</li>\r\n</ul>\r\n<h3>Considerations</h3>\r\n<ul>\r\n	<li><strong>tile2 </strong>is the fastest method, but it also uses up the most memory as scratch space. It requires two temporary matrices of sizes <strong>[feat_len, Alen, Blen]. </strong>In this particular case, feat_len was 3, Alen was 200 and Blen was 300. However it is easy for the scratch space requirements to grow to a few gigabytes when the number for points is much higher (as is the case with most machine learning algorithms).</li>\r\n	<li>Though <strong>gfor2 </strong>and <strong>tile1 </strong>give the same performance, <strong>tile1 </strong>should be preferred. This is because <strong>GFOR </strong>can not be nested. However using the <strong>tile1 </strong>method enables us to use GFOR at a higher level in the program.</li>\r\n	<li>Of the functions presented here, <strong>tile1</strong> is perhaps the best compromise when constrained by memory.</li>\r\n	<li>Hybrid algorithms which combine one or two of the method shown here can provide better performance than <strong>tile1.  </strong>We will talk about such algorithms at a later date.</li>\r\n</ul>','How to write vectorized code','','inherit','open','open','','5762-revision-v1','','','2014-06-06 19:19:38','2014-06-06 19:19:38','',5762,'http://sandbox.arrayfire.com/5762-revision-v1/',0,'revision','',0),(5769,17728,'2014-06-06 19:22:44','2014-06-06 19:22:44','A lot of scientists and programmers want to take advantage of fast and parallel computational devices. Writing vectorized code is becoming a necessity to get the best performance out of the current generation parallel hardware and scientific computing software. However writing vectorized code may not be intuitive immediately. There are many ways you can vectorize a given code segment. Each method has its own benefits and drawbacks. Hence writing vectorized code involves analyzing the pros and cons of the available methods and choosing the right one to solve your problem.\r\n\r\nIn this post we present various ways to vectorize your code using ArrayFire. ArrayFire is chosen because of my familiarity with the software. The same methods can be easily used in numpy, octave, julia or other scientific computing software.\r\n<h3>The problem</h3>\r\nIn this post we will be looking to speed up the calculation of distances from every point in a set <strong>A</strong> to every point in set <strong>B</strong>. i.e. if <strong> A </strong> has <strong> 200 </strong> points and <strong> B </strong> has <strong> 300 </strong> points, the distance matrix will be of size <strong>200 x 300</strong>. Each point has co-ordinates in 3 dimensional space. We can generate the necessary data in the following manner.\r\n\r\n<pre>\r\nA = randu(3, 200);\r\nB = randu(3, 300);\r\n</pre>\r\n<h3>Naive implementation</h3>\r\nThe naive method would be to have three loops. The outer most loop iterating through points in A. The second loop iterating through points in B. The inner most loop iterating through the three dimensions. You can find difference in co-ordinates between the two points and find the distance between the two points.\r\n\r\nThis can be implemented in the following manner.\r\n\r\n<pre>\r\nstatic array dist_naive(array a, array b)\r\n{   \r\n    array dist_mat = constant(0, a.dims(1), b.dims(1));\r\n\r\n    // Iterate through columns a                                                                                                                                                                                     \r\n    for (int ii = 0; ii < a.dims(1); ii++) {\r\n\r\n        // Iterate through columns of b                                                                                                                                                                              \r\n        for (int jj = 0; jj < b.dims(1); jj++) {\r\n\r\n            // Get the sum of absolute differences                                                                                                                                                                   \r\n            for (int kk = 0; kk < a.dims(0); kk++) {\r\n                dist_mat(ii, jj) += abs(a(kk, ii) - b(kk, jj));\r\n            }\r\n        }\r\n    }\r\n\r\n    return dist_mat;\r\n}\r\n</pre>\r\n<h3>Vectorizing along one dimension</h3>\r\nKeeping the outer two loops the same, you can improve the performance by treating the set of three co-ordinates as a single vector. You can perform the difference between these vectors in parallel. A reduction operation after getting the absolute differences will give us the distance without having to use the third loop.\r\n\r\n<pre>\r\nstatic array dist_vec(array a, array b)\r\n{   \r\n    array dist_mat = constant(0, a.dims(1), b.dims(1));\r\n\r\n    // Iterate through columns a                                                                                                                                                                                     \r\n    for (int ii = 0; ii < a.dims(1); ii++) {\r\n        array avec = a(span, ii);\r\n\r\n        // Iterate through columns of b                                                                                                                                                                              \r\n        for (int jj = 0; jj < b.dims(1); jj++) {\r\n            array bvec = b(span, jj);\r\n\r\n            // get SAD using sum on the vector                                                                                                                                                                       \r\n            dist_mat(ii, jj) = sum(abs(avec - bvec));\r\n        }\r\n    }\r\n\r\n    return dist_mat;\r\n}\r\n</pre>\r\n<h3>Using GFOR</h3>\r\nGFOR is a parallel version of the for loop in ArrayFire. Since GFOR\'s can not be nested, we can replace one of the for loops using GFOR. This can be done in the following manners.\r\n\r\n<pre>\r\nstatic array dist_gfor1(array a, array b)\r\n{\r\n    array dist_mat = constant(0, a.dims(1), b.dims(1));\r\n\r\n    // GFOR along columns of a                                                                                                                                                                                       \r\n    gfor (array ii, a.dims(1)) {\r\n        array avec = a(span, ii);\r\n\r\n        // Itere through columns of b                                                                                                                                                                                \r\n        for (int jj = 0; jj < b.dims(1); jj++) {\r\n            array bvec = b(span, jj);\r\n\r\n            // get SAD using sum on the vector                                                                                                                                                                       \r\n            dist_mat(ii, jj) = sum(abs(avec - bvec));\r\n        }\r\n    }\r\n\r\n    return dist_mat;\r\n}\r\n\r\nstatic array dist_gfor2(array a, array b)\r\n{   \r\n    array dist_mat = constant(0, a.dims(1), b.dims(1));\r\n\r\n    // GFOR along columns of b                                                                                                                                                                                       \r\n    gfor (array jj, b.dims(1)) {\r\n        array bvec = b(span, jj);\r\n\r\n        // Iterate through columns of A                                                                                                                                                                              \r\n        for (int ii = 0; ii < a.dims(1); ii++) {\r\n            array avec = a(span, ii);\r\n\r\n            // get SAD using sum on the vector                                                                                                                                                                       \r\n            dist_mat(ii, jj) = sum(abs(avec - bvec));\r\n        }\r\n    }\r\n\r\n    return dist_mat;\r\n}\r\n</pre>\r\n<h3>Vectorizing along two dimensions</h3>\r\nWe can get rid of another FOR loop to have 2-D vectorized code. You can get a single point from set <strong>A </strong>and replicate it to create a matrix that is the same size as <strong>B</strong>. You can now find distance of a <strong><em>single</em></strong> point in <strong>A </strong>from <strong><em>all </em></strong>points in <strong>B</strong>. The code can be seen below.\r\n\r\n<pre>\r\nstatic array dist_tile1(array a, array b)\r\n{   \r\n    // int feat_len = a.dims(0); // Same as b.dims(0);                                                                                                                                                               \r\n    int alen = a.dims(1);\r\n    int blen = b.dims(1);\r\n\r\n    array dist_mat = constant(0, alen, blen);\r\n\r\n    // Iterate through columns of b                                                                                                                                                                                  \r\n    for (int jj = 0; jj < blen; jj++) {\r\n\r\n        // Get the column vector of b                                                                                                                                                                                \r\n        // shape of bvec is (feat_len, 1)                                                                                                                                                                            \r\n        array bvec = b(span, jj);\r\n\r\n        // Tile avec to be same size as a                                                                                                                                                                            \r\n        // shape of bvec_tiled is (feat_len, alen)                                                                                                                                                                   \r\n        array bvec_tiled = tile(bvec, 1, alen);\r\n\r\n        // Get the sum of absolute differences                                                                                                                                                                       \r\n        array sad = sum(abs(bvec_tiled - a));\r\n\r\n        // sad is row vector, dist_mat needs column vector                                                                                                                                                           \r\n        // transpose sad and fill in dist_mat                                                                                                                                                                        \r\n        dist_mat(span, jj) = sad.T();\r\n    }\r\n\r\n    return dist_mat;\r\n}\r\n</pre>\r\n\r\n<h3><strong>Vectorizing along three dimensions</strong></h3>\r\nThe previous method can be further extended. This would involve getting the differences between every point in <strong>A<em> </em></strong> from every point in <strong>B </strong> in parallel. This can be achieved by modifying and tiling <strong>A</strong>, <strong>B </strong>to get matrices of size <strong>[3, Alen, Blen]</strong>.\r\n\r\nFor <strong>A, </strong>we need to tile it for each point present in <strong>B</strong>.<strong> </strong>This generates a 3D array of the desired dimensions. For <strong>B, </strong>we need to first modify it such that each point in <strong>B</strong> is represented in the 3rd dimension rather than the second. This is followed up by a tiling operation in the second dimension to generate a 3D array of the desired dimensions. A simple illustration of what is happening can be seen below.\r\n\r\n<pre>\r\nOriginal\r\nA [2 4] =\r\n       10.0000    11.0000    12.0000    13.0000\r\n       14.0000    15.0000    16.0000    17.0000\r\n\r\nB [2 3] =\r\n       20.0000    21.0000    22.0000\r\n       23.0000    24.0000    25.0000\r\n\r\nModified\r\nA_mod [2 4] =\r\n       10.0000    11.0000    12.0000    13.0000\r\n       14.0000    15.0000    16.0000    17.0000\r\n\r\nB_mod [2 1 3] =\r\n       20.0000\r\n       23.0000\r\n\r\n       21.0000\r\n       24.0000\r\n\r\n       22.0000\r\n       25.0000\r\n\r\nTiled\r\nA_tiled [2 4 3] =\r\n       10.0000    11.0000    12.0000    13.0000\r\n       14.0000    15.0000    16.0000    17.0000\r\n\r\n       10.0000    11.0000    12.0000    13.0000\r\n       14.0000    15.0000    16.0000    17.0000\r\n\r\n       10.0000    11.0000    12.0000    13.0000\r\n       14.0000    15.0000    16.0000    17.0000\r\n\r\nB_tiled [2 4 3] =\r\n       20.0000    20.0000    20.0000    20.0000\r\n       23.0000    23.0000    23.0000    23.0000\r\n\r\n       21.0000    21.0000    21.0000    21.0000\r\n       24.0000    24.0000    24.0000    24.0000\r\n\r\n       22.0000    22.0000    22.0000    22.0000\r\n       25.0000    25.0000    25.0000    25.0000\r\n</pre>\r\n\r\nOnce we have the tiled versions of the matrices, a single reduction generates the desired results in a single step. The code for this optimization can be seen below.\r\n<pre>\r\nstatic array dist_tile2(array a, array b)\r\n{   \r\n    int feat_len = a.dims(0);\r\n    int alen = a.dims(1);\r\n    int blen = b.dims(1);\r\n\r\n    // Shape of a is (feat_len, alen, 1)                                                                                                                                                                             \r\n    array a_mod = a;\r\n    // Reshape b from (feat_len, blen) to (feat_len, 1, blen)                                                                                                                                                        \r\n    array b_mod = moddims(b, feat_len, 1, blen);\r\n\r\n    // Tile both matrices to be (feat_len, alen, blen)                                                                                                                                                               \r\n    array a_tiled = tile(a_mod, 1, 1, blen);\r\n    array b_tiled = tile(b_mod, 1, alen, 1);\r\n\r\n    // Do The sum operation along first dimension                                                                                                                                                                    \r\n    // Output is of shape (1, alen, blen)                                                                                                                                                                            \r\n    array dist_mod = sum(abs(a_tiled - b_tiled));\r\n\r\n    // Reshape dist_mat from (1, alen, blen) to (alen, blen)                                                                                                                                                         \r\n    array dist_mat = moddims(dist_mod, alen, blen);\r\n    return dist_mat;\r\n}\r\n</pre>\r\n<h3>Results</h3>\r\nThe following results have been generated on a NVIDIA Quadro K5000.\r\n\r\n<pre>\r\nTime for dist_naive: 5006.01ms\r\nTime for dist_vec  : 2177.73ms\r\nTime for dist_gfor1: 10.80ms\r\nTime for dist_gfor2: 7.35ms\r\nTime for dist_tile1: 7.23ms\r\nTime for dist_tile2: 0.25ms\r\n</pre>\r\n<ul>\r\n	<li>As you can see the final performance improvements are about <em><strong>20,000 </strong><strong>times</strong><strong> faster</strong></em> than the <em><strong>naive implementation</strong></em>. It is also <em><strong>29 times faster</strong></em> than the next fastest methods.</li>\r\n	<li><strong>gfor2</strong> (GFOR over B) is faster than <b>gfor2</b> (GFOR over A) because <em><strong>B</strong></em><strong> </strong>has more points than <em><strong>A. </strong></em></li>\r\n	<li><strong>tile1</strong> and <strong>gfor2 </strong>have similar performance because they employ similar mechanisms internally.</li>\r\n</ul>\r\n<h3>Considerations</h3>\r\n<ul>\r\n	<li><strong>tile2 </strong>is the fastest method, but it also uses up the most memory as scratch space. It requires two temporary matrices of sizes <strong>[feat_len, Alen, Blen]. </strong>In this particular case, feat_len was 3, Alen was 200 and Blen was 300. However it is easy for the scratch space requirements to grow to a few gigabytes when the number for points is much higher (as is the case with most machine learning algorithms).</li>\r\n	<li>Though <strong>gfor2 </strong>and <strong>tile1 </strong>give the same performance, <strong>tile1 </strong>should be preferred. This is because <strong>GFOR </strong>can not be nested. However using the <strong>tile1 </strong>method enables us to use GFOR at a higher level in the program.</li>\r\n	<li>Of the functions presented here, <strong>tile1</strong> is perhaps the best compromise when constrained by memory.</li>\r\n	<li>Hybrid algorithms which combine one or two of the method shown here can provide better performance than <strong>tile1.  </strong>We will talk about such algorithms at a later date.</li>\r\n</ul>','How to write vectorized code','','inherit','open','open','','5762-revision-v1','','','2014-06-06 19:22:44','2014-06-06 19:22:44','',5762,'http://sandbox.arrayfire.com/5762-revision-v1/',0,'revision','',0),