Pençelerimi nasıl sıralayabilirim?


121

In my önceki soruya ben mükemmel bir cevabı var bir pençe bir basınç plakasını isabet nerede bana algılamak yardımcı ama şimdi bunlara karşılık gelen pençeleri bu sonuçları bağlamak mücadele ediyorum:

alternatif metin

Pençelere manuel olarak açıklama ekledim (RF = sağ ön, RH = sağ arka, LF = sol ön, LH = sol arka).

Gördüğünüz gibi açıkça tekrar eden bir model var ve neredeyse her ölçümde geri geliyor. Aşağıda, manuel olarak açıklama eklenen 6 denemenin sunumuna bir bağlantı verilmiştir.

İlk düşüncem, sıralamayı yapmak için buluşsal yöntem kullanmaktı, örneğin:

  • Ön ve arka pençeler arasında ağırlık taşıma oranı ~% 60-40;
  • Arka pençeler genellikle yüzey olarak daha küçüktür;
  • Pençeler (genellikle) uzamsal olarak sola ve sağa bölünmüştür.

Ancak, düşünmediğim bir varyasyonla karşılaştığım anda bende başarısız olacaklarından, buluşsal yöntemlerim konusunda biraz şüpheliyim. Ayrıca muhtemelen kendi kuralları olan topal köpeklerin ölçümleriyle de baş edemeyecekler.

Dahası, Joe tarafından önerilen ek açıklama bazen karışır ve pençenin gerçekte neye benzediğini hesaba katmaz.

Pençede pik tespiti ile ilgili soruma aldığım cevaplara dayanarak , pençeleri sıralamak için daha gelişmiş çözümler olduğunu umuyorum. Özellikle basınç dağılımı ve ilerlemesi her ayrı pençe için farklı olduğundan, neredeyse bir parmak izi gibi. Umarım pençelerimi sadece meydana gelme sırasına göre sıralamak yerine bunları kümelemek için kullanabilecek bir yöntem vardır.

alternatif metin

Bu yüzden sonuçları karşılık gelen pençeleriyle sıralamak için daha iyi bir yol arıyorum.

Meydan herkes kadar için, ben bir sözlük turşusu var olan her pençe basınç verilerini içeren tüm dilimlenmiş diziler (ölçümüyle birlikte) ve konumlarını açıklar dilim (plaka üzerinde ve zamanla yerini).

Açıklığa kavuşturmak gerekirse: walk_sliced_data, ölçümlerin adları olan ['ser_3', 'ser_2', 'sel_1', 'sel_2', 'ser_1', 'sel_3'] içeren bir sözlüktür. Her ölçüm, çıkarılan etkileri temsil eden başka bir sözlük, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] ("sel_1" den örnek) içerir.

Ayrıca pençenin kısmen ölçüldüğü yer (uzay veya zamanda) gibi 'yanlış' etkilerin göz ardı edilebileceğini unutmayın. Sadece bir kalıbı tanımaya yardımcı olabildikleri için faydalıdırlar, ancak analiz edilmezler.

Ve ilgilenen herkes için , projeyle ilgili tüm güncellemeleri içeren bir blog tutuyorum!


1
Evet, kullandığım yaklaşım pek işe yaramıyor. Daha ayrıntılı olarak açıklamak gerekirse, kullandığım yaklaşım sadece darbeleri sıralamak ve dokunulacak ilk pençenin dokunulacak 5. pençe ile aynı olduğunu varsaymaktı. (yani darbeleri sipariş edin ve bir modulo 4 kullanın). Bununla ilgili sorun, bazen arka pençelerin ilk pençe aşağıya dokunduktan sonra sensör pedine çarpmasıdır. Bu durumda, çarpan ilk pençe, 4. veya 3. pençeye çarpma ile eşleşir. Umarım bu biraz mantıklıdır.
Joe Kington

1
Her bir arka ayağın bir parmağının diğerlerinden önemli ölçüde daha az baskı uyguladığı için görüntüleri doğru bir şekilde yorumluyor muydum? Ayrıca, ayak parmağının her zaman "içeriye", yani köpeğin kütle merkezine doğru olduğu da görülmektedir. Bunu bir sezgisel olarak birleştirebilir misin?
Thomas Langston

1
Sınırlı görüntü işleme becerilerimin biraz paslı olduğunu kabul ediyorum, ancak her bir pençenin geniş orta pedinin en az dik eğimini almak kolayca mümkün müdür? En az diklik açısının çok yardımcı olacağı görülüyor (yayınlanan pençeler için elle çizilmiş bir örnek: imgur.com/y2wBC imgur.com/yVqVU imgur.com/yehOc imgur.com/q0tcD )
user470379

Verilerin nasıl walk_sliced_datayapılandırıldığını lütfen açıklayabilir misiniz ? 3B dizilerin sözlüklerinden oluşan bir sözlük görüyorum. Üçüncü boyutu düzeltir ve ilk ikisini bir görüntü olarak çizersem, sanırım pençeler görüyorum.
Steve Tjoa

@Thomas, evet her pençe farklı bir şekilde yüklenmiştir. Programın ne yapmasını istediğimi biliyorum ama nasıl programlayacağımı bilmiyorum ... @Steve, alt kısma açıklama ekledim :-)
Ivo Flipse

Yanıtlar:


123

Peki! Sonunda tutarlı bir şekilde çalışan bir şey elde etmeyi başardım! Bu problem beni birkaç günlüğüne çekti ... Eğlenceli şeyler! Bu cevabın uzunluğu için özür dilerim, ancak bazı konularda biraz detay vermem gerekiyor ... (Şimdiye kadarki en uzun spam olmayan yığın akışı yanıtı için bir rekor kırmış olsam da!)

Bir yan not olarak, Ivo tamamının veri kümesini kullanıyorum bir bağlantı sağlanan onun içinde asıl soruya . Her biri ascii dizileri olarak depolanan birkaç farklı deney çalışması içeren bir dizi rar dosyasıdır (köpek başına bir). Bağımsız kod örneklerini bu soruya kopyalayıp yapıştırmayı denemek yerine, işte tam, bağımsız kod içeren bir bitbucket mercurial deposu . İle klonlayabilirsiniz

hg clone https://joferkington@bitbucket.org/joferkington/paw-analysis


genel bakış

Sorunuzda belirttiğiniz gibi, soruna yaklaşmanın esasen iki yolu vardır. Aslında ikisini de farklı şekillerde kullanacağım.

  1. Hangi pençenin hangisi olduğunu belirlemek için pençe darbelerinin (zamansal ve uzaysal) sırasını kullanın.
  2. "Pençe izini" tamamen şekline göre tanımlamaya çalışın.

Temel olarak, ilk yöntem köpeğin pençeleri ile çalışır, yukarıdaki Ivo'nun sorusunda gösterilen yamuk benzeri modeli takip eder, ancak pençeler bu modeli takip etmediğinde başarısız olur. Çalışmadığında programatik olarak tespit etmek oldukça kolaydır.

Bu nedenle, hangi pençenin hangisi olduğunu anlamak için bir eğitim veri seti (~ 30 farklı köpekten ~ 2000 pençe etkisi) oluşturmak için işe yaradığı ölçümleri kullanabiliriz ve sorun denetimli bir sınıflandırmaya indirgenir (Bazı ek kırışıklıklar ile. .. Görüntü tanıma, "normal" denetimli sınıflandırma probleminden biraz daha zordur).


Örüntü Analizi

İlk yöntemi detaylandırmak için, bir köpek normalde yürürken (koşmuyor!) (Bu köpeklerden bazıları olmayabilir), pençelerin şu sırayla çarpmasını bekliyoruz: Ön Sol, Sağ Ön, Sağ Ön, Sol Arka , Ön Sol, vb. Model, ön sol veya ön sağ pençe ile başlayabilir.

Bu her zaman böyle olsaydı, etkileri basitçe ilk temas süresine göre sıralayabilir ve onları pençeye göre gruplamak için bir modulo 4 kullanabilirdik.

Normal Etki Sırası

Ancak her şey "normal" olsa bile bu işe yaramıyor. Bunun nedeni, desenin yamuk benzeri şeklidir. Bir arka pençe uzamsal olarak önceki ön pençenin arkasına düşer.

Bu nedenle, ilk ön pençe darbesinden sonraki arka pençe darbesi genellikle sensör plakasından düşer ve kaydedilmez. Benzer şekilde, sensör plakasından önceki pençe darbesi kaydedilmediğinden, son pençe darbesi genellikle dizideki bir sonraki pençe değildir.

Kaçırılan Hind Pençesi

Bununla birlikte, bunun ne zaman gerçekleştiğini ve sol veya sağ ön pençeyle mi başladığımızı belirlemek için pençe çarpma modelinin şeklini kullanabiliriz. (Aslında buradaki son etkiyle ilgili sorunları görmezden geliyorum. Yine de eklemek çok zor değil.)

def group_paws(data_slices, time):   
    # Sort slices by initial contact time
    data_slices.sort(key=lambda s: s[-1].start)

    # Get the centroid for each paw impact...
    paw_coords = []
    for x,y,z in data_slices:
        paw_coords.append([(item.stop + item.start) / 2.0 for item in (x,y)])
    paw_coords = np.array(paw_coords)

    # Make a vector between each sucessive impact...
    dx, dy = np.diff(paw_coords, axis=0).T

    #-- Group paws -------------------------------------------
    paw_code = {0:'LF', 1:'RH', 2:'RF', 3:'LH'}
    paw_number = np.arange(len(paw_coords))

    # Did we miss the hind paw impact after the first 
    # front paw impact? If so, first dx will be positive...
    if dx[0] > 0: 
        paw_number[1:] += 1

    # Are we starting with the left or right front paw...
    # We assume we're starting with the left, and check dy[0].
    # If dy[0] > 0 (i.e. the next paw impacts to the left), then
    # it's actually the right front paw, instead of the left.
    if dy[0] > 0: # Right front paw impact...
        paw_number += 2

    # Now we can determine the paw with a simple modulo 4..
    paw_codes = paw_number % 4
    paw_labels = [paw_code[code] for code in paw_codes]

    return paw_labels

Tüm bunlara rağmen, çoğu zaman düzgün çalışmıyor. Tam veri kümesindeki köpeklerin çoğu koşuyor gibi görünüyor ve pençe etkileri, köpek yürürken olduğu gibi aynı zamansal sırayı takip etmiyor. (Ya da belki köpeğin sadece ciddi kalça problemleri vardır ...)

Anormal Etki Sırası

Neyse ki, pençe etkilerinin beklenen uzaysal modelimizi takip edip etmediğini programatik olarak tespit edebiliriz:

def paw_pattern_problems(paw_labels, dx, dy):
    """Check whether or not the label sequence "paw_labels" conforms to our
    expected spatial pattern of paw impacts. "paw_labels" should be a sequence
    of the strings: "LH", "RH", "LF", "RF" corresponding to the different paws"""
    # Check for problems... (This could be written a _lot_ more cleanly...)
    problems = False
    last = paw_labels[0]
    for paw, dy, dx in zip(paw_labels[1:], dy, dx):
        # Going from a left paw to a right, dy should be negative
        if last.startswith('L') and paw.startswith('R') and (dy > 0):
            problems = True
            break
        # Going from a right paw to a left, dy should be positive
        if last.startswith('R') and paw.startswith('L') and (dy < 0):
            problems = True
            break
        # Going from a front paw to a hind paw, dx should be negative
        if last.endswith('F') and paw.endswith('H') and (dx > 0):
            problems = True
            break
        # Going from a hind paw to a front paw, dx should be positive
        if last.endswith('H') and paw.endswith('F') and (dx < 0):
            problems = True
            break
        last = paw
    return problems

Bu nedenle, basit uzamsal sınıflandırma her zaman işe yaramasa da, ne zaman çalışacağını makul bir güvenle belirleyebiliriz.

Eğitim Veri Kümesi

Doğru şekilde çalıştığı modele dayalı sınıflandırmalardan, doğru sınıflandırılmış pençelerden oluşan çok büyük bir eğitim veri seti oluşturabiliriz (32 farklı köpekten ~ 2400 pençe etkisi!).

Şimdi "ortalama" bir sol ön, vb. Pençenin neye benzediğine bakmaya başlayabiliriz.

Bunu yapmak için, herhangi bir köpek için aynı boyutsallık olan bir tür "pençe ölçüsü" ne ihtiyacımız var. (Tam veri setinde hem çok büyük hem de çok küçük köpekler var!) Bir İrlanda elkhound'undan alınan bir pençe izi, oyuncak bir kanişin pençe baskısından hem çok daha geniş hem de çok "ağır" olacaktır. Her bir pençe baskısını yeniden ölçeklendirmemiz gerekir, böylece a) aynı sayıda piksele sahip olurlar ve b) basınç değerleri standartlaştırılır. Bunu yapmak için, her pençe baskısını 20x20'lik bir ızgara üzerinde yeniden örnekledim ve pençe etkisi için maksimum, minimum ve ortalama basınç değerine dayalı olarak basınç değerlerini yeniden ölçeklendirdim.

def paw_image(paw):
    from scipy.ndimage import map_coordinates
    ny, nx = paw.shape

    # Trim off any "blank" edges around the paw...
    mask = paw > 0.01 * paw.max()
    y, x = np.mgrid[:ny, :nx]
    ymin, ymax = y[mask].min(), y[mask].max()
    xmin, xmax = x[mask].min(), x[mask].max()

    # Make a 20x20 grid to resample the paw pressure values onto
    numx, numy = 20, 20
    xi = np.linspace(xmin, xmax, numx)
    yi = np.linspace(ymin, ymax, numy)
    xi, yi = np.meshgrid(xi, yi)  

    # Resample the values onto the 20x20 grid
    coords = np.vstack([yi.flatten(), xi.flatten()])
    zi = map_coordinates(paw, coords)
    zi = zi.reshape((numy, numx))

    # Rescale the pressure values
    zi -= zi.min()
    zi /= zi.max()
    zi -= zi.mean() #<- Helps distinguish front from hind paws...
    return zi

Tüm bunlardan sonra, nihayet ortalama bir sol ön, sağ arka vb. Pençenin neye benzediğine bir göz atabiliriz. Bunun, çok farklı boyutlarda 30'dan fazla köpek için ortalamasının alındığını ve tutarlı sonuçlar aldığımızı unutmayın!

Ortalama Pençeler

Bununla birlikte, bunlar üzerinde herhangi bir analiz yapmadan önce, ortalamayı (tüm köpeklerin tüm bacakları için ortalama pençe) çıkarmamız gerekir.

Ortalama Pençe

Şimdi ortalamadan farkları analiz edebiliriz ki bu biraz daha kolay anlaşılabilir:

Diferansiyel Pençeler

Görüntü tabanlı Pençe Tanıma

Tamam ... Sonunda pençeleri eşleştirmeye başlayabileceğimiz bir dizi modelimiz var. Her pençe, paw_imagebu dört 400 boyutlu vektörle karşılaştırılabilen 400 boyutlu bir vektör ( fonksiyon tarafından döndürülen ) olarak değerlendirilebilir.

Ne yazık ki, sadece "normal" denetimli bir sınıflandırma algoritması kullanırsak (yani, 4 modelden hangisinin belirli bir pençe izine en yakın olduğunu basit bir mesafe kullanarak bulursak), tutarlı bir şekilde çalışmaz. Aslında, eğitim veri setinde rastgele şanstan çok daha iyisini yapmaz.

Bu, görüntü tanımada yaygın bir sorundur. Girdi verilerinin yüksek boyutsallığı ve görüntülerin biraz "bulanık" doğası nedeniyle (yani, bitişik pikseller yüksek bir kovaryansa sahiptir), basitçe bir görüntünün bir şablon görüntüsünden farkına bakmak, çok iyi bir ölçüm vermez. şekillerinin benzerliği.

Eigenpaws

Bunu aşmak için bir dizi "öz pençe" (yüz tanımadaki "özyüzler" gibi) oluşturmalı ve her pençe izini bu öz pençelerin bir kombinasyonu olarak tanımlamalıyız. Bu, temel bileşen analiziyle aynıdır ve temelde verilerimizin boyutluluğunu azaltmanın bir yolunu sağlar, böylece mesafe iyi bir şekil ölçüsüdür.

Boyutlardan daha fazla eğitim resmine sahip olduğumuz için (2400'e karşı 400), hız için "fantezi" doğrusal cebir yapmaya gerek yoktur. Doğrudan eğitim veri setinin kovaryans matrisi ile çalışabiliriz:

def make_eigenpaws(paw_data):
    """Creates a set of eigenpaws based on paw_data.
    paw_data is a numdata by numdimensions matrix of all of the observations."""
    average_paw = paw_data.mean(axis=0)
    paw_data -= average_paw

    # Determine the eigenvectors of the covariance matrix of the data
    cov = np.cov(paw_data.T)
    eigvals, eigvecs = np.linalg.eig(cov)

    # Sort the eigenvectors by ascending eigenvalue (largest is last)
    eig_idx = np.argsort(eigvals)
    sorted_eigvecs = eigvecs[:,eig_idx]
    sorted_eigvals = eigvals[:,eig_idx]

    # Now choose a cutoff number of eigenvectors to use 
    # (50 seems to work well, but it's arbirtrary...
    num_basis_vecs = 50
    basis_vecs = sorted_eigvecs[:,-num_basis_vecs:]

    return basis_vecs

Bunlar basis_vecs"öz pençeler" dir.

Eigenpaws

Bunları kullanmak için, her pençe görüntüsünü (20x20 görüntü yerine 400 boyutlu bir vektör olarak) temel vektörlerle nokta (yani matris çarpımı) yaparız. Bu bize görüntüyü sınıflandırmak için kullanabileceğimiz 50 boyutlu bir vektör (temel vektör başına bir eleman) verir. 20x20'lik bir görüntüyü her "şablon" pençenin 20x20 görüntüsüyle karşılaştırmak yerine, 50 boyutlu, dönüştürülmüş görüntüyü her 50 boyutlu dönüştürülmüş şablon pençeyle karşılaştırıyoruz. Bu, her bir ayak parmağının tam olarak nasıl konumlandırıldığı vb. İle ilgili küçük değişikliklere çok daha az duyarlıdır ve temel olarak sorunun boyutluluğunu sadece ilgili boyutlara indirger.

Eigenpaw tabanlı Pençe Sınıflandırması

Şimdi, hangi pençenin hangisi olduğunu sınıflandırmak için her bir bacak için 50 boyutlu vektörler ile "şablon" vektörleri arasındaki mesafeyi kullanabiliriz:

codebook = np.load('codebook.npy') # Template vectors for each paw
average_paw = np.load('average_paw.npy')
basis_stds = np.load('basis_stds.npy') # Needed to "whiten" the dataset...
basis_vecs = np.load('basis_vecs.npy')
paw_code = {0:'LF', 1:'RH', 2:'RF', 3:'LH'}
def classify(paw):
    paw = paw.flatten()
    paw -= average_paw
    scores = paw.dot(basis_vecs) / basis_stds
    diff = codebook - scores
    diff *= diff
    diff = np.sqrt(diff.sum(axis=1))
    return paw_code[diff.argmin()]

İşte sonuçların bazıları: alternatif metin alternatif metin alternatif metin

Kalan Sorunlar

Hala bazı problemler var, özellikle açık bir pençe izi yapamayacak kadar küçük köpeklerde ... (Ayak parmakları sensörün çözünürlüğünde daha net bir şekilde ayrıldığından büyük köpeklerde en iyi sonucu verir.) Ayrıca, kısmi pençe izleri bununla tanınmaz. sistem, yamuk-desen tabanlı sistem ile olabilirken.

Bununla birlikte, öz-ayak analizi doğası gereği bir mesafe ölçüsü kullandığından, pençeleri her iki şekilde sınıflandırabiliriz ve öz-ayak analizinin "kod çizelgesine" olan en küçük mesafesi bir eşiğin üzerinde olduğunda yamuk model tabanlı sisteme geri dönebiliriz. Yine de bunu henüz uygulamadım.

Vay be ... Bu uzun sürdü! Böyle eğlenceli bir soru sorduğum için şapkam Ivo'ya gitti!


2
Mükemmel cevap. Ben de öz pençe yöntemini denedim, ama senin kadar azimli değildim. Gördüğüm bir problem pençe kaydı, yani yüz kaydı yüz tanıma olduğu için. Her bir pençenin konumunu ve dönüşünü normalleştirmede herhangi bir sorunla karşılaştınız mı? Eğer öyleyse, o zaman belki de pençe, PCA yapmadan önce bazı çevirme-rotasyon değişmez özelliğe önceden işlenebilir.
Steve Tjoa

2
@Steve, Joe ile daha fazla nasıl geliştirebileceğim konusunda bazı tartışmalarım olmasına rağmen onları döndürmeyi denemedim. Bununla birlikte, şimdilik projemi bitirmek için, tüm pençelere manuel olarak açıklama ekledim, böylece onu tamamlayabilirim. Neyse ki bu, tanımayı daha hassas hale getirmek için farklı eğitim setleri oluşturmamıza da izin veriyor. Pençeleri döndürmek için ayak parmaklarını kullanmayı planlıyordum, ancak blogumda okuyabileceğiniz gibi, bu ilk sorumun görünmesini sağladığı kadar kolay değil ...
Ivo Flipse

@Temel evet, kendi web sitemi barındırmaya geçtim ve tüm Wordpress içeriğini taşıdım, ancak yorumumu artık burada düzenleyemiyorum. Onları burada bulabilmelisiniz: flipserd.com/blog/ivoflipse/post/improving-the-paw-detection
Ivo

4

Bilgiyi tamamen süreye dayalı olarak kullanarak, kinematik modelleme tekniklerinden yararlanabileceğinizi düşünüyorum; yani Ters Kinematik . Oryantasyon, uzunluk, süre ve toplam ağırlık ile birleştirildiğinde, bir miktar periyodiklik verir ki bu, "pençelerin sıralanması" probleminizi çözmeye çalışırken ilk adım olmasını umuyorum.

Tüm bu veriler, adım boyutuna ve ardından pençeye [indeks] göre sıralamak için kullanabileceğiniz sınırlı çokgenlerin (veya tuplların) bir listesini oluşturmak için kullanılabilir.


2

Testi çalıştıran teknisyenin ilk pençeyi (veya ilk ikisini) manuel olarak girmesini sağlayabilir misiniz? Süreç şunlar olabilir:

  • Teknolojiye adımların sırasını gösterin ve ilk pençeyi açıklamalarını isteyin.
  • Diğer pençeleri ilk pençeye göre etiketleyin ve tekniğin düzeltmeler yapmasına veya testi yeniden çalıştırmasına izin verin. Bu, topal veya 3 bacaklı köpeklere izin verir.

Kusursuz olmasalar da, aslında ilk pençelerin açıklamalarına sahibim. Bununla birlikte, ilk pençe her zaman bir ön pençedir ve arka pençeleri ayırmama yardımcı olmaz. Dahası, sıralama Joe'nun bahsettiği gibi mükemmel değil, çünkü bu, başlangıçta her iki cephenin de plakaya dokunmasını gerektiriyor.
Ivo Flipse

Ek açıklamalar, görüntü tanımayı kullanırken faydalı olacaktır, çünkü sahip olduğum 24 ölçümden dolayı, en az 24 pençeye zaten açıklama eklenmiş olacaktır. Daha sonra 4 grup halinde kümeleneceklerse, bunlardan ikisi, kümelemeden oldukça emin bir algoritma yapmak için yeterli miktarda ön ayak içermelidir.
Ivo Flipse

Yanlış okumadıysam, bağlantılı açıklamalı denemeler, arka pençenin 6 denemeden 4'ünde ilk olarak temas ettiğini gösteriyor.
Jamie Ide

Ah, zaman açısından demek istedim. Eğe boyunca ilerlerseniz, plakaya her zaman ilk temas eden ön ayak olmalıdır.
Ivo Flipse
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.