Repository: opencv/opencv
File: modules/video/src/dis_flow.cpp (C++)

Code before:
        ocl::KernelArg::PtrWriteOnly(dst_I0xy),
        ocl::KernelArg::PtrWriteOnly(dst_I0x),
        ocl::KernelArg::PtrWriteOnly(dst_I0y)
    );
    return kernelY.run(1, globalSizeY, localSizeY, false);
}

bool DISOpticalFlowImpl::ocl_calc(InputArray I0, InputArray I1, InputOutputArray flow)
{
    CV_INSTRUMENT_REGION();
    // not pure OpenCV code: CV_INSTRUMENT_REGION_OPENCL();

    UMat I0Mat = I0.getUMat();
    UMat I1Mat = I1.getUMat();
    bool use_input_flow = false;
    if (flow.sameSize(I0) && flow.depth() == CV_32F && flow.channels() == 2)
        use_input_flow = true;

    if (user_coarsest_scale != -1)
    {
        coarsest_scale = user_coarsest_scale;
    }
    else
    {
        coarsest_scale = min((int)(log(max(I0Mat.cols, I0Mat.rows) / (4.0 * patch_size)) / log(2.0) + 0.5), /* Original code search for maximal movement of width/4 */
                             (int)(log(min(I0Mat.cols, I0Mat.rows) / patch_size) / log(2.0)));              /* Deepest pyramid level greater or equal than patch*/
    }

    if (coarsest_scale<0)
        CV_Error(cv::Error::StsBadSize, "The input image must have either width or height >= 12");

    if (coarsest_scale<finest_scale)
    {
        // choose the finest level based on coarsest level.
        // Refs: https://github.com/tikroeger/OF_DIS/blob/2c9f2a674f3128d3a41c10e41cc9f3a35bb1b523/run_dense.cpp#L239
        int original_img_width = I0.size().width;
        autoSelectPatchSizeAndScales(original_img_width);
    }

    ocl_prepareBuffers(I0Mat, I1Mat, flow, use_input_flow);
    u_U[coarsest_scale].setTo(0.0f);

    for (int i = coarsest_scale; i >= finest_scale; i--)
    {
        CV_TRACE_REGION("coarsest_scale_iteration");
        w = u_I0s[i].cols;
        h = u_I0s[i].rows;
        ws = 1 + (w - patch_size) / patch_stride;
        hs = 1 + (h - patch_size) / patch_stride;

        if (!ocl_precomputeStructureTensor(u_I0xx_buf, u_I0yy_buf, u_I0xy_buf,

Review comment (suggestion):
The `coarsest_scale` adjustment should be applied to user provided value too. It prevents the further pipeline steps from too small pyramid layers.

Code after:
        ocl::KernelArg::PtrWriteOnly(dst_I0xy),
        ocl::KernelArg::PtrWriteOnly(dst_I0x),
        ocl::KernelArg::PtrWriteOnly(dst_I0y)
    );
    return kernelY.run(1, globalSizeY, localSizeY, false);
}

bool DISOpticalFlowImpl::ocl_calc(InputArray I0, InputArray I1, InputOutputArray flow)
{
    CV_INSTRUMENT_REGION();
    // not pure OpenCV code: CV_INSTRUMENT_REGION_OPENCL();

    UMat I0Mat = I0.getUMat();
    UMat I1Mat = I1.getUMat();
    bool use_input_flow = false;
    if (flow.sameSize(I0) && flow.depth() == CV_32F && flow.channels() == 2)
        use_input_flow = true;

    int max_possible_scale = min((int)(log(max(I0Mat.cols, I0Mat.rows) / (4.0 * patch_size)) / log(2.0) + 0.5), /* Original code search for maximal movement of width/4 */
                                 (int)(log(min(I0Mat.cols, I0Mat.rows) / patch_size) / log(2.0)));              /* Deepest pyramid level greater or equal than patch*/

    if (user_coarsest_scale != -1)
        coarsest_scale = min(user_coarsest_scale, max_possible_scale);
    else
        coarsest_scale = max_possible_scale;

    if (coarsest_scale<0)
        CV_Error(cv::Error::StsBadSize, "The input image must have either width or height >= 12");

    if (coarsest_scale<finest_scale)
    {
        // choose the finest level based on coarsest level.
        // Refs: https://github.com/tikroeger/OF_DIS/blob/2c9f2a674f3128d3a41c10e41cc9f3a35bb1b523/run_dense.cpp#L239
        int original_img_width = I0.size().width;
        autoSelectPatchSizeAndScales(original_img_width);
    }

    ocl_prepareBuffers(I0Mat, I1Mat, flow, use_input_flow);
    u_U[coarsest_scale].setTo(0.0f);

    for (int i = coarsest_scale; i >= finest_scale; i--)
    {
        CV_TRACE_REGION("coarsest_scale_iteration");
        w = u_I0s[i].cols;
        h = u_I0s[i].rows;
        ws = 1 + (w - patch_size) / patch_stride;
        hs = 1 + (h - patch_size) / patch_stride;

        if (!ocl_precomputeStructureTensor(u_I0xx_buf, u_I0yy_buf, u_I0xy_buf,
                                           u_I0x_buf, u_I0y_buf, u_I0xs[i], u_I0ys[i]))
            return false;