FC2カウンター FPGAの部屋 画像のエッジ検出9(汎用の3x3演算)
fc2ブログ

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

FPGAの部屋

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

画像のエッジ検出9(汎用の3x3演算)

ラプラシアン・フィルタはできたので、SobelフィルタやPrewittフィルタをやってみることにした。その際に、constant 値を変更することで、いろいろなフィルタになるように出来ないかということで、汎用の3x3演算回路を作ってみることにした。
まずは、constant宣言部分を貼る。

-- 設定できる係数は-16 to 15
-- ラプラシアン・フィルタ
constant Xnm1Ynm1VaL1 : integer := -1;
constant XnYnm1VaL1 : integer := -1;
constant Xnp1Ynm1VaL1 : integer := -1;
constant Xnm1YnVaL1 : integer := -1;
constant XnYnVaL1 : integer := 8;
constant Xnp1YnVaL1 : integer := -1;
constant Xnm1Ynp1VaL1 : integer := -1;
constant XnYnp1VaL1 : integer := -1;
constant Xnp1Ynp1VaL1 : integer := -1;

constant Xnm1Ynm1VaL2 : integer := 0;
constant XnYnm1VaL2 : integer := 0;
constant Xnp1Ynm1VaL2 : integer := 0;
constant Xnm1YnVaL2 : integer := 0;
constant XnYnVaL2 : integer := 0;
constant Xnp1YnVaL2 : integer := 0;
constant Xnm1Ynp1VaL2 : integer := 0;
constant XnYnp1VaL2 : integer := 0;
constant Xnp1Ynp1VaL2 : integer := 0;

-- Sobelフィルタ,X方向, Y方向
-- constant Xnm1Ynm1VaL1 : integer := -1;
-- constant XnYnm1VaL1 : integer := 0;
-- constant Xnp1Ynm1VaL1 : integer := 1;
-- constant Xnm1YnVaL1 : integer := -2;
-- constant XnYnVaL1 : integer := 0;
-- constant Xnp1YnVaL1 : integer := 2;
-- constant Xnm1Ynp1VaL1 : integer := -1;
-- constant XnYnp1VaL1 : integer := 0;
-- constant Xnp1Ynp1VaL1 : integer := 1;

-- constant Xnm1Ynm1VaL2 : integer := -1;
-- constant XnYnm1VaL2 : integer := -2;
-- constant Xnp1Ynm1VaL2 : integer := -1;
-- constant Xnm1YnVaL2 : integer := 0;
-- constant XnYnVaL2 : integer := 0;
-- constant Xnp1YnVaL2 : integer := 0;
-- constant Xnm1Ynp1VaL2 : integer := 1;
-- constant XnYnp1VaL2 : integer := 2;
-- constant Xnp1Ynp1VaL2 : integer := 1;

-- Prewittフィルタ, X方向, Y方向
-- constant Xnm1Ynm1VaL1 : integer := -1;
-- constant XnYnm1VaL1 : integer := 0;
-- constant Xnp1Ynm1VaL1 : integer := 1;
-- constant Xnm1YnVaL1 : integer := -1;
-- constant XnYnVaL1 : integer := 0;
-- constant Xnp1YnVaL1 : integer := 1;
-- constant Xnm1Ynp1VaL1 : integer := -1;
-- constant XnYnp1VaL1 : integer := 0;
-- constant Xnp1Ynp1VaL1 : integer := 1;

-- constant Xnm1Ynm1VaL2 : integer := -1;
-- constant XnYnm1VaL2 : integer := -1;
-- constant Xnp1Ynm1VaL2 : integer := -1;
-- constant Xnm1YnVaL2 : integer := 0;
-- constant XnYnVaL2 : integer := 0;
-- constant Xnp1YnVaL2 : integer := 0;
-- constant Xnm1Ynp1VaL2 : integer := 1;
-- constant XnYnp1VaL2 : integer := 1;
-- constant Xnp1Ynp1VaL2 : integer := 1;


それぞれの部分をコメントから解除することで、フィルタを切り替える。
演算部分を下に示す。

    op_int_vaL1 <= Xnm1Ynm1VaL1*CONV_INTEGER(Xnm1Ynm1) + XnYnm1VaL1*CONV_INTEGER(XnYnm1) + Xnp1Ynm1VaL1*CONV_INTEGER(Xnp1Ynm1)
        + Xnm1YnVaL1*CONV_INTEGER(Xnm1Yn) + XnYnVaL1*CONV_INTEGER(XnYn) + Xnp1YnVaL1*CONV_INTEGER(Xnp1Yn)
        + Xnm1Ynp1VaL1*CONV_INTEGER(Xnm1Ynp1) + XnYnp1VaL1*CONV_INTEGER(XnYnp1) + Xnp1Ynp1VaL1*CONV_INTEGER(Xnp1Ynp1);
        
    op_int_vaL2 <= Xnm1Ynm1VaL2*CONV_INTEGER(Xnm1Ynm1) + XnYnm1VaL2*CONV_INTEGER(XnYnm1) + Xnp1Ynm1VaL2*CONV_INTEGER(Xnp1Ynm1)
        + Xnm1YnVaL2*CONV_INTEGER(Xnm1Yn) + XnYnVaL2*CONV_INTEGER(XnYn) + Xnp1YnVaL2*CONV_INTEGER(Xnp1Yn)
        + Xnm1Ynp1VaL2*CONV_INTEGER(Xnm1Ynp1) + XnYnp1VaL2*CONV_INTEGER(XnYnp1) + Xnp1Ynp1VaL2*CONV_INTEGER(Xnp1Ynp1);
    
    op_vaL1 <= CONV_STD_LOGIC_VECTOR(op_int_vaL1, op_vaL1'length);
    op_vaL2 <= CONV_STD_LOGIC_VECTOR(op_int_vaL2, op_vaL2'length);

    process(op_vaL1) begin
        if op_vaL1(op_vaL1'left)='1' then -- 負の値
            abs_op_cal_vaL1 <= not(op_vaL1 -1);
        else -- 正の数
            abs_op_cal_vaL1 <= op_vaL1;
        end if;
    end process;
    process(op_vaL2) begin
        if op_vaL2(op_vaL2'left)='1' then -- 負の値
            abs_op_cal_vaL2 <= not(op_vaL2 -1);
        else -- 正の数
            abs_op_cal_vaL2 <= op_vaL2;
        end if;
    end process;
    abs_op_cal_val <= abs_op_cal_vaL1 + abs_op_cal_vaL2;

    ydata_out <= x"00" when h_valid_flag='0' or v_valid_flag='0' else
        x"FF" when (abs_op_cal_val(12) or abs_op_cal_val(11) or abs_op_cal_val(10) or abs_op_cal_val(9) or abs_op_cal_val(8))='1'
        else abs_op_cal_val(7 downto 0); -- 飽和演算


やはり、一旦integer に直して演算し、またstd_logic_vector に戻すことにした。op_int_vaL1とop_int_vaL2 はinteger だが範囲を-4096 to 4095 にしてある。
これでインプリメントしてやってみた。
その結果、ラプラシアン・フィルタは以前のように正常にエッジが検出できた。
edge_detect_18_091117.jpg

SobelフィルタとPrewittフィルタはエッジを検出しすぎて?ディスプレイの画面が真っ白になってしまった。値は合っていると思うのだが?どこがおかしいのか?
edge_detect_19_091117.jpg

  1. 2009年11月17日 05:06 |
  2. 画像処理
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


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

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