Program Listing for File xf_sw_utils.hpp
↰ Return to documentation for file (/tmp/ws/src/vitis_common/include/common/xf_sw_utils.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_SW_UTILS_H_
#define _XF_SW_UTILS_H_
#include "xf_common.hpp"
#include <iostream>
#include <cmath>
namespace xf {
namespace cv {
template <int _PTYPE, int _ROWS, int _COLS, int _NPC>
xf::cv::Mat<_PTYPE, _ROWS, _COLS, _NPC> imread(char* img, int type) {
::cv::Mat img_load = ::cv::imread(img, type);
xf::cv::Mat<_PTYPE, _ROWS, _COLS, _NPC> input(img_load.rows, img_load.cols);
if (img_load.data == NULL) {
fprintf(stderr, "\nError : Couldn't open the image at %s\n ", img);
exit(-1);
}
input.copyTo(img_load.data);
return input;
}
template <int _PTYPE, int _ROWS, int _COLS, int _NPC>
void imwrite(const char* str, xf::cv::Mat<_PTYPE, _ROWS, _COLS, _NPC>& output) {
int list_ptype[] = {CV_8UC1, CV_16UC1, CV_16SC1, CV_32SC1, CV_32FC1, CV_32SC1,
CV_16UC1, CV_32SC1, CV_8UC1, CV_8UC3, CV_16UC3, CV_16SC3};
int _PTYPE_CV = list_ptype[_PTYPE];
::cv::Mat input(output.rows, output.cols, _PTYPE_CV);
input.data = output.copyFrom();
::cv::imwrite(str, input);
}
template <int _PTYPE, int _ROWS, int _COLS, int _NPC>
void absDiff(::cv::Mat& cv_img, xf::cv::Mat<_PTYPE, _ROWS, _COLS, _NPC>& xf_img, ::cv::Mat& diff_img) {
assert((cv_img.rows == xf_img.rows) && (cv_img.cols == xf_img.cols) && "Sizes of cv and xf images should be same");
assert((xf_img.rows == diff_img.rows) && (xf_img.cols == diff_img.cols) &&
"Sizes of xf and diff images should be same");
assert(((_NPC == XF_NPPC8) || (_NPC == XF_NPPC4) || (_NPC == XF_NPPC2) || (_NPC == XF_NPPC1)) &&
"Only XF_NPPC1, XF_NPPC2, XF_NPPC4, XF_NPPC8 are supported");
assert((cv_img.channels() == XF_CHANNELS(_PTYPE, _NPC)) && "Number of channels of cv and xf images does not match");
int cv_bitdepth = 8;
int num_chnls = cv_img.channels();
int cv_nbytes = 1;
if (cv_img.depth() == CV_8U) {
cv_bitdepth = 8;
} else if (cv_img.depth() == CV_16S || cv_img.depth() == CV_16U) {
cv_bitdepth = 16;
} else if (cv_img.depth() == CV_32S || cv_img.depth() == CV_32F) {
cv_bitdepth = 32;
} else {
fprintf(stderr, "OpenCV image's depth not supported\n ");
return;
}
int cv_pixdepth = cv_bitdepth * num_chnls;
cv_nbytes = cv_bitdepth / 8;
int ch = 0;
int xf_npc_idx = 0;
int diff_ptr = 0;
int xf_ptr = 0;
int cv_ptr = 0;
XF_CTUNAME(_PTYPE, _NPC) cv_val = 0, xf_val = 0, diff_val = 0;
XF_TNAME(_PTYPE, _NPC) xf_val_total = 0;
for (int r = 0, xf_ptr = 0; r < cv_img.rows; ++r) {
for (int c = 0; c<cv_img.cols>> XF_BITSHIFT(_NPC); ++c) {
#ifdef __SDSVHLS__
xf_val_total = xf_img.data[xf_ptr++];
for (int b = 0; b < _NPC; ++b) {
for (int c = 0; c < num_chnls; ++c) {
for (int l = 0; l < cv_nbytes; ++l, ++xf_npc_idx) {
cv_val.range(((l + 1) * 8) - 1, l * 8) = cv_img.data[cv_ptr++];
xf_val.range(((l + 1) * 8) - 1, l * 8) =
xf_val_total.range(((xf_npc_idx + 1) * 8) - 1, xf_npc_idx * 8);
}
diff_val = __ABS((int)cv_val - (int)xf_val);
for (int l = 0; l < cv_nbytes; ++l) {
diff_img.data[diff_ptr++] = diff_val.range(((l + 1) * 8) - 1, l * 8);
}
}
}
xf_npc_idx = 0;
#else
for (int xf_npc_idx = 0; xf_npc_idx < _NPC; ++xf_npc_idx) {
for (int ch = 0; ch < num_chnls; ++ch) {
xf_val = xf_img.data[xf_ptr].chnl[xf_npc_idx][ch];
for (int b = 0; b < cv_nbytes; ++b) {
cv_val.range(((b + 1) * 8) - 1, b * 8) = cv_img.data[cv_ptr++];
}
diff_val = __ABS((int)cv_val - (int)xf_val);
for (int b = 0; b < cv_nbytes; ++b) {
diff_img.data[diff_ptr++] = diff_val.range(((b + 1) * 8) - 1, b * 8);
}
}
}
++xf_ptr;
#endif
}
}
}
void analyzeDiff(::cv::Mat& diff_img, int err_thresh, float& err_per) {
int cv_bitdepth;
if (diff_img.depth() == CV_8U) {
cv_bitdepth = 8;
} else if (diff_img.depth() == CV_16U || diff_img.depth() == CV_16S) {
cv_bitdepth = 16;
} else if (diff_img.depth() == CV_32S || diff_img.depth() == CV_32F) {
cv_bitdepth = 32;
} else {
fprintf(stderr, "OpenCV image's depth not supported for this function\n ");
return;
}
int cnt = 0;
double minval = std::pow(2.0, cv_bitdepth), maxval = 0;
int max_fix = (int)(std::pow(2.0, cv_bitdepth) - 1.0);
for (int i = 0; i < diff_img.rows; i++) {
for (int j = 0; j < diff_img.cols; j++) {
int v = 0;
for (int k = 0; k < diff_img.channels(); k++) {
int v_tmp = 0;
if (diff_img.channels() == 1) {
if (cv_bitdepth == 8)
v_tmp = (int)diff_img.at<unsigned char>(i, j);
else if (cv_bitdepth == 16 && diff_img.depth() == CV_16U) // 16 bitdepth
v_tmp = (int)diff_img.at<unsigned short>(i, j);
else if (cv_bitdepth == 16 && diff_img.depth() == CV_16S) // 16 bitdepth
v_tmp = (int)diff_img.at<short>(i, j);
else if (cv_bitdepth == 32 && diff_img.depth() == CV_32S)
v_tmp = (int)diff_img.at<int>(i, j);
} else // 3 channels
v_tmp = (int)diff_img.at< ::cv::Vec3b>(i, j)[k];
if (v_tmp > v) v = v_tmp;
}
if (v > err_thresh) {
cnt++;
if (diff_img.depth() == CV_8U)
diff_img.at<unsigned char>(i, j) = max_fix;
else if (diff_img.depth() == CV_16U)
diff_img.at<unsigned short>(i, j) = max_fix;
else if (diff_img.depth() == CV_16S)
diff_img.at<short>(i, j) = max_fix;
else if (diff_img.depth() == CV_32S)
diff_img.at<int>(i, j) = max_fix;
else
diff_img.at<float>(i, j) = (float)max_fix;
}
if (minval > v) minval = v;
if (maxval < v) maxval = v;
}
}
err_per = 100.0 * (float)cnt / (diff_img.rows * diff_img.cols);
std::cout << "\tMinimum error in intensity = " << minval << std::endl;
std::cout << "\tMaximum error in intensity = " << maxval << std::endl;
std::cout << "\tPercentage of pixels above error threshold = " << err_per << std::endl;
}
} // namespace cv
} // namespace xf
#endif