Bilgisayarla görme, yapay zekanın son derece ilgi çekici bir uygulaması olmaya devam ediyor. İster bir savaş alanındaki unsurları tanımak ister mahsul verimini tahmin etmek olsun, bilgisayarlı görme, muhtemelen yapay zekanın ticari açıdan en değerli (ve toplumsal açıdan önemli) alanlarından biridir.
Bununla birlikte, en iyi bilgisayarlı görme yeteneklerinin benimsenmesindeki hız sınırlayıcı, çoğu zaman bir veri kümesi oluşturma ve bilgisayarlı görme görevinizi yeni bir görüntü üzerinde gerçekleştirecek basit bir uçtan uca sistem tasarlamayla ilişkili karmaşıklıklardır.
Bu blog yazısında, CVAT ve MinIO Bucket Notifications gibi sınıfının en iyisi araçlarla bu sorunların nasıl çözüleceğine adım adım bakacağız. Bu yazının sonunda, özel bir veri kümesi üzerinde bir nesne algılama modelini eğitebilecek ve bunu, yeni bir görüntü göründüğünde tahminlerde bulunmak için kullanabileceksiniz.
Diyelim ki uydu görüntülerinde bulunan uçak türlerini tanıyabilmek istiyoruz. Ayrıca sıfırdan başladığımızı varsayalım: önceden oluşturulmuş veri kümeleri yok, önceden eğitilmiş modeller yok. Uydu görüntülerimizde tespit edip tanımak istediğimiz iki örnek uçak:
Bu yazıda özetlenen adımlar hemen hemen her alana genelleştirilebilir. Uçak türlerini tespit etmek yerine arazi kullanımını sınıflandırıyor veya mahsul verimini tahmin etmek için regresyon yapıyor olabiliriz. Geleneksel görüntülerin ötesinde, LiDAR nokta bulutları veya 3D Sismik Görüntüler gibi diğer çok boyutlu veri türlerini de eğitiyor ve bunlar üzerinde çıkarımlar yapıyor olabiliriz; mesele sadece eğitim verilerinin nasıl göründüğü (ve potansiyel olarak YOLO yerine farklı bir derin öğrenme modeli) meselesi haline geliyor. Belirli bir kullanım durumu için bunun nasıl görüneceğine ilişkin daha fazla sorunuz varsa GitHub deposunda sorun oluşturmaktan çekinmeyin!
Bu proje için, büyük ölçüde isteğe bağlı bir görüntüleme uydusuna sahip olmadığım için, Google Earth'teki hava alanlarını ziyaret ettim ve bu uçaklardan bazılarının görülebildiği alanların birden fazla ekran görüntüsünü aldım. Bu görüntü setinin birleştirilmesi oldukça zaman aldı, bu yüzden hepsini MinIO sunucumdaki "nesne algılama" başlıklı bir klasörde sakladım. Üretim ortamında, toplanan numunelerinizi MinIO'da saklamanın faydaları daha da ileri görüşlü hale gelir. Aktif-aktif çoğaltma, en yüksek düzeyde şifreleme ve süper hızlı GET/PUT'lar (birkaç örnek vermek gerekirse), özenle topladığınız örneklerin yüksek oranda kullanılabilir, güvenli ve emniyetli olacağı anlamına gelir.
Kullanım durumunuza yönelik bir nesne algılama modeli eğitmek amacıyla etiketlenmiş (veya 'açıklamalı') bir veri kümesine ihtiyaç vardır. Bunun için harika bir araç OpenCV'nin CVAT'ıdır. Harika bir özellik, CVAT'ın, klasörünüzün görüntülerini doğrudan veri kümesi açıklama aracına beslemek için MinIO klasörünüzü bir "bulut depolama" olarak bağlamaya yönelik bir yardımcı program sağlamasıdır. Bunu yapmak için, özellikle MinIO Sunucusunu şirket içinde veya yerel olarak dizüstü bilgisayarınızda çalıştırıyorsanız, MinIO Sunucunuzun ana bilgisayarının CVAT sunucusu tarafından erişilebilir olduğundan emin olun. Ayrıca, bir not olarak CVAT'ı kullanmanın iki yolu vardır: (1) app.cvat.ai adresinde sağlanan web uygulamasını kullanarak veya (2) yerel olarak çalıştırarak. Her iki durumda da CVAT'ı açtıktan sonra menü çubuğundaki "Bulut Depolamalar"a tıklayın. Buradan (S3 Uyumlu) MinIO kovanızı eklemek için bir form doldurabilirsiniz:
Şimdi “Görevler” altında yeni etiketleme görevimizi oluşturalım:
Doldurmanız gereken bir form istenecektir:
Görevi oluştururken sınıf etiketlerini doğru tanımlamak önemlidir (Algılamak istediğim iki düzleme karşılık gelen “SU30” ve “TU95” başlıklı iki Dikdörtgen etiketi tanımladım):
Artık geri kalan adım, önceden eklediğimiz MinIO paketimizi veri kaynağı olarak eklemektir. "Dosya Seç"in altında "Bulut Depolama"yı tıklayın ve bu kaynak için daha önce sağladığınız adı girin. Yukarıda “minio-cv-bucket” ismini kullandım.
Yükleme işlemi birkaç dakika sürecektir. Tamamlandığında, ek açıklama işinizi "İşler" altında görebilmeniz gerekir.
Artık işin üzerine tıklayarak görsellerinizin her birine açıklama eklemeye başlayabilirsiniz. Uyarı: Bu orantısız bir şekilde zaman alıcı bir süreç olabilir. Genel olarak, büyük açıklama gereksinimleri olan bir üretim ortamında, bu görevi özel bir dahili ekibe veya üçüncü taraf bir veri etiketleme şirketine devretmek en iyisi olabilir.
Açıklama eklemeyi tamamladığınızda veri kümesini YOLO formatında dışa aktarın.
Dışa aktarılan veri kümeniz zip dosyası biçiminde olacaktır. Sıkıştırılmış dosyayı açtığınızda, YOLO biçimli ek açıklama metin dosyaları kapalı bir klasörde olacaktır. Onlara göz atmaktan çekinmeyin. YOLO formatında, her görüntünün ek açıklamaları, her satırın sınırlayıcı kutunun ve sınıfın iki köşesini içerdiği bir metin dosyasındadır. Sınıf numarası, görevi oluştururken etiketleri tanımladığınız sıraya karşılık gelir. Yani bu örnekte 0, Su-30'a, 1 ise Tu-95'e karşılık gelecektir.
Bu noktada yeni bir çalışma dizini oluşturun (veya önceden oluşturduğunuz bir dizini girin). Bu dizin içinde 'dataset' adında bir alt dizin oluşturun. 'Veri kümesi' içinde, çalışma dizininiz şöyle görünecek şekilde dizinler oluşturun:
my_cv_project (WORKING DIRECTORY) |---- dataset |----images |----train |----val |----test |----annotations |----train |----val |----test
Artık hem görüntüler hem de bunlara karşılık gelen açıklamalar (metin dosyaları) için train, val ve test alt dizinlerini doldurmanız gerekecek. Numunelerinizi nasıl almak ve bölmek istediğiniz size kalmış. Toplam eğitim örneği miktarınızı %80 eğitim, %10 doğrulama ve %10 teste bölmek iyi bir uygulamadır. Resimlerinizi bölümlendirmeden önce rastgele karıştırdığınızdan emin olun.
Kişisel olarak, 'nesne algılama' grubumdaki tüm görüntüleri hızlı bir şekilde almak için MinIO Client'ın mc cp'sini komut satırında kullandım. Alternatif olarak, tüm örnek görsellerinizi yerel bilgisayarınızda zaten tek bir yerde bulunduruyorsanız, doğrudan bununla çalışabilirsiniz. Tüm örneklerimi tek bir yerde topladıktan sonra, resimlerimi ve açıklamalarımı karıştırmak, bölmek ve train, val ve test dizinlerine taşımak için bir Python betiği kullandım. İşte kolaylık sağlamak için sağlanan komut dosyası . Nasıl kullanılacağına dair herhangi bir sorunuz varsa, depoda sorun yapmaktan çekinmeyin!
Son olarak, resimler/tren, resimler/val veya resimler/test'e yerleştirdiğiniz her resim için eşleşen ek açıklama .txt dosyasının aynı zamanda annotations/ dizini içindeki karşılık gelen alt dizinde olduğundan emin olun. Örneğin:
my_cv_project (WORKING DIRECTORY) |---- dataset |----images |----train - 5.png - 3.png - 2.png |----val - 4.png |----test - 1.png |----annotations |----train - 5.txt - 3.txt - 2.txt |----val - 4.txt |----test - 1.txt
Artık verilerimiz hazır. Nesne algılama modelimize bir göz atıp eğitime başlamanın zamanı geldi.
Nesne tanımada mevcut altın standart (performans ve kullanım kolaylığı açısından), YOLO (Yalnızca Bir Kez Bakarsınız) sınıfı modellerdir. Bu yazının yazıldığı sırada YOLOv8 en son sürümdür ve Ultralytics tarafından açık kaynak olarak korunmaktadır. YOLOv8, modeli yeni oluşturulan ek açıklamalarımız üzerinde eğitmek (ve sonunda çıkarımı da yürütmek) için kullanabileceğimiz basit bir API sağlar.
YOLOv8'i indirelim:
$ pip install ultralytics
Artık eğitmek, doğrulamak ve tahmin etmek için YOLOv8 CLI aracını veya Python SDK'yı kullanabiliriz. Daha fazla bilgi için YOLOv8 belgelerine bakın.
Çalışma dizininizde veri kümesinin konumlarını ve sınıflarla ilgili ayrıntıları belirten bir YAML dosyası tanımlayın. Yolların daha önce çalışma dizininde oluşturduğum yollarla aynı olduğuna dikkat edin. Dosyamı ' objdetect.yaml ' olarak adlandırdım. Ayrıca, iki uçak sınıfı etiketinin CVAT'ta olduğu gibi aynı sırada tanımlanması gerektiğine dikkat edin.
train: ./dataset/images/train/ val: ./dataset/images/val/ test: ./dataset/images/test/ # number of classes nc: 2 # class names names: ["SU-30","TU-95"]
Aşağıdaki komutla (YOLO CLI aracını kullanarak) YOLOv8 modelini veri kümemiz üzerinde eğitmeye başlayın. Eğitim için yapılandırabileceğiniz tüm farklı seçenekler hakkında daha fazla bilgi edinmek için YOLO belgelerine bakın. Burada 100 dönemlik eğitime başlıyorum ve görüntü boyutunu 640 piksel olarak ayarlıyorum (eğitim sırasında tüm eğitim görsellerimiz buna göre ölçeklendirilecektir):
$ yolo task=detect \ mode=train \ model=yolov8s.pt \ data=objdetect.yaml \ epochs=100 \ imgsz=640
Eğitim biraz zaman alacaktır, özellikle de bir dizüstü bilgisayar üzerinde çalışıyorsanız (benim gibi), o yüzden şimdi ara vermek (veya önceden okumak 😀) için iyi bir zaman!
Eğitim döngüsünün sonunda, eğitilen modeliniz diğer ilginç grafikler ve çizelgelerle birlikte 'çalışmalar' adı verilen otomatik olarak oluşturulan bir dizinde saklanacaktır. Terminal çıkışı (aşağıdaki gibi) en son çalıştırmanın sonuçlarının spesifik konumunu gösterecektir. Bir modeli her eğittiğinizde, 'runs/detect/' içinde benzer bir dizin oluşturulacaktır.
Results saved to runs/detect/train
Not: run/detect/train/weights/, tam olarak eğitilmiş ağırlıklara sahip PT dosyalarını içerecektir. Bu konumu daha sonra hatırlayın.
Doğrulamayı aşağıdaki komutla çalıştırabilirsiniz:
$ yolo task=detect \ mode=val \ model=path/to/best.pt \ data=objdetect.yaml
Sonuçlar otomatik olarak çalışma dizininizdeki 'çalıştır/algıla/val' biçiminde bir yola sahip bir klasörde saklanacaktır.
Test kümesinde çıkarım yapmak için aşağıdaki komutu kullanabilirsiniz:
$ yolo task=detect \ mode=predict \ model=path/to/best.pt \ conf=0.5 \ source=dataset/images/test
Sonuçlar 'çalıştır/algıla/tahmin et' dosyasında saklanacaktır. İşte test setindeki bazı tahmin sonuçları:
Artık uydu görüntüsünde bulunan bazı uçak türlerini tanıyabilen eğitilmiş bir modelimiz olduğuna göre, bunu yeni görüntüler için basit bir şekilde nasıl kullanabiliriz ?
MinIO Bucket Notifications bunun için mükemmel bir araçtır. Bir webhook yardımıyla kovamıza düşen yeni bir görüntü üzerinden otomatik olarak nesne algılama çıkarımı yapabilecek bir sistem kurabiliriz.
Yüksek düzeyde 3 adımımız var. Öncelikle eğitilen modelimizle yeni bir görüntü üzerinde nesne tespiti gerçekleştirmek için webhook görevi görebilecek bir uç nokta tanımlamamız gerekiyor. İkinci olarak, MinIO Sunucu dağıtımımız için, bazı olaylar meydana geldiğinde webhook uç noktamıza ulaşması talimatını veren bazı ortam değişkenlerini yapılandırmamız gerekiyor. Üçüncü olarak, ne tür paket olayları (yani PUT) üzerinde işlem yapmak istediğimizi yapılandırmamız gerekiyor. Adım adım üzerinden geçelim.
MinIO paketine eklenen yeni bir görüntü üzerinde çıkarım yapan basit bir Flask tabanlı sunucunun ( detection_server.py ) kodu:
""" This is a simple Flask inference server implementation that serves as a webhook for the event of a new image being added to a MinIO bucket. Object detection using YOLO will be performed on that image and the resulting predictions will be returned. """ from flask import Flask, request, abort, make_response from ultralytics import YOLO import tempfile from minio import Minio # Make sure the following are populated with your MinIO details # (Best practice is to use environment variables!) MINIO_ENDPOINT = '' MINIO_ACCESS_KEY = '' MINIO_SECRET_KEY = '' model = YOLO('/PATH/TO/best.pt') # load a custom model (path to trained weights) client = Minio( MINIO_ENDPOINT, access_key=MINIO_ACCESS_KEY, secret_key=MINIO_SECRET_KEY, ) app = Flask(__name__) @app.route('/', methods=['POST']) async def inference_bucket_webhook(): """ This endpoint will be called when a new object is placed in your inference bucket """ if request.method == 'POST': # Get the request event from the 'POST' call event = request.json bucket = event['Records'][0]['s3']['bucket']['name'] obj_name = event['Records'][0]['s3']['object']['key'] with tempfile.TemporaryDirectory() as temp_dir: temp_file_name = temp_dir+'/'+obj_name client.fget_object(bucket, obj_name, temp_file_name) # See https://docs.ultralytics.com/modes/predict/ for more information about YOLO inference options results = model.predict(source=temp_file_name, conf=0.5, stream=False) # A list of bounding boxes (if any) is returned. # Each bounding box is in the format [x1, y1, x2, y2, probability, class]. result = {"results": results[0].boxes.data.tolist()} print(result) resp = make_response(result, 200) return resp else: abort(400) if __name__ == '__main__': app.run()
Çıkarım sunucusunu başlatalım:
$ python detection_server.py * Serving Flask app 'detection_server' * Debug mode: off * Running on http://127.0.0.1:5000 Press CTRL+C to quit
Flask uygulamasının çalıştığı ana bilgisayar adını ve bağlantı noktasını not edin.
Daha sonra MinIO tarafındaki web kancalarını yapılandırmaya başlayalım. Öncelikle aşağıdaki ortam değişkenlerini ayarlayın. <FONKSİYON ADI> kısmını seçtiğiniz bir fonksiyon adıyla değiştirin. Basit olması açısından 'çıkarımı' tercih ettim. Ayrıca uç nokta ortam değişkeninin çıkarım sunucunuz için doğru ana makineye ve bağlantı noktasına ayarlandığından emin olun. Bu durumda http://localhost:5000 Flask uygulamamızın çalıştığı yerdir.
$ export MINIO_NOTIFY_WEBHOOK_ENABLE_<YOURFUNCTIONNAME>=on $ export MINIO_NOTIFY_WEBHOOK_ENDPOINT_<YOURFUNCTIONNAME>=http://localhost:5000
Şimdi, mc admin service restart ALIAS komutunu kullanarak MinIO Sunucusunu yeniden başlatın veya sunucuyu ilk kez başlatıyorsanız minio sunucu komutunu da kullanabilirsiniz. MinIO Sunucusunu yeniden başlatma/yeniden başlatma hakkında daha fazla bilgi için MinIO belgelerine bakın. Not: ALIAS, MinIO sunucu dağıtımınızın takma adı ile değiştirilmelidir. Bir takma adın nasıl ayarlanacağı veya mevcut takma adların nasıl görüntüleneceği hakkında daha fazla bilgi için dokümanlara göz atın.
Son olarak haber almak istediğimiz paketi ve etkinliği ekleyelim. Bizim durumumuzda, kovamıza ` put' olayları (yeni nesnelerin oluşturulması) hakkında bilgi almak istiyoruz. Bu amaç için “tespit-çıkarım” başlıklı yepyeni, boş bir kova hazırladım ve bunu 'KOVA'nın yerine koyacağım.
$ mc event add ALIAS/BUCKET arn:minio:sqs::<YOURFUNCTIONNAME>:webhook --event put
Bu komutu çalıştırdığınızda " s3:ObjectCreated:* " çıktısının alınıp alınmadığını doğrulayarak paket bildirimleri için doğru olay türünü yapılandırıp yapılandırmadığınızı kontrol edebilirsiniz:
$ mc event ls local/detect-inference arn:minio:sqs::<YOURFUNCTIONNAME>:webhook
Paket olaylarını bir webhook'ta yayınlamaya ilişkin daha ayrıntılı bir açıklama için dokümanlara göz atın. Artık yepyeni bir görüntü üzerinde nesne algılamayı denemeye hazırız!
Çıkarım yapmak istediğim yeni görsel ('1.png' başlıklı):
Yeni görüntüyü 'çıkarımı tespit etme' grubuma bırakıyorum:
Neredeyse anında Flask sunucumda aşağıdaki sonuçları görebiliyorum:
$ python detection_server.py * Serving Flask app 'detection_server' * Debug mode: off * Running on http://127.0.0.1:5000 Press CTRL+C to quit image 1/1 /var/folders/xf/q7x0z8sn5nvckccp1g0m1vpm0000gn/T/tmpo6jx3w8u/1.png: 448x736 2 SU-30s, 101.0ms Speed: 4.1ms preprocess, 101.0ms inference, 5.8ms postprocess per image at shape (1, 3, 448, 736) {'results': [[1927.78369140625, 627.7123413085938, 1995.090576171875, 715.3443603515625, 0.8142037987709045, 0.0], [1735.740234375, 477.2108154296875, 1809.181640625, 555.767578125, 0.7766116261482239, 0.0]]} 127.0.0.1 - - [14/Sep/2023 15:39:21] "POST / HTTP/1.1" 200 -
Sonuçlar listesinde tespit edilen her sınırlayıcı kutunun YOLO formatında [x1, y1, x2, y2, olasılık, sınıf] olduğunu unutmayın. Orijinal görüntünün üzerine eklenen sınırlayıcı kutular ve tahmin edilen sınıflar şunlardır:
Not: Üretim ortamları ve/veya büyük makine öğrenimi modelleri için, çıkarımı daha sağlam ve güvenilir hale getirmek amacıyla PyTorch Serve veya Triton Server gibi yerleşik bir model hizmet çerçevesinin kullanılması iyi bir fikirdir. Bununla ilgileniyorsanız, MinIO ve PyTorch Serve ile Yapay Zeka Modeli Hizmetini Optimize Etme hakkındaki önceki yazıya göz atın.
Yaptık! Toplanan görüntü örneklerimizi güvenli ve kullanılabilir tutmak için MinIO ve CVAT'ın nasıl bir araya geldiğinin yanı sıra özel nesne algılama veri kümemizi nasıl oluşturacağımızı da inceledik. Daha sonra özel görevimiz için kendi özel YOLO modelimizi eğittik. Son olarak, 50 satırın biraz üzerinde kodla, MinIO Bucket Notifications'ı kullanarak, özel eğitilmiş nesne algılama modelimizi geçerek yeni bir görüntü çalıştırabilecek bir çıkarım sunucusu oluşturduk.
Ayrıca, bilgisayarla görmenin görev açısından kritik uygulamalarının çoğu için, çıkarımı uçta gerçekleştirmek en iyisidir. Aksi takdirde, söz konusu uygulamalar, yeni verilerin genel buluta yüklenmesi ve buluttaki bir çıkarım sunucusunun yanıtla geri dönmesinin beklenmesiyle ilişkili gecikmelere karşı savunmasızdır; hatalı ağ bağlantısı risklerinden bahsetmeye bile gerek yok. Bu nedenle, veri katmanı olarak MinIO'yu merkeze alan bir bilgisayarlı görüntü hattı çok daha anlamlıdır. Tamamen yerleşik donanım ve yazılımla, eğitimli modelimizi yakalayabilen, depolayabilen ve yeni görüntüler üzerinde kullanabilen bir hava alanı üzerinde uçan bir drone hayal edin. MinIO sunucusunun yerel dağıtımıyla, gönderinin sonunda oluşturduğumuz Kova Bildirimi tabanlı çıkarım sistemi, bu senaryo ve bunun gibi sayısız senaryo için mükemmel şekilde çalışıyor.
Sorularınız varsa Slack Kanalımıza katılın veya [email protected] adresinden bize bir not bırakın. Sana yardım etmek için burdayız.
Burada da yayınlandı.