Bu örnekte de işaret işleme uygulamalarına devam ediyoruz. Bir önceki başlık bir alçak geçiren filtre uygulaması gerçekleştirmiştik. Bu örnekte ise işaret işleme uygulamarı arasında bulunan temel imge (görüntü) işleme algoritmalarından ve VHDL ile tasarımından bahsedeceğiz.
Uygulamaya geçmeden önce ilk olarak temel imge işleme işlemleri tanıtılacak olup ardından VHDL kodları verilecektir. Örnek uygulamada kullanılan görüntü 8 bit gri seviyeli bir görüntüdür. Bu yüzden her beneğin (pixel) alabileceği değerler 0 ile 255 arasında olmaktadır. (x,y) gösterimi ise imgenin her bir beneğinin koordinatlarını temsil etmektedir. Temel imge işleme algoritmaları sırasıyla verildiği gibidir:
Aynalama : Aynalama işleminde en soldaki sütun en sağdaki sütüna, en sağdaki sütün ise en soldaki sütuna yazılacak şekilde imge elemanları yer değiştirir (Şekil 1).
Şekil 1 İmgede aynalama
Ters Çevirme : Ters çevirme işleminde en alttaki satır en üstteki satıra, en üstteki satır ise en alttaki alttaki yazılacak şekilde imge elemanları yer değiştirir (Şekil 2).
Şekil 2 İmgede ters çevirme
Negatifleme : İmge değerlerinin ters çevrilmesi ile yapılmaktadır. Aşağıda negatifleme işlemine ilişkin denklem verilmiştir. 255 değeri 8bitlik bir beneğin alabileceği azami değer olup farklı bit uzunlukları için bu değer değişebilir.
Eşikleme : İmge değerlerinin bir sayı değerinden büyük veya küçük olması durumuna göre eşikleme yapılmaktadır. Aşağıda eşikleme işlemine ilişkin denklem verilmiştir.
Parlaklık : İmge değerlerinin bir sayı değeriyle toplanması veya çıkarılması ile parlaklık ayarı yapılmaktadır. Aşağıda parlaklık ayarlamasına ilişkin denklem verilmiştir. Bu işlem yapılırken her bir beneğin alabileceği azami ve asgari değerlere dikkat edilmelidir aksi halde istenmeyen sonuçlar oluşabilir. Örneğin 250 değerine sahip bir beneğe 10 eklenirse değerde taşma oluşacak ve beneğin yeni değeri 5 olacağı için siyaha dönecektir.(imgenin beneklerinin 8 bitlik uzunluğa sahip olduğu kabul edilmiştir.)
Karşıtlık : İmge değerlerinin bir sayı değeriyle çarpılması ile karşıtlık ayarı yapılmaktadır. Aşağıda karşıtlık ayarlamasına ilişkin denklem verilmiştir. Bu işlem yapılırken her bir beneğin alabileceği azami ve asgari değerlere dikkat edilmelidir aksi halde istenmeyen sonuçlar oluşabilir.
Örnek 1 : Aşağıda temel imge algoritmalarının gerçekleştirildiği temel_imge_isleme.vhd VHDL kodu verilmiştir. temel_imge_isleme varlığında uygulanacak algoritmaya ilişkin RAM’dan okunacak datanın adres tanımlama işlemleri 83-91. satırlar arasında tanımlanmıştır. 101-131. satırlar arasında ise uygulanacak algoritmaya ilişkin hesaplama işlemleri yapılmaktadır.
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use work.ornekler_paket.all; entity temel_imge_isleme is generic( IMGE_SATIR : integer := 8; IMGE_SUTUN : integer := 8; VERI_UZUNLUGU : integer := 24 ); port( in_clk : in std_logic; in_rst : in std_logic; in_en : in std_logic; in_basla : in std_logic; in_islem : in std_logic_vector(2 downto 0); in_data : in std_logic_vector(VERI_UZUNLUGU - 1 downto 0); in_data_vld : in std_logic; out_addr : out std_logic_vector(log2_int(IMGE_SATIR * IMGE_SUTUN) - 1 downto 0); out_addr_vld : out std_logic; out_data : out std_logic_vector(7 downto 0); out_data_vld : out std_logic; out_tamam : out std_logic ); end temel_imge_isleme; architecture Behavioral of temel_imge_isleme is constant AYNALAMA : std_logic_vector(2 downto 0) := "000"; constant TERS_CEVIRME : std_logic_vector(2 downto 0) := "001"; constant NEGATIFLEME : std_logic_vector(2 downto 0) := "010"; constant ESIKLEME : std_logic_vector(2 downto 0) := "011"; constant PARLAKLIK_ARTIR : std_logic_vector(2 downto 0) := "100"; constant PARLAKLIK_AZALT : std_logic_vector(2 downto 0) := "101"; constant KARSITLIK_ARTIR : std_logic_vector(2 downto 0) := "110"; constant KARSITLIK_AZALT : std_logic_vector(2 downto 0) := "111"; type t_Imge_Isleme is (BOSTA, RAMDAN_OKU, OKUMA_BEKLE, ISLEM_YAP, SAYAC_KONT, TAMAM ); signal r_Imge_Isleme : t_Imge_Isleme := RAMDAN_OKU; signal n_i : integer := 0; signal n_j : integer := 0; signal r_addr : std_logic_vector(log2_int(IMGE_SATIR * IMGE_SUTUN) - 1 downto 0) := (others => '0'); signal r_addr_vld : std_logic := '0'; signal r_data : std_logic_vector(7 downto 0) := (others => '0'); signal r_data_vld : std_logic := '0'; signal r_tamam : std_logic := '0'; begin out_addr <= r_addr; out_addr_vld <= r_addr_vld; out_data <= r_data; out_data_vld <= r_data_vld; out_tamam <= r_tamam; process(in_clk, in_rst) begin if in_rst = '1' then r_Imge_Isleme <= BOSTA; n_i <= 0; n_j <= 0; r_addr <= (others => '0'); r_addr_vld <= '0'; r_data <= (others => '0'); r_data_vld <= '0'; r_tamam <= '0'; elsif rising_edge(in_clk) then if in_en = '1' then r_data_vld <= '0'; r_addr_vld <= '0'; r_tamam <= '0'; case r_Imge_Isleme is when BOSTA => if in_basla = '1' then r_Imge_Isleme <= RAMDAN_OKU; end if; when RAMDAN_OKU => if in_islem = AYNALAMA then r_addr <= conv_std_logic_vector(n_i * IMGE_SUTUN + (IMGE_SUTUN - 1 - n_j) , r_addr'length); elsif in_islem = TERS_CEVIRME then r_addr <= conv_std_logic_vector((IMGE_SATIR - 1 -n_i) * IMGE_SUTUN + n_j , r_addr'length); elsif in_islem = NEGATIFLEME or in_islem = ESIKLEME or in_islem = PARLAKLIK_ARTIR or in_islem = PARLAKLIK_AZALT or in_islem = KARSITLIK_ARTIR or in_islem = KARSITLIK_AZALT then r_addr<= conv_std_logic_vector(n_i * IMGE_SUTUN + n_j , r_addr'length); end if; r_addr_vld <= '1'; r_Imge_Isleme <= OKUMA_BEKLE; when OKUMA_BEKLE => if in_data_vld = '1' then r_data <= in_data; r_Imge_Isleme <= ISLEM_YAP; end if; when ISLEM_YAP => if in_islem = AYNALAMA or in_islem = TERS_CEVIRME then r_data <= r_data; elsif in_islem = NEGATIFLEME then r_data <= 255 - r_data; elsif in_islem = ESIKLEME then if r_data > 128 then r_data <= conv_std_logic_vector(255, r_data'length); else r_data <= (others => '0'); end if; elsif in_islem = PARLAKLIK_ARTIR then if r_data > 210 then r_data <= conv_std_logic_vector(255, r_data'length); else r_data <= r_data + 45; end if; elsif in_islem = PARLAKLIK_AZALT then if r_data < 45 then r_data <= conv_std_logic_vector(0, r_data'length); else r_data <= r_data - 45; end if; elsif in_islem = KARSITLIK_ARTIR then if r_data > 128 then r_data <= conv_std_logic_vector(255, r_data'length); else r_data <= r_data(6 downto 0) & '0'; end if; elsif in_islem = KARSITLIK_AZALT then r_data <= '0' & r_data(7 downto 1); end if; r_data_vld <= '1'; r_Imge_Isleme <= SAYAC_KONT; when SAYAC_KONT => if n_j = IMGE_SUTUN - 1 then n_j <= 0; if n_i = IMGE_SATIR - 1 then n_i <= 0; r_Imge_Isleme <= TAMAM; else n_i <= n_i + 1; r_Imge_Isleme <= RAMDAN_OKU; end if; else n_j <= n_j + 1; r_Imge_Isleme <= RAMDAN_OKU; end if; when TAMAM => r_tamam <= '1'; r_Imge_Isleme <= BOSTA; when others => NULL; end case; end if; end if; end process; end Behavioral;
temel_imge_isleme varlığının benzetiminin yapılabilmesi için aşağıda tb_temel_imge_isleme.vhd VHDL sınama kodu verilmiştir. Kodda dosyadan okunan imge dataları RAM bloğuna yazılmaktadır. Dataların RAM bloğuna yazılma işlemi tamamlandıktan sonra temel_imge_isleme varlığı aktif edilemektedir.
temel_imge_isleme varlığında uygulanacak olan algoritmaya göre adres bilgisi üretilir ve o adreste bulunan data RAM üzerinden okunur. RAM üzerinden okunan data temel_imge_isleme varlığında uygulanacak algoritmaya göre işlendikten sonra çıkışa aktarılmaktadır. Çıkışa aktarılan data tekrardan dosyaya yazılmaktadır.
Eşikleme algoritmasının eşik değeri 128 olarak belirlenmiştir. Parlaklık artırmak/ için eklenecek/çıkarılacak sayı 45’tir. Karşıtlık artırma işlemi için 2 ile çarpma işlemi yapılmıştır. Karşıtlık azaltma işlemi için ise 0.5 ile çarpma işlemi yapılmıştır.
Yapılan işlemlerden sonra oluşacak görüntüler sırasıyla verilmiştir. Şekil 3.a’da orijinal imge, Şekil 3.b’de aynalama algoritması uygulanarak elde edilen yeni imge, Şekil 3.c’de ters çevirme algoritması uygulanarak elde edilen yeni imge, Şekil 3.d’de negatifleme algoritması uygulanarak elde edilen yeni imge, Şekil 3.e’de eşikleme algoritması uygulanarak elde edilen yeni imge, Şekil 3.f’de parlaklığın artırıldığı yeni imge, Şekil 3.g’de parlaklığın azaltıldığı yeni imge, Şekil 3.h’de karşıtlığın artırıldığı yeni imge ve Şekil 3.i’de karşıtlığın azaltıldığı yeni imge gösterilmiştir.
(a) | (b) | (c) |
(d) | (e) | (f) |
(g) | (h) | (i) |
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; use std.textio.ALL; use work.ornekler_paket.all; entity tb_temel_imge_isleme is end tb_temel_imge_isleme; architecture Behavioral of tb_temel_imge_isleme is component temel_imge_isleme generic( IMGE_SATIR : integer := 8; IMGE_SUTUN : integer:= 8; VERI_UZUNLUGU : integer:= 24 ); port( in_clk : in std_logic; in_rst : in std_logic; in_en : in std_logic; in_basla : in std_logic; in_islem : in std_logic_vector(2 downto 0); in_data : in std_logic_vector(VERI_UZUNLUGU - 1 downto 0); in_data_vld : in std_logic; out_addr : out std_logic_vector(log2_int(IMGE_SATIR * IMGE_SUTUN) - 1 downto 0); out_addr_vld : out std_logic; out_data : out std_logic_vector(7 downto 0); out_data_vld : out std_logic; out_tamam : out std_logic ); end component; component block_ram generic( VERI_UZUNLUGU : integer := 8; RAM_DERINLIGI : integer := 110 ); port(in_clk : in std_logic; in_rst : in std_logic; in_ram_aktif : in std_logic; in_yaz_en : in std_logic; in_oku_en : in std_logic; in_data_addr : in std_logic_vector(log2_int(RAM_DERINLIGI) - 1 downto 0); in_data : in std_logic_vector(VERI_UZUNLUGU - 1 downto 0); out_data : out std_logic_vector(VERI_UZUNLUGU - 1 downto 0); out_data_vld : out std_logic ); end component; constant CLK_PERIOD : time := 20 ns; constant IMGE_SATIR : integer := 256; constant IMGE_SUTUN : integer := 256; constant VERI_UZUNLUGU : integer := 8; constant VERI_YOLU_OKUMA : string := "C:\cameraman.txt"; constant VERI_YOLU_YAZMA : string := "D:\cameraman_sonuc.txt"; constant AYNALAMA : std_logic_vector(2 downto 0) := "000"; constant TERS_CEVIRME : std_logic_vector(2 downto 0) := "001"; constant NEGATIFLEME : std_logic_vector(2 downto 0) := "010"; constant ESIKLEME : std_logic_vector(2 downto 0) := "011"; constant PARLAKLIK_ARTIR : std_logic_vector(2 downto 0) := "100"; constant PARLAKLIK_AZALT : std_logic_vector(2 downto 0) := "101"; constant KARSITLIK_ARTIR : std_logic_vector(2 downto 0) := "110"; constant KARSITLIK_AZALT : std_logic_vector(2 downto 0) := "111"; type t_Imge_Isleme is (RAM_OKUMA, RAM_YAZMA, TAMAM); signal r_Imge_Isleme : t_Imge_Isleme := RAM_YAZMA; signal in_clk : std_logic := '0'; signal in_rst : std_logic := '0'; signal in_basla : std_logic := '0'; signal in_ram_aktif : std_logic := '1'; signal out_data_vld : std_logic := '0'; signal out_data : std_logic_vector(7 downto 0) := (others => '0'); signal in_ram_data : std_logic_vector(VERI_UZUNLUGU - 1 downto 0) := (others => '0'); signal in_ram_data_addr : std_logic_vector(log2_int(IMGE_SATIR * IMGE_SUTUN) - 1 downto 0) := (others => '0'); signal out_ram_data : std_logic_vector(VERI_UZUNLUGU - 1 downto 0) := (others => '0'); signal out_data_addr : std_logic_vector(log2_int(IMGE_SATIR * IMGE_SUTUN) - 1 downto 0) := (others => '0'); signal out_ram_data_vld : std_logic := '0'; signal in_en : std_logic := '0'; signal in_yaz_en : std_logic := '0'; signal in_oku_en : std_logic := '0'; signal data_sayac : integer := 0; signal out_data_addr_vld : std_logic := '0'; signal r_imge_isleme_tamam : std_logic := '0'; begin process begin in_clk <= '1'; wait for CLK_PERIOD / 2; in_clk <= '0'; wait for CLK_PERIOD / 2; end process; process begin in_basla <= '1'; wait for CLK_PERIOD; in_basla <= '0'; wait; end process; process(in_clk) file dosya_okuma : text open read_mode is VERI_YOLU_OKUMA; file dosya_yazma : text open write_mode is VERI_YOLU_YAZMA; variable satir_okuma : line; variable satir_yazma : line; variable data_okuma : integer; begin if rising_edge(in_clk) then if out_data_vld = '1' then write(satir_yazma, conv_integer(out_data)); writeline(dosya_yazma, satir_yazma); end if; case r_Imge_Isleme is when RAM_YAZMA => if not endfile(dosya_okuma) then readline(dosya_okuma, satir_okuma); read(satir_okuma, data_okuma); in_ram_data <= conv_std_logic_vector( data_okuma, VERI_UZUNLUGU); in_ram_data_addr <= conv_std_logic_vector( data_sayac, in_ram_data_addr'length); in_en <= '0'; in_yaz_en <= '1'; data_sayac <= data_sayac + 1; else r_Imge_Isleme <= RAM_OKUMA; in_yaz_en <= '0'; end if; when RAM_OKUMA => in_en <= '1'; in_ram_data_addr <= out_data_addr; in_oku_en <= out_data_addr_vld ; if r_imge_isleme_tamam = '1' then r_Imge_Isleme <= TAMAM; end if; when TAMAM => null; when others => NULL; end case; end if; end process; temel_imge_isleme_map : temel_imge_isleme generic map( IMGE_SATIR => IMGE_SATIR, IMGE_SUTUN => IMGE_SUTUN, VERI_UZUNLUGU => VERI_UZUNLUGU ) port map( in_clk => in_clk, in_rst => in_rst, in_en => in_en, in_basla => in_basla, in_islem => KARSITLIK_AZALT, in_data => out_ram_data, in_data_vld => out_ram_data_vld, out_addr => out_data_addr, out_addr_vld => out_data_addr_vld, out_data => out_data, out_data_vld => out_data_vld, out_tamam => r_imge_isleme_tamam ); block_ram_map : block_ram generic map( VERI_UZUNLUGU => VERI_UZUNLUGU, RAM_DERINLIGI => IMGE_SATIR * IMGE_SUTUN ) port map( in_clk => in_clk, in_rst => in_rst, in_ram_aktif => in_ram_aktif, in_yaz_en => in_yaz_en, in_oku_en => in_oku_en, in_data_addr => in_ram_data_addr, in_data => in_ram_data, out_data => out_ram_data, out_data_vld => out_ram_data_vld ); end Behavioral;
RAM uygulamasında güncelleme yapılarak data okuma işleminin geçerli olduğuna dair sinyal üreten çıkış portunun eklendiği block_ram.vhd VHDL kodu verilmiştir. temel_imge_isleme varlığında RAM’dan tanımlı adresteki data isteme işlemi yapıldıktan sonra, adresten okunan datanın geçerli olması beklenmektedir. Bu işlem 20. satırda tanımlı out_data_vld çıkış portundan sağlanmaktadır. Bu port değeri data okuma işlemi gerçekleştiğinde ‘1’, aksi durumlarda ‘0’ çıkışı vermektedir.
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; use work.ornekler_paket.all; entity block_ram is generic( VERI_UZUNLUGU : integer := 8; RAM_DERINLIGI : integer := 110 ); port( in_clk : in std_logic; in_rst : in std_logic; in_ram_aktif : in std_logic; in_yaz_en : in std_logic; in_oku_en : in std_logic; in_data_addr : in std_logic_vector(log2_int(RAM_DERINLIGI) - 1 downto 0); in_data : in std_logic_vector(VERI_UZUNLUGU - 1 downto 0); out_data : out std_logic_vector(VERI_UZUNLUGU - 1 downto 0); out_data_vld : out std_logic ); end block_ram; architecture Behavioral of block_ram is type t_BRAM_DATA is array (0 to RAM_DERINLIGI - 1) of std_logic_vector(VERI_UZUNLUGU - 1 downto 0) ; signal r_BRAM_DATA : t_BRAM_DATA := (others =>(others => '0')); begin process(in_clk, in_rst) begin if in_rst = '1' then -- r_BRAM_DATA <= (others =>(others => '0')); elsif rising_edge(in_clk) then if in_ram_aktif = '1' then if in_oku_en = '1' then out_data <= r_BRAM_DATA( conv_integer( in_data_addr)); out_data_vld <= '1'; else out_data_vld <= '0'; end if; if in_yaz_en = '1' then r_BRAM_DATA(conv_integer(in_data_addr)) <= in_data; end if; end if; end if; end process; end Behavioral;
Aşağıda imgenin dosya işleminin yapıldığı MATLAB kodu verilmiştir.
clc, clear all, close all; imge = imread('cameraman.tif'); dosya = fopen('cameraman.txt', 'w'); [satir sutun] = size(imge); for n_i = 1 : satir for n_j = 1 : sutun if n_i == satir && n_j == sutun fprintf(dosya, '%d', imge(n_i, n_j)); else fprintf(dosya, '%d\n', imge(n_i, n_j)); end end end fclose(dosya);
Aşağıda dosyadan imge okuma işleminin yapıldığı MATLAB kodu verilmiştir.
clc, clear all, close all; imge = imread('cameraman.tif'); imshow(imge) [satir sutun] = size(imge); dosya = fopen('D:\cameraman_sonuc.txt', 'r'); imge_okunan = fscanf(dosya, '%d')'; for n_i = 1 : satir for n_j = 1 : sutun yeni_imge(n_i, n_j) = imge_okunan((n_i - 1)* sutun + n_j); end end fclose(dosya); figure, imshow(uint8(yeni_imge))