Program Listing for File xf_cca_custom.hpp

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

/*
 * Copyright 2020 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_CCA_CUSTOM_HPP__
#define __XF_CCA_CUSTOM_HPP__

#include "ap_int.h"
#include "../common/xf_common.hpp"
#include "../common/xf_utility.hpp"

namespace xf {
namespace cv {

template <int WIDTH>
void process_row(uint8_t* in_ptr, uint8_t* tmp_out_ptr, bool* lab_arr, int& obj_pix, int width) {
// clang-format off
#pragma HLS INLINE
    // clang-format on

    bool a, b, c, d;
    a = 1;
    b = lab_arr[0];
    c = lab_arr[1];
    d = 1;

PROC_ROW_LOOP:
    for (int j = 0; j < width; j++) {
// clang-format off
#pragma HLS LOOP_TRIPCOUNT min=1 max=WIDTH
#pragma HLS PIPELINE II=1
        // clang-format on
        bool lab;
        unsigned char out;

        if (in_ptr[j] != 0) {
            if ((a || b || c || d) == 1) {
                lab = 1;
                out = 0;
            } else {
                lab = 0;
                out = 255;
            }
        } else {
            lab = 0;
            out = 0;
            obj_pix++;
        }

        lab_arr[j] = lab;
        tmp_out_ptr[j] = out;
        a = b;
        b = c;
        c = lab_arr[j + 2];
        d = lab;
    }
}

template <int HEIGHT, int WIDTH>
void fw_cca(uint8_t* in_ptr, uint8_t* tmp_out_ptr, int& obj_pix, int height, int width) {
// clang-format off
#pragma HLS INLINE OFF
    // clang-format on

    obj_pix = 0;
    int offset = 0;
    bool lab_arr[WIDTH + 2];
    for (int i = 0; i < width + 2; i++) {
// clang-format off
#pragma HLS LOOP_TRIPCOUNT min=1 max=WIDTH
#pragma HLS PIPELINE II=1
        // clang-format on
        lab_arr[i] = 1;
    }

    for (int i = 0; i < height; i++) {
// clang-format off
#pragma HLS LOOP_TRIPCOUNT min=1 max=HEIGHT
        // clang-format on
        process_row<WIDTH>(in_ptr + offset, tmp_out_ptr + offset, lab_arr, obj_pix, width);
        offset += width;
    }
}

template <int WIDTH>
void read_row_to_ram(uint8_t* _fw_pass, uint8_t* ram, int width) {
// clang-format off
#pragma HLS INLINE OFF
    // clang-format on

    for (int j = 0; j < width; j++) {
// clang-format off
#pragma HLS LOOP_TRIPCOUNT min=1 max=WIDTH
#pragma HLS PIPELINE II=1
        // clang-format on
        ram[j] = _fw_pass[j];
    }
}

template <int WIDTH>
void write_row_to_mem(uint8_t* ram, uint8_t* _dst, int width) {
// clang-format off
#pragma HLS INLINE OFF
    // clang-format on

    for (int j = 0; j < width; j++) {
// clang-format off
#pragma HLS LOOP_TRIPCOUNT min=1 max=WIDTH
#pragma HLS PIPELINE II=1
        // clang-format on
        _dst[j] = ram[j];
    }
}

template <int HEIGHT, int WIDTH>
void rev_cca(uint8_t* in_ptr, uint8_t* tmp_out_ptr, int height, int width) {
// clang-format off
#pragma HLS INLINE OFF
    // clang-format on

    bool lab_arr[WIDTH + 2], flag = 0;
    int obj_pix;

    for (int i = 0; i < width + 2; i++) {
// clang-format off
#pragma HLS LOOP_TRIPCOUNT min=1 max=WIDTH
#pragma HLS PIPELINE II=1
        // clang-format on
        lab_arr[i] = 1;
    }

    uint8_t rd_linebuff1[WIDTH], rd_linebuff2[WIDTH];
    uint8_t wrt_linebuff1[WIDTH], wrt_linebuff2[WIDTH];

    int rd_offset = (height * width);
    int wrt_offset = (height * width);

    rd_offset -= width;
    read_row_to_ram<WIDTH>(in_ptr + rd_offset, rd_linebuff1, width);

    rd_offset -= width;
    read_row_to_ram<WIDTH>(in_ptr + rd_offset, rd_linebuff2, width);
    process_row<WIDTH>(rd_linebuff1, wrt_linebuff1, lab_arr, obj_pix, width);

REV_ROW_LOOP:
    for (int i = 0; i < height - 2; i++) {
// clang-format off
#pragma HLS LOOP_TRIPCOUNT min=1 max=HEIGHT
        // clang-format on
        rd_offset -= width;
        wrt_offset -= width;

        if (flag == 0) {
            read_row_to_ram<WIDTH>(in_ptr + rd_offset, rd_linebuff1, width);
            process_row<WIDTH>(rd_linebuff2, wrt_linebuff2, lab_arr, obj_pix, width);
            write_row_to_mem<WIDTH>(wrt_linebuff1, tmp_out_ptr + wrt_offset, width);
            flag = 1;
        } else {
            read_row_to_ram<WIDTH>(in_ptr + rd_offset, rd_linebuff2, width);
            process_row<WIDTH>(rd_linebuff1, wrt_linebuff1, lab_arr, obj_pix, width);
            write_row_to_mem<WIDTH>(wrt_linebuff2, tmp_out_ptr + wrt_offset, width);
            flag = 0;
        }
    }

    wrt_offset -= width;

    if (flag == 0) {
        process_row<WIDTH>(rd_linebuff2, wrt_linebuff2, lab_arr, obj_pix, width);
        write_row_to_mem<WIDTH>(wrt_linebuff1, tmp_out_ptr + wrt_offset, width);
        flag = 1;
    } else {
        process_row<WIDTH>(rd_linebuff1, wrt_linebuff1, lab_arr, obj_pix, width);
        write_row_to_mem<WIDTH>(wrt_linebuff2, tmp_out_ptr + wrt_offset, width);
        flag = 0;
    }

    wrt_offset -= width;

    if (flag == 0)
        write_row_to_mem<WIDTH>(wrt_linebuff1, tmp_out_ptr + wrt_offset, width);
    else
        write_row_to_mem<WIDTH>(wrt_linebuff2, tmp_out_ptr + wrt_offset, width);
}

template <int HEIGHT, int WIDTH>
void pass_1(uint8_t* in_ptr1,
            uint8_t* in_ptr2,
            uint8_t* tmp_out_ptr1,
            uint8_t* tmp_out_ptr2,
            int& obj_pix,
            int height,
            int width) {
// clang-format off
#pragma HLS INLINE OFF
// clang-format on

    fw_cca<HEIGHT,WIDTH>(in_ptr1,tmp_out_ptr1,obj_pix,height,width);
    rev_cca<HEIGHT,WIDTH>(in_ptr2,tmp_out_ptr2,height,width);
}

template <int HEIGHT, int WIDTH>
void pass_2 (uint8_t* tmp_out_ptr1, uint8_t* tmp_out_ptr2, uint8_t* out_ptr, int& def_pix, int height, int width) {
// clang-format off
#pragma HLS INLINE OFF
    // clang-format on

    int idx = 0;
    def_pix = 0;
    for (int i = 0; i < height; i++) {
// clang-format off
#pragma HLS LOOP_TRIPCOUNT min=1 max=HEIGHT
#pragma HLS LOOP_FLATTEN
        // clang-format on
        for (int j = 0; j < width; j++) {
// clang-format off
#pragma HLS LOOP_TRIPCOUNT min=1 max=WIDTH
#pragma HLS PIPELINE II=1
            // clang-format on
            uint8_t tmp = tmp_out_ptr1[idx] & tmp_out_ptr2[idx];
            out_ptr[idx++] = tmp;
            if (tmp != 0) def_pix++;
        }
    }
}

template <int HEIGHT, int WIDTH>
void ccaCustom(uint8_t* in_ptr1,      // input image pointer for forward pass
               uint8_t* in_ptr2,      // input image pinter for the parallel
                                      // computation of reverse pass
               uint8_t* tmp_out_ptr1, // pointer to store and read from the
                                      // temporary buffer in DDR for the forward
                                      // pass
               uint8_t* tmp_out_ptr2, // pointer to store and read from the
                                      // temporary buffer in DDR for the reverse
                                      // pass
               uint8_t* out_ptr,      // output defects image
               int& obj_pix,          // output - object pixels without defects
               int& def_pix,          // output - defect pixels
               int height,
               int width) {
// clang-format off
#pragma HLS INLINE OFF
    // clang-format on

    for (int i = 0; i < 2; i++) {
        if (i == 0)
            pass_1<HEIGHT, WIDTH>(in_ptr1, in_ptr2, tmp_out_ptr1, tmp_out_ptr2, obj_pix, height, width);
        else
            pass_2<HEIGHT, WIDTH>(tmp_out_ptr1, tmp_out_ptr2, out_ptr, def_pix, height, width);
    }

    return;
}
// ======================================================================================

} // end of cv
} // end of xf

#endif // end of __XF_CCA_CUSTOM_HPP__