FC2カウンター FPGAの部屋 2020年03月11日
FC2ブログ

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

FPGAの部屋

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

Vivado HLS 2019.2 で xfOpenCV のAXI4-Stream 版 medianblur をやってみる1

Vivado HLS 2019.2 で xfOpenCV の medianblur をやってみる1”で動いていた AXI4-Stream 版 medianblur が動かなくなったと書いたが、これは、画像の大きさを指定するところで、height と width を取り違えていたからだった。4k2k 画像から HD 画像に変更しようとして、height と width を間違ってしまっていたのだった。orz

新たに作り直したAXI4-Steram 版の medianblur を紹介する。だいぶ自分の書き方になってきたのだが、xf_headers.h は Xilinx 社のソースコードをそのまま使用している。
なお、白黒画像とカラー画像を define で切り替えるようにしてある。

最初に xf_median_blur.h を貼っておく。

// xf_median_blur.h
// 2020/03/09 by marsee
// xfopencv/examples/medianblur/xf_median_blur_config.h のコードを引用している
// https://github.com/Xilinx/xfopencv/blob/master/examples/medianblur/xf_median_blur_config.h
// xfopencv/examples/medianblur/xf_config_params.h のコードを引用している
// https://github.com/Xilinx/xfopencv/blob/master/examples/medianblur/xf_config_params.h

#ifndef __XF_MEDIAN_BLUR_H__
#define __XF_MEDIAN_BLUR_H__

#include "hls_stream.h"
#include "ap_int.h"
#include "common/xf_common.h"
#include "imgproc/xf_median_blur.hpp"
#include "common/xf_axi_sdata.h"

#define NO  1  // Normal Operation
#define RO  0  // Resource Optimized

#define RGB 1
#define GRAY 0

/* Filter window size*/
#define WINDOW_SIZE 3

/*  set the height and weight  */
#define WIDTH  1920
#define HEIGHT 1080

#if NO
#define NPxPC XF_NPPC1
#else
#define NPxPC XF_NPPC8
#endif

#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;

#endif


xf_median_blur.cpp を貼っておく。
(2020/03/12:修正) img_height と img_width を AXI4-Lite Slave に変更した。

// xf_median_blur.cpp
// 2020/03/08 by marsee

// xfopencv/HLS_Use_Model/Standalone_HLS_AXI_Example/xf_ip_accel_app.cpp のコードを引用している
// https://github.com/Xilinx/xfopencv/blob/master/HLS_Use_Model/Standalone_HLS_AXI_Example/xf_ip_accel_app.cpp
// xfopencv/examples/medianblur/xf_median_blur_accel.cpp のコードを引用している
// https://github.com/Xilinx/xfopencv/blob/master/examples/medianblur/xf_median_blur_accel.cpp

#include "xf_median_blur.h"
#include "common/xf_infra.h"

void median_blur_accel(xf::Mat<TYPE, HEIGHT, WIDTH, NPxPC> &_src, xf::Mat<TYPE, HEIGHT, WIDTH, NPxPC> &_dst)
{
    xf::medianBlur <WINDOW_SIZE, XF_BORDER_REPLICATE, TYPE, HEIGHT, WIDTH,  NPxPC> (_src, _dst);
}

void xf_median_blur(AXI_STREAM& _src, AXI_STREAM& _dst, int img_height, int img_width){
#pragma HLS INTERFACE s_axilite port=img_width
#pragma HLS INTERFACE s_axilite port=img_height
#pragma HLS INTERFACE s_axilite port=return
#pragma HLS INTERFACE axis register both  port=_src
#pragma HLS INTERFACE axis register both  port=_dst

     xf::Mat<TYPE, HEIGHT, WIDTH, NPxPC> img_in(img_height, img_width);
     xf::Mat<TYPE, HEIGHT, WIDTH, NPxPC> img_out(img_height, img_width);

#pragma HLS stream variable=img_in.data dim=1 depth=16
#pragma HLS stream variable=img_out.data dim=1 depth=16
#pragma HLS dataflow

    xf::AXIvideo2xfMat(_src, img_in);

    median_blur_accel(img_in, img_out);

    xf::xfMat2AXIvideo(img_out, _dst);
}


最後にテストベンチの xf_median_blur_tb.cpp を貼っておく。

// xf_median_blur_config_tb.cpp
// 2020/03/08 by marsee

// xfopencv/HLS_Use_Model/Standalone_HLS_AXI_Example/xf_dilation_tb.cpp のコードを引用している
// https://github.com/Xilinx/xfopencv/blob/master/HLS_Use_Model/Standalone_HLS_AXI_Example/xf_dilation_tb.cpp
// xfopencv/examples/medianblur/xf_median_blur_tb.cpp のコードを引用している
// https://github.com/Xilinx/xfopencv/blob/master/examples/medianblur/xf_median_blur_tb.cpp

#include "xf_headers.h"
#include "xf_median_blur.h"
#include "common/xf_infra.h"
#include "common/xf_axi.h"

void xf_median_blur(AXI_STREAM& _src, AXI_STREAM& _dst, int img_height, int img_width);

int main(int argc, char** argv)
{

    if(argc != 2)
    {
        fprintf(stderr,"Invalid Number of Arguments!\nUsage:\n");
        fprintf(stderr,"<Executable Name> <input image path> \n");
        return -1;
    }

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

    // reading in the color image
#if GRAY
    in_img = cv::imread(argv[1], 0);
#else
    in_img = cv::imread(argv[1], 1);
#endif
    if (in_img.data == NULL)
    {
        fprintf(stderr,"Cannot open image at %s\n", argv[1]);
        return 0;
    }
    // create memory for output images
    /*  reading the gray/color image  */
#if GRAY
    ocv_ref.create(in_img.rows,in_img.cols,CV_8UC1);
    out_img.create(in_img.rows,in_img.cols,CV_8UC1);
    diff.create(in_img.rows,in_img.cols,CV_8UC1);
    in_img1.create(in_img.rows,in_img.cols,CV_8UC1);

#else
    ocv_ref.create(in_img.rows,in_img.cols,CV_8UC3);
    out_img.create(in_img.rows,in_img.cols,CV_8UC3);
    diff.create(in_img.rows,in_img.cols,CV_8UC3);
    in_img1.create(in_img.rows,in_img.cols,CV_8UC3);
#endif
    int img_height = in_img.rows;
    int img_width = in_img.cols;

    /////////////////   Opencv  Reference  ////////////////////////
    cv::medianBlur(in_img,ocv_ref,WINDOW_SIZE);
    cv::imwrite("out_ocv.jpg", ocv_ref);

    AXI_STREAM _src,_dst;

    cvMat2AXIvideoxf<NPxPC>(in_img, _src);
    xf_median_blur(_src, _dst, img_height, img_width);
    AXIvideo2cvMatxf<NPxPC>(_dst, in_img1);

    cv::imwrite("hls.jpg", in_img1);
    //////////////////  Compute Absolute Difference ////////////////////

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

    float err_per;
    xf::analyzeDiff(diff,0,err_per);
    cv::imwrite("diff_img.jpg",diff);

    in_img.~Mat();
    out_img.~Mat();
    ocv_ref.~Mat();
    in_img.~Mat();
    in_img1.~Mat();
    diff.~Mat();

    if(err_per > 0.0f)
    {
        return 1;
    }

    return 0;
}


Vivado HLS 2019.2 で medianblur プロジェクトを作成した。
xfOpenCV_90_200310.png

Vivado HLS 2019.2 の Project メニューから Project Settings... を選択すると、Project Settings (medianblur) ダイアログが開く。
Project Settings (medianblur) ダイアログで、Simulation をクリックして、xf_median_blur_tb.cpp の CFLAGS に

-D__SDSVHLS__ -I/home/masaaki/xfopencv/include --std=c++0x

を設定した。
また、Input Arguments に

im0.jpg

を設定した。

同様に、Project Settings (medianblur) ダイアログで、Synthesis をクリックして、 xf_median_blur.cpp の CFLAGS に

-D__SDSVHLS__ -I/home/masaaki/xfopencv/include --std=c++0x

を設定した。

最後に Solution メニューの Solution Settings... を選択して、Solution Settings (solution1) ダイアログが表示される。 Cosimulation をクリックして、Input Arguments に

im0.jpg

を設定した。

im0.jpg は”Vivado HLS 2019.2 で xfOpenCV の medianblur をやってみる1”と同じもので、ノイズを加えてあるカラー画像となっている。これは、xfopencv/examples/medianblur/data/im0.jpg を、Pinta ツールのサイズ変換で 800 x 450 ピクセルに縮小して、ノイズを加えた画像である。
  1. 2020年03月11日 04:23 |
  2. reVISION, xfOpenCV
  3. | トラックバック:0
  4. | コメント:0