滤波测试激励编写
一、测试激励编写
#include <iostream>
#include <cmath>
#include <opencv2/opencv.hpp>
#include "hls_stream.h"
#include "ap_int.h"
#include "bil_filter.h"
// ------------------------- 娴嬭瘯鍙傛暟 -------------------------
#define TEST_ROWS 1080
#define TEST_COLS 1920
#define TEST_NPPC 4
// --------------------------------------------------
void bilateral_filter_software(
const cv::Mat& src, cv::Mat& dst,
float sigma_s, float sigma_r)
{
dst.create(src.size(), src.type());
int radius = 2;
// 棰勮绠楃┖闂存潈閲�
float space_w[5][5];
for (int i = -radius; i <= radius; i++) {
for (int j = -radius; j <= radius; j++) {
space_w[i+radius][j+radius] = exp(-(i*i + j*j) / (2.0 * sigma_s * sigma_s));
}
}
// 棰勮绠楀�煎煙鏉冮噸
float range_w[256];
for (int i = 0; i < 256; i++) {
range_w[i] = exp(-(i*i) / (2.0 * sigma_r * sigma_r));
}
// 婊ゆ尝璁$畻 (鍖呭惈杈圭晫闀滃儚澶勭悊)
for (int i = 0; i < src.rows; i++) {
for (int j = 0; j < src.cols; j++) {
float sum_w = 0.0;
float sum_v = 0.0;
for (int r = -radius; r <= radius; r++) {
for (int c = -radius; c <= radius; c++) {
int nr = std::abs(i + r);
int nc = std::abs(j + c);
if (nr >= src.rows) nr = 2 * src.rows - nr - 2;
if (nc >= src.cols) nc = 2 * src.cols - nc - 2;
uchar neighbor = src.at<uchar>(nr, nc);
uchar center = src.at<uchar>(i, j);
int diff = abs(center - neighbor);
float w = space_w[r+radius][c+radius] * range_w[diff];
sum_w += w;
sum_v += neighbor * w;
}
}
dst.at<uchar>(i, j) = cv::saturate_cast<uchar>(sum_v / sum_w + 0.5f);
}
}
}
// ------------------------- -------------------------
int main() {
std::cout << ">>> Start Bilateral Filter Testbench <<<" << std::endl;
// 1.
cv::Mat src_img = cv::imread("gray_img.png", cv::IMREAD_GRAYSCALE);
if (src_img.empty()) {
std::cerr << "Error: Cannot load input.png! Generating a synthetic image." << std::endl;
src_img.create(TEST_ROWS, TEST_COLS, CV_8UC1);
cv::randu(src_img, 0, 256); //
}
cv::resize(src_img, src_img, cv::Size(TEST_COLS, TEST_ROWS));
const int COLS_BLOCK = TEST_COLS / TEST_NPPC;
// 2.
weight_t space_weight[25];
weight_t range_weight[256];
float sigma_s = 2.0f;
float sigma_r = 30.0f;
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
float val = exp(-((i-2)*(i-2) + (j-2)*(j-2)) / (2.0 * sigma_s * sigma_s));
space_weight[i*5 + j] = (weight_t)val;
}
}
for (int i = 0; i < 256; i++) {
float val = exp(-(i*i) / (2.0 * sigma_r * sigma_r));
range_weight[i] = (weight_t)val;
}
// 3. 澹版槑 AXI-Stream
hls::stream< ap_uint<8*TEST_NPPC> > src_stream("src_stream");
hls::stream< ap_uint<8*TEST_NPPC> > dst_stream("dst_stream");
// 4. 灏� OpenCV 鏁版嵁鍐欏叆杈撳叆娴� (鎵撳寘)
for (int i = 0; i < TEST_ROWS; i++) {
for (int j = 0; j < COLS_BLOCK; j++) {
ap_uint<8*TEST_NPPC> pkt = 0;
for (int k = 0; k < TEST_NPPC; k++) {
uchar pix = src_img.at<uchar>(i, j * TEST_NPPC + k);
pkt(8*(k+1)-1, 8*k) = pix; // 浣庝綅鏀惧墠涓�涓儚绱狅紝楂樹綅鏀惧悗涓�涓儚绱�
}
src_stream.write(pkt);
}
}
// 5. 璋冪敤寰呮祴纭欢妯″潡
std::cout << "Running HLS Hardware Model..." << std::endl;
bilateral_top(src_stream, dst_stream, space_weight, range_weight);
// 6.
cv::Mat hw_dst_img(TEST_ROWS, TEST_COLS, CV_8UC1);
for (int i = 0; i < TEST_ROWS; i++) {
for (int j = 0; j < COLS_BLOCK; j++) {
ap_uint<8*TEST_NPPC> pkt = dst_stream.read();
for (int k = 0; k < TEST_NPPC; k++) {
hw_dst_img.at<uchar>(i, j * TEST_NPPC + k) = pkt(8*(k+1)-1, 8*k);
}
}
}
// 7.
std::cout << "Running Software Reference Model..." << std::endl;
cv::Mat sw_dst_img;
bilateral_filter_software(src_img, sw_dst_img, sigma_s, sigma_r);
// 8.
int err_count = 0;
int max_err = 0;
double total_sq_err = 0.0;
for (int i = 0; i < TEST_ROWS; i++) {
for (int j = 0; j < TEST_COLS; j++) {
int hw_val = hw_dst_img.at<uchar>(i, j);
int sw_val = sw_dst_img.at<uchar>(i, j);
int diff = abs(hw_val - sw_val);
if (diff > 2) {
err_count++;
}
if (diff > max_err) {
max_err = diff;
}
total_sq_err += (diff * diff);
}
}
double mse = total_sq_err / (TEST_ROWS * TEST_COLS);
double psnr = (mse == 0) ? 100.0 : 10.0 * log10(255.0 * 255.0 / mse);
// std::cout << "------ Verification Results ------" << std::endl;
// std::cout << "Max Absolute Error: " << max_err << std::endl;
// std::cout << "Error Count (>2): " << err_count << " / " << TEST_ROWS*TEST_COLS << std::endl;
// std::cout << "PSNR: " << psnr << " dB" << std::endl;
cv::imwrite("hw_output.png", hw_dst_img);
cv::imwrite("sw_output.png", sw_dst_img);
std::cout << "Images saved to hw_output.png and sw_output.png" << std::endl;
// if (max_err <= 3 && psnr > 35.0) {
// std::cout << ">>> TEST PASSED <<<" << std::endl;
// return 0;
// } else {
// std::cout << ">>> TEST FAILED <<<" << std::endl;
// return 1;
// }
return 0;
}
上述代码是测试激励的编写
二、核心代码设计
