private void SampleForm_Load(object sender, EventArgs e) { #region Corner Tracking Initialization uint width = 1024, height = 1024; UIntPtr max_keypoint_count = (UIntPtr)10000; // maximum number of keypoints to track float harris_strength_thresh = 0.0005f; // minimum corner strength to keep a corner float harris_min_distance = 5.0f; // radial L2 distance for non-max suppression float harris_sensitivity = 0.04f; // multiplier k in det(A) - k * trace(A)^2 int harris_gradient_size = 3; // window size for gradient computation int harris_block_size = 3; // block window size for Harris corner score UIntPtr lk_pyramid_levels = (UIntPtr)6; // number of pyramid levels for optical flow float lk_pyramid_scale = VX.SCALE_PYRAMID_HALF; // pyramid levels scale by factor of two TerminationCriteria lk_termination = TerminationCriteria.Both; // iteration termination criteria (eps & iterations) float lk_epsilon = 0.01f; // convergence criterion uint lk_num_iterations = 5; // maximum number of iterations bool lk_use_initial_estimate = false; // don't use initial estimate uint lk_window_dimension = 6; // window size for evaluation float trackable_kp_ratio_thr = 0.8f; // threshold for the ration of tracked keypoints to all // Create the OpenVX context and make sure the returned context is valid. _Context = VX.CreateContext(); // Create OpenVX image object for input RGB image. _ImageInput = VX.CreateImage(_Context, width, height, DfImage.Rgb); // OpenVX optical flow functionality requires image pyramids for the current // and the previous image. It also requires keypoints that correspond // to the previous pyramid and will output updated keypoints into // another keypoint array. To be able to toggle between the current and // the previous buffers, you need to use OpenVX delay objects and vxAgeDelay(). // Create OpenVX pyramid and array object exemplars and create OpenVX delay // objects for both to hold two of each. Note that the exemplar objects are not // needed once the delay objects are created. using (Pyramid pyramid = VX.CreatePyramid(_Context, lk_pyramid_levels, lk_pyramid_scale, width, height, DfImage.U8)) _PyramidDelay = VX.CreateDelay(_Context, pyramid, (UIntPtr)2); using (OpenVX.Array keypoints = VX.CreateArray(_Context, OpenVX.Type.Keypoint, max_keypoint_count)) _KeypointsDelay = VX.CreateDelay(_Context, keypoints, (UIntPtr)2); // An object from a delay slot can be accessed using vxGetReferenceFromDelay API. // You need to use index = 0 for the current object and index = -1 for the previous object. _PyramidCurrent = VX.GetReferenceFromDelay(_PyramidDelay, 0); _PyramidPrevious = VX.GetReferenceFromDelay(_PyramidDelay, -1); _KeypointsCurrent = VX.GetReferenceFromDelay(_KeypointsDelay, 0); _KeypointsPrevious = VX.GetReferenceFromDelay(_KeypointsDelay, -1); // Harris and optical flow algorithms require their own graph objects. // The Harris graph needs to extract gray scale image out of input RGB, // compute an initial set of keypoints, and compute an initial pyramid for use // by the optical flow graph. Graph graphHarris = VX.CreateGraph(_Context); Graph graphTrack = VX.CreateGraph(_Context); // Harris and pyramid computation expect input to be an 8-bit image. // Given that input is an RGB image, it is best to extract a gray image // from RGB image, which requires two steps: // - perform RGB to IYUV color conversion // - extract Y channel from IYUV image // This requires two intermediate OpenVX image objects. Since you don't // need to access these objects from the application, they can be virtual // objects that can be created using the vxCreateVirtualImage API. OpenVX.Image harris_yuv_image = VX.CreateVirtualImage(graphHarris, width, height, DfImage.Iyuv); OpenVX.Image harris_gray_image = VX.CreateVirtualImage(graphHarris, width, height, DfImage.U8); OpenVX.Image opticalflow_yuv_image = VX.CreateVirtualImage(graphTrack, width, height, DfImage.Iyuv); OpenVX.Image opticalflow_gray_image = VX.CreateVirtualImage(graphTrack, width, height, DfImage.U8); // The Harris corner detector and optical flow nodes (see "VX/vx_nodes.h") // need several scalar objects as parameters. Scalar strength_thresh = VX.CreateScalar(_Context, ref harris_strength_thresh); Scalar min_distance = VX.CreateScalar(_Context, ref harris_min_distance); Scalar sensitivity = VX.CreateScalar(_Context, ref harris_sensitivity); Scalar epsilon = VX.CreateScalar(_Context, ref lk_epsilon); Scalar num_iterations = VX.CreateScalar(_Context, ref lk_num_iterations); Scalar use_initial_estimate = VX.CreateScalar(_Context, ref lk_use_initial_estimate); // Now all the objects have been created for building the graphs. // First, build a graph that performs Harris corner detection and initial pyramid computation. // See "VX/vx_nodes.h" for APIs how to add nodes into a graph. Node[] nodesHarris = new Node[] { VX.ColorConvertNode(graphHarris, _ImageInput, harris_yuv_image), VX.ChannelExtractNode(graphHarris, harris_yuv_image, Channel.ChannelY, harris_gray_image), VX.GaussianPyramidNode(graphHarris, harris_gray_image, _PyramidCurrent), VX.HarrisCornersNode(graphHarris, harris_gray_image, strength_thresh, min_distance, sensitivity, harris_gradient_size, harris_block_size, _KeypointsCurrent, Reference.Null) }; VX.Release(nodesHarris); VX.VerifyGraph(graphHarris); // Now, build a graph that computes image pyramid for the next frame, // and tracks features using optical flow. Node[] nodesTrack = new Node[] { VX.ColorConvertNode(graphTrack, _ImageInput, opticalflow_yuv_image), VX.ChannelExtractNode(graphTrack, opticalflow_yuv_image, Channel.ChannelY, opticalflow_gray_image), VX.GaussianPyramidNode(graphTrack, opticalflow_gray_image, _PyramidCurrent), VX.OpticalFlowPyrLKNode(graphTrack, _PyramidPrevious, _PyramidCurrent, _KeypointsPrevious, _KeypointsPrevious, _KeypointsCurrent, lk_termination, epsilon, num_iterations, use_initial_estimate, (UIntPtr)lk_window_dimension ) }; VX.Release(nodesTrack); VX.VerifyGraph(graphTrack); _GraphHarris = graphHarris; _GraphTrack = graphTrack; #endregion }