FC2カウンター FPGAの部屋 PYNQ の画像ファイル・フォーマットを調査するために choose_RGB IP を Vitis HLS 2021.2 で作成する1
fc2ブログ

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

FPGAの部屋

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

PYNQ の画像ファイル・フォーマットを調査するために choose_RGB IP を Vitis HLS 2021.2 で作成する1

自作した Vivado プロジェクトの DMA_pow2_test を PYNQ で実行する2(制御用 Python コードの書き方を調べる)”で引用した pynq-helloworld/resizer_pl.ipynb ファイルだが、このフレーム・ワークを自分で使用しようとした時に 32 ビット・フィールドの内の R, G, B の割当が分からない?ので、Vitis HLS 2021.2 を使って、確かめてみることにした。

choose_RGB.cpp を示す。

// choose_RGB.cpp
// 2021/03/10 by marsee
//

#include <stdint.h>
#include <ap_int.h>
#include <hls_stream.h>
#include <ap_axi_sdata.h>

int choose_RGB(hls::stream<ap_axiu<32,1,1,1> >& ins, hls::stream<ap_axiu<32,1,1,1> >& outs,
        int32_t row_size, int32_t col_size, int32_t choose_rgb_val){
#pragma HLS INTERFACE mode=s_axilite port=choose_rgb_val
#pragma HLS INTERFACE mode=s_axilite port=col_size
#pragma HLS INTERFACE mode=s_axilite port=row_size
#pragma HLS INTERFACE mode=s_axilite port=return
#pragma HLS INTERFACE mode=axis register_mode=both port=outs register
#pragma HLS INTERFACE mode=axis register_mode=both port=ins register

    ap_axiu<32,1,1,1> dt;

    for(int row=0; row < row_size; row++){
#pragma HLS LOOP_TRIPCOUNT avg=4 max=4 min=4
        for(int col=0; col < col_size; col++){
#pragma HLS LOOP_TRIPCOUNT avg=32 max=32 min=32
            ins >> dt;
            switch(choose_rgb_val){
            case 0:
                dt.data &= 0xff;
                break;
            case 1:
                dt.data &= 0xff00;
                break;
            case 2:
                dt.data &= 0xff0000;
                break;
            default:
                dt.data &= 0xff000000;
            }
            outs << dt;
        }
    }
    return(0);
}


テストベンチの choose_RGB_tb.cpp を示す。

// choose_RGB_tb.cpp
// 2022/03/10 by marsee
//

#include <stdio.h>
#include <stdint.h>
#include <ap_int.h>
#include <hls_stream.h>
#include <ap_axi_sdata.h>
#include "opencv2/opencv.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgcodecs/imgcodecs.hpp"

int choose_RGB(hls::stream<ap_axiu<32,1,1,1> >& ins, hls::stream<ap_axiu<32,1,1,1> >& outs,
        int32_t row_size, int32_t col_size, int32_t choose_rgb_val);

const char INPUT_IMG_FILE[] = "RGB_test.png";
const char OUTPUT_IMG_FILE[] = "output.png";
const int32_t choose_rgb_val = 1;

int main(){
    hls::stream<ap_axiu<32,1,1,1> > ins;
    hls::stream<ap_axiu<32,1,1,1> > outs;
    ap_axiu<32,1,1,1> pix;
    ap_axiu<32,1,1,1> vals;

    // JPG ファイルをMat に読み込む
    cv::Mat img = cv::imread(INPUT_IMG_FILE);

    // ピクセルを入れる領域の確保
    std::vector<uint32_t> rd_buf(sizeof(uint32_t)*img.cols*img.rows);
    std::vector<uint32_t> out_buf(sizeof(uint32_t)*img.cols*img.rows);

    // rd_bmp にJPGのピクセルを代入
    cv::Mat_<cv::Vec3b> dst_vec3b = cv::Mat_<cv::Vec3b>(img);
    for (int y=0; y<img.rows; y++){
        for (int x=0; x<img.cols; x++){
            cv::Vec3b pixel;
            pixel = dst_vec3b(y,x);
            rd_buf[y*img.cols+x] = (pixel[0] & 0xff) | ((pixel[1] & 0xff)<<8) | ((pixel[2] & 0xff)<<16); // RGB 8 bits
            // blue - pixel[0]; green - pixel[1]; red - pixel[2];
        }
    }
    for(int j=0; j < img.rows; j++){
        for(int i=0; i < img.cols; i++){
            pix.data = (int32_t)rd_buf[(j*img.cols)+i];

            if (j==0 && i==0)   // 最初のデータの時に TUSER を 1 にする
                pix.user = 1;
            else
                pix.user = 0;

            if (i == img.cols-1) // 行の最後でTLASTをアサートする
                pix.last = 1;
            else
                pix.last = 0;

            pix.keep = 0xf;
            pix.strb = 0xf;
            ins << pix;
        }
    }

    choose_RGB(ins, outs, img.rows, img.cols, choose_rgb_val);

    // out_buf に結果を代入
    for(int j=0; j<img.rows; j++){
        for(int i=0; i<img.cols; i++){
            outs >> pix;
            out_buf[j*img.cols+i] = pix.data;
        }
    }

    // wbmpf に結果を代入
    cv::Mat wbmpf(img.rows, img.cols, CV_8UC3);
    cv::Mat_<cv::Vec3b> sob_vec3b = cv::Mat_<cv::Vec3b>(wbmpf);
    for (int y=0; y<wbmpf.rows; y++){
        for (int x=0; x<wbmpf.cols; x++){
            cv::Vec3b pixel;
            pixel = sob_vec3b(y,x);
            uint32_t rbg = out_buf[y*wbmpf.cols+x];
            pixel[0] = (rbg & 0xff); // blue
            pixel[1] = ((rbg >> 8) & 0xff); // green
            pixel[2] = ((rbg >> 16) & 0xff); // red
            sob_vec3b(y,x) = pixel;
        }
    }
    // 結果を画像ファイルへ出力する
    cv::imwrite(OUTPUT_IMG_FILE, wbmpf);
}


画像ファイルは、32 X 4 ピクセルの R, G, B, RGB 色の行を Pinta で作成した RGB_test.png を使用する。
image_format4PYNQ_1_220311.png

Vitis HLS 2021.2 の choose_RGB プロジェクトを示す。
image_format4PYNQ_2_220311.png

今回のテストベンチ・コードでは OpenCV ライブラリを使用している。
Vitis HLS 2021.1 には内蔵された OpenCV は無いので、別にインストールした OpenCV を指定する。
Vitis HLS の Project メニューから Project Settings... を選択して、Project Settings ダイアログを開いた。
Simulation タブを開いて、choose_RGB_tb.cpp の CFLAGS に

-I/usr/local/include


を設定した。
linker Flags に

-L/usr/local/lib -lopencv_core -lopencv_imgcodecs -lopencv_imgproc


を設定した。
image_format4PYNQ_3_220311.png

更に、 Synthesis をクリックして、 Top Function に choose_RGB を指定した。
image_format4PYNQ_4_220311.png
  1. 2022年03月11日 04:15 |
  2. PYNQ
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


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

トラックバック URL
https://marsee101.blog.fc2.com/tb.php/5526-d345b7c9
この記事にトラックバックする(FC2ブログユーザー)