YOLO'da Nesne Tespiti Yapılan Görüntüyü Frame Olarak Kaydetme ve Frameleri Video Olarak Birleştirme

Merhaba,
YOLO ile video üzerinde detection işlemi yaparken bir önizleme ekranı açılıyor ve video bittiğinde kapanıyor. 
Eğer detect edilen framelari tek tek kaydetmek isterseniz  -prefix output parametresini eklemeniz yeterli.

sudo ./darknet detector demo cfg/coco.data cfg/yolo.cfg cfg/yolo.weights data/myvideos/vapur.MOV -prefix output






NOT:
Makinanızda FFmpeg kurulu değil ise Ubuntu 16.04 LTS üzerinde FFmpeg Kurulumu başlıklı yazıdaki adımları izleyerek kurulum yapabilirsiniz.

Peki bu frameleri video olarak nasıl birleştirebiliriz?

output_00000001.jpg formatında kaydedilen frameleri aşağıdaki komut ile ffmpeg paketini kullanarak results klasörü altına vapur.mp4 olarak video dosyasının oluşturulduğunu göreceksiniz.

sudo ffmpeg -r 60 -f image2 -s 1280x720 -i output_%08d.jpg -codec:v libx264 -pix_fmt yuv420p results/vapur.mp4

 


FFMpeg detaylı kullanımı için dökümantasyonunu inceleyebilirsiniz.

Ubuntu 16.04 LTS üzerinde FFmpeg Kurulumu

Merhaba,
FFmpeg resmi sitesindeki indirme seçeneklerinin sayfasına buradan gidiyoruz.

Orta bölümdeki büyük yeşil "Download" buttonuna tıklayarak en son stabil versiyonunun sıkıştırılmış dosyasını makinamıza indiriyoruz.

Sıkıştırılmış dosyanın bulunduğu klasöre giderek, aşağıdaki komut ile sıkıştırılmış dosyadan ffmpeg  klasörünü çıkartıyoruz ve çıkarttığımız ffmpeg klasörü içerisine giriyoruz.

tar xf ffmpeg-3.4.tar.bz2
cd ffmpeg-3.4

ffmpeg klasörü altında aşağıdaki komutu çalıştırıyoruz.

sudo ./configure

Eğer yukarıdaki hatayı alırsanız sonuna --disable-x86asm parametresini ekleyerek yeniden configure komutunu çalıştırınız.

sudo ./configure --disable-x86asm

İşlem tamamlandıktan sonra derleme işlemini başlatalım

make -j8

No: -j8 parametresi opsiyoneldir. Derleme işlemini hızlandırmak için "-j çekirdek sayısı" parametresini ekleyebilirsiniz.

Derleme işlemi tamamlandıktan sonra yükleme işlemini çalıştıralım

sudo make install -j8

Başarıyla tamamlanıp tamamlanmadığı kontrol edelim.

ffmpeg -version

Herşey yolunda gözüküyor :)

Detaylı kullanım için dökümantasyonunu inceleyebilirsiniz.

 

YOLO: Gerçek Zamanlı Nesne Tespiti Kütüphanesi (Darknet) Kurulumu

Merhaba,

Bu yazıda açık kaynaklı yapay sinir ağı kütüphanesi olan Darknet kütüphanesinin makinamıza kurulumunu ve 2017 yılı itibariyle gerçek zamanlı olarak en hızlı şekilde nesne tespiti yapabilen YOLO(You Only Look Once) algoritmasının önceden eğitilmiş modelini kullanarak nesne tespiti demosunu nasıl çalıştıracağımızı görelim.

KURULUM

Github üzerinden darknet deposunu git ile klonlayalım ve darknet klasörü içerisine girelim.

git clone https://github.com/pjreddie/darknet.git
cd darknet

Derleme işlemini başlatmadan önce darknet klasörü içerisindeki Makefile dosyasını inceleyelim.

GPU=1
CUDNN=0
OPENCV=1
OPENMP=0
DEBUG=0

...

Biz sadece yukarıdaki ilk 5 satırı ile ilgileneceğiz.

CUDA destekli Nvidia ekran kartınız varsa ve GPU üzerinde çalıştırmak istiyorsanız Makefile dosyasında ilk satırdaki GPU değerini 1 olarak değiştiriyoruz.

  • GPU ile derlemek istiyorsanız makinanızda CUDA 8 versiyonu yüklü olması gerekmektedir. CUDA kurulumu için daha önceki  yazıma buradan göz atabilirsiniz.

Web kameranızdan görüntü almak için Makefile dosyasında üçüncü satırdaki OPENCV değerini 1 olarak değiştiriyoruz.

  • OpenCV destekli derlemek için makinanızda OpenCV yüklü ve derlenmiş olması gerekmektedir. Eğer kurulum yapmadıysanız "Ubuntu Üzerinde OpenCV Kurulumu" başlıklı yazımdaki adımları izleyerek kurulum yapabilirsiniz.

Sadece CPU üzerinde çalıştırmak isterseniz Makefile dosyasında yukarıdaki değişiklikleri yapmadan derleyebilirsiniz.

make komutu çalıştırarak derleme işlemini başlatalım.

~/darknet$ make -j8

-j8 parametresi opsiyoneldir. Derleme işlemini hızlandırmak için "-j çekirdek sayısı" parametresini ekleyebilirsiniz.

CPU üzerinde derleme yaptınızda sorun yaşayacağınızı düşünmüyorum. Ancak GPU üzerinde ve OpenCV destekli derleme yaparken hata alabilirsiniz. CUDA ve OpenCV kurulum işlemlerinizi kontrol ediniz.

Derleme işlemi sorunsuz şekilde tamamlandıysa denemeye geçebiliriz.

DEMO

Önceden eğitilmiş modelin ağırlık dosyalarını aşağıdaki komut ile indirelim.

wget https://pjreddie.com/media/files/yolo.weights

Ben ağırlık dosyasını da yapılandırma dosyalarının olduğu cfg klasörü altına indirdim. Siz dilediğiniz yere indirebilirsiniz.

Data klasörü altındaki örnek dog.jpg görselinde nesne tanıma ve yerini saptamasını istiyorsak, aşağıdaki şekilde ağ dosyasını (yolo.cfg), indirdiğimiz ağırlık dosyasını (yolo.weights) ve görselin yolunu parametre olarak belirterek  detect komutu çalıştıralım.

./darknet detect cfg/yolo.cfg cfg/yolo.weights data/dog.jpg

 

 

İşlem sonunda görsel içerisinde  dog: 82%, car: 26%, truck: 65%, bicycle: 85% oranlarında nesneleri içerdiğini ve nesnelerin konumlarını sınırlayıcı kutu içerisine aldığını görüyoruz.

 

Webcam ile gerçek zamanlı nesne tespiti için COCO veriseti'ni kullanarak detector demo komutunu çalıştırıyoruz

./darknet detector demo cfg/coco.data cfg/yolo.cfg cfg/yolo.weights

 

Video üzerinde gerçek zamanlı nesne tespiti için ise webcam ile çalıştırdığımız komut sonuna videonun dosya yolunu belirtmemiz yeterli

./darknet detector demo cfg/coco.data cfg/yolo.cfg cfg/yolo.weights <video dosya yolu>

ÇALIŞMALARIM

İstanbul trafiğinde çekilmiş olan kısa bir video üzerindeki nesne tespiti denememi izleyebilirsiniz.

Telefon ile çektiğim başka bir video üzerindeki nesne tespiti denememi izleyebilirsiniz.

Bilgisayar özellikleri video açıklamalarında mevcuttur.

 
Son olarak
Joseph Redmon'dan "Bilgisayarlar nesneleri anında nasıl tanımayı öğrenirler" başlıklı YOLO sunumunu izleyebilirsiniz

Referanslar:

 

 

Ubuntu - Windows Dual Boot Partition Mount Hatasının Çözümü

Eğer Windows ve Ubuntu dual boot kullanıyorsanız ve bir nedenden dolayı NTFS formatlı bir diskinizde Ubuntu üzerinde aşağıdaki hatayı alıyorsanız;

Error mounting /dev/sda1 at /media/yavuz/DEPO: ....... exited with non-zero exit status 14: The disk contains an unclean file system (0, 0).
Metadata kept in Windows cache, refused to mount.
Failed to mount ‘/dev/sda1’: Operation not permitted
The NTFS partition is in an unsafe state. Please resume and shutdown
Windows fully (no hibernation or fast restarting), or mount the volume
read-only with the ‘ro’ mount option.

Çözüm çok kolay.

Ubuntu üzerinde zaten yüklü olan ntfsfix ile hatalı görünen bölümü belirterek düzeltebilirsiniz.

Terminal üzerinden aşağıdaki komutu çalıştırmanız yeterli.

sudo ntfsfix /dev/sdXY


Not: burada XY, hatada gösterilen bölümdür. Örneğin sda1 veya sdb2 veya sda5. Resimde göründüğü gibi benim bölüm sda1 olduğundan sudo ntfsfix /dev/sda1 komutunu çalıştırıyorum.

Caffe Fine-Tuning (Caffe'yi Kendi Verisetiniz ile Kullanma)

Merhaba,

Uygulamalarda genelde evrişimsel sinir ağlarını (convolutional neural network) rastgele başlatma ile sıfırdan eğitmiyoruz. Bunun nedeni gerekli ağ derinliği için yeterli veri setimizin olmamasıdır. Bunun yerine kendi verisetimize benzer çok büyük bir veriseti ile (örneğin 1000 kategoriye ayrılmış yaklaşık 1.000.000 ImageNet görüntüsü) eğitilmiş parametreleri başlangıç parametresi olarak alırız. Bu ağlar bir kaç GPU ile haftalarca eğitilmiş ağlardır. Ayrıca derin evrişimsel sinir ağlarında ilk katmanlar genel özelliklerin ağırlıklarını tutarken son katmanlara doğru sınıfa özgü özelliklerin ağırlıkları tutulur. Önceden eğitilmiş model, kendi sınıflandırma sorunumuzla alakalı özellikleri zaten barındırıyor olduğundan yarar sağlacaktır.

Elbette, veri kümemiz, örneğin tıbbi görüntüler veya Çin el yazısı karakterler gibi bazı spesifik alanlar ise ve bu alanda önceden eğitim almış ağlar bulunamazsa, o zaman ağın sıfırdan eğitim yapmayı düşünebiliriz.

Caffe ile önceden eğitilmiş ağ üzerinde kendi verisetimiz için ince ayar yaparak yeniden nasıl eğitilir inceleyelim.

Ön çalışmalar

Örnek olarak üzerinde çalışacağımız doku örneklerini buradan Outex_TC_00014 verisetini indirelim.
Outex_TC_00014 verisetinde 68 sınıf, bir sınıftan 3 farklı aydınlatma koşulu altında 20şer fotoğraf olmak üzere toplam 4080 adet resim bulunuyor.

Öncelikle verisetindeki tüm .bmp resimlerini .jpg olarak convert etmek için, mogrify kütüphanesinden yararlanılarak aşağıdaki komut terminalden çalıştıralım.

mogrify -path /home/yavuz/myprojects/myjupyter/images/Outex_TC_00014/images_jpg/ -format jpg /home/yavuz/myprojects/myjupyter/images/Outex_TC_00014/images/*.bmp

Bu sayede images klasörü altındaki tüm .bmp formatındaki resimler images_jpg klasörü altında .jpg formatına çevrilerek koplayanmış oldu.

Daha sonra ilk iki aydınlatma koşulu altındaki örnekleri train için, üçüncü aydınlatma koşulu altındaki örnekleri ise test için klasörlere ayıralım.

Train klasöründe 2720 adet, test klasöründe ise 1360 adet resim bulunmalıdır.

Aynı şekilde "FileFullPath Class" formatında(Örn: /home/yavuz/caffe/examples/outexTC14/train/002641.jpg 64) olacak şekilde test klasörü altındaki resimler için test.txt ve train klasörü altındaki resimler için ise train.txt oluşturalım.

Son olarak modelin iyi öğrenmesi için test.txt ve train.txt içerisindeki örneklerin sıralı şekilde olmaması gerekiyor. Sıralamayı karıştırmak için terminal üzerinden shuf paketinden yararlanarak aşağıdaki komut ile karıştırılmış train.txt ve test.txt ler üretelim.

shuf train.txt > train_rndm.txt
shuf test.txt > test_rndm.txt

Ön işlemler için yazdığım çalışma notebook'una buradan erişebilirsiniz.

Verisetinin jpg formatına çevrilmiş, train ve test klasörlerine ayrılmış şekilde düzenlediğim halini buradan indirebilirsiniz.

LMDB'ye Dönüştürme

Caffe'de verisetini LMDB formatına çevirmek için bir script örneği mevcut.
(caffe/examples/imagenet/create_imagenet.sh)

caffe/examples altına yeni bir klasör(outexTC14) açalım. 

caffe/examples/imagenet/ altındaki create_imagenet.sh ve make_imagenet_mean.sh scriptlerini examples altına yeni açtığımız klasör içerisine(caffe/examples/outexTC14/) kopyalayalım.

create_imagenet.sh ı düzenleyelim;

  • EXAMPLE=examples/outexTC14 : LMDB yi saklamak istediğimiz klasör
  • DATA=data/outexTC14 : test.txt ve train.txt dosyalarının da bulunduğu klasör
  • TRAIN_DATA_ROOT=/home/yavuz/caffe/examples/outexTC14/train/ : train resimlerinin bulunduğu klasör
  • VAL_DATA_ROOT=/home/yavuz/caffe/examples/outexTC14/test/ : test resimlerinin bulunduğu klasör
  • RESIZE=true : eğer resimleriniz 256x256 değilse
  • Sondaki kod parçacığını da aşağıdaki gibi $DATA/train_rndm.txt, $DATA/test_rndm.txt ve $EXAMPLE/outexTC14_train_lmdb, $EXAMPLE/outexTC14_test_lmdb olarak düzenlenir.
    GLOG_logtostderr=1 $TOOLS/convert_imageset \
        --resize_height=$RESIZE_HEIGHT \
        --resize_width=$RESIZE_WIDTH \
        --shuffle \
        $TRAIN_DATA_ROOT \
        $DATA/train_rndm.txt \
        $EXAMPLE/outexTC14_train_lmdb
    
    echo "Creating val lmdb..."
    
    GLOG_logtostderr=1 $TOOLS/convert_imageset \
        --resize_height=$RESIZE_HEIGHT \
        --resize_width=$RESIZE_WIDTH \
        --shuffle \
        $VAL_DATA_ROOT \
        $DATA/test_rndm.txt \
        $EXAMPLE/outexTC14_test_lmdb

make_imagenet_mean.sh'ı düzenleyelim;

EXAMPLE=examples/outexTC14
DATA=data/outexTC14
TOOLS=build/tools

$TOOLS/compute_image_mean $EXAMPLE/outexTC14_train_lmdb \
  $DATA/imagenet_mean.binaryproto

caffe/data klasörü altına da yeni bir klasör(outexTC14) açalım. Yukarıda make_imagenet_mean.sh ve create_imagenet.sh scriptleri içerisinde yeni açtığımız klasörü data/outexTC14 olarak belirtmiştik.

Yeni açtığımız caffe/data/outexTC14 klasörü içerisine yukarıda oluşturduğumuz train_rndm.txt ve test_rndm.txt dosyalarını kopyalayalım.

Şimdi scriptlerimizi çalıştırmaya hazırız.
Terminalden caffe klasörümüz içerisinde aşağıdaki komut ile önce create_imagenet.sh scriptimizi çalıştıralım.

~/caffe$ examples/outexTC14/create_imagenet.sh 

Bu script çalışması sonucunda caffe/examples/outexTC14/ içerisinde outexTC14_test_lmdb ve outexTC14_train_lmdb adında iki klasör oluşmuş olması gerekiyor.


Terminalden caffe klasörümüz içerisinde aşağıdaki komut ile önce make_imagenet_mean.sh scriptimizi çalıştıralım.

examples/outexTC14/make_imagenet_mean.sh

Bu script çalışması sonucunda caffe/data/outexTC14/ içerisinde imagenet_mean.binaryproto adında dosya oluşmuş olması gerekiyor.

Ağ Düzenleme

caffe/models klasörü altına yine aynı isimde yeni bir klasör(outexTC14) açalım. Fine-tuning için caffe içerisinde var olan FlickrStyleCaffeNet ağından yararlanalım.
caffe/models/finetune_flickr_style altındaki train_val.prototxt, solver.prototxt ve deploy.prototxt dosyalarını yeni açtığımız caffe/models/outexTC14 klasörü altına kopyalayalım.

train_val.prototxt'ı düzenleyelim;

  • name: "OutexTC14CaffeNet"
  • transform_param (Birinci TRAIN Layer'ında)
        mean_file: "data/outexTC14/imagenet_mean.binaryproto"
  • image_data_param (Birinci TRAIN Layer'ında)
        source: "data/outexTC14/train_rndm.txt"
  • transform_param (İkinci TEST Layer'ında)
        mean_file: "data/outexTC14/imagenet_mean.binaryproto"
  • image_data_param (Birinci TRAIN Layer'ında)
        source: "data/outexTC14/test_rndm.txt"
  • inner_product_param (En son layer)
        num_output: 68
    (Verisetimizdeki sınıf sayımız)
name: "OutexTC14CaffeNet"
layer {
  name: "data"
  type: "ImageData"
  top: "data"
  top: "label"
  include {
    phase: TRAIN
  }
  transform_param {
    mirror: true
    crop_size: 227
    mean_file: "data/outexTC14/imagenet_mean.binaryproto"
  }
  image_data_param {
    source: "data/outexTC14/train_rndm.txt"
    batch_size: 50
    new_height: 256
    new_width: 256
  }
}
layer {
  name: "data"
  type: "ImageData"
  top: "data"
  top: "label"
  include {
    phase: TEST
  }
  transform_param {
    mirror: false
    crop_size: 227
    mean_file: "data/outexTC14/imagenet_mean.binaryproto"
  }
  image_data_param {
    source: "data/outexTC14/test_rndm.txt"
    batch_size: 50
    new_height: 256
    new_width: 256
  }
}
layer {
  name: "conv1"
  type: "Convolution"
  bottom: "data"
  top: "conv1"
  param {
    lr_mult: 1
    decay_mult: 1
  }
  param {
    lr_mult: 2
    decay_mult: 0
  }
  convolution_param {
    num_output: 96
    kernel_size: 11
    stride: 4
    weight_filler {
      type: "gaussian"
      std: 0.01
    }
    bias_filler {
      type: "constant"
      value: 0
    }
  }
}
...
...
...
layer {
  name: "fc8_flickr"
  type: "InnerProduct"
  bottom: "fc7"
  top: "fc8_flickr"
  # lr_mult is set to higher than for other layers, because this layer is starting from random while the others are already trained
  param {
    lr_mult: 10
    decay_mult: 1
  }
  param {
    lr_mult: 20
    decay_mult: 0
  }
  inner_product_param {
    num_output: 68
    weight_filler {
      type: "gaussian"
      std: 0.01
    }
    bias_filler {
      type: "constant"
      value: 0
    }
  }
}
layer {
  name: "accuracy"
  type: "Accuracy"
  bottom: "fc8_flickr"
  bottom: "label"
  top: "accuracy"
  include {
    phase: TEST
  }
}
layer {
  name: "loss"
  type: "SoftmaxWithLoss"
  bottom: "fc8_flickr"
  bottom: "label"
  top: "loss"
}

solver.prototxt'ı düzenleyelim;

  • net: "models/outexTC14/train_val.prototxt"
  • test_iter: 27 (batch_size: 50 olduğundan ve 1360 test verimiz olduğundan yaklaşık olarak 1360/50 = 27)
  • base_lr: 0.0001 (learning rate)
  • snapshot_prefix: "models/outexTC14/outexTC14"
net: "models/outexTC14/train_val.prototxt"
test_iter: 27
test_interval: 100
# lr for fine-tuning should be lower than when starting from scratch
base_lr: 0.0001
lr_policy: "step"
gamma: 0.1
# stepsize should also be lower, as we're closer to being done
stepsize: 20000
display: 20
max_iter: 100000
momentum: 0.9
weight_decay: 0.0005
snapshot: 1000
snapshot_prefix: "models/outexTC14/outexTC14"
# uncomment the following to default to CPU mode solving
solver_mode: GPU

deploy.prototxt'ı düzenleyelim;
(train_val.prototxt'deki değişiklikler gibi)

  • name: "OutexTC14CaffeNet"
  •  inner_product_param
        num_output: 68

 

Son olarak .prototxt'lerimizi düzenledikten sonra train için bir ağırlık dosyasına ihtiyacımız olduğundan caffe/models/bvlc_reference_caffenet altındaki bvlc_reference_caffenet.caffemodel dosyasını kendi model klasörümüz caffe/models/outexTC14 klasörü altına kopyalayalım.

Eğitim

Bir ağın eğitimi için ihityacımız olan herşeyi hazırladık. ./caffe klasörü altında aşağıdaki fine-tuning train komutu ile eğitimi başlatalım.

./build/tools/caffe train -solver models/outexTC14/solver.prototxt -weights models/outexTC14/bvlc_reference_caffenet.caffemodel

Eğer log almak isterseniz yukarıdaki komut sonuna 2>&1 | tee -a log_outexTC14_20170812.log ekleyebilirsiniz.

Log çıktısını vcaffe ile görselleştirebilirsiniz.

./build/tools/caffe train -solver models/outexTC14_2/solver.prototxt -weights models/outexTC14_2/bvlc_reference_caffenet.caffemodel 2>&1 | tee -a log_outexTC14_20170812.log



Gördüğünüz gibi eğitim makul bir çizgide ilerliyor. Burada amacımız yüksek bir başarım elde etmek değil. Hazır eğitilmiş bir ağ üzerinden ince ayarlar yaparak ve kendi verisetimize göre düzenleyerek yeniden nasıl train edebileceğimizi görmekti.
Sizler de AlexNet için aynı adımları gerçekleştirebilirsiniz.

Sınıflandırma

Eğittimiz modeli kullanarak sınıflandırma yapmak istediğimizde sınıf isimlerimizin bulunduğu bir labels.txt dosyasına ihtiyacımız var.

train.txt de test.txt içerisinde belirttiğimiz sınıflara karşılık belirlediğimiz etiketleri aşağıdaki formatta caffe/models/outexTC14 altına labels.txt oluşturuyoruz.

0 doku0
1 doku1
2 doku2
3 doku3
4 doku4
...
67 doku67

Aşağıdaki komut ile deploy.prototxt, istediğimiz iterasyondaki .caffemodel, .binaryproto, labels.txt ve sınıflandırmasını istediğimiz resmin full path'ini belirterek çalıştırıyoruz.

./build/examples/cpp_classification/classification.bin models/outexTC14/deploy.prototxt models/outexTC14/outexTC14_iter_7000.caffemodel data/outexTC14/imagenet_mean.binaryproto data/outexTC14/labels.txt /home/yavuz/caffe/examples/outexTC14/test/002740.jpg

002740.jpg resminin %83,14 ile doku1 sınfına ait olduğunu görüyoruz.



Eksik ve hataları veya yorumlarınızı paylaşırsanız sevinirim.

Yönlendirme ve destekleri için tez danışmanım Erhan hocama teşekkürler.

Faydalı Linkler: