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

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

FPGAの部屋

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

ET2009に11/19(木)に行きます

FPGAカンファレンス東京は、急に重要な仕事が入ってしまっていけなくなってしまい残念だった。
ET2009には、行こうと思っている。行くのは木曜日だ。FPGAの無料セミナーも申し込んだし、出張の申請もした。午後はFPGAの無料セミナーを受講して、主に午前中に展示を見ようと思っている。XilinxやAlteraブース、その他楽しみなブースがありそうなので、楽しみだ。ここは見ておいた方が良いというところがあったら教えてください。よろしくお願いします。それでは、会場でお会いしましょう。
  1. 2009年11月17日 12:26 |
  2. その他のFPGAの話題
  3. | トラックバック:0
  4. | コメント:6

画像のエッジ検出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