Saya membantu klinik hewan mengukur tekanan di bawah kaki anjing. Saya menggunakan Python untuk analisis data saya dan sekarang saya terjebak mencoba untuk membagi cakram menjadi subregional (anatomi).
Saya membuat array 2D dari setiap kaki, yang terdiri dari nilai maksimal untuk setiap sensor yang telah dimuat oleh kaki dari waktu ke waktu. Berikut adalah contoh satu kaki, di mana saya menggunakan Excel untuk menggambar area yang ingin saya 'deteksi'. Ini adalah kotak 2 per 2 di sekitar sensor dengan maxima lokal, yang bersama-sama memiliki jumlah terbesar.
Jadi saya mencoba beberapa percobaan dan memutuskan untuk hanya mencari maksimum setiap kolom dan baris (tidak dapat melihat satu arah karena bentuk paw). Ini tampaknya 'mendeteksi' lokasi jari-jari yang terpisah dengan cukup baik, tetapi juga menandai sensor tetangga.
Jadi apa cara terbaik untuk memberi tahu Python yang mana dari maksimum ini yang saya inginkan?
Catatan: Kotak 2x2 tidak bisa tumpang tindih, karena harus terpisah!
Juga saya menggunakan 2x2 sebagai solusi, ada solusi yang lebih maju, tetapi saya hanya seorang ilmuwan gerakan manusia, jadi saya bukan programmer sejati atau ahli matematika, jadi tolong jaga agar tetap 'sederhana'.
Berikut ini adalah versi yang dapat dimuatnp.loadtxt
Hasil
Jadi saya mencoba solusi @ jextee (lihat hasil di bawah). Seperti yang Anda lihat, ini bekerja sangat baik di kaki depan, tetapi bekerja kurang baik untuk kaki belakang.
Lebih khusus lagi, itu tidak bisa mengenali puncak kecil itu ujung keempat. Ini jelas melekat pada kenyataan bahwa loop terlihat dari atas ke bawah menuju nilai terendah, tanpa memperhitungkan di mana ini.
Adakah yang tahu cara men-tweak algoritma @ jextee, sehingga mungkin bisa menemukan jari ke-4 juga?
Karena saya belum memproses percobaan lain, saya tidak dapat menyediakan sampel lain. Tapi data yang saya berikan sebelumnya adalah rata-rata dari setiap kaki. File ini adalah larik dengan data maksimal 9 kaki sesuai urutan kontak.
Gambar ini menunjukkan bagaimana mereka tersebar secara spasial di atas piring.
Memperbarui:
Saya telah membuat blog untuk siapa saja yang tertarik dan saya sudah menyiapkan SkyDrive dengan semua pengukuran mentah. Jadi bagi siapa pun yang meminta lebih banyak data: lebih banyak kekuatan untuk Anda!
Pembaruan baru:
Jadi setelah bantuan yang saya dapatkan dengan pertanyaan saya tentang deteksi kaki dan penyortiran kaki , saya akhirnya dapat memeriksa deteksi jari kaki untuk setiap kaki! Ternyata, itu tidak bekerja dengan baik dalam apa pun kecuali ukuran kaki seperti yang ada dalam contoh saya sendiri. Tentu saja di belakang, itu salah saya sendiri untuk memilih 2x2 begitu sewenang-wenang.
Ini adalah contoh yang bagus tentang kesalahannya: kuku dikenali sebagai jari kaki dan 'tumit' sangat lebar, sehingga dikenali dua kali!
Kaki terlalu besar, jadi mengambil ukuran 2x2 tanpa tumpang tindih, menyebabkan beberapa jari kaki terdeteksi dua kali. Sebaliknya, pada anjing kecil seringkali gagal menemukan jari kaki ke-5, yang saya duga disebabkan oleh area 2x2 yang terlalu besar.
Setelah mencoba solusi saat ini pada semua pengukuran saya, saya sampai pada kesimpulan mengejutkan bahwa untuk hampir semua anjing kecil saya tidak menemukan jari kaki ke-5 dan bahwa lebih dari 50% dampak untuk anjing besar itu akan menemukan lebih banyak!
Jadi jelas saya perlu mengubahnya. Dugaan saya sendiri adalah mengubah ukuran neighborhood
menjadi sesuatu yang lebih kecil untuk anjing kecil dan lebih besar untuk anjing besar. Tapi generate_binary_structure
saya tidak akan membiarkan saya mengubah ukuran array.
Oleh karena itu, saya berharap ada orang lain yang memiliki saran yang lebih baik untuk menemukan jari kaki, mungkin berskala jari kaki dengan ukuran kaki?
sumber
Jawaban:
Saya mendeteksi puncak menggunakan filter maksimum lokal . Ini adalah hasil dari dataset pertama Anda 4 kaki:
Saya juga menjalankannya pada dataset kedua 9 kaki dan berhasil juga .
Inilah cara Anda melakukannya:
Yang perlu Anda lakukan adalah menggunakan
scipy.ndimage.measurements.label
topeng untuk memberi label pada semua objek yang berbeda. Maka Anda akan dapat bermain dengan mereka secara individual.Perhatikan bahwa metode ini berfungsi dengan baik karena latar belakangnya tidak berisik. Jika ya, Anda akan mendeteksi sekelompok puncak yang tidak diinginkan lainnya di latar belakang. Faktor penting lainnya adalah ukuran lingkungan . Anda harus menyesuaikannya jika ukuran puncaknya berubah (seharusnya tetap proporsional).
sumber
Larutan
File data: paw.txt . Kode sumber:
Keluaran tanpa kotak tumpang tindih. Tampaknya area yang sama dipilih seperti pada contoh Anda.
Beberapa komentar
Bagian yang sulit adalah untuk menghitung jumlah semua kotak 2x2. Saya berasumsi Anda membutuhkan semuanya, jadi mungkin ada beberapa yang tumpang tindih. Saya menggunakan irisan untuk memotong kolom pertama / terakhir dan baris dari array 2D asli, dan kemudian tumpang tindih semuanya bersama-sama dan menghitung jumlah.
Untuk memahaminya dengan lebih baik, gambar array 3x3:
Kemudian Anda dapat mengambil irisannya:
Sekarang bayangkan Anda menumpuknya satu di atas yang lain dan menjumlahkan elemen pada posisi yang sama. Jumlah ini akan menjadi jumlah yang sama persis di atas kotak 2x2 dengan sudut kiri atas di posisi yang sama:
Saat Anda memiliki jumlah lebih dari kotak 2x2, Anda dapat menggunakan
max
untuk menemukan maksimum, atausort
, atausorted
untuk menemukan puncak.Untuk mengingat posisi puncak, saya memasangkan setiap nilai (jumlah) dengan posisi ordinalnya dalam array yang rata (lihat
zip
). Kemudian saya menghitung posisi baris / kolom lagi ketika saya mencetak hasilnya.Catatan
Saya mengizinkan kotak 2x2 untuk tumpang tindih. Versi yang diedit menyaring beberapa dari mereka sehingga hanya kotak yang tidak tumpang tindih yang muncul dalam hasil.
Memilih jari (ide)
Masalah lain adalah bagaimana memilih apa yang mungkin menjadi jari dari semua puncak. Saya punya ide yang mungkin berhasil atau tidak. Saya tidak punya waktu untuk mengimplementasikannya sekarang, jadi pseudo-code saja.
Saya perhatikan bahwa jika jari-jari depan tetap berada pada lingkaran yang hampir sempurna, jari belakang harus berada di dalam lingkaran itu. Juga, jari-jari depan memiliki jarak yang kurang lebih sama. Kita dapat mencoba menggunakan sifat heuristik ini untuk mendeteksi jari.
Kode palsu:
Ini adalah pendekatan brute-force. Jika N relatif kecil, maka saya pikir itu bisa dilakukan. Untuk N = 12, ada C_12 ^ 5 = 792 kombinasi, kali 5 cara untuk memilih jari belakang, jadi 3960 kasus untuk dievaluasi untuk setiap kaki.
sumber
Ini adalah masalah registrasi gambar . Strategi umum adalah:
Inilah pendekatan kasar dan siap , "hal terbodoh yang mungkin bisa berhasil":
Untuk mengatasi masalah orientasi, Anda dapat memiliki 8 atau lebih pengaturan awal untuk arah dasar (Utara, Timur Laut, dll). Jalankan masing-masing secara terpisah dan buang semua hasil di mana dua jari atau lebih berakhir pada piksel yang sama. Saya akan memikirkan ini lagi, tetapi hal semacam ini masih diteliti dalam pemrosesan gambar - tidak ada jawaban yang benar!
Gagasan yang sedikit lebih rumit: K-means clustering. Tidak seburuk itu.
Kemudian beralih hingga konvergensi:
Metode ini hampir pasti akan memberikan hasil yang jauh lebih baik, dan Anda mendapatkan massa masing-masing cluster yang dapat membantu dalam mengidentifikasi jari-jari kaki.
(Sekali lagi, Anda telah menentukan jumlah cluster di depan. Dengan pengelompokan Anda harus menentukan kepadatan dengan satu atau lain cara: Baik memilih jumlah cluster, sesuai dalam kasus ini, atau memilih jari-jari cluster dan melihat berapa banyak Anda berakhir dengan. Contoh yang terakhir adalah mean-shift .)
Maaf tentang kurangnya detail implementasi atau spesifikasi lainnya. Saya akan membuat kode ini tetapi saya punya tenggat waktu. Jika tidak ada yang berhasil minggu depan, beri tahu saya dan saya akan mencobanya.
sumber
Dengan menggunakan homologi persisten untuk menganalisis set data Anda, saya mendapatkan hasil berikut (klik untuk memperbesar):
Ini adalah versi 2D dari metode deteksi puncak yang dijelaskan dalam jawaban SO ini . Gambar di atas hanya menunjukkan kelas homologi persisten 0-dimensi yang diurutkan berdasarkan kegigihan.
Saya melakukan peningkatan pada dataset asli dengan faktor 2 menggunakan scipy.misc.imresize (). Namun, perhatikan bahwa saya menganggap empat cakar sebagai satu dataset; membaginya menjadi empat akan membuat masalah lebih mudah.
Metodologi. Gagasan di balik ini cukup sederhana: Pertimbangkan grafik fungsi dari fungsi yang menetapkan setiap piksel levelnya. Ini terlihat seperti ini:
Sekarang perhatikan ketinggian air pada ketinggian 255 yang terus-menerus turun ke tingkat yang lebih rendah. Di pulau-pulau maxima lokal muncul (lahir). Pada titik sadel dua pulau bergabung; kami menganggap pulau yang lebih rendah untuk bergabung ke pulau yang lebih tinggi (kematian). Diagram kegigihan yang disebut (dari kelas homologi dimensi ke-0, pulau-pulau kita) menggambarkan nilai-nilai kelahiran-mati dari semua pulau:
The ketekunan dari sebuah pulau kemudian perbedaan antara sejak lahir dan kematian-tingkat; jarak vertikal sebuah titik ke diagonal utama abu-abu. Sosok itu memberi label pulau-pulau dengan mengurangi kegigihan.
Gambar pertama menunjukkan lokasi kelahiran pulau-pulau. Metode ini tidak hanya memberikan maksimum lokal tetapi juga mengukur "signifikansi" mereka dengan kegigihan yang disebutkan di atas. Satu kemudian akan menyaring semua pulau dengan ketekunan yang terlalu rendah. Namun, dalam contoh Anda, setiap pulau (yaitu, setiap maksimum lokal) adalah puncak yang Anda cari.
Kode python dapat ditemukan di sini .
sumber
Masalah ini telah dipelajari secara mendalam oleh fisikawan. Ada implementasi yang baik di ROOT . Lihatlah kelas TSpectrum (khususnya TSpectrum2 untuk kasus Anda) dan dokumentasi untuk mereka.
Referensi:
... dan bagi mereka yang tidak memiliki akses ke berlangganan NIM:
sumber
Berikut adalah sebuah ide: Anda menghitung Laplacian (diskrit) dari gambar. Saya berharap itu menjadi (negatif dan) besar di maxima, dengan cara yang lebih dramatis daripada di gambar aslinya. Dengan demikian, maxima bisa lebih mudah ditemukan.
Berikut adalah ide lain: jika Anda tahu ukuran khas dari tempat-tempat bertekanan tinggi, pertama-tama Anda dapat menghaluskan gambar dengan membelitnya dengan Gaussian dengan ukuran yang sama. Ini dapat memberi Anda gambar yang lebih sederhana untuk diproses.
sumber
Hanya beberapa ide dari kepala saya:
Anda mungkin juga ingin melihat OpenCV , itu punya Python API yang cukup baik dan mungkin memiliki beberapa fungsi yang Anda anggap berguna.
sumber
Saya yakin Anda sudah cukup untuk melanjutkan sekarang, tetapi saya tidak bisa tidak menyarankan menggunakan metode k-means clustering. k-means adalah algoritma pengelompokan tanpa pengawasan yang akan membawa Anda data (dalam sejumlah dimensi - saya kebetulan melakukan ini dalam 3D) dan mengaturnya menjadi k cluster dengan batas-batas yang berbeda. Sangat menyenangkan di sini karena Anda tahu persis berapa banyak jari kaki yang seharusnya dimiliki oleh gigi taring ini.
Selain itu, ini diterapkan di Scipy yang sangat bagus ( http://docs.scipy.org/doc/scipy/reference/cluster.vq.html ).
Berikut adalah contoh apa yang dapat dilakukan untuk menyelesaikan klaster 3D secara spasial:
Apa yang ingin Anda lakukan sedikit berbeda (2D dan termasuk nilai tekanan), tapi saya masih berpikir Anda bisa mencobanya.
sumber
terima kasih untuk data mentah. Saya di kereta dan ini sejauh yang saya dapat (berhenti saya akan datang). Saya memijat file txt Anda dengan regexps dan memasukkannya ke halaman html dengan beberapa javascript untuk visualisasi. Saya membagikannya di sini karena beberapa, seperti saya, mungkin merasa lebih mudah diretas daripada python.
Saya pikir pendekatan yang baik adalah skala dan rotasi invarian, dan langkah selanjutnya adalah menyelidiki campuran gaussians. (masing-masing paw pad menjadi pusat gaussian).
sumber
Solusi fisikawan:
Tetapkan 5 marka-kaki yang diidentifikasi oleh posisi mereka
X_i
dan init dengan posisi acak. Tentukan beberapa fungsi energi yang menggabungkan beberapa penghargaan untuk lokasi penanda di posisi kaki dengan beberapa hukuman karena tumpang tindih penanda; Katakanlah:(
S(X_i)
adalah kekuatan rata-rata dalam 2x2 persegi di sekitarX_i
,alfa
adalah parameter yang akan memuncak secara eksperimental)Sekarang saatnya untuk melakukan beberapa sihir Metropolis-Hastings:
1. Pilih penanda acak dan pindahkan dengan satu piksel ke arah acak.
2. Hitung dE, perbedaan energi yang disebabkan gerakan ini.
3. Dapatkan nomor acak seragam dari 0-1 dan sebut saja r.
4. Jika
dE<0
atauexp(-beta*dE)>r
, terima langkah dan lanjutkan ke 1; jika tidak, batalkan pemindahan dan lanjutkan ke 1.Ini harus diulang sampai marker akan menyatu menjadi cakar. Beta mengontrol pemindaian untuk mengoptimalkan tradeoff, sehingga harus juga dioptimalkan secara eksperimental; itu juga dapat terus meningkat dengan waktu simulasi (simulated annealing).
sumber
Inilah pendekatan lain yang saya gunakan ketika melakukan sesuatu yang serupa untuk teleskop besar:
1) Cari piksel tertinggi. Setelah Anda memilikinya, cari yang paling cocok untuk 2x2 (mungkin memaksimalkan jumlah 2x2), atau lakukan kecocokan gaussian 2d di dalam sub wilayah katakanlah 4x4 berpusat pada piksel tertinggi.
Kemudian atur 2x2 piksel yang Anda temukan ke nol (atau mungkin 3x3) di sekitar pusat puncak
kembali ke 1) dan ulangi sampai puncak tertinggi jatuh di bawah ambang batas kebisingan, atau Anda memiliki semua jari kaki yang Anda butuhkan
sumber
Mungkin patut untuk dicoba dengan jaringan saraf jika Anda dapat membuat beberapa data pelatihan ... tetapi ini membutuhkan banyak sampel yang dianotasi dengan tangan.
sumber
garis besar kasar ...
Anda mungkin ingin menggunakan algoritma komponen yang terhubung untuk mengisolasi setiap wilayah paw. wiki memiliki deskripsi yang layak tentang ini (dengan beberapa kode) di sini: http://en.wikipedia.org/wiki/Connected_Component_Labeling
Anda harus membuat keputusan tentang apakah menggunakan 4 atau 8 keterhubungan. secara pribadi, untuk sebagian besar masalah saya lebih suka koneksi-6. Lagi pula, setelah Anda memisahkan masing-masing "paw print" sebagai wilayah yang terhubung, itu akan cukup mudah untuk beralih ke wilayah tersebut dan menemukan maxima. setelah Anda menemukan maxima, Anda bisa memperbesar wilayah itu secara iteratif hingga Anda mencapai ambang yang telah ditentukan untuk mengidentifikasi itu sebagai "jari" yang diberikan.
satu masalah halus di sini adalah bahwa segera setelah Anda mulai menggunakan teknik visi komputer untuk mengidentifikasi sesuatu sebagai kaki kanan / kiri / depan / belakang dan Anda mulai melihat jari kaki individu, Anda harus mulai mengambil rotasi, skew, dan terjemahan ke dalam akun. ini dicapai melalui analisis yang disebut "momen". ada beberapa momen berbeda untuk dipertimbangkan dalam aplikasi penglihatan:
momen sentral: momen invarian terjemahan dinormalisasi: scaling dan terjemahan momen invarian hu: terjemahan, skala, dan rotasi invarian
informasi lebih lanjut tentang momen dapat ditemukan dengan mencari "momen gambar" di wiki.
sumber
Mungkin Anda bisa menggunakan sesuatu seperti Gaussian Mixture Models. Berikut adalah paket Python untuk melakukan GMM (baru saja melakukan pencarian Google) http://www.ar.media.kyoto-u.ac.jp/members/david/softwares/em/
sumber
Sepertinya Anda bisa menipu sedikit menggunakan algoritma jetxee. Dia menemukan tiga jari kaki pertama baik-baik saja, dan Anda harus bisa menebak di mana yang keempat didasarkan itu.
sumber
Masalah menarik. Solusi yang akan saya coba adalah sebagai berikut.
Terapkan filter low pass, seperti konvolusi dengan topeng gaussian 2D. Ini akan memberi Anda banyak nilai (mungkin, tetapi tidak harus floating point).
Lakukan penindasan non-maksimal 2D menggunakan radius perkiraan yang diketahui dari setiap paw pad (atau jari kaki).
Ini akan memberi Anda posisi maksimal tanpa memiliki banyak kandidat yang berdekatan. Hanya untuk memperjelas, jari-jari topeng pada langkah 1 juga harus serupa dengan jari-jari yang digunakan pada langkah 2. Jari-jari ini bisa dipilih, atau dokter hewan dapat secara eksplisit mengukurnya sebelumnya (ini akan bervariasi dengan usia / jenis / dll).
Beberapa solusi yang disarankan (pergeseran rata-rata, jaring saraf, dan sebagainya) mungkin akan bekerja pada tingkat tertentu, tetapi terlalu rumit dan mungkin tidak ideal.
sumber
Nah, ini beberapa kode sederhana dan tidak terlalu efisien, tetapi untuk ukuran set data ini tidak masalah.
Saya pada dasarnya hanya membuat array dengan posisi kiri atas dan jumlah masing-masing 2x2 persegi dan mengurutkannya dengan jumlah. Saya kemudian mengambil kotak 2x2 dengan jumlah pertengkaran tertinggi, memasukkannya ke dalam
best
array, dan menghapus semua kotak 2x2 lainnya yang menggunakan bagian mana saja dari 2x2 persegi yang baru saja dihapus ini.Tampaknya berfungsi dengan baik kecuali dengan paw terakhir (yang dengan jumlah terkecil di paling kanan dalam gambar pertama Anda), ternyata ada dua kotak 2x2 lain yang memenuhi syarat dengan jumlah yang lebih besar (dan mereka memiliki jumlah yang sama dengan satu sama lain). Salah satunya masih memilih satu kotak dari kotak 2x2 Anda, tetapi yang lainnya ke kiri. Untungnya, kita beruntung memilih lebih dari yang Anda inginkan, tetapi ini mungkin memerlukan beberapa ide lain untuk digunakan untuk mendapatkan apa yang sebenarnya Anda inginkan sepanjang waktu.
sumber
Hanya ingin memberi tahu kalian ada pilihan bagus untuk menemukan
maxima
gambar lokal dengan python:atau untuk skimage
0.8.0
:http://scikit-image.org/docs/0.8.0/api/skimage.feature.peak.html
sumber
Mungkin pendekatan naif sudah cukup di sini: Buat daftar semua kotak 2x2 di pesawat Anda, pesan dengan jumlah mereka (dalam urutan menurun).
Pertama, pilih kotak bernilai tertinggi ke dalam "daftar kaki" Anda. Kemudian, pilih 4 dari kotak terbaik berikutnya yang tidak bersinggungan dengan kotak yang sebelumnya ditemukan.
sumber
Ada beberapa perangkat lunak luas yang tersedia dari komunitas astronomi dan kosmologi - ini adalah bidang penelitian yang signifikan baik secara historis maupun saat ini.
Jangan khawatir jika Anda bukan astronom - ada yang mudah digunakan di luar lapangan. Misalnya, Anda dapat menggunakan astropi / fotutil:
https://photutils.readthedocs.io/en/stable/detection.html#local-peak-detection
[Tampaknya agak kasar untuk mengulang kode sampel pendek mereka di sini.]
Daftar teknik / paket / tautan yang mungkin tidak lengkap dan sedikit menarik diberikan di bawah ini - tambahkan lebih banyak di komentar dan saya akan memperbarui jawaban ini seperlunya. Tentu saja ada pertukaran akurasi dan sumber daya komputasi. [Jujur, ada terlalu banyak untuk memberikan contoh kode dalam satu jawaban seperti ini jadi saya tidak yakin apakah jawaban ini akan terbang atau tidak.]
Sumber Extractor https://www.astromatic.net/software/sextractor
MultiNest https://github.com/farhanferoz/MultiNest [+ pyMultiNest]
Tantangan pencarian sumber ASKAP / EMU: https://arxiv.org/abs/1509.03931
Anda juga dapat mencari tantangan ekstraksi sumber Planck dan / atau WMAP.
...
sumber
Bagaimana jika Anda melanjutkan langkah demi langkah: pertama-tama Anda menemukan maksimum global, proses jika perlu titik-titik di sekitarnya diberi nilainya, kemudian atur wilayah yang ditemukan ke nol, dan ulangi untuk yang berikutnya.
sumber
Saya tidak yakin ini menjawab pertanyaan, tetapi sepertinya Anda bisa mencari n puncak tertinggi yang tidak memiliki tetangga.
Inilah intinya. Perhatikan bahwa itu ada di Ruby, tetapi idenya harus jelas.
sumber