Program Listing for File xf_otsuthreshold.hpp
↰ Return to documentation for file (/tmp/ws/src/vitis_common/include/imgproc/xf_otsuthreshold.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_OTSUTHRESHOLD_HPP_
#define _XF_OTSUTHRESHOLD_HPP_
#include "../common/xf_types.hpp"
#include "../core/xf_math.h"
#include "xf_histogram.hpp"
namespace xf {
namespace cv {
static void xfOtsuKernel(uint32_t _hist[0][256], uint16_t _height, uint16_t _width, uint8_t& thresh) {
// clang-format off
#pragma HLS INLINE off
// clang-format on
ap_uint<33> HistArray[256] = {0};
ap_uint<45> tmp1, tmp2;
ap_uint<25> total;
uint8_t max_val = 0;
unsigned int sum = 0;
unsigned short int cols = _width;
unsigned short int rows = _height;
char shift1 = 0, shift2 = 0;
char shift3, shift4;
unsigned int wB = 0;
unsigned int wF = 0;
unsigned long long int sumB = 0;
unsigned long long int varMax = 0;
unsigned int wdt = xf::cv::Inverse(cols, 16, &shift1); // Q0.24
unsigned int hgt = xf::cv::Inverse(rows, 16, &shift2); // Q0.24
char n1, n2;
if (shift1 > 24) {
wdt = wdt >> (shift1 - 24);
shift1 = 24;
} else if (((shift1 >> 1) << 1) != shift1) {
wdt = wdt << (24 - shift1);
shift1 = 24;
}
if (shift2 > 24) {
hgt = hgt >> (shift2 - 24);
shift2 = 24;
} else if (((shift2 >> 1) << 1) != shift2) {
hgt = hgt << (24 - shift2);
shift2 = 24;
}
shift3 = shift1 >> 1;
shift4 = shift2 >> 1;
tmp1 = (cols * wdt) >> shift3; // Q0.12
tmp2 = (rows * hgt) >> shift4; // Q0.12
total = tmp1 * tmp2; // Q0.25
HISTOGRAM_NORM_LOOP:
for (uint16_t i = 0; i < 256; i++) {
// clang-format off
#pragma HLS PIPELINE
// clang-format on
tmp1 = (ap_uint<45>)_hist[0][i];
tmp2 = (tmp1 * wdt) >> shift3;
HistArray[i] = (tmp2 * hgt) >> shift4; // Histogram array is expressed in Q8.25
}
SUM_LOOP:
for (uint16_t i = 0; i < 256; i++) {
// clang-format off
#pragma HLS PIPELINE
// clang-format on
sum = sum + i * HistArray[i]; // sum is expressed in Q8.24
}
THRESHOLD_LOOP:
for (uint16_t i = 0; i < 256; i++) {
// clang-format off
#pragma HLS LOOP_TRIPCOUNT min=256 max=256
#pragma HLS PIPELINE
// clang-format on
wB = wB + HistArray[i]; // wB is expressed in Q0.25
if (wB > 0) {
if ((wB >> (shift3 + shift4)) == 1) break;
wF = total - wB; // wF is expressed in Q0.25
sumB = sumB + HistArray[i] * i; // sumB is expressed in Q8.24
unsigned int b = (wF + wB); // b is expressed in Q0.25
long long int a1 = (sumB * b) >> (shift3 + shift4); // a1 is expressed in Q8.25
long long int c1 = ((long long int)sum * wB) >> (shift3 + shift4); // c1 is expressed in Q8.25
long long int d = a1 - c1;
d = __ABS(d);
unsigned int res = (d * d) >> (shift3 + shift4 + 10); // res is expressed in Q16.16
unsigned short int x_inv1 = (unsigned short int)(wB >> 9);
unsigned short int x_inv2 = (unsigned short int)(wF >> 9);
unsigned int val1 = xf::cv::Inverse(x_inv1, 0, &n1);
unsigned int val2 = xf::cv::Inverse(x_inv2, 0, &n2);
unsigned long long int maxtmp =
(unsigned long long int)((unsigned long long int)res * (unsigned long long int)val1) >> n1;
unsigned long long max = (maxtmp * (unsigned long long)val2) >> n2;
if (max > varMax) {
varMax = max;
max_val = i;
}
}
}
thresh = max_val;
}
/*********************************************************************
* Otsuthreshold : Computes the otsu threshold for the input image
*********************************************************************/
template <int SRC_T, int ROWS, int COLS, int NPC = 1>
void OtsuThreshold(xf::cv::Mat<SRC_T, ROWS, COLS, NPC>& _src_mat, uint8_t& _thresh) {
#ifndef __SYNTHESIS__
assert(((NPC == XF_NPPC1) || (NPC == XF_NPPC8)) && "NPC must be XF_NPPC1, XF_NPPC8 ");
assert(((_src_mat.rows <= ROWS) && (_src_mat.cols <= COLS)) && "ROWS and COLS should be greater than input image");
#endif
uint32_t hist[XF_CHANNELS(SRC_T, NPC)][256];
uint8_t thresh;
// clang-format off
#pragma HLS INLINE off
#pragma HLS interface ap_fifo port=hist
// clang-format on
uint16_t width = _src_mat.cols >> (XF_BITSHIFT(NPC));
uint16_t height = _src_mat.rows;
xFHistogramKernel<SRC_T, ROWS, COLS, XF_DEPTH(SRC_T, NPC), NPC, XF_WORDWIDTH(SRC_T, NPC),
((COLS >> (XF_BITSHIFT(NPC))) >> 1), XF_CHANNELS(SRC_T, NPC)>(_src_mat, hist, height, width);
xfOtsuKernel(hist, height, _src_mat.cols, thresh);
_thresh = thresh;
}
} // namespace cv
} // namespace xf
#endif //