Program Listing for File xf_stereo_pipeline.hpp

Return to documentation for file (/tmp/ws/src/vitis_common/include/imgproc/xf_stereo_pipeline.hpp)

/*
 * Copyright 2019 Xilinx, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef _XF_STEREO_PIPELINE_HPP_
#define _XF_STEREO_PIPELINE_HPP_

#ifndef __cplusplus
#error C++ is needed to include this header
#endif

#include "hls_stream.h"
#include "utils/x_hls_traits.h"
#include "../common/xf_common.hpp"
#include "../common/xf_utility.hpp"

#define _XF_INTER_BITS_ 5

namespace xf {
namespace cv {

template <typename T>
struct xfInitUndistortRectifyMap_traits {
    typedef T FRAMET;
    typedef T FRAME2T;
};

// Approximation of 1/x around x=1.
// In most cases (e.g. float), we just do computation in type T.
template <typename T>
T xf_one_over_x_approx(T x) {
    return T(1.0) / x;
}

// if x is ~ 1+delta, then 1/x is 1-delta+..., or 2-x;
template <int W, int I, ap_q_mode Q, ap_o_mode O>
ap_fixed<W, I, Q, O> xf_one_over_x_approx(ap_fixed<W, I, Q, O> x) {
    return 2 - x;
}

template <int W, int I, ap_q_mode Q, ap_o_mode O>
ap_ufixed<W, I, Q, O> xf_one_over_x_approx(ap_ufixed<W, I, Q, O> x) {
    return 2 - x;
}

// Approximation of 1/(1+x) around x=0.
// In most cases (e.g. float), we just do computation in type T.
template <typename T>
T xf_one_over_one_plus_x_approx(T x) {
    return T(1.0) / (T(1.0) + x);
}

// if x is ~ 1+delta, then 1/x is 1-delta+delta^2-...
template <int W, int I, ap_q_mode Q, ap_o_mode O>
ap_fixed<W, I, Q, O> xf_one_over_one_plus_x_approx(ap_fixed<W, I, Q, O> x) {
    return 1 - x;
}

template <int W, int I, ap_q_mode Q, ap_o_mode O>
ap_ufixed<W, I, Q, O> xf_one_over_one_plus_x_approx(ap_ufixed<W, I, Q, O> x) {
    return 1 - x;
}

template <typename FRAMET,
          typename FRAME2T,
          typename ROWT,
          typename COLT,
          typename ROWOUTT,
          typename COLOUTT,
          typename CM_T,
          int CM_SIZE,
          int N>
void xFComputeUndistortCoordinates(
    CM_T* cameraMatrix, CM_T* distCoeffs, CM_T* ir, int noRotation, ROWT i, COLT j, ROWOUTT& u, COLOUTT& v) {
    CM_T zo = 0;
    CM_T k1 = distCoeffs[0];
    CM_T k2 = distCoeffs[1];
    CM_T p1 = distCoeffs[2];
    CM_T p2 = distCoeffs[3];
    CM_T k3 = N >= 5 ? distCoeffs[4] : zo;
    CM_T k4 = N >= 8 ? distCoeffs[5] : zo;
    CM_T k5 = N >= 8 ? distCoeffs[6] : zo;
    CM_T k6 = N >= 8 ? distCoeffs[7] : zo;

    CM_T u0 = cameraMatrix[2];
    CM_T v0 = cameraMatrix[5];
    CM_T fx = cameraMatrix[0];
    CM_T fy = cameraMatrix[4];

    // FRAMET is the type of normalized coordinates.
    // If IR is float, then FRAMET will also be float
    // If IR is ap_fixed, then FRAMET will be some ap_fixed type with more integer bits
    //             typedef typename x_traits<typename x_traits<ROWT,ICMT>::MULT_T,
    //                                       typename x_traits<COLT,ICMT>::MULT_T >::ADD_T FRAMET;
    //    typedef ap_fixed<18,2, AP_TRN, AP_SAT> FRAMET; // Assume frame coordinates are in [-1,1)
    //    typedef CMT FRAMET;
    // typedef float FRAMET;

    FRAMET _x, _y, x, y;
    _x = i * ir[1] + j * ir[0] + ir[2];
    _y = i * ir[4] + j * ir[3] + ir[5];

    if (noRotation) {
        // A special case if there is no rotation: equivalent to cv::initUndistortMap
        x = _x;
        y = _y;
    } else {
        FRAMET w = i * ir[7] + j * ir[6] + ir[8];
        FRAMET winv = xf_one_over_x_approx(w);
        x = (FRAMET)(_x * winv);
        y = (FRAMET)(_y * winv);
    }

    typename hls::x_traits<FRAMET, FRAMET>::MULT_T x2t = x * x, y2t = y * y; // Full precision result here.
    FRAME2T _2xy = 2 * x * y;
    FRAME2T r2 = x2t + y2t;
    FRAME2T x2 = x2t, y2 = y2t;

    FRAMET kr = (1 + FRAMET(FRAMET(k3 * r2 + k2) * r2 + k1) * r2);
    FRAME2T krd = FRAMET(FRAMET(k6 * r2 + k5) * r2 + k4) * r2;

    if (N > 5) kr = kr * xf_one_over_one_plus_x_approx(krd);

    u = fx * (FRAMET(x * kr) + FRAMET(p1 * _2xy) + FRAMET(p2 * (2 * x2 + r2))) + u0;
    v = fy * (FRAMET(y * kr) + FRAMET(p1 * (r2 + 2 * y2)) + FRAMET(p2 * _2xy)) + v0;
}

template <int ROWS, int COLS, int CM_SIZE, typename CM_T, int N, int MAP_T, int NPC, typename MAP_type>
void xFInitUndistortRectifyMapInverseKernel(CM_T* cameraMatrix,
                                            CM_T* distCoeffs,
                                            CM_T* ir,
                                            xf::cv::Mat<MAP_T, ROWS, COLS, NPC>& map1,
                                            xf::cv::Mat<MAP_T, ROWS, COLS, NPC>& map2,
                                            uint16_t rows,
                                            uint16_t cols,
                                            int noRotation = false) {
// clang-format off
    #pragma HLS INLINE OFF
    // clang-format on

    CM_T cameraMatrixHLS[CM_SIZE];
    CM_T distCoeffsHLS[N];
    CM_T iRnewCameraMatrixHLS[CM_SIZE];
// clang-format off
    #pragma HLS ARRAY_PARTITION variable=cameraMatrixHLS complete dim=0
    #pragma HLS ARRAY_PARTITION variable=distCoeffsHLS complete dim=0
    #pragma HLS ARRAY_PARTITION variable=iRnewCameraMatrixHLS complete dim=0
    // clang-format on

    for (int i = 0; i < CM_SIZE; i++) {
// clang-format off
        #pragma HLS PIPELINE II=1
        // clang-format on
        cameraMatrixHLS[i] = cameraMatrix[i];
        iRnewCameraMatrixHLS[i] = ir[i];
    }
    for (int i = 0; i < N; i++) {
// clang-format off
        #pragma HLS PIPELINE II=1
        // clang-format on
        distCoeffsHLS[i] = distCoeffs[i];
    }

    MAP_type mx;
    MAP_type my;

#ifndef __SYNTHESIS__
    assert(rows <= ROWS);
    assert(cols <= COLS);
#endif

    int idx = 0;
loop_height:
    for (int i = 0; i < rows; i++) {
// clang-format off
        #pragma HLS LOOP_TRIPCOUNT min=1 max=ROWS
    // clang-format on
    loop_width:
        for (int j = 0; j < cols; j++) {
// clang-format off
            #pragma HLS LOOP_TRIPCOUNT min=1 max=COLS
            #pragma HLS PIPELINE II=1
            // clang-format on
            typedef ap_uint<BitWidth<ROWS>::Value> ROWT;
            typedef ap_uint<BitWidth<COLS>::Value> COLT;
            ROWT ifixed = i;
            COLT jfixed = j;

            ap_fixed<1 + BitWidth<COLS>::Value + _XF_INTER_BITS_, 1 + BitWidth<COLS>::Value, AP_RND, AP_SAT> u;
            ap_fixed<1 + BitWidth<ROWS>::Value + _XF_INTER_BITS_, 1 + BitWidth<ROWS>::Value, AP_RND, AP_SAT> v;
            xFComputeUndistortCoordinates<
                typename xfInitUndistortRectifyMap_traits<CM_T>::FRAMET,
                typename xfInitUndistortRectifyMap_traits<CM_T>::FRAME2T, ROWT, COLT,
                ap_fixed<1 + BitWidth<COLS>::Value + _XF_INTER_BITS_, 1 + BitWidth<COLS>::Value, AP_RND, AP_SAT>,
                ap_fixed<1 + BitWidth<ROWS>::Value + _XF_INTER_BITS_, 1 + BitWidth<ROWS>::Value, AP_RND, AP_SAT>, CM_T,
                CM_SIZE, N>(cameraMatrixHLS, distCoeffsHLS, iRnewCameraMatrixHLS, noRotation, ifixed, jfixed, u, v);

            float mx = (float)u;
            float my = (float)v;

            map1.write_float(idx, mx);
            map2.write_float(idx++, my);
        }
    }
}

template <int CM_SIZE, int DC_SIZE, int MAP_T, int ROWS, int COLS, int NPC>
void InitUndistortRectifyMapInverse(ap_fixed<32, 12>* cameraMatrix,
                                    ap_fixed<32, 12>* distCoeffs,
                                    ap_fixed<32, 12>* ir,
                                    xf::cv::Mat<MAP_T, ROWS, COLS, NPC>& _mapx_mat,
                                    xf::cv::Mat<MAP_T, ROWS, COLS, NPC>& _mapy_mat,
                                    int _cm_size,
                                    int _dc_size) {
// clang-format off
    #pragma HLS INLINE OFF
    // clang-format on

    xFInitUndistortRectifyMapInverseKernel<ROWS, COLS, CM_SIZE, ap_fixed<32, 12>, DC_SIZE, MAP_T, NPC,
                                           XF_TNAME(MAP_T, NPC)>(cameraMatrix, distCoeffs, ir, _mapx_mat, _mapy_mat,
                                                                 _mapx_mat.rows, _mapx_mat.cols);
}
} // namespace cv
} // namespace xf
#endif // _XF_STEREO_PIPELINE_HPP_