Görüntü İşleme / Image Processing İşlemleri

Delphi'de kod yazma ile ilgili sorularınızı bu foruma yazabilirsiniz.
Kullanıcı avatarı
rsimsek
Admin
Mesajlar: 4482
Kayıt: 10 Haz 2003 01:48
Konum: İstanbul

Görüntü İşleme / Image Processing İşlemleri

Mesaj gönderen rsimsek »

Gördüğüm kadarıyla bu konuda daha önce bir kaç soru gelmiş olsa da somut bir çözüm sunulamamış :?

Benim sormak istediğim de digital foroğraf makinaları ile panoromik çekim modu ile ardışık şekilde çekilen fotoğrafların belli programlarla ortak noktalarının bulunup birleştirilmesi.. Bu konuda bilgisi olup da paylaşmak isteyen var mı :?: Bu işi delphi ortamından nasıl yaparız :?:
Bilgiyi paylaşarak artıralım! Hayatı kolaylaştıralım!!
mkysoft
Kıdemli Üye
Mesajlar: 3103
Kayıt: 26 Ağu 2003 12:35
Konum: Berlin
İletişim:

Mesaj gönderen mkysoft »

benim bildiğim kadarıyla bu tür programlar kenar bulma algoritmalarını kullanıyorlar. kenar bulma algoritması yardımıyla resmi renklerinden arındırarak sadece nesnelerin kenarları çizilmiş bir resim elde ediyorlar. Daha sonra nesne benzerlikleri kullanıyorlar. Bunun için çizgilerin denklemlerini çıkarıyor olmalılar. daha sonra bir birine en yakın değerleri veren fonskiyonları kesişme noktası olarak belirleyip bu noktalardan birleştiriyor.
kenar bulma algoritmalarıyla ilgili örnek çok olmalı sanırım.
http://library.wolfram.com/infocenter/Demos/394/
bu adreste kenar belirleme (edge detection) algoritmasının matematiksel hesaplamaları var.
Bu konuda kenar belirleme olayını kullanarak 2 resmin benzerliği üzerine program yazmış bir arkadaşım vardı. ona bir email atayım. sanırım delphide yazmıştı uygulamayı.
sizede kolay gelsin.
Kullanıcı avatarı
rsimsek
Admin
Mesajlar: 4482
Kayıt: 10 Haz 2003 01:48
Konum: İstanbul

Mesaj gönderen rsimsek »

Teşşekür ediyorum, verdiğin linkteki bilgileri incelemekteyim.
Bilgiyi paylaşarak artıralım! Hayatı kolaylaştıralım!!
Kullanıcı avatarı
Opt2000
Üye
Mesajlar: 216
Kayıt: 09 Tem 2003 10:04

Mesaj gönderen Opt2000 »

Selam,

Daha önce benzer işlemler yaptım. Programın temel algoritmasını şunun üzerine kurmuştum:

1. Find Edges gibi bir process ile resmin genel hatlarının tespit edilmesi
2. Resmin siyah beyaza çevrilmesi (ara tonlar yok, 2 renk)
3. Belirli aralıklarla, yatay ve dikey histogramların karşılaştırılması. Benzerlik hassasiyetini en çok belirleyen kısım da burası oluyor. Histogramdan kastım da, her satır/sütun için yatay/dikey olarak siyah noktaların toplanması ve belli tolerans aralığında kıyaslanması. Biraz kötü anlattım biliyorum, ama bunu anlatmaktan ziyade göstermek daha mantıklı. Eğer konuya daha detaylı ilgi duyan arkadaşlar olursa, bir şeyler çizerek anlatırım. Haber vermeniz yeterli. Bu sistem özellikle OCR işlemlerinde güzel sonuç veriyor, ama aslında OCR işlemleri için de neurol networkler kurmak gerekiyor. Biraz daha derin ve zor bir konu anlayacağınız.

3 Maddeye alternatif olarak (pek tavsiye etmem ama) resimlerin blok halde kıyaslanması yapılabilir. Siyah ve beyaz değerlerin toplanması, genel alana göre bir oran üzerinde benzeliğin aşağı yukarı tahmin edilmesi. Ama bu yöntem, sadece belirli durumlarda elle tutulur sonuçlar veriyor. Örneğin PDF dosyasını, TIF olarak kaydedip OCR işlemine soktunuz. Verdiğim örnekte dikkat ederseniz aslında yazı tipini, yazının puntosunu vs gibi bilgileri zaten biliyorsunuz. Bu mantığı tavsiye etmememe rağmen buraya yazmamın sebebi ise, kodlamasının daha kolay olması.

Delphi'de bu işi yapmak mümkün elbette (En azından ben daha önce yaptım :) ) Ama burada bir takım sıkıntılar var. Örneğin, 1 bit resim üzerinde döngü kurmak çok zor ve yavaş. Bu yüzden burada bir takım ayak oyunları yapmak gerekiyor. Resmi 1 bite çevirmek yerine, sadece siyah ve beyaz renklerinden oluşan bir palet yüklemek çok daha mantıklı.

Bir de kesinlikle Canvas.Pixels prosedüründen uzak durmak gerekiyor. Bunun yerine Scanline kullanılmalı. Scanline'ı kullanırken de, Scanline'ı bir array gibi kullanmak yerine, Scanline[y] değerini bir pointer atayıp, sonra da pointerı hareket ettirmek daha yüksek performans veriyor. Üstelik bu mantıkla sütunlar için de scanline kullanabilirsiniz.

Eğer çok fazla low level işlem uygulanacaksa, ben size kendi resim formatınızı hazırlamanızı tavsiye ederim. Böylece çok daha esnek hareket edebilirsiniz. Bu resim formatına sadece LoadFromBitmap ve SaveToBitmap fonksiyonları ekleyerek arabirim sıkıntısından da kurtulabilirsiniz.

Kabaca söyleyebileceklerim (sanırım) bu kadar. Eğer daha özel bir soru olursa, belki daha fazla yardımcı olabilirim.

Kolay gelsin,
Bahadır Alkaç
Kullanıcı avatarı
bluekid
Kıdemli Üye
Mesajlar: 541
Kayıt: 11 Haz 2004 10:45
İletişim:

Mesaj gönderen bluekid »

Benim sormak istediğim de digital foroğraf makinaları ile panoromik çekim modu ile ardışık şekilde çekilen fotoğrafların belli programlarla ortak noktalarının bulunup birleştirilmesi..
anladığım kadarıyla kenar bulmaya gerek yok Opt2000 3. söylediği işini görür
Kullanıcı avatarı
rsimsek
Admin
Mesajlar: 4482
Kayıt: 10 Haz 2003 01:48
Konum: İstanbul

Mesaj gönderen rsimsek »

@Opt2000 verdiğiniz bilgiler için çok teşekkürler.. Sanırım biraz daha detay veya kaynağa ihtiyacım var :wink:
bk yazdı:
Benim sormak istediğim de digital foroğraf makinaları ile panoromik çekim modu ile ardışık şekilde çekilen fotoğrafların belli programlarla ortak noktalarının bulunup birleştirilmesi..
anladığım kadarıyla kenar bulmaya gerek yok Opt2000 3. söylediği işini görür
Kenar bulmak olayını ben farklı iki resimdeki ortak kenarlar olarak anlıyorum. O yüzden @Opt2000 ın söylediği histogramların karşılaştırılması da sanırım böyle bir yöntem..?
Bilgiyi paylaşarak artıralım! Hayatı kolaylaştıralım!!
Kullanıcı avatarı
Opt2000
Üye
Mesajlar: 216
Kayıt: 09 Tem 2003 10:04

Mesaj gönderen Opt2000 »

Selam,

Kenar bulma (Find Edges) işleminin uygulanması, biraz da resme bağlı. Eğer resim blok halde birbirine yakın renklerden oluşuyorsa o zaman kenar bulma uygulamak daha iyi sonuç veriyor. Çünkü sadece kontrast ayarı ile birbirine yakın renkler ayrılmıyor, aksine daha çok birbirine yaklaşıyor (Zaten kontrastın anlamı da bu :)). Bu yüzden daha çok çekilen resimle ilgili. Ama benim tahminime göre panoramik çekimlerin birleştirilmesinde kenar bulma algoritmasına pek de gerek yok. Çünkü zaten birleştirilecek olan kısımda kontrol edilecek yer çok fazla değil. Hatta buna benzer bir proje bile hazırlamıştım, daha doğrusu bir öğrencinin ödeviydi :oops: Ama fotograf değil, iki ayrı Webcamden gelen görüntüyü otomatik olarak birleştirmeye çalışıyordu. Yanlış hatırlamıyorsam, birinci resimde seçtiğiniz bir alanı ikinci resimde bulmaya çalışıyor ve ikinci resmi, üst üste gelecek şekilde kaydırıyordu. Burada tek can sıkıcı konu belli bir seçin yapılması gerekliliği. Tahmin edebileceğiniz gibi bu da önemli bir sorun değil. Bu akşam eve gidecek olursam, isteyen arkadaşlara algoritmayı gönderebilirim.

Kolay gelsin,
Bahadır Alkaç
Kullanıcı avatarı
rsimsek
Admin
Mesajlar: 4482
Kayıt: 10 Haz 2003 01:48
Konum: İstanbul

Mesaj gönderen rsimsek »

Opt2000 yazdı:.. Bu akşam eve gidecek olursam, isteyen arkadaşlara algoritmayı gönderebilirim. ..
İsteyen benim şimdilik :wink: Bir yerlerden başlamak için ne kadar ipucu varsa toplamam lazım :wink:
Bilgiyi paylaşarak artıralım! Hayatı kolaylaştıralım!!
t-hex
Kıdemli Üye
Mesajlar: 531
Kayıt: 18 Mar 2005 02:45
Konum: İstanbul/Antalya
İletişim:

Mesaj gönderen t-hex »

http://filters.sourceforge.net/filterslist.htm adresinde delphide kullanılabilecek resim işleme ile ilgili bir kütüphane var. Belki işinize yarayan bir şeyler çıkar.
Kullanıcı avatarı
rsimsek
Admin
Mesajlar: 4482
Kayıt: 10 Haz 2003 01:48
Konum: İstanbul

Mesaj gönderen rsimsek »

Teşekkürler, inceleyeceğim.
Bilgiyi paylaşarak artıralım! Hayatı kolaylaştıralım!!
fduman
Moderator
Mesajlar: 2749
Kayıt: 17 Ara 2004 12:02
Konum: Ankara

Mesaj gönderen fduman »

Ne güzel başlık oldu bu. Elinize sağlık. :) Birkaç yöntem kod örneği de olsa keşke. ;)
Kullanıcı avatarı
rsimsek
Admin
Mesajlar: 4482
Kayıt: 10 Haz 2003 01:48
Konum: İstanbul

Mesaj gönderen rsimsek »

Araştırmalar devam ediyor, bulunca paylaşacağım inşallah :wink:
Bilgiyi paylaşarak artıralım! Hayatı kolaylaştıralım!!
Kullanıcı avatarı
Opt2000
Üye
Mesajlar: 216
Kayıt: 09 Tem 2003 10:04

Mesaj gönderen Opt2000 »

Selam,

Arkadaşlar, son 2-3 gündür eve gidemiyorum, o yüzden de örnek kod gönderemiyorum. İnşallah bu akşam eve gideceğim, sanırım başlangıç yapacak seviyede birkaç örnek gönderebileceğim.

Kolay gelsin
Bahadır Alkaç
Kullanıcı avatarı
Opt2000
Üye
Mesajlar: 216
Kayıt: 09 Tem 2003 10:04

Mesaj gönderen Opt2000 »

Selam,

Aşağıdaki kod, daha önce yazdığım bir projeden çıkardığım kodlardır. Bu projedeki asıl amaç, iki ayrı WebCam’den gelen görüntüyü birleştirmek ve daha geniş açılı bir görüntü elde etmek. Kameralardan görüntü alma kısımlarını falan sildim, çünkü bununla ilgili zaten bir sürü örnek kod bulunabilir (Zaten bu kısmı hazır bir bileşenle çözmüştüm). Fonksiyona iki adet resmi, bir de her iki resimde de ortak bir alanı göndermek gerekiyor. Tabii tahmin edebileceğiniz gibi, ortak alan kısmını da biz tesbit edebilirdik, ama daha önceki mesajda da söylediğim gibi, öğrenci ödevi olduğu için mümkün olduğunca abartmamak gerekiyordu. Eğer işinize yarayacak olursa bunu siz de girebilirsiniz zaten.

Kodun temel mantığı da şunun üzerine kurulu. Burada bize gelecek olan resimler 24 bit resimler. Aksi takdirde program hata verecek. İlk resimde gönderilen alanın pixel değerleri toplanıyor. Daha sonra da aynı işlem ikinci resimde yapılıyor, ama ikinci resimdeki tam koordinatlar bilinmediği için asıl arama ikinci resimde yapılıyor.

Algoritmayı eleştirmeyeceğim (sonuçta ben yazdım he he), çünkü normalde bu iş böyle yapılmaz. Daha önce yazdığım gibi, normalde find edges gibi bir algoritma ile ana hatlar çıkarılır, sonra sana olarak küçük parçalara bölünür (örneğin 64 * 64 gibi) ve bu parçaların yatay ve dikey histogramları çıkarılır ve bu histogramlar karşılaştırılır. Bununla ilgili size bir örnek daha göndereceğim, ama ne yazık ki o kod, Delphi ile değil, C++ Builder ile yazıldı. Gerçi VCL olduğu için aşağı yukarı aynı, ama hem notasyon farklı, hem de C’nin özellikle pointer işlemlerindeki esnekliğinden dolayı anlaşılması biraz daha güç olabilir. Yalnız biraz önce baktığımda, o projede bazı özellikleri abarttığımı gördüm, bu yüzden onun kodunu foruma yazmaktansa, komple kaynak kodu ve projeyi göndermek daha mantıklı geldi. (Özellikle işlemlerin biraz daha rahat olması için kendi resim formatım olacak bir class yazmışım falan, şimdi hepsini foruma yazmaya kalksam boş yere kirlilik yaratacak). Kodu gönderebileceğim bir adres bilmiyorum, eğer bu konuda yardımcı olursanız, o projeyi gönderebilirim.

Herkese kolay gelsin,
Bahadır Alkaç

Kod: Tümünü seç

function TForm1.AnalysisImage2(Img1, Img2: TBitmap; RefRect: TRect): TRect;
var
  I,J:integer;
  Sum1:DynamicArray;
  Sum2:DynamicArray;
  K,L:integer;
  AWidth,AHeight:integer;
  Tolerance:integer;
begin
  SetLength(Sum1,(RefRect.Right - RefRect.Left));
  SetLength(Sum2,(RefRect.Right - RefRect.Left));
  for I:=RefRect.Left to RefRect.Right-1 do
  begin
    SetLength(Sum1[I - RefRect.Left],(RefRect.Bottom - RefRect.Top));
    SetLength(Sum2[I - RefRect.Left],(RefRect.Bottom - RefRect.Top));
  end;

  lblInfo.Caption:='Analysing first image...';
  Application.ProcessMessages;

  J:=RefRect.Top;
  while (J<RefRect.Bottom) do
  begin
    I:=RefRect.Left;
    While (I<RefRect.Right) do
    begin
      Sum1[(I - RefRect.Left) div Chunk,(J-RefRect.Top) div Chunk]:=GetSum(Img1,Rect(I,J,I + Chunk,J + Chunk));
      Inc(I,Chunk);
    end;
    Inc(J,Chunk);
  end;

  lblInfo.Caption:='Analysing second image...';
  Application.ProcessMessages;

  AWidth:=RefRect.Right - RefRect.Left;
  AHeight:=RefRect.Bottom - RefRect.Top;
  Tolerance:=StrToInt(txtTolerance.Text) * 3 * Chunk * Chunk;

  pbProgress.Max:=Img2.Width-AWidth-Chunk-1;
  for I:=0 to Img2.Width-AWidth-Chunk-1 do
  begin
    for J:=0 to Img2.Height-AHeight-Chunk-1 do
    begin
      L:=J;
      while (L<J + AHeight)do
      begin
        K:=I;
        while(K<I + AWidth) do
        begin
          Sum2[(K - I)div Chunk,(L - J) div Chunk]:=GetSum(Img2,Rect(K,L,K + Chunk,L + Chunk));
          Inc(K,Chunk);
        end;
        Inc(L,Chunk);
      end;

      if AreArraysEqueal(Sum1,Sum2,Tolerance) then
      begin
        Result:=Rect(I,J,I + AWidth,J + AHeight);
        lblInfo.Caption:='';
        pbProgress.Position:=0;

        Exit;
      end;
    end;
    pbProgress.StepIt;
  end;

  pbProgress.Position:=0;
  lblInfo.Caption:='';
  Application.ProcessMessages;

  Result:=Rect(-1,-1,-1,-1);
end;



function TForm1.GetSum(Img: TBitmap;ARect:TRect): integer;
var
  I:integer;
  J:integer;
  ScanLine:PByteArray;
begin

  Result:=0;
  for J:=ARect.Top to ARect.Bottom do
  begin
    ScanLine:=Img.ScanLine[J];
    I:=ARect.Left * 3;

    while (I<ARect.Right * 3) do
    begin
      Result:=Result + ScanLine[I];
      Inc(I,1);
    end;
  end;
end;


function TForm1.AreArraysEqueal(BaseList, SearchList: DynamicArray;
  Tolerance:integer): boolean;
var
  I,J:integer;
begin
  for I:=Low(BaseList) to High(BaseList) div Chunk -1 do
  begin
    for J:=Low(BaseList[I]) to High(BaseList[I]) div Chunk-1 do
    begin
      if not InRange(SearchList[I,J],BaseList[I,J] - Tolerance,BaseList[I,J] + Tolerance) then
      begin
        Result:=false;
        Exit;
      end;
    end;
  end;

  Result:=true;
end;

Kullanıcı avatarı
Opt2000
Üye
Mesajlar: 216
Kayıt: 09 Tem 2003 10:04

Mesaj gönderen Opt2000 »

Kodu önce Word'e aldım, sonra buraya kopyaladım, o yüzden indentler bozulmuş, kusura bakmayın :oops:
Cevapla