*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of NVIDIA CORPORATION nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
const static char *const sSDKsample = "HSOpticalFlow";
const float THRESHOLD = 0.05f;
#include <cuda_runtime.h>
#include <helper_functions.h>
#include "common.h"
#include "flowCUDA.h"
#include "flowGold.h"
void WriteFloFile(const char *name, int w, int h, int s, const float *u, const float *v)
{
FILE *stream;
stream = fopen(name, "wb");
if (stream == 0) {
printf("Could not save flow to \"%s\"\n", name);
return;
}
float data = 202021.25f;
fwrite(&data, sizeof(float), 1, stream);
fwrite(&w, sizeof(w), 1, stream);
fwrite(&h, sizeof(h), 1, stream);
for (int i = 0; i < h; ++i) {
for (int j = 0; j < w; ++j) {
const int pos = j + i * s;
fwrite(u + pos, sizeof(float), 1, stream);
fwrite(v + pos, sizeof(float), 1, stream);
}
}
fclose(stream);
}
bool LoadImageAsFP32(float *&img_data, int &img_w, int &img_h, int &img_s, const char *name, const char *exePath)
{
printf("Loading \"%s\" ...\n", name);
char *name_ = sdkFindFilePath(name, exePath);
if (!name_) {
printf("File not found\n");
return false;
}
unsigned char *data = 0;
unsigned int w = 0, h = 0;
bool result = sdkLoadPPM4ub(name_, &data, &w, &h);
if (result == false) {
printf("Invalid file format\n");
return false;
}
img_w = w;
img_h = h;
img_s = iAlignUp(img_w);
img_data = new float[img_s * h];
const int widthStep = 4 * img_w;
for (int i = 0; i < img_h; ++i) {
for (int j = 0; j < img_w; ++j) {
img_data[j + i * img_s] = ((float)data[j * 4 + i * widthStep]) / 255.0f;
}
}
return true;
}
bool CompareWithGold(int width,
int height,
int stride,
const float *h_uGold,
const float *h_vGold,
const float *h_u,
const float *h_v)
{
float error = 0.0f;
for (int i = 0; i < height; ++i) {
for (int j = 0; j < width; ++j) {
const int pos = j + i * stride;
error += fabsf(h_u[pos] - h_uGold[pos]) + fabsf(h_v[pos] - h_vGold[pos]);
}
}
error /= (float)(width * height);
printf("L1 error : %.6f\n", error);
return (error < THRESHOLD);
}
int main(int argc, char **argv)
{
printf("%s Starting...\n\n", sSDKsample);
findCudaDevice(argc, (const char **)argv);
const char *const sourceFrameName = "frame10.ppm";
const char *const targetFrameName = "frame11.ppm";
int width;
int height;
int stride;
float *h_source;
float *h_target;
if (!LoadImageAsFP32(h_source, width, height, stride, sourceFrameName, argv[0])) {
exit(EXIT_FAILURE);
}
if (!LoadImageAsFP32(h_target, width, height, stride, targetFrameName, argv[0])) {
exit(EXIT_FAILURE);
}
float *h_uGold = new float[stride * height];
float *h_vGold = new float[stride * height];
float *h_u = new float[stride * height];
float *h_v = new float[stride * height];
const float alpha = 0.2f;
const int nLevels = 5;
const int nSolverIters = 500;
const int nWarpIters = 3;
ComputeFlowGold(
h_source, h_target, width, height, stride, alpha, nLevels, nWarpIters, nSolverIters, h_uGold, h_vGold);
ComputeFlowCUDA(h_source, h_target, width, height, stride, alpha, nLevels, nWarpIters, nSolverIters, h_u, h_v);
bool status = CompareWithGold(width, height, stride, h_uGold, h_vGold, h_u, h_v);
WriteFloFile("FlowGPU.flo", width, height, stride, h_u, h_v);
WriteFloFile("FlowCPU.flo", width, height, stride, h_uGold, h_vGold);
delete[] h_uGold;
delete[] h_vGold;
delete[] h_u;
delete[] h_v;
delete[] h_source;
delete[] h_target;
exit(status ? EXIT_SUCCESS : EXIT_FAILURE);
}