Program Listing for File xf_canny.hpp
↰ Return to documentation for file (/tmp/ws/src/vitis_common/include/imgproc/xf_canny.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_CANNY_HPP_
#define _XF_CANNY_HPP_
#ifndef __cplusplus
#error C++ is needed to use this file!
#endif
typedef unsigned short uint16_t;
typedef unsigned char uchar;
#include "hls_stream.h"
#include "../common/xf_common.hpp"
#include "../common/xf_utility.hpp"
#include "../core/xf_math.h"
//#include "xf_sobel.hpp"
#include "xf_canny_sobel.hpp"
#include "xf_averagegaussianmask.hpp"
#include "xf_magnitude.hpp"
#include "xf_canny_utils.hpp"
namespace xf {
namespace cv {
template <int IN_T, int ROWS, int COLS, int DEPTH, int NPC, int WORDWIDTH, int TC>
void xFDuplicate_rows(xf::cv::Mat<IN_T, ROWS, COLS, NPC>& _src_mat, // hls::stream< XF_SNAME(WORDWIDTH) > &_src_mat,
xf::cv::Mat<IN_T, ROWS, COLS, NPC>& _src_mat1,
xf::cv::Mat<IN_T, ROWS, COLS, NPC>& _dst1_mat,
xf::cv::Mat<IN_T, ROWS, COLS, NPC>& _dst2_mat,
xf::cv::Mat<IN_T, ROWS, COLS, NPC>& _dst1_out_mat,
xf::cv::Mat<IN_T, ROWS, COLS, NPC>& _dst2_out_mat,
uint16_t img_height,
uint16_t img_width) {
img_width = img_width >> XF_BITSHIFT(NPC);
ap_uint<13> row, col;
Row_Loop:
for (row = 0; row < img_height; row++) {
// clang-format off
#pragma HLS LOOP_TRIPCOUNT min=ROWS max=ROWS
#pragma HLS LOOP_FLATTEN off
// clang-format on
Col_Loop:
for (col = 0; col < img_width; col++) {
// clang-format off
#pragma HLS LOOP_TRIPCOUNT min=TC max=TC
#pragma HLS pipeline
// clang-format on
XF_SNAME(WORDWIDTH) tmp_src, tmp_src1;
tmp_src1 = _src_mat1.read(row * img_width + col);
tmp_src = _src_mat.read(row * img_width + col);
_dst1_mat.write(row * img_width + col, tmp_src);
_dst2_mat.write(row * img_width + col, tmp_src);
_dst1_out_mat.write(row * img_width + col, tmp_src1);
_dst2_out_mat.write(row * img_width + col, tmp_src1);
}
}
}
template <int SRC_T,
int DST_T,
int ROWS,
int COLS,
int DEPTH_SRC,
int DEPTH_DST,
int NPC,
int NPC1,
int WORDWIDTH_SRC,
int WORDWIDTH_DST>
void xFPackNMS(xf::cv::Mat<SRC_T, ROWS, COLS, NPC>& _src_mat, // hls::stream< XF_SNAME(WORDWIDTH_SRC) >& _src_mat,
xf::cv::Mat<DST_T, ROWS, COLS, NPC1>& _dst_mat, // hls::stream< XF_SNAME(WORDWIDTH_DST)>& _dst_mat,
uint16_t imgheight,
uint16_t imgwidth) {
int npcCols = imgwidth;
int divNum = (int)(imgwidth / 32);
int npcColsNxt = (divNum + 1) * 32;
if (imgwidth % 32 != 0) {
npcCols = npcColsNxt;
}
const int num_clks_32pix = 32 / NPC;
int col_loop_count_ac = (imgwidth / NPC);
int col_loop_count = (npcCols / NPC);
// printf("col_loop_count:%d %d \n",col_loop_count_ac,col_loop_count);
ap_uint<64> val;
int read_ind = 0, write_ind = 0;
rowLoop:
for (int i = 0; i < (imgheight); i++) {
// clang-format off
#pragma HLS LOOP_TRIPCOUNT min=ROWS max=ROWS
#pragma HLS LOOP_FLATTEN off
// clang-format on
colLoop:
for (int j = 0; j < col_loop_count; j = j + (num_clks_32pix)) {
// clang-format off
#pragma HLS LOOP_TRIPCOUNT min=COLS/32 max=COLS/32
#pragma HLS pipeline
// clang-format on
for (int k = 0; k < num_clks_32pix; k++) {
// clang-format off
#pragma HLS UNROLL
// clang-format on
if ((j + k) >= col_loop_count_ac) {
val.range(k * 2 * NPC + (NPC * 2 - 1), k * 2 * NPC) = 0; //_src_mat.read(read_ind++);
} else {
val.range(k * 2 * NPC + (NPC * 2 - 1), k * 2 * NPC) = _src_mat.read(read_ind++);
}
}
_dst_mat.write(write_ind++, val);
}
}
}
// xFDuplicate_rows
template <int SRC_T,
int DST_T,
int NORM_TYPE,
int ROWS,
int COLS,
int DEPTH_IN,
int DEPTH_OUT,
int NPC,
int NPC1,
int WORDWIDTH_SRC,
int WORDWIDTH_DST,
int TC,
int TC1,
int TC2,
int FILTER_TYPE,
bool USE_URAM>
void xFCannyKernel(xf::cv::Mat<SRC_T, ROWS, COLS, NPC>& _src_mat,
xf::cv::Mat<DST_T, ROWS, COLS, NPC1>& _dst_mat,
unsigned char _lowthreshold,
unsigned char _highthreshold,
uint16_t img_height,
uint16_t img_width) {
// clang-format off
#pragma HLS INLINE OFF
// clang-format on
// clang-format off
#pragma HLS DATAFLOW
// clang-format on
if (NPC == 8) {
xf::cv::Mat<XF_8UC1, ROWS, COLS, NPC> gaussian_mat(img_height, img_width);
xf::cv::Mat<XF_16SC1, ROWS, COLS, NPC> gradx_mat(img_height, img_width);
xf::cv::Mat<XF_16SC1, ROWS, COLS, NPC> gradx1_mat(img_height, img_width);
xf::cv::Mat<XF_16SC1, ROWS, COLS, NPC> gradx2_mat(img_height, img_width);
xf::cv::Mat<XF_16SC1, ROWS, COLS, NPC> grady_mat(img_height, img_width);
xf::cv::Mat<XF_16SC1, ROWS, COLS, NPC> grady1_mat(img_height, img_width);
xf::cv::Mat<XF_16SC1, ROWS, COLS, NPC> grady2_mat(img_height, img_width);
xf::cv::Mat<XF_16SC1, ROWS, COLS, NPC, TC1> magnitude_mat(img_height, img_width);
xf::cv::Mat<XF_8UC1, ROWS, COLS, NPC, TC2> phase_mat(img_height, img_width);
xf::cv::Mat<XF_2UC1, ROWS, COLS, NPC> nms_mat(img_height, img_width);
xFAverageGaussianMask3x3<SRC_T, SRC_T, ROWS, COLS, DEPTH_IN, NPC, WORDWIDTH_SRC, (COLS >> XF_BITSHIFT(NPC))>(
_src_mat, gaussian_mat, img_height, img_width);
xFSobel<SRC_T, XF_16SC1, ROWS, COLS, DEPTH_IN, XF_16SP, NPC, WORDWIDTH_SRC, XF_128UW, FILTER_TYPE, USE_URAM>(
gaussian_mat, gradx_mat, grady_mat, XF_BORDER_REPLICATE, img_height, img_width);
xFDuplicate_rows<XF_16SC1, ROWS, COLS, XF_16SP, NPC, XF_128UW, TC>(
gradx_mat, grady_mat, gradx1_mat, gradx2_mat, grady1_mat, grady2_mat, img_height, img_width);
magnitude<NORM_TYPE, XF_16SC1, XF_16SC1, ROWS, COLS, NPC, TC1>(gradx1_mat, grady1_mat, magnitude_mat);
xFAngle<XF_16SC1, XF_8UC1, ROWS, COLS, XF_16SP, XF_8UP, NPC, XF_128UW, XF_64UW, TC2>(
gradx2_mat, grady2_mat, phase_mat, img_height, img_width);
xFSuppression3x3<XF_16SC1, XF_8UC1, XF_2UC1, ROWS, COLS, XF_16SP, XF_8UP, DEPTH_OUT, NPC, XF_128UW, XF_64UW,
XF_16UW, (COLS >> XF_BITSHIFT(NPC)), TC2, TC1>(
magnitude_mat, phase_mat, nms_mat, _lowthreshold, _highthreshold, img_height, img_width);
xFPackNMS<XF_2UC1, DST_T, ROWS, COLS, XF_2UP, DEPTH_OUT, NPC, NPC1, XF_16UW, WORDWIDTH_DST>(
nms_mat, _dst_mat, img_height, img_width);
}
if (NPC == 1) {
xf::cv::Mat<XF_8UC1, ROWS, COLS, NPC> gaussian_mat(img_height, img_width);
xf::cv::Mat<XF_16SC1, ROWS, COLS, NPC> gradx_mat(img_height, img_width);
xf::cv::Mat<XF_16SC1, ROWS, COLS, NPC> gradx1_mat(img_height, img_width);
xf::cv::Mat<XF_16SC1, ROWS, COLS, NPC> gradx2_mat(img_height, img_width);
xf::cv::Mat<XF_16SC1, ROWS, COLS, NPC> grady_mat(img_height, img_width);
xf::cv::Mat<XF_16SC1, ROWS, COLS, NPC> grady1_mat(img_height, img_width);
xf::cv::Mat<XF_16SC1, ROWS, COLS, NPC> grady2_mat(img_height, img_width);
xf::cv::Mat<XF_16SC1, ROWS, COLS, NPC, TC1> magnitude_mat(img_height, img_width);
xf::cv::Mat<XF_8UC1, ROWS, COLS, NPC, TC2> phase_mat(img_height, img_width);
xf::cv::Mat<XF_2UC1, ROWS, COLS, NPC> nms_mat(img_height, img_width);
xFAverageGaussianMask3x3<SRC_T, SRC_T, ROWS, COLS, DEPTH_IN, NPC, WORDWIDTH_SRC, (COLS >> XF_BITSHIFT(NPC))>(
_src_mat, gaussian_mat, img_height, img_width);
xFSobel<SRC_T, XF_16SC1, ROWS, COLS, DEPTH_IN, XF_16SP, NPC, WORDWIDTH_SRC, XF_16UW, FILTER_TYPE, USE_URAM>(
gaussian_mat, gradx_mat, grady_mat, XF_BORDER_REPLICATE, img_height, img_width);
xFDuplicate_rows<XF_16SC1, ROWS, COLS, XF_16SP, NPC, XF_16UW, TC>(
gradx_mat, grady_mat, gradx1_mat, gradx2_mat, grady1_mat, grady2_mat, img_height, img_width);
magnitude<NORM_TYPE, XF_16SC1, XF_16SC1, ROWS, COLS, NPC, TC1>(gradx1_mat, grady1_mat, magnitude_mat);
xFAngle<XF_16SC1, XF_8UC1, ROWS, COLS, XF_16SP, XF_8UP, NPC, XF_16UW, XF_8UW, TC2>(
gradx2_mat, grady2_mat, phase_mat, img_height, img_width);
xFSuppression3x3<XF_16SC1, XF_8UC1, XF_2UC1, ROWS, COLS, XF_16SP, XF_8UP, XF_2UP, NPC, XF_16UW, XF_8UW, XF_2UW,
(COLS >> XF_BITSHIFT(NPC)), TC2, TC1>(magnitude_mat, phase_mat, nms_mat, _lowthreshold,
_highthreshold, img_height, img_width);
xFPackNMS<XF_2UC1, DST_T, ROWS, COLS, XF_2UP, DEPTH_OUT, NPC, NPC1, XF_2UW, WORDWIDTH_DST>(
nms_mat, _dst_mat, img_height, img_width);
}
}
/**********************************************************************
* xFCanny : Calls the Main Function depends on requirements
**********************************************************************/
template <int ROWS,
int COLS,
int DEPTH_IN,
int DEPTH_OUT,
int NPC,
int WORDWIDTH_SRC,
int WORDWIDTH_DST,
int FILTER_TYPE,
bool USE_URAM>
void xFCannyEdgeDetector(hls::stream<XF_SNAME(WORDWIDTH_SRC)>& _src_mat,
hls::stream<XF_SNAME(WORDWIDTH_DST)>& out_strm,
unsigned char _lowthreshold,
unsigned char _highthreshold,
int _norm_type,
uint16_t imgheight,
uint16_t imgwidth) {
#ifndef __SYNTHESIS__
assert(((_norm_type == XF_L1NORM) || (_norm_type == XF_L2NORM)) &&
"The _norm_type must be 'XF_L1NORM' or'XF_L2NORM'");
#endif
xFCannyKernel<ROWS, COLS, DEPTH_IN, DEPTH_OUT, NPC, WORDWIDTH_SRC, WORDWIDTH_DST, (COLS >> XF_BITSHIFT(NPC)),
((COLS >> XF_BITSHIFT(NPC)) * 3), FILTER_TYPE, USE_URAM>(
_src_mat, out_strm, _lowthreshold, _highthreshold, _norm_type, imgheight, imgwidth);
}
template <int FILTER_TYPE,
int NORM_TYPE,
int SRC_T,
int DST_T,
int ROWS,
int COLS,
int NPC,
int NPC1,
bool USE_URAM = false>
void Canny(xf::cv::Mat<SRC_T, ROWS, COLS, NPC>& _src_mat,
xf::cv::Mat<DST_T, ROWS, COLS, NPC1>& _dst_mat,
unsigned char _lowthreshold,
unsigned char _highthreshold) {
// clang-format off
#pragma HLS INLINE OFF
// clang-format on
#ifndef __SYNTHESIS__
assert(((NORM_TYPE == XF_L1NORM) || (NORM_TYPE == XF_L2NORM)) &&
"The _norm_type must be 'XF_L1NORM' or'XF_L2NORM'");
#endif
if (NORM_TYPE == 1) {
xFCannyKernel<SRC_T, DST_T, NORM_TYPE, ROWS, COLS, XF_DEPTH(SRC_T, NPC), XF_DEPTH(DST_T, NPC1), NPC, NPC1,
XF_WORDWIDTH(SRC_T, NPC), XF_WORDWIDTH(DST_T, NPC1), (COLS >> XF_BITSHIFT(NPC)), 2,
((COLS >> XF_BITSHIFT(NPC)) * 3), FILTER_TYPE, USE_URAM>(
_src_mat, _dst_mat, _lowthreshold, _highthreshold, _src_mat.rows, _src_mat.cols);
} else {
xFCannyKernel<SRC_T, DST_T, NORM_TYPE, ROWS, COLS, XF_DEPTH(SRC_T, NPC), XF_DEPTH(DST_T, NPC1), NPC, NPC1,
XF_WORDWIDTH(SRC_T, NPC), XF_WORDWIDTH(DST_T, NPC1), (COLS >> XF_BITSHIFT(NPC)), 2,
((COLS >> XF_BITSHIFT(NPC)) * 3), FILTER_TYPE, USE_URAM>(
_src_mat, _dst_mat, _lowthreshold, _highthreshold, _src_mat.rows, _src_mat.cols);
}
}
} // namespace cv
} // namespace xf
#endif