Temel İmge İşleme Algoritmalarının VHDL ile Gerçeklenmesi

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)
Şekil 3 Temel imge işleme algoritmaları çıktıları (a) Orijinal imge, (b)Aynalama yapılmış imge, (c)Ters çevrilmiş imge, (d) Negatifleme yapılmış imge, (e) Eşikleme yapılmış imge, (f)Parlaklık artırılmış imge, (g) Parlaklık azaltılmış imge, (h) Karşıtlık artırılmış imge, (i) Karşıtlık azaltılmış imge
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))

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir