.. _program_listing_file__tmp_ws_src_vitis_common_include_imgproc_xf_autowhitebalance.hpp: Program Listing for File xf_autowhitebalance.hpp ================================================ |exhale_lsh| :ref:`Return to documentation for file ` (``/tmp/ws/src/vitis_common/include/imgproc/xf_autowhitebalance.hpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp /* * 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_AWB_HPP_ #define _XF_AWB_HPP_ #include "../common/xf_common.hpp" #include "hls_stream.h" #ifndef XF_IN_STEP #define XF_IN_STEP 8 #endif #ifndef XF_OUT_STEP #define XF_OUT_STEP 8 #endif #define MAX(x, y) (((x) > (y)) ? (x) : (y)) #define MIN(x, y) (((x) < (y)) ? (x) : (y)) template T xf_satcast_awb(int in_val){}; template <> inline ap_uint<8> xf_satcast_awb >(int v) { return (v > 255 ? 255 : v); }; template <> inline ap_uint<10> xf_satcast_awb >(int v) { return (v > 1023 ? 1023 : v); }; template <> inline ap_uint<12> xf_satcast_awb >(int v) { return (v > 4095 ? 4095 : v); }; template <> inline ap_uint<16> xf_satcast_awb >(int v) { return (v > 65535 ? 65535 : v); }; namespace xf { namespace cv { template void AWBGainUpdateKernel(xf::cv::Mat& src1, xf::cv::Mat& dst, float thresh, int i_gain[3]) { int width = src1.cols >> XF_BITSHIFT(NPC); int height = src1.rows; printf("%d %d %d\n", i_gain[0], i_gain[1], i_gain[2]); const int STEP = XF_DTPIXELDEPTH(SRC_T, NPC); XF_TNAME(SRC_T, NPC) in_pix, out_pix; for (int i = 0; i < height; i++) { // clang-format off #pragma HLS LOOP_TRIPCOUNT min=ROWS max=ROWS #pragma HLS LOOP_FLATTEN OFF // clang-format on ColLoop1: for (int j = 0; j < width; j++) { // clang-format off #pragma HLS LOOP_TRIPCOUNT min=TC max=TC #pragma HLS pipeline // clang-format on in_pix = src1.read(i * width + j); for (int p = 0; p < XF_NPIXPERCYCLE(NPC) * PLANES; p++) { // clang-format off #pragma HLS unroll // clang-format on XF_CTUNAME(SRC_T, NPC) val = in_pix.range(p * STEP + STEP - 1, p * STEP); ap_uint<40> outval = ((val * i_gain[p % 3]) >> STEP); out_pix.range(p * STEP + STEP - 1, p * STEP) = xf_satcast_awb(outval); } dst.write(i * width + j, out_pix); } } } template void AWBChannelGainKernel(xf::cv::Mat& src1, xf::cv::Mat& dst, float thresh, int i_gain[3]) { int width = src1.cols >> XF_BITSHIFT(NPC); int height = src1.rows; const int STEP = XF_DTPIXELDEPTH(SRC_T, NPC); ap_uint<13> i = 0, j = 0; XF_TNAME(SRC_T, NPC) in_pix, out_pix; XF_CTUNAME(SRC_T, NPC) r, g, b, b1 = 0, g1 = 0, r1 = 0; XF_SNAME(WORDWIDTH_DST) pxl_pack_out; XF_SNAME(WORDWIDTH_SRC) pxl_pack1, pxl_pack2; int maxval = (1 << (XF_DTPIXELDEPTH(SRC_T, NPC))) - 1; // 65535.0f; ap_ufixed<32, 32> thresh255 = ap_ufixed<32, 32>(thresh * maxval); int minRGB, maxRGB; ap_ufixed<40, 40> tmpsum_vals[(1 << XF_BITSHIFT(NPC)) * PLANES]; ap_ufixed<40, 40> sum[PLANES]; // clang-format off #pragma HLS ARRAY_PARTITION variable=tmpsum_vals complete dim=0 #pragma HLS ARRAY_PARTITION variable=sum complete dim=0 // clang-format on for (j = 0; j < ((1 << XF_BITSHIFT(NPC)) * PLANES); j++) { // clang-format off #pragma HLS UNROLL // clang-format on tmpsum_vals[j] = 0; } for (j = 0; j < PLANES; j++) { // clang-format off #pragma HLS UNROLL // clang-format on sum[j] = 0; } int p = 0, read_index = 0; Row_Loop: for (i = 0; i < height; i++) { // clang-format off #pragma HLS LOOP_TRIPCOUNT min=ROWS max=ROWS // clang-format on Col_Loop: for (j = 0; j < (width); j++) { // clang-format off #pragma HLS LOOP_TRIPCOUNT min=COLS/NPC max=COLS/NPC #pragma HLS pipeline II=1 #pragma HLS LOOP_FLATTEN OFF // clang-format on XF_TNAME(SRC_T, NPC) in_buf; in_buf = src1.read(i * width + j); dst.write(i * width + j, in_buf); PLANES_LOOP: for (int p = 0; p < XF_NPIXPERCYCLE(NPC) * PLANES; p = p + PLANES) { // clang-format off #pragma HLS unroll // clang-format on XF_CTUNAME(SRC_T, NPC) val1 = in_buf.range(p * STEP + STEP - 1, p * STEP); XF_CTUNAME(SRC_T, NPC) val2 = in_buf.range(p * STEP + (2 * STEP) - 1, p * STEP + STEP); XF_CTUNAME(SRC_T, NPC) val3 = in_buf.range(p * STEP + (3 * STEP) - 1, p * STEP + 2 * STEP); minRGB = MIN(val1, MIN(val2, val3)); maxRGB = MAX(val1, MAX(val2, val3)); if ((maxRGB - minRGB) * maxval > thresh255 * maxRGB) continue; tmpsum_vals[p] = tmpsum_vals[p] + val1; tmpsum_vals[(p) + 1] = tmpsum_vals[(p) + 1] + val2; tmpsum_vals[(p) + 2] = tmpsum_vals[(p) + 2] + val3; } } } for (int c = 0; c < PLANES; c++) { for (j = 0; j < (1 << XF_BITSHIFT(NPC)); j++) { // clang-format off #pragma HLS UNROLL // clang-format on sum[c] = (sum[c] + tmpsum_vals[j * PLANES + c]); } } ap_ufixed<40, 40> max_sum_fixed = MAX(sum[0], MAX(sum[1], sum[2])); printf("%ld %ld %ld\n", (unsigned long)sum[0], (unsigned long)sum[1], (unsigned long)sum[2]); ap_ufixed<40, 2> bval = (float)0.1; ap_ufixed<40, 40> zero = 0; ap_ufixed<56, STEP> dinB1; ap_ufixed<56, STEP> dinG1; ap_ufixed<56, STEP> dinR1; if (sum[0] < bval) { dinB1 = 0; } else { dinB1 = (ap_ufixed<56, STEP>)((ap_ufixed<56, STEP>)max_sum_fixed / sum[0]); } if (sum[1] < bval) { dinG1 = 0; } else { dinG1 = (ap_ufixed<56, STEP>)((ap_ufixed<56, STEP>)max_sum_fixed / sum[1]); } if (sum[2] < bval) { dinR1 = 0; } else { dinR1 = (ap_ufixed<56, STEP>)((ap_ufixed<56, STEP>)max_sum_fixed / sum[2]); } ap_ufixed<56, STEP> gain_max1 = MAX(dinB1, MAX(dinG1, dinR1)); if (gain_max1 > 0) { dinB1 /= gain_max1; dinG1 /= gain_max1; dinR1 /= gain_max1; } float a1 = dinB1; float a2 = dinG1; float a3 = dinR1; printf("division values : %f %f %f\n", a1, a2, a3); // int i_gain[3] = {0, 0, 0}; i_gain[0] = (dinB1 * (1 << STEP)); i_gain[1] = (dinG1 * (1 << STEP)); i_gain[2] = (dinR1 * (1 << STEP)); } template void AWBNormalizationkernel(xf::cv::Mat& src, xf::cv::Mat& dst, uint32_t hist[3][HIST_SIZE], float p, float inputMin, float inputMax, float outputMin, float outputMax) { // clang-format off #pragma HLS INLINE OFF // clang-format on short width = dst.cols >> XF_BITSHIFT(NPC); short height = dst.rows; const int STEP = XF_DTPIXELDEPTH(SRC_T, NPC); ap_uint bins = HIST_SIZE; // number of bins at each histogram level ap_uint nElements = HIST_SIZE; // int(pow((float)bins, (float)depth)); int total = dst.cols * dst.rows; ap_fixed min_vals = inputMin - 0.5f; ap_fixed max_vals = inputMax + 0.5f; ap_fixed minValue[3] = {min_vals, min_vals, min_vals}; //{-0.5, -0.5, -0.5}; ap_fixed maxValue[3] = {max_vals, max_vals, max_vals}; //{12287.5, 16383.5, 12287.5}; ap_fixed s1 = p; ap_fixed s2 = p; int rval = s1 * total / 100; int rval1 = (100 - s2) * total / 100; // fprintf(stderr,"after normalization step 1"); // clang-format off #pragma HLS ARRAY_PARTITION variable = minValue complete dim = 0 #pragma HLS ARRAY_PARTITION variable = maxValue complete dim = 0 // clang-format on for (int j = 0; j < 3; ++j) // searching for s1 and s2 { ap_uint p1 = 0; ap_uint p2 = bins - 1; ap_uint<32> n1 = 0; ap_uint<32> n2 = total; ap_fixed interval = (max_vals - min_vals) / bins; for (int k = 0; k < 1; ++k) // searching for s1 and s2 { int value = hist[j][p1]; int value1 = hist[j][p2]; while (n1 + hist[j][p1] < rval && p1 < HIST_SIZE) { #pragma HLS PIPELINE #pragma HLS LOOP_TRIPCOUNT min = 255 max = 255 #pragma HLS DEPENDENCE variable = hist array intra false #pragma HLS DEPENDENCE variable = minValue intra false n1 += hist[j][p1++]; minValue[j] += interval; } // p1 *= bins; while (n2 - hist[j][p2] > rval1 && p2 != 0) { #pragma HLS PIPELINE #pragma HLS LOOP_TRIPCOUNT min = 255 max = 255 #pragma HLS DEPENDENCE variable = hist array intra false #pragma HLS DEPENDENCE variable = maxValue intra false n2 -= hist[j][p2--]; maxValue[j] -= interval; } // p2 = (p2 + 1) * bins - 1; // interval /= bins; } } // fprintf(stderr,"after normalization step 2"); ap_fixed maxmin_diff[3]; // clang-format off #pragma HLS ARRAY_PARTITION variable = maxmin_diff complete dim = 0 // clang-format on ap_fixed newmax = inputMax; ap_fixed newmin = 0.0f; maxmin_diff[0] = maxValue[0] - minValue[0]; maxmin_diff[1] = maxValue[1] - minValue[1]; maxmin_diff[2] = maxValue[2] - minValue[2]; ap_fixed newdiff = newmax - newmin; XF_TNAME(SRC_T, NPC) in_buf_n, in_buf_n1, out_buf_n; printf("valuesmin max :%f %f %f %f %f %f\n", (float)maxValue[0], (float)maxValue[1], (float)maxValue[2], (float)minValue[0], (float)minValue[1], (float)minValue[2]); int pval = 0, read_index = 0, write_index = 0; ap_uint<13> row, col; ap_fixed inv_val[3]; if (maxmin_diff[0] != 0) inv_val[0] = ((ap_fixed)1 / maxmin_diff[0]); if (maxmin_diff[1] != 0) inv_val[1] = ((ap_fixed)1 / maxmin_diff[1]); if (maxmin_diff[2] != 0) inv_val[2] = ((ap_fixed)1 / maxmin_diff[2]); Row_Loop1: for (row = 0; row < height; row++) { // clang-format off #pragma HLS LOOP_TRIPCOUNT min=ROWS max=ROWS // clang-format on Col_Loop1: for (col = 0; col < width; col++) { // clang-format off #pragma HLS LOOP_TRIPCOUNT min=COLS/NPC max=COLS/NPC #pragma HLS pipeline II=1 #pragma HLS LOOP_FLATTEN OFF // clang-format on in_buf_n = src.read(read_index++); ap_fixed value = 0; ap_fixed divval = 0; ap_fixed finalmul = 0; ap_int<32> dstval; for (int p = 0, bit = 0; p < XF_NPIXPERCYCLE(NPC) * XF_CHANNELS(SRC_T, NPC); p++, bit = p % 3) { // clang-format off #pragma HLS unroll // clang-format on XF_CTUNAME(SRC_T, NPC) val = in_buf_n.range(p * STEP + STEP - 1, p * STEP); value = val - minValue[bit]; divval = value * inv_val[p % 3]; finalmul = divval * newdiff; dstval = (int)(finalmul + newmin); if (dstval.range(31, 31) == 1) { dstval = 0; } out_buf_n.range(p * STEP + STEP - 1, p * STEP) = xf_satcast_awb(dstval); } dst.write(row * width + col, out_buf_n); } } } template void AWBhistogramkernel(xf::cv::Mat& src1, xf::cv::Mat& src2, uint32_t hist[3][HIST_SIZE], float p, float inputMin, float inputMax, float outputMin, float outputMax) { // clang-format off #pragma HLS INLINE OFF // clang-format on const int STEP = XF_DTPIXELDEPTH(SRC_T, NPC); int width = src1.cols >> XF_BITSHIFT(NPC); int height = src1.rows; XF_TNAME(SRC_T, NPC) in_pix, in_pix1, out_pix; int writenct = 0; //******************** Simple white balance ******************** int depth = 3; // depth of histogram tree int bins = HIST_SIZE; // number of bins at each histogram level int nElements = HIST_SIZE; // int(pow((float)bins, (float)depth)); int val[3]; // histogram initialization INITIALIZE_HIST: for (int k = 0; k < HIST_SIZE; k++) { // clang-format off #pragma HLS PIPELINE #pragma HLS LOOP_TRIPCOUNT min=HIST_SIZE max=HIST_SIZE // clang-format on INITIALIZE: for (int hi = 0; hi < 3; hi++) { // clang-format off #pragma HLS UNROLL // clang-format on hist[hi][k] = 0; } } // Temporary array used while computing histogram ap_uint<32> tmp_hist[XF_NPIXPERCYCLE(NPC) * XF_CHANNELS(SRC_T, NPC)][HIST_SIZE]; ap_uint<32> tmp_hist1[XF_NPIXPERCYCLE(NPC) * XF_CHANNELS(SRC_T, NPC)][HIST_SIZE]; // clang-format off #pragma HLS RESOURCE variable=tmp_hist core=RAM_T2P_BRAM #pragma HLS RESOURCE variable=tmp_hist1 core=RAM_T2P_BRAM #pragma HLS ARRAY_PARTITION variable=tmp_hist complete dim=1 #pragma HLS ARRAY_PARTITION variable=tmp_hist1 complete dim=1 // clang-format on XF_TNAME(SRC_T, NPC) in_buf, in_buf1, temp_buf; bool flag = 0; HIST_INITIALIZE_LOOP: for (ap_uint<32> i = 0; i < HIST_SIZE; i++) // { // clang-format off #pragma HLS PIPELINE // clang-format on for (ap_uint<5> j = 0; j < XF_NPIXPERCYCLE(NPC) * XF_CHANNELS(SRC_T, NPC); j++) { // clang-format off #pragma HLS LOOP_TRIPCOUNT min=HIST_SIZE max=HIST_SIZE // clang-format on tmp_hist[j][i] = 0; tmp_hist1[j][i] = 0; } } static uint32_t old[XF_NPIXPERCYCLE(NPC) * XF_CHANNELS(SRC_T, NPC)] = {}; static uint32_t old1[XF_NPIXPERCYCLE(NPC) * XF_CHANNELS(SRC_T, NPC)] = {}; static uint32_t acc[XF_NPIXPERCYCLE(NPC) * XF_CHANNELS(SRC_T, NPC)] = {}; static uint32_t acc1[XF_NPIXPERCYCLE(NPC) * XF_CHANNELS(SRC_T, NPC)] = {}; #pragma HLS ARRAY_PARTITION variable = old complete #pragma HLS ARRAY_PARTITION variable = old1 complete #pragma HLS ARRAY_PARTITION variable = acc complete #pragma HLS ARRAY_PARTITION variable = acc1 complete int readcnt = 0; ap_fixed min_vals = inputMin - 0.5f; ap_fixed max_vals = inputMax + 0.5f; ap_fixed minValue = min_vals, minValue1 = min_vals; ap_fixed maxValue = max_vals, maxValue1 = max_vals; ap_fixed interval = ap_fixed(maxValue - minValue) / bins; ap_fixed internal_inv = ((ap_fixed)1 / interval); int pos = 0, pos1 = 0; int currentBin = 0, currentBin1 = 0; ROW_LOOP: for (int row = 0; row != (height); row++) // histogram filling { // clang-format off #pragma HLS LOOP_TRIPCOUNT min=1 max=ROWS // clang-format on COL_LOOP: for (int col = 0; col < (width); col = col + 2) // histogram filling { // clang-format off #pragma HLS PIPELINE II=2 #pragma HLS LOOP_FLATTEN OFF #pragma HLS LOOP_TRIPCOUNT min=1 max=COLS/4 // clang-format on in_pix = src1.read(row * (width) + col); in_pix1 = src1.read((row * (width) + col) + 1); src2.write(row * (width) + col, in_pix); src2.write(row * (width) + col + 1, in_pix1); PLANES_LOOP: for (ap_uint<9> j = 0; j < XF_NPIXPERCYCLE(NPC) * XF_CHANNELS(SRC_T, NPC); j++) { // clang-format off #pragma HLS DEPENDENCE variable=tmp_hist array intra false #pragma HLS DEPENDENCE variable=tmp_hist1 array intra false #pragma HLS UNROLL // clang-format on XF_CTUNAME(SRC_T, NPC) val = 0, val1 = 0; val = in_pix.range(j * STEP + STEP - 1, j * STEP); val1 = in_pix1.range(j * STEP + STEP - 1, j * STEP); currentBin = int((val - minValue) * internal_inv); currentBin1 = int((val1 - minValue1) * internal_inv); uint32_t tmp = old[j]; uint32_t tmp1 = old1[j]; uint32_t tmp_acc = acc[j]; uint32_t tmp_acc1 = acc1[j]; if (tmp == currentBin) { tmp_acc = tmp_acc + 1; } else { tmp_hist[j][tmp] = tmp_acc; tmp_acc = tmp_hist[j][currentBin] + 1; } if (tmp1 == currentBin1) { tmp_acc1 = tmp_acc1 + 1; } else { tmp_hist1[j][tmp1] = tmp_acc1; tmp_acc1 = tmp_hist1[j][currentBin1] + 1; } old[j] = currentBin; old1[j] = currentBin1; acc[j] = tmp_acc; acc1[j] = tmp_acc1; } } } END_HIST_LOOP: for (ap_uint<5> ch_ppc = 0; ch_ppc < (XF_NPIXPERCYCLE(NPC) * XF_CHANNELS(SRC_T, NPC)); ch_ppc++) { // clang-format off #pragma HLS LOOP_TRIPCOUNT min=1 max=6 #pragma HLS UNROLL // clang-format on uint32_t tmp = old[ch_ppc]; uint32_t tmp1 = old1[ch_ppc]; tmp_hist[ch_ppc][tmp] = acc[ch_ppc]; tmp_hist1[ch_ppc][tmp1] = acc1[ch_ppc]; } // Now merge computed partial histograms const int num_ch = XF_CHANNELS(SRC_T, NPC); MERGE_HIST_LOOP: for (ap_uint<32> i = 0; i < HIST_SIZE; i++) { // clang-format off #pragma HLS pipeline // clang-format on MERGE_HIST_CH_UNROLL: for (ap_uint<5> ch = 0; ch < num_ch; ch++) { // clang-format off #pragma HLS UNROLL // clang-format on uint32_t value = 0; MERGE_HIST_NPPC_UNROLL: for (ap_uint<5> p = 0; p < XF_NPIXPERCYCLE(NPC); p++) { // clang-format off #pragma HLS UNROLL // clang-format on value += tmp_hist[p * num_ch + ch][i] + tmp_hist1[p * num_ch + ch][i]; } hist[ch][i] = value; } } } template void AWBhistogram(xf::cv::Mat& src1, xf::cv::Mat& src2, uint32_t histogram[3][HIST_SIZE], float thresh, float inputMin, float inputMax, float outputMin, float outputMax) { // clang-format off #pragma HLS INLINE OFF // clang-format on AWBhistogramkernel( src1, src2, histogram, thresh, inputMin, inputMax, outputMin, outputMax); } template void AWBNormalization(xf::cv::Mat& src, xf::cv::Mat& dst, uint32_t histogram[3][HIST_SIZE], float thresh, float inputMin, float inputMax, float outputMin, float outputMax) { // clang-format off #pragma HLS INLINE OFF // clang-format on AWBNormalizationkernel( src, dst, histogram, thresh, inputMin, inputMax, outputMin, outputMax); } template void AWBGainUpdate(xf::cv::Mat& src1, xf::cv::Mat& src2, float thresh, int i_gain[3]) { xf::cv::AWBGainUpdateKernel> XF_BITSHIFT(NPC))>(src1, src2, thresh, i_gain); } template void AWBChannelGain(xf::cv::Mat& src, xf::cv::Mat& dst, float thresh, int i_gain[3]) { xf::cv::AWBChannelGainKernel> XF_BITSHIFT(NPC))>(src, dst, thresh, i_gain); } } } #endif //_XF_AWB_HPP_