FC2カウンター FPGAの部屋 Vitis_Vision
fc2ブログ

FPGAやCPLDの話題やFPGA用のツールの話題などです。 マニアックです。 日記も書きます。

FPGAの部屋

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。Xilinx ISEの初心者の方には、FPGAリテラシーおよびチュートリアルのページをお勧めいたします。

Vitis HLS 2021.2 で Vitis Vision Library L1 を使用するために TCL スクリプトでプロジェクトを作成する9(modefilter 編4)

Vitis HLS 2021.2 で Vitis Vision Library L1 を使用するために TCL スクリプトでプロジェクトを作成する8(modefilter 編3)”の続き。

Vitis Vision Library L1 にすでにある run_hls.tcl を少し改造して Vitis HLS 2021.2 のプロジェクトを生成するということで、前回は、modefilter の C/RTL 協調シミュレーション、Export RTL、Implementation を行った。今回は、シミュレーション用の画像を 800 x 600 ピクセルのノイズ付加した画像に切り替えて、ノイズ除去性能を確認する。その際に、HEIGHT と WIDTH (画像の最大値)を HD 解像度に設定して実際に使用できる IP にしてみよう。

使用する画像は、メディアン・フィルタに時に使用したノイズ付加画像の test2.jpg を使用する。
ただし画像のサイズは 800 x 600 ピクセルとした。
Vitis_Vision2_218_220211.jpg

この test2.jpg を xf_mode_filter_axis ディレクトリにコピーした。
Vitis_Vision2_209_220210.png

ますは、xf_modefilter_config.h の HEIGHT を 1920 に WIDTH を 1080 に変更した。
Vitis_Vision2_210_220210.png

Vitis HLS 2021.2 の Project メニューから Project Settings... を選択した。
Project Settings (modefilter.prj) ダイアログが開く。
左のウインドウで Simulation をクリックする。
Input Arguments に

/media/masaaki/Ubuntu_Disk/Vitis_HLS/ZYBO_Z7_20/2021.2/xf_mode_filter_axis/test2.jpg

を設定した。
Vitis_Vision2_211_220210.png

C シミュレーションを行った。
Vitis_Vision2_212_220210.png

出力された out_img.jpg と入力画像の in_img.jpg を示す。
3 x 3 の mode filter では多少 1 x 1 のランダム・ノイズが取れているが、メディアン・フィルタよりはノイズが取れていないようだ。
Vitis_Vision2_213_220210.jpg

C コードの合成を行った。結果を示す。
Vitis_Vision2_214_220210.png

C/RTL 協調シミュレーションでは、やはり、Input Arguments に

/media/masaaki/Ubuntu_Disk/Vitis_HLS/ZYBO_Z7_20/2021.2/xf_mode_filter_axis/test2.jpg

を設定した。
Dump Trace は port でやってみたが、なかなか終わらなかったので、none に設定した。
Vitis_Vision2_215_220210.png

C/RTL 協調シミュレーションの結果を示す。
Vitis_Vision2_215_220210.png

レイテンシは 490017 クロックなので、490017 / 480000 ≒ 1.02 クロック / ピクセルだった。

Export RTL を行った。

Implementation を行った。
前回より、LUT が 57 個、FF が 94 個、BRAM が 6 個増えていた。
CP achieved post-implementation は 7.004 ns だった。前回より良くなっている。
Vitis_Vision2_217_220210.png
  1. 2022年02月11日 05:29 |
  2. Vitis_Vision
  3. | トラックバック:0
  4. | コメント:0

Vitis HLS 2021.2 で Vitis Vision Library L1 を使用するために TCL スクリプトでプロジェクトを作成する8(modefilter 編3)

Vitis HLS 2021.2 で Vitis Vision Library L1 を使用するために TCL スクリプトでプロジェクトを作成する7(modefilter 編2)”の続き。

Vitis Vision Library L1 にすでにある run_hls.tcl を少し改造して Vitis HLS 2021.2 のプロジェクトを生成するということで、前回は、modefilter のC シミュレーション、C コードの合成を行った。今回は、C/RTL 協調シミュレーション、Export RTL、Implementation を行った。

C/RTL 協調シミュレーションを行う。
Co-Simulation Dialog では、Input Argumets に /media/masaaki/Ubuntu_Disk/Xilinx_github/Vitis_Libraries/vision/data/128x128.png を設定した。
Dump Trace を port に設定した。
Vitis_Vision2_203_220209.png

C/RTL 協調シミュレーションの結果を示す。
Vitis_Vision2_204_220209.png

128 x 128 ピクセル = 16384 ピクセルで、レイテンシは 18449 クロックなので、約 1.13 クロック / ピクセルとなった。

C/RTL 協調シミュレーションの全体波形を示す。
Vitis_Vision2_205_220209.png

1 行分を拡大した。
Vitis_Vision2_206_220209.png

Export RTL を行った。
xf_mode_filter_axis/modefilter.prj/sol1/export.zip が出力されていた。
Vitis_Vision2_207_220209.png

Implementation を行った。
CP achieved post-implementation は 7.286 ns と良さそうだ。
Vitis_Vision2_208_220209.png
  1. 2022年02月10日 04:55 |
  2. Vitis_Vision
  3. | トラックバック:0
  4. | コメント:0

Vitis HLS 2021.2 で Vitis Vision Library L1 を使用するために TCL スクリプトでプロジェクトを作成する7(modefilter 編2)

Vitis HLS 2021.2 で Vitis Vision Library L1 を使用するために TCL スクリプトでプロジェクトを作成する6(modefilter 編1)”の続き。

Vitis Vision Library L1 にすでにある run_hls.tcl を少し改造して Vitis HLS 2021.2 のプロジェクトを生成するということで、前回は、Vitis Vision Library のユーザーズ・マニュアルにある Getting Started with HLS を使った方法はうまく行かなかったので、run_hls.tcl を書き換えることにした。そして、ソースコード・ファイルやテストベンチ・ファイル、ヘッダ・ファイルも AXI4-Stream 入出力に変更した。Vitis HLS 2021.2 の xf_mode_filter_axis プロジェクトを作成することができた。今回は、C シミュレーション、C コードの合成を行った。

Vitis HLS 2021.2 の xf_mode_filter_axis プロジェクトを示す。このプロジェクトは ZYBO Z7-20 用だ。
Vitis_Vision2_193_220208.png

すでに C シミュレーションはやってあるのだが、GUI 上でやってみた。
Vitis_Vision2_194_220208.png

xf_mode_filter_axis/modefilter.prj/sol1/csim/build ディレクトリを見た。
Vitis_Vision2_196_220208.png

元画像の in_img2.jpg とソースコードの出力の out_jmg.jpg を比べてみた。
Vitis_Vision2_195_220208.png

試しに build/xf_config_params.h の WINDOW_SIZE を 5 から 3 に変更した。
Vitis_Vision2_197_220208.png

C シミュレーションをやり直して、成功した。
もう一度、xf_mode_filter_axis/modefilter.prj/sol1/csim/build ディレクトリの元画像の in_img2.jpg とソースコードの出力の out_jmg.jpg を比べてみた。
Vitis_Vision2_198_220209.png

こちらのほうが、元画像からの差異は少ない。こっちでやってみることにした。それに、C コードの合成時のリソース使用率も当然ながら低い。

C コードの合成を行った。
結果を示す。
Vitis_Vision2_199_220209.png
Vitis_Vision2_200_220209.png
Vitis_Vision2_201_220209.png
Vitis_Vision2_202_220209.png
  1. 2022年02月09日 04:47 |
  2. Vitis_Vision
  3. | トラックバック:0
  4. | コメント:0

Vitis HLS 2021.2 で Vitis Vision Library L1 を使用するために TCL スクリプトでプロジェクトを作成する6(modefilter 編1)

Vitis HLS 2021.2 で Vitis Vision Library L1 を使用するために TCL スクリプトでプロジェクトを作成する5(fast 編3)”の続き。

前回の fast 編では、TCL スクリプトを自分で生成したが、今回は、Vitis Vision Library L1 にすでにある run_hls.tcl を少し改造して Vitis HLS 2021.2 のプロジェクトを生成してみよう。少ししか改造しなくてプロジェクトを生成できそうだ。Vitis Vision Library のユーザーズ・マニュアルにある Getting Started with HLS を使った方法はうまく行かなかったので、run_hls.tcl を書き換えることにした。そして、ソースコード・ファイルやテストベンチ・ファイル、ヘッダ・ファイルも AXI4-Stream 入出力に変更した。

今回は、modefilter を題材にやってみよう。

modefilter をコピーした。
Vitis_Vision2_189_220207.png

run_hls.tcl を書き換えた。

source settings.tcl

の行をコメントアウトして、XPART、 XF_PROJ_ROOT、 OPENCV_INCLUDE、 OPENCV_LIB、 CSIM の環境変数を追加した。Vitis HLS のプロジェクトができれば文句ないので、CSIM だけ 1 にした。後、CLKP を 3.3 ns から 10 ns に変更した。build ディレクトリへのインクルード・パスと合成時のトップ関数の名前も修正した。
run_hls.tcl を示す。

#
# 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.
#
# 2022/02/07 : modified by marsee

#source settings.tcl

set PROJ "modefilter.prj"
set SOLN "sol1"
set XPART "xc7z020-clg400-1"
set XF_PROJ_ROOT "/media/masaaki/Ubuntu_Disk/Xilinx_github/Vitis_Libraries/vision"
set OPENCV_INCLUDE "/usr/local/include"
set OPENCV_LIB "/usr/local/lib"
set CSIM "1"
set BUILD_DIR "/media/masaaki/Ubuntu_Disk/Vitis_HLS/ZYBO_Z7_20/2021.2/xf_mode_filter_axis/build"
if {![info exists CLKP]} {
  set CLKP 10
}

open_project -reset $PROJ

add_files "xf_modefilter_accel.cpp" -cflags "-I${XF_PROJ_ROOT}/L1/include -I ${BUILD_DIR} -I ./ -D__SDSVHLS__ -std=c++0x" -csimflags "-I${XF_PROJ_ROOT}/L1/include -I ${BUILD_DIR} -I ./ -D__SDSVHLS__ -std=c++0x"
add_files -tb "xf_modefilter_tb.cpp" -cflags "-I${OPENCV_INCLUDE} -I${XF_PROJ_ROOT}/L1/include -I ${XF_PROJ_ROOT}/L1/examples/modefilter/build -I ./ -D__SDSVHLS__ -std=c++0x" -csimflags "-I${XF_PROJ_ROOT}/L1/include -I ${XF_PROJ_ROOT}/L1/examples/modefilter/build -I ./ -D__SDSVHLS__ -std=c++0x"
set_top modefilter_axis

open_solution -reset $SOLN

set_part $XPART
create_clock -period $CLKP

if {$CSIM == 1} {
  csim_design -ldflags "-L ${OPENCV_LIB} -lopencv_imgcodecs -lopencv_imgproc -lopencv_core -lopencv_highgui -lopencv_flann -lopencv_features2d" -argv " ${XF_PROJ_ROOT}/data/128x128.png "
}

if {$CSYNTH == 1} {
  csynth_design
}

if {$COSIM == 1} {
  cosim_design -ldflags "-L ${OPENCV_LIB} -lopencv_imgcodecs -lopencv_imgproc -lopencv_core -lopencv_highgui -lopencv_flann -lopencv_features2d" -argv " ${XF_PROJ_ROOT}/data/128x128.png "
}

if {$VIVADO_SYN == 1} {
  export_design -flow syn -rtl verilog
}

if {$VIVADO_IMPL == 1} {
  export_design -flow impl -rtl verilog
}

exit


修正した xf_mode_filter_axis.h を示す。

/*
 * Copyright 2020 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.
 */
// 2022/02/07 :  modified by marsee

#ifndef _XF_MODE_FILTER_CONFIG_H_
#define _XF_MODE_FILTER_CONFIG_H_

#include <stdint.h>
#include "hls_stream.h"
#include "ap_int.h"
#include "common/xf_common.hpp"
#include "common/xf_utility.hpp"
#include "ap_axi_sdata.h"
#include "common/xf_infra.hpp"
#include "common/xf_axi_io.hpp"
#include "xf_config_params.h"

#include "imgproc/xf_modefilter.hpp"

#define HEIGHT 128
#define WIDTH 128

// Set the optimization type:
#if NO == 1
#define NPC1 XF_NPPC1
#define PTR_WIDTH 128
#else

#if GRAY
#define NPC1 XF_NPPC8
#else
#define NPC1 XF_NPPC1
#endif

#define PTR_WIDTH 128
#endif

// Set the pixel depth:
#if GRAY
#define TYPE XF_8UC1
#define STREAMW 8
#else
#define TYPE XF_8UC3
#define STREAMW 32
#endif
typedef hls::stream<ap_axiu<STREAMW,1,1,1> > AXI_STREAM;

void modefilter_axis(AXI_STREAM& _src, int32_t rows, int32_t cols, AXI_STREAM& _dst);

#endif // end of _XF_MEDIAN_BLUR_CONFIG_H_


修正した xf_modefilter_accel.cpp を示す。

/*
 * Copyright 2020 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.
 */
// 2022/02/07 : Change to AXI4-Stream input / output. by marsee

#include "xf_modefilter_config.h"

void modefilter_axis(AXI_STREAM& _src, int32_t rows, int32_t cols, AXI_STREAM& _dst) {
// clang-format off
    #pragma HLS INTERFACE mode=axis register_mode=both port=_src register
    #pragma HLS INTERFACE mode=axis register_mode=both port=_dst register
    #pragma HLS INTERFACE s_axilite  port=rows                        bundle=control
    #pragma HLS INTERFACE s_axilite  port=cols                        bundle=control
    #pragma HLS INTERFACE s_axilite  port=return                      bundle=control
    // clang-format on

    xf::cv::Mat<TYPE, HEIGHT, WIDTH, NPC1> imgInput(rows, cols);
    xf::cv::Mat<TYPE, HEIGHT, WIDTH, NPC1> imgOutput(rows, cols);

// clang-format off
    #pragma HLS DATAFLOW
    // clang-format on

    xf::cv::AXIvideo2xfMat<STREAMW, TYPE>(_src, imgInput);

    // Run xfOpenCV kernel:
    xf::cv::modefilter<WINDOW_SIZE, XF_BORDER_REPLICATE, TYPE, HEIGHT, WIDTH, NPC1>(imgInput, imgOutput);

    xf::cv::xfMat2AXIvideo<STREAMW, TYPE>(imgOutput, _dst);

    return;
} // End of kernel


修正した xf_modefilter_tb.cpp を示す。

/*
 * Copyright 2020 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.
 */
// 2022/02/07 : Change to AXI4-Stream input / output. by marsee

#include "opencv2/opencv.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgcodecs/imgcodecs.hpp"
#include "common/xf_headers.hpp"
#include "common/xf_axi.hpp"
#include "common/xf_sw_utils.hpp"
#include <stdio.h>
#include <stdlib.h>
#include "xf_modefilter_config.h"

using namespace std;
cv::RNG rng(12345);
void mode_filter_rgb(cv::Mat _src, cv::Mat _dst, int win_sz) {
    int win_sz_sq = win_sz * win_sz;
    int window[win_sz_sq];
    cv::Scalar value(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
    cv::Mat _src_border;

    _src_border.create(_src.rows + win_sz - 1, _src.cols + win_sz - 1, CV_8UC3);

    int border = floor(win_sz / 2);

    cv::copyMakeBorder(_src, _src_border, border, border, border, border, cv::BORDER_REPLICATE, value);

    for (int k = 0; k < 3; k++) {
        for (int i = 0; i < _src.rows; i++) {
            for (int j = 0; j < _src.cols; j++) {
                for (int p = 0; p < win_sz; p++) {
                    for (int q = 0; q < win_sz; q++) {
                        // cout<<p<<" "<<q<<" "<<endl;
                        window[q + p * win_sz] = _src_border.at<cv::Vec3b>(i + p, j + q)[k];
                    }
                }

                int max_count = 0, idx = 0;

                for (int m = 0; m < win_sz_sq; m++) {
                    int count = 1;
                    for (int n = m + 1; n < win_sz_sq - 1; n++) {
                        if (window[m] == window[n]) count++;
                    }
                    if (count > max_count) {
                        max_count = count;
                    }
                }

                for (int m = 0; m < win_sz_sq; m++) {
                    int count = 1;
                    for (int n = m + 1; n < win_sz_sq - 1; n++) {
                        if (window[m] == window[n]) count++;
                    }

                    if (count == max_count) {
                        idx = m;
                    }
                }

                _dst.at<cv::Vec3b>(i, j)[k] = window[idx];
            }
        }
    }
    return;
}
void mode_filter_gray(cv::Mat _src, cv::Mat _dst, int win_sz) {
    int win_sz_sq = win_sz * win_sz;
    int window[win_sz_sq];
    int i_1_index = 0, j_1_index = 0, i_plus_index = 0, j_plus_index = 0;

    cv::Mat _src_border;

    _src_border.create(_src.rows + win_sz - 1, _src.cols + win_sz - 1, CV_8UC1);

    int border = floor(win_sz / 2);

    cv::copyMakeBorder(_src, _src_border, border, border, border, border, cv::BORDER_REPLICATE);

    for (int i = 0; i < _src.rows; i++) {
        for (int j = 0; j < _src.cols; j++) {
            for (int p = 0; p < win_sz; p++) {
                for (int q = 0; q < win_sz; q++) {
                    window[q + p * win_sz] = _src_border.at<uchar>(i + p, j + q);
                }
            }
            int max_count = 0, idx = 0;

            for (int i = 0; i < win_sz_sq; i++) {
                int count = 1;
                for (int j = i + 1; j < win_sz_sq - 1; j++) {
                    if (window[i] == window[j]) count++;
                }
                if (count > max_count) {
                    max_count = count;
                }
            }

            for (int i = 0; i < win_sz_sq; i++) {
                int count = 1;
                for (int j = i + 1; j < win_sz_sq - 1; j++) {
                    if (window[i] == window[j]) count++;
                }

                if (count == max_count) {
                    idx = i;
                }
            }

            _dst.at<uchar>(i, j) = window[idx];
        }
    }

    return;
}

int main(int argc, char** argv) {
    if (argc != 2) {
        fprintf(stderr, "Usage: <executable> <input image path>\n");
        return -1;
    }

    cv::Mat in_img, out_img, ocv_ref, ocv_ref1, diff;

//  Reading in the image:
#if GRAY
    cout << "gray:";
    in_img = cv::imread(argv[1], 0); // reading in the gray image
    imwrite("in_img1.jpg", in_img);
#else
    in_img = cv::imread(argv[1], 1); // reading in the color image
    imwrite("in_img2.jpg", in_img);
#endif

    if (!in_img.data) {
        return -1;
    }

// imwrite("in_img.jpg", in_img);

// create memory for output image
#if GRAY
    cout << "gray:";
    ocv_ref.create(in_img.rows, in_img.cols, CV_8UC1);
    ocv_ref1.create(in_img.rows, in_img.cols, CV_8UC1);
    out_img.create(in_img.rows, in_img.cols, CV_8UC1); // create memory for output image
    diff.create(in_img.rows, in_img.cols, CV_8UC1);
#else
    ocv_ref.create(in_img.rows, in_img.cols, CV_8UC3);
    ocv_ref1.create(in_img.rows, in_img.cols, CV_8UC3);
    out_img.create(in_img.rows, in_img.cols, CV_8UC3); // create memory for output image
    diff.create(in_img.rows, in_img.cols, CV_8UC3);
#endif

#if GRAY
    cout << "gray:";
    mode_filter_gray(in_img, ocv_ref, WINDOW_SIZE);
#else
    cout << "rgb";
    mode_filter_rgb(in_img, ocv_ref, WINDOW_SIZE);
#endif

    //modefilter_accel((ap_uint<PTR_WIDTH>*)in_img.data, in_img.rows, in_img.cols, (ap_uint<PTR_WIDTH>*)out_img.data);
    AXI_STREAM _src,_dst;
    xf::cv::cvMat2AXIvideoxf<NPC1, STREAMW>(in_img, _src);
    modefilter_axis(_src, in_img.rows, in_img.cols, _dst);
    xf::cv::AXIvideo2cvMatxf<NPC1, STREAMW>(_dst, out_img);

    imwrite("out_img.jpg", out_img);
    imwrite("ocv_ref.jpg", ocv_ref);
    // imwrite("ocv_ref.jpg", ocv_ref1);

    cv::absdiff(ocv_ref, out_img, diff);

    imwrite("diff.jpg", diff);
    absdiff(ocv_ref, out_img, diff);
    // Save the difference image for debugging purpose:
    cv::imwrite("error.png", diff);
    float err_per;
    xf::cv::analyzeDiff(diff, 0, err_per);

    if (err_per > 0.0f) {
        fprintf(stderr, "ERROR: Test Failed.\n ");
        return 1;
    }
    std::cout << "Test Passed " << std::endl;

    return 0;
}


run_hls.tcl を起動した。
vitis_hls -f run_hls.tcl
Vitis_Vision2_190_220207.png
Vitis_Vision2_191_220207.png

C シミュレーションは通った。
  1. 2022年02月08日 04:10 |
  2. Vitis_Vision
  3. | トラックバック:0
  4. | コメント:0

Vitis HLS 2021.2 で Vitis Vision Library L1 を使用するために TCL スクリプトでプロジェクトを作成する5(fast 編3)

Vitis HLS 2021.2 で Vitis Vision Library L1 を使用するために TCL スクリプトでプロジェクトを作成する4(fast 編2)”の続き。

TCL スクリプトで Vitis HLS 2021.2 のプロジェクトを作成して、Vitis Vision Library L1 をやってみることにしたということで、前回は、xf_fast_axis_home.tcl を起動したら、C シミュレーションがエラーになった。原因は、OpenCV の cv::FAST() が undefined reference だったので、この行と関連する行をコメントアウトした。すると、C シミュレーションが成功した。今回は、C コードの合成、C/RTL 協調シミュレーション、Export RTL 、Implementation を行った。

C/RTL 協調シミュレーションを行った。
最大画像のピクセル数が 1920 x 1080 = 2073600 ピクセルだが、レイテンシは 4173698 クロックだった。これだとクロック / ピクセルは 2 を超えてしまうが、後の C/RTL 協調シミュレーションを見ると、そんなことはないようだ。バグなのか?
Vitis_Vision2_174_220206.png
Vitis_Vision2_175_220206.png
Vitis_Vision2_176_220206.png
Vitis_Vision2_177_220206.png

C/RTL 協調シミュレーションを行った。
Co-simulation Dialog で、Input Arguments に /media/masaaki/Ubuntu_Disk/Vitis_HLS/ZYBO_Z7_20/2021.2/xf_fast_axis/test2.jpg を設定し、Dump Trace を port に設定した。
Vitis_Vision2_178_220206.png

結果を示す。
400 x 300 = 120000 ピクセルに対して、128433 クロックなので、約 1.07 クロック / ピクセルとなった。
Vitis_Vision2_179_220206.png

C/RTL 協調シミュレーションの全体波形を示す。
Vitis_Vision2_182_220206.png

拡大した。
Vitis_Vision2_183_220206.png

p_dst_TVALID も p_src_TREADY もいい感じだ。

更に拡大した。
p_src_TDATA も p_dst_TDATA も 8 ビットで、p_dst_TDATA はコーナー発見で 0x00 から 0xff になるのが分かる。
Vitis_Vision2_184_220206.png

Export RTL を行った。
xf_fast_axis/solution1/impl ディレクトリの export.zip が生成された。
Vitis_Vision2_180_220206.png

Implementation を行った。
CP achieved post-implementation が 9.747 ns で危ない感じだ。
Vitis_Vision2_181_220206.png

もう少し CP achieved post-implementation を改善したい。
solution2 を作成して、Uncertainty を 4 ns に設定した。
Vitis_Vision2_185_220206.png

C コードの合成を行った。
Vitis_Vision2_186_220206.png

Implementation を行った。
Vitis_Vision2_187_220206.png

CP achieved post-implementation は 8.763 ns だった。良さそうだ。

solution1 と solution2 を比較した。
Vitis_Vision2_188_220206.png
  1. 2022年02月06日 06:00 |
  2. Vitis_Vision
  3. | トラックバック:0
  4. | コメント:0

Vitis HLS 2021.2 で Vitis Vision Library L1 を使用するために TCL スクリプトでプロジェクトを作成する4(fast 編2)

Vitis HLS 2021.2 で Vitis Vision Library L1 を使用するために TCL スクリプトでプロジェクトを作成する3(fast 編1)”の続き。

TCL スクリプトで Vitis HLS 2021.2 のプロジェクトを作成して、Vitis Vision Library L1 をやってみることにしたということで、前回は、fast をやってみることにした。コードを貼って、xf_fast_axis ディレクトリを作成し、フィルを入れた。今回は、xf_fast_axis_home.tcl を起動したら、C シミュレーションがエラーになった。原因は、OpenCV の cv::FAST() が undefined reference だったことだ。

ターミナルで、xf_fast_axis_home.tcl を起動した。
vitis_hls -f xf_fast_axis_home.tcl
Vitis_Vision2_167_220205.png
Vitis_Vision2_168_220205.png

ログを貼っておく。

(base) masaaki@masaaki-H110M4-M01:/media/masaaki/Ubuntu_Disk/Vitis_HLS/ZYBO_Z7_20/2021.2/xf_fast_axis$ vitis_hls -f xf_fast_axis_home.tcl 

****** Vitis HLS - High-Level Synthesis from C, C++ and OpenCL v2021.2 (64-bit)
  **** SW Build 3367213 on Tue Oct 19 02:47:39 MDT 2021
  **** IP Build 3369179 on Thu Oct 21 08:25:16 MDT 2021
    ** Copyright 1986-2021 Xilinx, Inc. All Rights Reserved.

source /media/masaaki/Ubuntu_Disk/tools/Xilinx/Vitis_HLS/2021.2/scripts/vitis_hls/hls.tcl -notrace
INFO: Applying HLS Y2K22 patch v1.2 for IP revision
INFO: [HLS 200-10] Running '/media/masaaki/Ubuntu_Disk/tools/Xilinx/Vitis_HLS/2021.2/bin/unwrapped/lnx64.o/vitis_hls'
INFO: [HLS 200-10] For user 'masaaki' on host 'masaaki-H110M4-M01' (Linux_x86_64 version 4.15.0-166-generic) on Sat Feb 05 03:21:48 JST 2022
INFO: [HLS 200-10] On os Ubuntu 18.04.6 LTS
INFO: [HLS 200-10] In directory '/media/masaaki/Ubuntu_Disk/Vitis_HLS/ZYBO_Z7_20/2021.2/xf_fast_axis'
WARNING: [HLS 200-40] Environment variable 'C_INCLUDE_PATH' is set to :/usr/local/cuda/include.
Sourcing Tcl script 'xf_fast_axis_home.tcl'
INFO: [HLS 200-1510] Running: open_project xf_fast_axis 
INFO: [HLS 200-10] Creating and opening project '/media/masaaki/Ubuntu_Disk/Vitis_HLS/ZYBO_Z7_20/2021.2/xf_fast_axis/xf_fast_axis'.
INFO: [HLS 200-1510] Running: set_top fast_accel_axis 
INFO: [HLS 200-1510] Running: add_files xf_fast_axis.cpp -cflags -I/media/masaaki/Ubuntu_Disk/Xilinx_github/Vitis_Libraries/vision/L1/include -std=c++0x 
INFO: [HLS 200-10] Adding design file 'xf_fast_axis.cpp' to the project
INFO: [HLS 200-1510] Running: add_files -tb xf_fast_axis_tb.cpp -cflags -I/media/masaaki/Ubuntu_Disk/Xilinx_github/Vitis_Libraries/vision/L1/include -I/usr/local/include -std=c++0x -Wno-unknown-pragmas -csimflags -Wno-unknown-pragmas 
INFO: [HLS 200-10] Adding test bench file 'xf_fast_axis_tb.cpp' to the project
INFO: [HLS 200-1510] Running: open_solution solution1 -flow_target vivado 
INFO: [HLS 200-10] Creating and opening solution '/media/masaaki/Ubuntu_Disk/Vitis_HLS/ZYBO_Z7_20/2021.2/xf_fast_axis/xf_fast_axis/solution1'.
INFO: [HLS 200-1505] Using flow_target 'vivado'
Resolution: For help on HLS 200-1505 see www.xilinx.com/cgi-bin/docs/rdoc?v=2021.2;t=hls+guidance;d=200-1505.html
INFO: [HLS 200-1510] Running: set_part xc7z020-clg400-1 
INFO: [HLS 200-1611] Setting target device to 'xc7z020-clg400-1'
INFO: [HLS 200-1510] Running: create_clock -period 10 -name default 
INFO: [SYN 201-201] Setting up clock 'default' with a period of 10ns.
INFO: [HLS 200-1510] Running: config_export -format ip_catalog -rtl verilog -vivado_clock 10 
INFO: [HLS 200-1510] Running: csim_design -ldflags -L/usr/local/lib -lopencv_core -lopencv_imgcodecs -lopencv_imgproc -argv /media/masaaki/Ubuntu_Disk/Vitis_HLS/ZYBO_Z7_20/2021.2/xf_fast_axis/test2.jpg 
INFO: [SIM 211-2] *************** CSIM start ***************
INFO: [SIM 211-4] CSIM will launch GCC as the compiler.
   Compiling ../../../../xf_fast_axis_tb.cpp in debug mode
   Compiling ../../../../xf_fast_axis.cpp in debug mode
   Generating csim.exe
Makefile.rules:392: recipe for target 'csim.exe' failed
In file included from /media/masaaki/Ubuntu_Disk/Xilinx_github/Vitis_Libraries/vision/L1/include/common/xf_structs.hpp:27:0,
                 from /media/masaaki/Ubuntu_Disk/Xilinx_github/Vitis_Libraries/vision/L1/include/common/xf_common.hpp:20,
                 from /media/masaaki/Ubuntu_Disk/Xilinx_github/Vitis_Libraries/vision/L1/include/common/xf_sw_utils.hpp:20,
                 from /media/masaaki/Ubuntu_Disk/Xilinx_github/Vitis_Libraries/vision/L1/include/common/xf_headers.hpp:28,
                 from ../../../../xf_fast_axis_tb.cpp:24:
/media/masaaki/Ubuntu_Disk/tools/Xilinx/Vitis_HLS/2021.2/include/ap_axi_sdata.h:97:45: warning: variable templates only available with -std=c++14 or -std=gnu++14
 template <typename T> constexpr std::size_t bitwidth = sizeof(T) * CHAR_BIT;
                                             ^~~~~~~~
/media/masaaki/Ubuntu_Disk/tools/Xilinx/Vitis_HLS/2021.2/include/ap_axi_sdata.h:99:48: warning: variable templates only available with -std=c++14 or -std=gnu++14
 template <std::size_t W> constexpr std::size_t bitwidth<ap_int<W>> = W;
                                                ^~~~~~~~~~~~~~~~~~~
/media/masaaki/Ubuntu_Disk/tools/Xilinx/Vitis_HLS/2021.2/include/ap_axi_sdata.h:100:48: warning: variable templates only available with -std=c++14 or -std=gnu++14
 template <std::size_t W> constexpr std::size_t bitwidth<ap_uint<W>> = W;
                                                ^~~~~~~~~~~~~~~~~~~~
/media/masaaki/Ubuntu_Disk/tools/Xilinx/Vitis_HLS/2021.2/include/ap_axi_sdata.h:102:23: warning: variable templates only available with -std=c++14 or -std=gnu++14
 constexpr std::size_t bitwidth<ap_fixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N>> = _AP_W;
                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/media/masaaki/Ubuntu_Disk/tools/Xilinx/Vitis_HLS/2021.2/include/ap_axi_sdata.h:104:23: warning: variable templates only available with -std=c++14 or -std=gnu++14
 constexpr std::size_t bitwidth<ap_ufixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N>> = _AP_W;
                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/media/masaaki/Ubuntu_Disk/tools/Xilinx/Vitis_HLS/2021.2/include/ap_axi_sdata.h:107:23: warning: variable templates only available with -std=c++14 or -std=gnu++14
 constexpr std::size_t bytewidth = (bitwidth<T> + CHAR_BIT - 1) / CHAR_BIT;
                       ^~~~~~~~~
In file included from /media/masaaki/Ubuntu_Disk/Xilinx_github/Vitis_Libraries/vision/L1/include/common/xf_axi.hpp:23:0,
                 from ../../../../xf_fast_axis_tb.cpp:25:
/media/masaaki/Ubuntu_Disk/tools/Xilinx/Vitis_HLS/2021.2/include/utils/x_hls_utils.h:246:10: warning: ‘hls_preserve’ attribute directive ignored [-Wattributes]
 T reg(T d)
          ^
In file included from /media/masaaki/Ubuntu_Disk/Xilinx_github/Vitis_Libraries/vision/L1/include/common/xf_structs.hpp:27:0,
                 from /media/masaaki/Ubuntu_Disk/Xilinx_github/Vitis_Libraries/vision/L1/include/common/xf_common.hpp:20,
                 from ../../../../xf_fast_axis.h:12,
                 from ../../../../xf_fast_axis.cpp:6:
/media/masaaki/Ubuntu_Disk/tools/Xilinx/Vitis_HLS/2021.2/include/ap_axi_sdata.h:97:45: warning: variable templates only available with -std=c++14 or -std=gnu++14
 template <typename T> constexpr std::size_t bitwidth = sizeof(T) * CHAR_BIT;
                                             ^~~~~~~~
/media/masaaki/Ubuntu_Disk/tools/Xilinx/Vitis_HLS/2021.2/include/ap_axi_sdata.h:99:48: warning: variable templates only available with -std=c++14 or -std=gnu++14
 template <std::size_t W> constexpr std::size_t bitwidth<ap_int<W>> = W;
                                                ^~~~~~~~~~~~~~~~~~~
/media/masaaki/Ubuntu_Disk/tools/Xilinx/Vitis_HLS/2021.2/include/ap_axi_sdata.h:100:48: warning: variable templates only available with -std=c++14 or -std=gnu++14
 template <std::size_t W> constexpr std::size_t bitwidth<ap_uint<W>> = W;
                                                ^~~~~~~~~~~~~~~~~~~~
/media/masaaki/Ubuntu_Disk/tools/Xilinx/Vitis_HLS/2021.2/include/ap_axi_sdata.h:102:23: warning: variable templates only available with -std=c++14 or -std=gnu++14
 constexpr std::size_t bitwidth<ap_fixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N>> = _AP_W;
                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/media/masaaki/Ubuntu_Disk/tools/Xilinx/Vitis_HLS/2021.2/include/ap_axi_sdata.h:104:23: warning: variable templates only available with -std=c++14 or -std=gnu++14
 constexpr std::size_t bitwidth<ap_ufixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N>> = _AP_W;
                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/media/masaaki/Ubuntu_Disk/tools/Xilinx/Vitis_HLS/2021.2/include/ap_axi_sdata.h:107:23: warning: variable templates only available with -std=c++14 or -std=gnu++14
 constexpr std::size_t bytewidth = (bitwidth<T> + CHAR_BIT - 1) / CHAR_BIT;
                       ^~~~~~~~~
In file included from /media/masaaki/Ubuntu_Disk/Xilinx_github/Vitis_Libraries/vision/L1/include/common/xf_axi_io.hpp:19:0,
                 from /media/masaaki/Ubuntu_Disk/Xilinx_github/Vitis_Libraries/vision/L1/include/common/xf_infra.hpp:29,
                 from ../../../../xf_fast_axis.h:15,
                 from ../../../../xf_fast_axis.cpp:6:
/media/masaaki/Ubuntu_Disk/tools/Xilinx/Vitis_HLS/2021.2/include/utils/x_hls_utils.h:246:10: warning: ‘hls_preserve’ attribute directive ignored [-Wattributes]
 T reg(T d)
          ^
obj/xf_fast_axis_tb.o: In function `main':
/media/masaaki/Ubuntu_Disk/Vitis_HLS/ZYBO_Z7_20/2021.2/xf_fast_axis/xf_fast_axis/solution1/csim/build/../../../../xf_fast_axis_tb.cpp:51: undefined reference to `cv::FAST(cv::_InputArray const&, std::vector<cv::KeyPoint, std::allocator<cv::KeyPoint> >&, int, bool)'
collect2: error: ld returned 1 exit status
make: *** [csim.exe] Error 1
ERROR: [SIM 211-100] 'csim_design' failed: compilation error(s).
INFO: [SIM 211-3] *************** CSIM finish ***************
INFO: [HLS 200-111] Finished Command csim_design CPU user time: 7.47 seconds. CPU system time: 0.5 seconds. Elapsed time: 6.79 seconds; current allocated memory: -937.109 MB.
4
    while executing
"source xf_fast_axis_home.tcl"
    ("uplevel" body line 1)
    invoked from within
"uplevel \#0 [list source $arg] "

INFO: [HLS 200-112] Total CPU user time: 9.37 seconds. Total CPU system time: 0.94 seconds. Total elapsed time: 15.71 seconds; peak allocated memory: 211.121 MB.
INFO: [Common 17-206] Exiting vitis_hls at Sat Feb  5 03:22:04 2022...
(base) masaaki@masaaki-H110M4-M01:/media/masaaki/Ubuntu_Disk/Vitis_HLS/ZYBO_Z7_20/2021.2/xf_fast_axis$ 


エラーは、

xf_fast_axis_tb.cpp:51: undefined reference to `cv::FAST(cv::_InputArray const&, std::vector<cv::KeyPoint, std::allocator<cv::KeyPoint> >&, int, bool)'

だった。
いろいろと cv::FAST() をいじってみたが、エラーが解消されない。
それじゃということで、OpenCV の関数なので、ハードウェアには関係ないので、コメントアウトすることにした。それに関連する行もコメントアウトした。新しい xf_fast_axis_tb.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.
 */
// xf_fast_axis_tb.cpp
// 2022/02/03 by marsee
// fast_accel を AXI4-Stream 入出力に変更
// 2022/02/04 : cv::FASTと関連する文ををコメントアウト、コンパイルが通らなかったため。。。orz

#include "opencv2/opencv.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgcodecs/imgcodecs.hpp"
#include "opencv2/features2d.hpp"
#include "common/xf_headers.hpp"
#include "common/xf_axi.hpp"
#include "common/xf_sw_utils.hpp"
#include "xf_fast_axis.h"

void fast_accel_axis(AXI_STREAM& _src, AXI_STREAM& _dst, unsigned char threshold,
    int32_t row, int32_t cols);

int main(int argc, char** argv) {
    cv::Mat in_img, out_img, out_img_ocv, out_hls;
    cv::Mat in_gray;

    in_img = cv::imread(argv[1], 1); // reading in the color image

    if (!in_img.data) {
        fprintf(stderr, "Failed to load the image ... %s\n ", argv[1]);
        return -1;
    }

    std::vector<cv::KeyPoint> keypoints;

    uchar_t threshold = 20; // threshold

    cvtColor(in_img, in_gray, cv::COLOR_BGR2GRAY);

    // OPenCV reference function

    //cv::FAST(in_gray, keypoints, threshold, true, (cv::FastFeatureDetector::DetectorType)0);

    unsigned short imgwidth = in_img.cols;
    unsigned short imgheight = in_img.rows;

    out_hls.create(in_gray.rows, in_gray.cols, CV_8U);

    // Call the top function
    AXI_STREAM _src,_dst;
    xf::cv::cvMat2AXIvideoxf<NPxPC, STREAMW>(in_gray, _src);
    fast_accel_axis(_src, _dst, threshold, imgheight, imgwidth);
    xf::cv::AXIvideo2cvMatxf<NPxPC, STREAMW>(_dst, out_hls);

    std::vector<cv::Point> hls_points;
    std::vector<cv::Point> ocv_points;
    std::vector<cv::Point> common_points;
    std::vector<cv::Point> noncommon_points;

    FILE *fp, *fp1;
    fp = fopen("ocvpoints.txt", "w");
    fp1 = fopen("hlspoints.txt", "w");

    int nsize = keypoints.size();

    printf("ocvpoints:%d=\n", nsize);

    for (int i = 0; i < nsize; i++) {
        int x = keypoints[i].pt.x;
        int y = keypoints[i].pt.y;
        ocv_points.push_back(cv::Point(x, y));
        // fprintf(fp, "x = %d, y = %d\n", x, y);
    }
    // fclose(fp);

    out_img_ocv = in_img.clone();

    int ocv_x = 0, ocv_y = 0;

    for (int cnt1 = 0; cnt1 < keypoints.size(); cnt1++) {
        ocv_x = keypoints[cnt1].pt.x;
        ocv_y = keypoints[cnt1].pt.y;
        cv::circle(out_img_ocv, cv::Point(ocv_x, ocv_y), 5, cv::Scalar(0, 0, 255), 2, 8, 0);
    }
    cv::imwrite("output_ocv.png", out_img_ocv);
    //
    out_img = in_gray.clone();

    for (int j = 0; j < out_hls.rows; j++) {
        for (int i = 0; i < out_hls.cols; i++) {
            unsigned char value = out_hls.at<unsigned char>(j, i);
            if (value != 0) {
                short int y, x;
                y = j;
                x = i;

                cv::Point tmp;
                tmp.x = i;
                tmp.y = j;

                hls_points.push_back(tmp);
                if (j > 0) cv::circle(out_img, cv::Point(x, y), 5, cv::Scalar(0, 0, 255, 255), 2, 8, 0);
            }
        }
    }

    int nsize1 = hls_points.size();
    printf("hls_points.size() = %d\n", hls_points.size());

    int Nocv = ocv_points.size();
    int Nhls = hls_points.size();

    for (int r = 0; r < nsize1; r++) {
        int a, b;
        a = (int)hls_points[r].x;
        b = (int)hls_points[r].y;
        fprintf(fp1, "x = %d, y = %d\n", a, b);
    }
    fclose(fp1);

    for (int j = 0; j < Nocv; j++) {
        for (int k = 0; k < Nhls; k++) {
            if ((ocv_points[j].x == ((hls_points[k].x))) && (ocv_points[j].y == ((hls_points[k].y)))) {
                common_points.push_back(ocv_points[j]);
            }
        }
    }

    FILE* fpt3;
    fpt3 = fopen("common.txt", "w");

    for (unsigned int p = 0; p < common_points.size(); p++) {
        fprintf(fpt3, "x = %d, y = %d\n", common_points[p].x, common_points[p].y);
    }

    fclose(fpt3);

    cv::imwrite("output_hls.png", out_img);

    // Results verification:
    float persuccess, perloss, pergain;

    int totalocv = ocv_points.size();
    int totalhls = hls_points.size();
    int ncommon = common_points.size();

    persuccess = (((float)ncommon / totalhls) * 100);
    perloss = (((float)(totalocv - ncommon) / totalocv) * 100);
    pergain = (((float)(totalhls - ncommon) / totalhls) * 100);

    std::cout << "INFO: Verification results:" << std::endl;
    std::cout << "\tCommon = " << ncommon << std::endl;
    std::cout << "\tSuccess = " << persuccess << std::endl;
    std::cout << "\tLoss = " << perloss << std::endl;
    std::cout << "\tGain = " << pergain << std::endl;

    /*if (persuccess < 80) {
        fprintf(stderr, "ERROR: Test Failed.\n ");
        return EXIT_FAILURE;
    } */

    return 0;
}


Vitis HLS 2021.2 の GUI を立ち上げた。
Vitis_Vision2_169_220205.png

テストベンチ・ファイルを変更した。
C シミュレーションを実行したら、成功した。
Vitis_Vision2_170_220205.png

xf_fast_axis/solution1/csim/build ディレクトリに移動した。
Vitis_Vision2_171_220205.png

output_hls.png が生成されていた。
元画像を白黒にして、コーナーに丸を付けている。
Vitis_Vision2_172_220205.png

hlspoitns.txt を見ると、コーナーが座標で表されている。
Vitis_Vision2_173_220205.png
  1. 2022年02月05日 03:52 |
  2. Vitis_Vision
  3. | トラックバック:0
  4. | コメント:0

Vitis HLS 2021.2 で Vitis Vision Library L1 を使用するために TCL スクリプトでプロジェクトを作成する3(fast 編1)

Vitis HLS 2021.2 で Vitis Vision Library L1 を使用するために TCL スクリプトでプロジェクトを作成する2(resize 編2)”の続き。

TCL スクリプトで Vitis HLS 2021.2 のプロジェクトを作成して、Vitis Vision Library L1 をやってみることにしたということで、前回は、AXI4-Stream 入出力版の resize の C シミュレーション、C コードの合成、C/RTL 協調シミュレーション、Export RTL、 Implementation を行った。今回は、fast をやってみることにした。コードを貼っておく。

まずは、Vitis HLS 2021.2 のプロジェクトを作成するための TCL スクリプトの xf_fast_axis_home.tcl を示す。

open_project xf_fast_axis
set_top fast_accel_axis
add_files xf_fast_axis.cpp -cflags "-I/media/masaaki/Ubuntu_Disk/Xilinx_github/Vitis_Libraries/vision/L1/include -std=c++0x"
add_files -tb xf_fast_axis_tb.cpp -cflags "-I/media/masaaki/Ubuntu_Disk/Xilinx_github/Vitis_Libraries/vision/L1/include -I/usr/local/include -std=c++0x -Wno-unknown-pragmas" -csimflags "-Wno-unknown-pragmas"
open_solution "solution1" -flow_target vivado
set_part {xc7z020-clg400-1}
create_clock -period 10 -name default
config_export -format ip_catalog -rtl verilog -vivado_clock 10
csim_design -ldflags {-L/usr/local/lib -lopencv_core -lopencv_imgcodecs -lopencv_imgproc} -argv {/media/masaaki/Ubuntu_Disk/Vitis_HLS/ZYBO_Z7_20/2021.2/xf_fast_axis/test2.jpg}
exit


xf_fast_axis.h を示す。

// xf_fast_axis.h
// 2022/02/03 by marsee
// Vitis_Libraries/vision/L1/examples/fast/xf_fast_config.h, Vitis_Libraries/vision/L1/examples/fast/build/xf_config_params.h を引用
//

#ifndef _XF_FAST_CONFIG_H_
#define _XF_FAST_CONFIG_H_

#include <stdint.h>
#include "hls_stream.h"
#include "ap_int.h"
#include "common/xf_common.hpp"
#include "common/xf_utility.hpp"
#include "ap_axi_sdata.h"
#include "common/xf_infra.hpp"
#include "common/xf_axi_io.hpp"
#include "features/xf_fast.hpp"

#define RGB  0
#define GRAY 1

#define NPxPC XF_NPPC1

#if GRAY
#define TYPE XF_8UC1
#define CHANNELS 1
#define STREAMW 8
#else
#define TYPE XF_8UC3
#define CHANNELS 3
#define STREAMW 32
#endif
typedef hls::stream<ap_axiu<STREAMW,1,1,1> > AXI_STREAM;

#define NMS 1

#define WIDTH 1920
#define HEIGHT 1080

#define MAXCORNERS 1024

#endif


xf_fast_axis.cpp を示す。

// xf_fast_axis.cpp
// 2022/02/03 by marsee
// Vitis_Libraries/vision/L1/examples/fast/xf_fast_accel.cpp から引用した
// https://github.com/Xilinx/Vitis_Libraries/blob/master/vision/L1/examples/fast/xf_fast_accel.cpp

#include "xf_fast_axis.h"

void fast_accel_axis(AXI_STREAM& _src, AXI_STREAM& _dst, unsigned char threshold, 
    int32_t row, int32_t cols){
#pragma HLS INTERFACE mode=s_axilite port=threshold
#pragma HLS INTERFACE mode=s_axilite port=cols
#pragma HLS INTERFACE mode=s_axilite port=row
#pragma HLS INTERFACE mode=s_axilite port=return
#pragma HLS INTERFACE mode=axis register_mode=both port=_src register
#pragma HLS INTERFACE mode=axis register_mode=both port=_dst register

    xf::cv::Mat<TYPE, HEIGHT, WIDTH, NPxPC> img_in(row, cols);
    xf::cv::Mat<TYPE, HEIGHT, WIDTH, NPxPC> img_out(row, cols);

#pragma HLS DATAFLOW

    xf::cv::AXIvideo2xfMat<STREAMW, TYPE>(_src, img_in);

    xf::cv::fast<NMS, TYPE, HEIGHT, WIDTH, NPxPC>(img_in, img_out, threshold);

    xf::cv::xfMat2AXIvideo<STREAMW, TYPE>(img_out, _dst);
}


テストベンチの xf_fast_axis_tb.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.
 */
 // xf_fast_axis_tb.cpp
 // 2022/02/03 : fast_accel を AXI4-Stream 入出力に変更 by marsee
 // 

#include "opencv2/opencv.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgcodecs/imgcodecs.hpp"
#include "common/xf_headers.hpp"
#include "common/xf_axi.hpp"
#include "common/xf_sw_utils.hpp"
#include "xf_fast_axis.h"

void fast_accel_axis(AXI_STREAM& _src, AXI_STREAM& _dst, unsigned char threshold,
    int32_t row, int32_t cols);

int main(int argc, char** argv) {
    cv::Mat in_img, out_img, out_img_ocv, out_hls;
    cv::Mat in_gray;

    in_img = cv::imread(argv[1], 1); // reading in the color image

    if (!in_img.data) {
        fprintf(stderr, "Failed to load the image ... %s\n ", argv[1]);
        return -1;
    }

    std::vector<cv::KeyPoint> keypoints;

    uchar_t threshold = 20; // threshold

    cvtColor(in_img, in_gray, cv::COLOR_BGR2GRAY);

    // OPenCV reference function

    cv::FAST(in_gray, keypoints, threshold, NMS);

    unsigned short imgwidth = in_img.cols;
    unsigned short imgheight = in_img.rows;

    out_hls.create(in_gray.rows, in_gray.cols, CV_8U);

    // Call the top function
    AXI_STREAM _src,_dst;
    xf::cv::cvMat2AXIvideoxf<NPxPC, STREAMW>(in_gray, _src);
    fast_accel_axis(_src, _dst, threshold, imgheight, imgwidth);
    xf::cv::AXIvideo2cvMatxf<NPxPC, STREAMW>(_dst, out_hls);

    std::vector<cv::Point> hls_points;
    std::vector<cv::Point> ocv_points;
    std::vector<cv::Point> common_points;
    std::vector<cv::Point> noncommon_points;

    FILE *fp, *fp1;
    fp = fopen("ocvpoints.txt", "w");
    fp1 = fopen("hlspoints.txt", "w");

    int nsize = keypoints.size();

    printf("ocvpoints:%d=\n", nsize);

    for (int i = 0; i < nsize; i++) {
        int x = keypoints[i].pt.x;
        int y = keypoints[i].pt.y;
        ocv_points.push_back(cv::Point(x, y));
        // fprintf(fp, "x = %d, y = %d\n", x, y);
    }
    // fclose(fp);

    out_img_ocv = in_img.clone();

    int ocv_x = 0, ocv_y = 0;

    for (int cnt1 = 0; cnt1 < keypoints.size(); cnt1++) {
        ocv_x = keypoints[cnt1].pt.x;
        ocv_y = keypoints[cnt1].pt.y;
        cv::circle(out_img_ocv, cv::Point(ocv_x, ocv_y), 5, cv::Scalar(0, 0, 255), 2, 8, 0);
    }
    cv::imwrite("output_ocv.png", out_img_ocv);
    //
    out_img = in_gray.clone();

    for (int j = 0; j < out_hls.rows; j++) {
        for (int i = 0; i < out_hls.cols; i++) {
            unsigned char value = out_hls.at<unsigned char>(j, i);
            if (value != 0) {
                short int y, x;
                y = j;
                x = i;

                cv::Point tmp;
                tmp.x = i;
                tmp.y = j;

                hls_points.push_back(tmp);
                if (j > 0) cv::circle(out_img, cv::Point(x, y), 5, cv::Scalar(0, 0, 255, 255), 2, 8, 0);
            }
        }
    }

    int nsize1 = hls_points.size();

    int Nocv = ocv_points.size();
    int Nhls = hls_points.size();

    for (int r = 0; r < nsize1; r++) {
        int a, b;
        a = (int)hls_points[r].x;
        b = (int)hls_points[r].y;
        fprintf(fp1, "x = %d, y = %d\n", a, b);
    }
    fclose(fp1);

    for (int j = 0; j < Nocv; j++) {
        for (int k = 0; k < Nhls; k++) {
            if ((ocv_points[j].x == ((hls_points[k].x))) && (ocv_points[j].y == ((hls_points[k].y)))) {
                common_points.push_back(ocv_points[j]);
            }
        }
    }

    FILE* fpt3;
    fpt3 = fopen("common.txt", "w");

    for (unsigned int p = 0; p < common_points.size(); p++) {
        fprintf(fpt3, "x = %d, y = %d\n", common_points[p].x, common_points[p].y);
    }

    fclose(fpt3);

    cv::imwrite("output_hls.png", out_img);

    // Results verification:
    float persuccess, perloss, pergain;

    int totalocv = ocv_points.size();
    int totalhls = hls_points.size();
    int ncommon = common_points.size();

    persuccess = (((float)ncommon / totalhls) * 100);
    perloss = (((float)(totalocv - ncommon) / totalocv) * 100);
    pergain = (((float)(totalhls - ncommon) / totalhls) * 100);

    std::cout << "INFO: Verification results:" << std::endl;
    std::cout << "\tCommon = " << ncommon << std::endl;
    std::cout << "\tSuccess = " << persuccess << std::endl;
    std::cout << "\tLoss = " << perloss << std::endl;
    std::cout << "\tGain = " << pergain << std::endl;

    if (persuccess < 80) {
        fprintf(stderr, "ERROR: Test Failed.\n ");
        return EXIT_FAILURE;
    }

    return 0;
}


400 x 300 ピクセルの test2.jpg 画像を示す。
Vitis_Vision2_164_220202.png

xf_fast_axis ディレクトリを作成して、ファイルを置いておいた。
Vitis_Vision2_166_220204.png
  1. 2022年02月04日 04:27 |
  2. Vitis_Vision
  3. | トラックバック:0
  4. | コメント:0
»