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.
In many cases, setting up a test harness is a ton of work. This is where ArrayFire can come in handy.
Recently 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.
This 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.
We 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.
std::string goldPath = std::string(gold) + path; std::string testPath = std::string("output/") + path; af::array goldImage = af::loadimage(goldPath.c_str(), true) / 255.0f; af::array testImage = af::loadimage(testPath.c_str(), true) / 255.0f; af::array diffImage = af::abs(goldImage - testImage); float mean = af::mean(diffImage); if(mean < 0.001f) { fprintf ( stderr, "FOUND MISMATCH\n" ) ; result = false; printf("!!!***FAILED***!!!: %s\n", path); stats(diffImage); if(visualize) { // colormap af::fig("color", "default"); // image operations af::fig("sub", 3, 1, 1); af::image(goldImage); af::fig("title", "GOLD"); af::fig("sub", 3, 1, 2); af::image(testImage); af::fig("title", "TEST"); af::fig("sub", 3, 1, 3); af::image(diffImage); af::fig("title", "DIFF"); // Force screen refresh (optional) af::fig("draw"); getchar(); } }
As 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.
ArrayFire 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.