FC2カウンター FPGAの部屋 Vivado HLSにおける固定小数点の誤差を平均2乗誤差で算出する

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

FPGAの部屋

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

Vivado HLSにおける固定小数点の誤差を平均2乗誤差で算出する

Vivado HLS 2014.4 で int 型で予め左シフトして小数を整数にして演算したり、固定小数点型を使って小数点を含んだ演算をしてきた。今までフィーリングでこれで大丈夫かな?と判定してきたが、流石になにか判定基準が欲しい。

そこで、平均2乗誤差を導入することにした。平均2乗誤差 MSE (mean squared error) を次に式で求めることにする。(「二乗誤差とPSNR」を参照させて頂いた)

Σ((浮動小数点数のアンシャープマスキング・フィルタ処理値) - (固定小数点のアンシャープマスキング・フィルタ処理値))の2乗) / (総画素数 - 2行分の画素)

分母だが、最上位の2行は元の画素値なので、それを含めない画素数とした。

これを計算して見ると、固定小数点型を使用した場合の

ap_ufixed<8, 8, AP_RND, AP_SAT> z;

と定義した時の平均2乗誤差を示す。(C シミュレーション結果)
unsharp_mask_70_151013.png

mse_b = 0.00679348
mse_g = 0.00679348
mse_r = 0.0078125
mse = 0.00713315

となった。
なお、mse_b が青の平均2乗誤差、mse_g が緑の平均2乗誤差、mse_r が赤の平均2乗誤差、mse がその3色の平均2乗誤差となる。

次に、

ap_ufixed<8, 8, AP_TRN, AP_SAT> z;

と定義した時の平均2乗誤差は、

mse_b = 0.0108696
mse_g = 0.0125679
mse_r = 0.0288723
mse = 0.0174366

となって、AP_RND よりも大きくなった。(C シミュレーション結果)
unsharp_mask_71_151013.png

次に、 int 型で予め左シフトして小数を整数にして演算した時の平均2乗誤差を示す。(C シミュレーション結果)
unsharp_mask_72_151013.png

mse_b = 0.0108696
mse_g = 0.0125679
mse_r = 0.0288723
mse = 0.0174366

固定小数点型で量子化モードが AP_TRN の時の平均2乗誤差と同じになった。

ちなみに、 int 型で予め左シフトして小数を整数にして演算した時で、PRECISION を 8 にした時の平均2乗誤差を示す。(今までは 6。C++ソースコード参照

mse_b = 0.00611413
mse_g = 0.00577446
mse_r = 0.0115489
mse = 0.0078125


どの辺りの平均2乗誤差を目指そうか?迷うが、PRECISION = 8 のアンシャープマスキング・フィルタ画像と PRECISION = 6 のアンシャープマスキング・フィルタ画像がほとんど変わらないので、 PRECISION = 6 の時の平均2乗誤差を目標としよう。
つまり、固定小数点での量子化モードはAP_TRN にする事になる。

PRECISION = 8 のアンシャープマスキング・フィルタ画像を示す。(K = 2.5)
unsharp_mask_73_151013.png

PRECISION = 6 のアンシャープマスキング・フィルタ画像を示す。(K = 2.5)
unsharp_mask_74_151013.png

平均2乗誤差を取る付近の unsharp_mask_axis_tb.cpp のコードを下に示す。

    // ハードウェアとソフトウェアのラプラシアン・フィルタの値のチェック
    cout << endl;
    cout << "outs" << endl;
    double mse = 0;    // 全体の平均2乗誤差
    double mse_r = 0;    // 赤の平均2乗誤差
    double mse_g = 0;    // 緑の平均2乗誤差
    double mse_b = 0;    // 青の平均2乗誤差
    for(int j=0; j < bmpihr.biHeight; j++){
        for(i=0; i < bmpihr.biWidth; i++){
            outs >> vals;
            outs_soft >> vals_soft;
            ap_int<32> val = vals.data;
            ap_int<32> val_soft = vals_soft.data;

            hw_usmd[(j*bmpihr.biWidth)+i] = (int)val;

            if (val != val_soft){
                printf("ERROR HW and SW results mismatch i = %ld, j = %ld, HW = %d, SW = %d\n", i, j, (int)val, (int)val_soft);
                //return(1);
            }
            if (vals.last)
                cout << "AXI-Stream is end" << endl;
            mse_b += pow(((val_soft & 0xff) - (val & 0xff)), 2.0);
            mse_g += pow((((val_soft>>8)&0xff) - ((val>>8)&0xff)), 2.0);
            mse_r += pow((((val_soft>>16)&0xff) - ((val>>16)&0xff)), 2.0);
        }
    }
    mse_b = mse_b/(bmpihr.biWidth*(bmpihr.biHeight-2)); // 2行は元の画素値なので、平均から外す
    mse_g = mse_g/(bmpihr.biWidth*(bmpihr.biHeight-2)); // 2行は元の画素値なので、平均から外す
    mse_r = mse_r/(bmpihr.biWidth*(bmpihr.biHeight-2)); // 2行は元の画素値なので、平均から外す
    mse = (mse_b + mse_g + mse_r)/3;
    cout << "mse_b = " << mse_b << endl;
    cout << "mse_g = " << mse_g << endl;
    cout << "mse_r = " << mse_r << endl;
    cout << "mse = " << mse << endl;
    //cout << "Success HW and SW results match" << endl;
    cout << endl;

  1. 2015年10月13日 16:02 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


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

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