FC2カウンター FPGAの部屋 Vivado HLS 2015.4 で OpenCV を使ってみた3(Sobelフィルタを試した1)

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

FPGAの部屋

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

Vivado HLS 2015.4 で OpenCV を使ってみた3(Sobelフィルタを試した1)

Vivado HLS 2015.4 で OpenCV を使ってみた2(テストベンチに Mat を使って実装した)”の続き。

前回はテストベンチをOpenCV 2.X のMat で書き直した。今回はSobel フィルタを試してみた。
初めにカラーの状態でSobel フィルタを試してみたところ、上手く行ったのだが、GRAY変換してSobel フィルタを掛ける所で、いろいろと試行錯誤してしまった。最初はhls::CvtColor の書き方が分からなかったのだが、”Output of hls::CvtColor appears gray scale.”を見たら分かった。このWebページからは、GRAY_IMAGEの定義も引用させて頂いた。ありがとうございます。ただ、このWebページではHLS_RGB2GRAY を使っているようだが、Mat フォーマットを考えても HLS_BGR2GRAY のようだ。(ツィターで教えて頂いた皆さん、ありがとうございました)
しかし、多少問題があって、HLS_RGB2GRAY を使った時は(当然、OpenCVのテストベンチの方も CV_RGB2GRAY を使用している)エラーが 0 なのだが、HLS_BGR2GRAY を使った時はエラーが 3 つほど出てしまう。どのエラーも誤差は 1 か 2 なので、演算誤差なのかな?と思うので、これで良しとした。(演算の時の型が違うのだろうか?浮動小数点演算と整数演算の違いとか?まだ分からないが。。。)
なお、Xilinx Wiki の hls::CvtColor のページを参考にした。

昨日1日がかりで出来上がったテストベンチの opencv_ex_ug_tb.cpp を示す。Sobel フィルタは X 軸方向のみとなっている。

// opencv_ex_ug_tb.cpp
// 2016/04/02 by marsee
// OpenCV 2 の Mat を使用したバージョン
// 2016/04/03 : グレー変換あり Sobel フィルタ

#include <iostream>
#include "hls_opencv.h"
#include "opencv_ex_ug.h"

using namespace cv;

#define INPUT_IMAGE        "test.jpg"
#define OUTPUT_IMAGE    "test_result.jpg"
#define OUTPUT_IMAGE_CV    "test_result_cv.jpg"

void image_filter(AXI_STREAM& INPUT_STREAM, AXI_STREAM& OUTPUT_STREAM, int rows, int
cols);
void opencv_imaga_filter(Mat& src, Mat& dst);

int main (int argc, char** argv) {
    // OpenCV で 画像を読み込む
    Mat src = imread(INPUT_IMAGE);
    AXI_STREAM src_axi, dst_axi;

    // Mat フォーマットから AXI4 Stream へ変換
    cvMat2AXIvideo(src, src_axi);

    // image_filter() 関数をコール
    image_filter(src_axi, dst_axi, src.rows, src.cols);

    // AXI4 Stream から Mat フォーマットへ変換
    // dst は宣言時にサイズとカラー・フォーマットを定義する必要がある
    Mat dst(src.rows, src.cols, CV_8UC3);
    AXIvideo2cvMat(dst_axi, dst);

    // Mat フォーマットからファイルに書き込み
    imwrite(OUTPUT_IMAGE, dst);

    // opencv_image_filter() をコール
    Mat dst_cv(src.rows, src.cols, CV_8UC3);
    opencv_imaga_filter(src, dst_cv);
    imwrite(OUTPUT_IMAGE_CV, dst_cv);

    // dst と dst_cv が同じ画像かどうか?比較する
    for (int y=0; y<src.rows; y++){
        Vec3b* dst_ptr = dst.ptr<Vec3b>(y);
        Vec3b* dst_cv_ptr = dst_cv.ptr<Vec3b>(y);
        for (int x=0; x<src.cols; x++){
            Vec3b dst_bgr = dst_ptr[x];
            Vec3b dst_cv_bgr = dst_cv_ptr[x];

            // bgr のどれかが間違っていたらエラー
            if (dst_bgr[0] != dst_cv_bgr[0] || dst_bgr[1] != dst_cv_bgr[1] || dst_bgr[2] != dst_cv_bgr[2]){
                printf("x = %d, y = %d,  Error dst=%d,%d,%d dst_cv=%d,%d,%d\n", x, y,
                        dst_bgr[0], dst_bgr[1], dst_bgr[0], dst_cv_bgr[0], dst_cv_bgr[1], dst_cv_bgr[2]);
                //return 1;
            }
        }
    }
    printf("Test with 0 errors.\n");

    return 0;
}

void opencv_imaga_filter(Mat& src, Mat& dst){
    Mat gray(src.rows, src.cols, CV_8UC1);
    Mat img0g(src.rows, src.cols, CV_8UC1);

    cvtColor(src, gray, CV_BGR2GRAY);
    Sobel(gray, img0g, IPL_DEPTH_16S, 103);
    cvtColor(img0g, dst, CV_GRAY2BGR);

}


ヘッダの opencv_ex_ug.h を示す。

// 2016/04/03 : GRAY_IMAGE を追加

#ifndef __opencv_ex_ug_H__
#define __opencv_ex_ug_H__

#include "ap_axi_sdata.h"
#include "hls_video.h"

#define MAX_HEIGHT    600
#define MAX_WIDTH    800

typedef hls::stream<ap_axiu<32,1,1,1> > AXI_STREAM;
typedef hls::Scalar<3unsigned char> RGB_PIXEL;
typedef hls::Mat<MAX_HEIGHT, MAX_WIDTH, HLS_8UC3> RGB_IMAGE;
typedef hls::Mat<MAX_HEIGHT, MAX_WIDTH, HLS_8UC1> GRAY_IMAGE;
#endif


C++ソースコードの opencv_ex_ug.cpp を示す。

// opencv_ex_ug.cpp
// 2016/04/02 by marsee
// 2016/04/03 : グレー変換あり Sobel フィルタ

#include "opencv_ex_ug.h"

void image_filter(AXI_STREAM& INPUT_STREAM, AXI_STREAM& OUTPUT_STREAM, int rows, int
cols) {
#pragma HLS DATAFLOW
#pragma HLS INTERFACE ap_stable port=cols
#pragma HLS INTERFACE ap_stable port=rows
#pragma HLS INTERFACE s_axilite port=return
#pragma HLS INTERFACE axis port=OUTPUT_STREAM
#pragma HLS INTERFACE axis port=INPUT_STREAM
#pragma HLS INTERFACE s_axilite port=cols
#pragma HLS INTERFACE s_axilite port=rows

    RGB_IMAGE img_0(rows, cols);
    GRAY_IMAGE img_1g(rows, cols);
    GRAY_IMAGE img_2g(rows, cols);
    RGB_IMAGE img_3(rows, cols);

    hls::AXIvideo2Mat(INPUT_STREAM, img_0);
    hls::CvtColor<HLS_BGR2GRAY>(img_0, img_1g);
    hls::Sobel<1,0,3>(img_1g, img_2g);
    hls::CvtColor<HLS_GRAY2BGR>(img_2g, img_3);
    hls::Mat2AXIvideo(img_3, OUTPUT_STREAM);
}


C シミュレーションを行った。結果を示す。3つエラーが出ている。
Vivado_HLS_OpenCV_17_160403.png

今回から、画像を変更した今までは、A という文字だったがエッジフィルタの効果がよくわからなかったので、画像にした。自分で撮影したZYBOボードの写真の一部を使っている。test.jpg を下に示す。写真のサイズは 189 x 146 ピクセルと中途半端なサイズとなっている。
Vivado_HLS_OpenCV_27_160404.jpg

次に、test_result.jpg つまり、Vivado HLSのHLS ビデオライブラリを使用した場合のSobel フィルタ出力画像を示す。(X 軸方向成分のみです)
Vivado_HLS_OpenCV_28_160404.jpg

最後に、test_result_cv.jpg 、OpenCV での出力画像を示す。(X 軸方向成分のみです)
Vivado_HLS_OpenCV_29_160404.jpg

Vivado HLS 2015.4 で OpenCV を使ってみた4(Sobelフィルタを試した2)”に続く。
  1. 2016年04月04日 04:42 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック URL
http://marsee101.blog19.fc2.com/tb.php/3434-30723059
この記事にトラックバックする(FC2ブログユーザー)