OpenCV ile nesne algılama hakkında

Sanırım her şeyi en başından başlayarak anlatmam gerekecek.

Aslında bot oluşturmakla ilgili kitaplar falan var ama ben onların yaklaşımıyla değil kendi bakış açımla yazmaya çalışacağım.

Hayatta iki tür insan vardır, biri hemen sonucu alıp işine gücüne devam edenler, diğeri ise sonuca giderken arkasında ne olup bittiğini anlamak için zaman ayıran insanlar.

İlk tür insanlara kızmam, saygı duyarım. Hadi işimi gör bende kodumu alıp gideyim demeleri normal. İnsanların aceleleri var. Ama maalesef ben o insan türüne hitap edemiyorum.

Bunun arka planında neler dönüyor diye düşünecekler varsa karaladıklarımı okumaya devam edebilirler.

Öncelikle bir işi yapmanın birden çok yolu vardır. Yol tektir diyemeyeceğim. Bu nedenler birden çok yoldan bir kaçına bakmak gerekir. Tercihler ilerlenecek yolu belirler.

Genelde bu aralar şuraya buraya tıklayan makrolar vs tarzında talepler çok görmeye başladım. Sanırım online oyunlarda sıkılanlar buna çözümler arıyor.

Bu durumda ilk basamak. Bu sıkıntıyı aşan bir bot programlayan kesin biri vardır. Onların hazır kodu yada programı doğrudan kullanılabilir.

Ama bu işin arka planı nedir nasıl yaklaşabiliriz dersek iş bu durumda farklı yürüyecektir.

Neden gaz ve toz bulutu dedim?

Basit.

İlk kural, işletim sistemini tanı kuralı.

İşletim sistemini tanımadan bilgisayara asla tam olarak hakim olamazsınız.

Üzerinde koşturduğunuz tüm programlar döner dolarış, işletim sisteminin istediği şekilde çalışır.

Ve işletim sistemlerinin kurallarına uyarlar.

Bunları anlamadan, yapmak yada yaptırmak istediğinizi yapmaya çalışırsanız, ya anlamadığınız hazır kodları yada hazır kütüphaneleri kullanırsınız.

Bu durumda, kodu değiştirdiğinizde beklediğiniz sonuçlara ulaşamayabilirsiniz.

Bu sefer kendiniz o kütüphaneyi öğrenmeye çalışırken yada bu şekilde çözemiyorum deyip vazgeçme noktasında bulabilirsiniz.

Konunun başına yani ilk soruya bağlayacağım.

Ama öncesinde şurada anlaşalım.

Windows işletim sistemi konuştuğumuzu varsayalım.

Anlatacaklarım antroid ve linux türevlerini kapsamayacaktır fakan onlarda da benzer yaklaşımlar vardır.

Windows klasiğidir çoklu çalıştırma desteği sunan, bir işletim sistemidir denir.

Yani birden fazla programı aynı anda çalıştırırsınız.

Bu bir not defteri, bir oyun, bir video bir web sayfası yada başka bir program olabilir.

Konumuz bir bot tasarımı,

Ve bir şeylere tıklamak bir şeyleri sürüklemek, bir şeyleri öne getirmek yada arka plana itmek isteyebilirsiniz.

Peki nasıl yaparız?

Daha doğrusu önce windows bunu nasıl yapar?

Windows bir program çalıştırdığınızda ona bir processID ( işlem numarası) atar ve bir listede tutar, ve bu process in bir geri çağrılarılabilir fonksiyonunun da adresini kaydettirmenizi ister. (aslında bir kaç callback fonksiyon vardır ama örnek bir olsun.)

Bu listedeki id leri kullanarak sıra ile işlemci zamanı tahsis ederek programları yürütür, durdurur, sonra diğerine de aynısını liste boyunca devam eder.

Bu liste üzerindeki hızlı göngü paralel çalışma/ çoklu çalışma yanılgısını yaratır.

Bu process lerin bazılarının pencereleri olabilir, hatta birden fazla penceresi olabilir ve hatta hiç penceresi olmadan da çalışan process ler olabilir.

Her bir process in idsi olduğu gibi her bir pencereninde windows handle adında bir id numarası olur.

Siz, tıklamak sürüklemek, çift tıklamak gibi bir eylem gerçekleştirdiğinizde, mouse imlecinizin altında aktif hangi pencere varsa, o pencerenin idsine ait callback fonksiyon çağırılır ve ona tıklama mesajı gönderilir.

Eğer id ile ayrılmamış olsa idi, bir tıkladığınızda tüm pencereler tıklamaya cevap vermek zorunda kalırdı, oysaki sadece ilgili pencere bu mesajı işler diğer pencereler bu mesaj ile ilgilenmez.

Bunu neden anlattım.

Bir bot yazdığınızda, eğer doğru programı tespit etmedi iseniz, doğru pencereye ulaşamadıysanız, doğru pencerenin button idsine ulaşmadı iseniz, gönderdiğiniz tıklama mesajı anlamlı olmayacak ve istediğiniz gibi çalışmayacaktır.

Aynısını, online web browser üzerinde de söyleyebiliriz, sekme, frame ve butan kimliklerine ulaşmada ilgili tıklama mesajlarını ulaştıramazsınız.

Bu anlattığım ileri seviye bir teknik olup, window enumeration olarak adlandırılan, pencere listelerine ulaşmayı ve doğru pencereye komutlar yada mause yada buton mesajları hatta klavye mesajları da göndermeyi sağlayan bir yoldur.

Sonuç adı üstünde bot, programa özel çalışır. Programı inceleyip, hangi pencereleri, alt pencereleri açtığını tespit edip doğrudan bunlara mesaj yollayabilirsiniz.

Python Examples of win32gui.EnumWindows (programcreek.com)

Kodları denemedim, genelde c ve c++ ile kodlamayı tercih ederim ama buradan da deneyerek pencereleri nasıl listeleyeceğinizi görebilirsiniz.

Mesela bir programı kapatmak isteyebilirsiniz.

automation - How to close two windows of the same application using python? - Stack Overflow

Kullanacağınız programın pencere ve alt pencerelerini inceler, ne zaman hangi hallerde tıklayacağınızı yada ne zaman ön plana getirip ne zaman arka plana iteceğinizi tespit edersiniz.

Ardından ilgili buton yada pencereye mouse mesajını doğrudan gönderirsiniz.

Bu kadar karmaşaya girmem ben sadece mouse tıklasın istiyorum derseniz.

Dikkat etmeniz gereken ikinci bir husus ortaya çıkacak.

Ekran çözünürlüğünüz önemli.

Çünkü mousa bir koordinata git ve tıkla diyeceksiniz.

Ama o koordinat o çözünürlük değerlerine göre geçerlidir.

Eğer çözünürlük farklı ve pencere de farklı bir yerde duruyorsa tıkladığınızda altında buton olmayacak sonuçta butona tıklanmadığı için de iş doğru yapılmamış olacak.

Burada yine işletim sisteminin önemi devreye giriyor.

İki tip koordinat var. Aslında daha çok da şu an girmeyeyeim.

Bir çalıştırdığınız pencerenin koordinatları içerisinde geçerli, diğer ise tüm masa üstü koordinatlarına göre imlecinizi konumlayacak olan.

Bu ikisinin farkını ikisi arasında nasıl geçiş yapacağınızı iyi bilmelisiniz.

Bunun için aslında windows basit bir yol sunar.

Açılan pencerenizin köşe koordinatı ile masa üstü koordinatınızın köşe koordinatını deplase ederek iki şekilde de kullanmanızı sağlar.

Ama bunu tam kavramadan bir butona tıklamaya çalıştığınızda buton yerine çalıştırdığınız pencereyi sıfır koordinatı sayan bir noktadan ötelenerek yanlış yere tıklayabilirsiniz.

Laf kalabalığını özetleyim.

Birinci yöntem, programın bileşenlerine dokunarak id ler üzerinden yönetmek

İkinci yöntem, imleç koordinatları ile tıklamayı simüle etmek.

Simüle edilen tıklama koordinatı doğru değilse çuvallarsınız.

Pencere en üstte değilse çuvallarsınız vs. vs.

İşletim sistemini tanıyın, pencere buton enümerasyonlarını öğrenin.

Gelelim.

Yukarıdaki ilk mesaja dair hususa.

Uzun iletişim sonunda bir altılı resim gurubu içinde doğru resme tıklamak için bir bottan bahsediyoruz.

Masa üstü ekran resmi alırım.

Masa üstü ekran resmi üzerinde tanımladığım resim koordinatlarını eşleştiririm.

Bu koordinatlardan tıklayacağım resimi bulurum.

x+Resim eni/2, y+resim boyu/2 gibi tam göbeğinden bir resim koordinatı belirlerim.

Arkasından bu koordinatın resimin pixel koordinatı olduğunu hatırlar masa üstü mouse koordinatına çeviririm.

Sonra bu koordinata bir tıklama mesajı gönderirim.

İşlem basamakları bu kadar.

Ama gerçe oyunu görse idim. ID lerini tespit eder, buton id sine doğrudan tıklama mesajı gönderir koordinatlarla da uğraşmazdım.

Biri işletim sistemi mantığı, diğeri ise bir nevi mouse makrosu tanımlamak.

Burada ayırt edici tek husus var.

OpenCV ile resim içinde belirli bir resmi yada deseni mi aramak mı gerek, yada özellikli resmimizdeki ayırt edici bir renk pixelini tespit edip.

O pixel varsa doğru resim budur deyip geçmek mi?

Bence opencv ile tüm resim sürekl yüz yada plaka tanır gibi resim kontrolü yapmaktansa, doğru resim içinde ayırt edici pixelleri tespit edip onu karşılaştırara koordinat ve doğru resmi de bulabiliriz.

Tabi illaki resim içinde resim aramak da bir çözüm.

Ama bana hep KISS presibi öğretildi. Keep it Simple and Stupid…

Şimdi yol ayrımı.

Kırmızı hap mı mavi hap mı?

Mavi hapı alın mutlu mesut kodunuzla devam edin…

Yada kırmızı hapı alıp işletim sisteminin olay yakalama (event handlig), pencere kulpları (window handle), process id ( işlem kimlikleri) gibi konulara boğulun…

Sonrasında zaten mause tıklaması göndermek dışında, metin kutularını bulup içlerini otomatik doldurmaya başladığınızı bile göreceksiniz.

Bu kadar laf salatası ve tek satır kod yok.

Üzgünüm.

Balık tutmayı anlatmak benim işim balık verecek hiç zamanım yok, yine uykumdan eksiltip bu saatte yazıyorum.

4 Beğeni