Görüntü İşleme / Image Processing İşlemleri
Forum kuralları
Forum kurallarını okuyup, uyunuz!
Forum kurallarını okuyup, uyunuz!
Görüntü İşleme / Image Processing İşlemleri
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
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!!
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.
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.
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ç
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ç
@Opt2000 verdiğiniz bilgiler için çok teşekkürler.. Sanırım biraz daha detay veya kaynağa ihtiyacım var
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..?bk yazdı:anladığım kadarıyla kenar bulmaya gerek yok Opt2000 3. söylediği işini görürBenim 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..
Bilgiyi paylaşarak artıralım! Hayatı kolaylaştıralım!!
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 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ç
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 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ç
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.
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ç
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;