Mengenali masalah morfometrik (yang berhubungan dengan jumlah, ukuran, atau bentuk objek dalam sebuah gambar) Show
Karena sistem komputer menjadi lebih cepat dan lebih kuat, dan kamera serta sistem pencitraan lainnya telah menjadi hal biasa di banyak bidang kehidupan lainnya, kebutuhan telah berkembang bagi para peneliti untuk dapat memproses dan menganalisis data gambar. Mempertimbangkan besarnya volume data yang dapat dilibatkan - gambar beresolusi tinggi yang menghabiskan banyak ruang disk/memori virtual, dan/atau kumpulan banyak gambar yang harus diproses bersama - dan sifat yang memakan waktu dan rawan kesalahan Pelajaran ini memperkenalkan perangkat sumber terbuka untuk memproses data gambar. bahasa pemrograman Python dan perpustakaan scikit-image (________0______32). Dengan desain eksperimental yang hati-hati, kode Python dapat menjadi alat yang ampuh dalam menjawab berbagai jenis pertanyaan Penggunaan Pemrosesan Citra dalam PenelitianPemrosesan otomatis dapat digunakan untuk menganalisis berbagai properti gambar, termasuk distribusi dan perubahan warna pada gambar, jumlah, ukuran, posisi, orientasi, dan bentuk objek pada gambar, dan bahkan - bila digabungkan dengan pembelajaran mesin Beberapa contoh metode pengolahan citra yang diterapkan dalam penelitian antara lain
Dengan pelajaran ini, kami bertujuan untuk memberikan landasan menyeluruh dalam konsep dasar dan keterampilan bekerja dengan data gambar dengan Python. Most of the examples used in this lesson focus on one particular class of image processing technique, morphometrics, but what you will learn can be used to solve a much wider range of problems MorphometricsMorphometrics involves counting the number of objects in an image, analyzing the size of the objects, or analyzing the shape of the objects. For example, we might be interested in automatically counting the number of bacterial colonies growing in a Petri dish, as shown in this image We could use image processing to find the colonies, count them, and then highlight their locations on the original image, resulting in an image like this
As we move through this workshop, we will learn image analysis methods useful for many different scientific problems. These will be linked together and applied to a real problem in the final end-of-workshop capstone challenge Let’s get started, by learning some basics about how images are represented and stored digitally
Image Basics
The images we see on hard copy, view with our electronic devices, or process with our programs are represented and stored in the computer as numeric abstractions, approximations of what we see with our eyes in the real world. Before we begin to learn how to process images with Python programs, we need to spend some time understanding how these abstractions work PixelsIt is important to realise that images are stored as rectangular arrays of hundreds, thousands, or millions of discrete “picture elements,” otherwise known as pixels. Each pixel can be thought of as a single square point of coloured light For example, consider this image of a maize seedling, with a square area designated by a red box Now, if we zoomed in close enough to see the pixels in the red box, we would see something like this Note that each square in the enlarged image area - each pixel - is all one colour, but that each pixel can have a different colour from its neighbors. Viewed from a distance, these pixels seem to blend together to form the image we see Working with PixelsAs noted, in practice, real world images will typically be made up of a vast number of pixels, and each of these pixels will be one of potentially millions of colours. While we will deal with pictures of such complexity shortly, let’s start our exploration with 15 pixels in a 5 X 3 matrix with 2 colours and work our way up to that complexity
First, the necessary imports
Sekarang setelah perpustakaan kami dimuat, kami akan menjalankan Jupyter Magic Command yang akan memastikan gambar kami ditampilkan di dokumen Jupyter kami dengan informasi piksel yang akan membantu kami menjalankan perintah dengan lebih efisien nanti di sesi
Dengan itu, mari muat data gambar kita dari disk menggunakan fungsi 52 dari modul 53 dan tampilkan menggunakan fungsi 54 dari modul 55. _56 adalah pustaka Python untuk membaca dan menulis data gambar. _53 menentukan bahwa kami ingin menggunakan versi 3 dari 56. Versi ini memiliki manfaat mendukung data gambar nD (multidimensi) secara asli (pikirkan volume, film)
Anda mungkin berpikir, "Itu memang terlihat seperti angka delapan, dan saya melihat dua warna tetapi bagaimana bisa hanya 15 piksel". Tampilan dari delapan yang Anda lihat memang menggunakan lebih banyak piksel layar untuk menampilkan delapan kami yang begitu besar, tetapi itu tidak berarti ada informasi untuk semua piksel layar tersebut di dalam file. Semua piksel ekstra itu adalah konsekuensi dari penampil kami membuat piksel tambahan melalui interpolasi. Itu bisa saja menampilkannya sebagai gambar kecil yang hanya menggunakan 15 piksel layar jika penampil dirancang berbeda Meskipun banyak format file gambar berisi metadata deskriptif yang penting, sebagian besar file gambar hanyalah kumpulan informasi numerik yang, jika ditafsirkan menurut aturan tertentu, dapat dikenali sebagai gambar bagi kita. Gambar kami dari delapan tidak terkecuali, dan 53 menyimpan data gambar itu dalam larik larik yang membuat matriks 5 x 3 15 piksel. Kita dapat mendemonstrasikannya dengan memanggil properti bentuk dari variabel gambar kita dan melihat matriks dengan mencetak variabel gambar kita ke layar
Jadi jika kita memiliki alat yang memungkinkan kita memanipulasi susunan angka ini, kita dapat memanipulasi gambar. Pustaka 33 dapat sangat berguna di sini, jadi mari kita coba menggunakan 33 pengirisan array. Perhatikan bahwa perilaku default dari fungsi 54 menambahkan nomor baris dan kolom yang akan membantu kami saat kami mencoba menangani individu atau grup piksel. Pertama, mari kita memuat salinan lain dari delapan kita, lalu membuatnya terlihat seperti nolTo make it look like a zero, we need to change the number underlying the centremost pixel to be 1. Dengan bantuan header baris dan kolom tersebut, pada skala kecil ini kita dapat menentukan piksel tengah berada di baris berlabel 2 dan kolom berlabel 1. Dengan menggunakan pemotongan array, kita kemudian dapat mengalamatkan dan menetapkan nilai baru ke posisi itu
Lebih banyak warnaSampai saat ini, kami hanya memiliki matriks 2 warna, tetapi kami dapat memiliki lebih banyak jika kami menggunakan angka atau pecahan lain. Salah satu cara umum adalah menggunakan angka antara 0 dan 255 untuk memungkinkan 256 warna berbeda atau 256 tingkat abu-abu berbeda. Mari kita coba itu 0Kami sekarang memiliki 3 warna, tetapi apakah itu tiga warna yang Anda harapkan? . Ini adalah konsekuensi dari peta warna default (cmap) di perpustakaan ini. Anda dapat menganggap peta warna sebagai asosiasi atau pemetaan angka ke warna tertentu. Namun, tujuannya di sini bukan untuk memiliki satu angka untuk setiap kemungkinan warna, melainkan untuk memiliki rangkaian warna yang menunjukkan intensitas relatif. Dalam kasus khusus kami di sini misalnya, 255 atau intensitas tertinggi dipetakan ke kuning, dan 0 atau intensitas terendah dipetakan ke ungu tua. Peta warna terbaik untuk data Anda akan bervariasi dan ada banyak opsi bawaan, tetapi pemilihan default ini tidak sembarangan. Banyak ilmu pengetahuan menjadikan ini sebagai default karena kekokohannya terkait dengan bagaimana pikiran manusia menginterpretasikan nilai warna relatif, kemampuan cetak skala abu-abu, dan ramah buta warna (Anda dapat membaca lebih lanjut tentang peta warna default ini di Matplotlib . Jadi ini adalah tempat yang baik untuk memulai, dan Anda harus mengubahnya hanya dengan tujuan dan pemikiran ke depan. Untuk saat ini, mari kita lihat bagaimana Anda dapat melakukannya dengan menggunakan peta alternatif yang mungkin pernah Anda lihat sebelumnya di mana akan lebih mudah untuk melihatnya sebagai kontinum intensitas yang dipetakan. skala abu-abu _1Di atas kami memiliki matriks data dasar yang persis sama, tetapi dalam skala abu-abu. Nol peta menjadi hitam, 255 peta menjadi putih, dan 128 peta menjadi abu-abu sedang. Di sini kami hanya memiliki satu saluran dalam data dan menggunakan peta warna skala abu-abu untuk merepresentasikan pencahayaan, atau intensitas data dan oleh karena itu saluran ini disebut sebagai saluran pencahayaan Bahkan Lebih Banyak WarnaIni semua baik dan bagus pada skala ini, tetapi apa yang terjadi ketika kita malah memiliki gambar pemandangan alam yang berisi jutaan warna. Memiliki pemetaan angka satu ke satu untuk diwarnai seperti ini akan menjadi tidak efisien dan membuat penyesuaian dan alat bangunan untuk melakukannya sangat sulit. Daripada angka yang lebih besar, solusinya adalah memiliki lebih banyak angka dalam dimensi yang lebih banyak. Menyimpan angka dalam matriks multidimensi di mana setiap warna atau properti seperti transparansi dikaitkan dengan dimensinya sendiri memungkinkan kontribusi individual ke piksel disesuaikan secara independen. Kemampuan untuk memanipulasi properti kelompok piksel secara terpisah akan menjadi kunci untuk teknik tertentu yang dieksplorasi di bab selanjutnya dari pelajaran ini. Untuk memulai, mari kita lihat contoh bagaimana berbagai dimensi informasi digabungkan untuk menghasilkan kumpulan piksel menggunakan matriks 4 X 4 dengan 3 dimensi untuk warna merah, hijau, dan biru. Daripada memuatnya dari file, kami akan membuat contoh ini menggunakan numpy _2 _3Sebelumnya kami memiliki satu angka yang dipetakan ke satu warna atau intensitas. Sekarang kami menggabungkan efek dari 3 angka untuk mendapatkan nilai warna tunggal. Mari kita lihat contohnya menggunakan kotak biru di akhir baris kedua, yang memiliki indeks [1, 3] _4Ini keluaran. array([ 7, 1, 110]) Bilangan bulat berurutan mewakili Merah, Hijau, dan Biru. Melihat 3 nilai dan mengetahui bagaimana mereka memetakan, dapat membantu kita memahami mengapa warnanya biru. Jika kita membagi setiap nilai dengan 255, yang merupakan maksimum, kita dapat menentukan seberapa besar kontribusinya relatif terhadap potensi maksimumnya. Secara efektif, merah berada di 7/255 atau 2. 8 persen dari potensinya, warna hijau berada pada 1/255 atau 0. 4 persen, dan biru adalah 110/255 atau 43. 1 persen dari potensinya. Jadi, saat Anda mencampurkan ketiga intensitas warna tersebut, biru menang dengan margin yang lebar, tetapi merah dan hijau masih berkontribusi untuk membuatnya menjadi warna biru yang sedikit berbeda dari 0,0,110 dengan sendirinya. Warna-warna ini dipetakan ke dimensi matriks dapat disebut sebagai saluran. Mungkin bermanfaat untuk menampilkan masing-masing saluran ini secara terpisah, untuk membantu kami memahami apa yang sedang terjadi. Kita dapat melakukannya dengan mengalikan representasi susunan gambar kita dengan matriks 1d yang memiliki satu untuk saluran yang ingin kita pertahankan dan nol untuk sisanya. 5 _6 _7Jika kita melihat kotak [1, 3] atas pada ketiga gambar, kita dapat melihat masing-masing kontribusi warna tersebut beraksi. Perhatikan bahwa ada beberapa kotak pada gambar biru yang terlihat lebih biru pekat daripada kotak [1, 3]. Ketika ketiga saluran digabungkan, cahaya biru dari kotak-kotak itu diencerkan oleh kekuatan relatif merah dan hijau yang dicampur dengannya. Warna RGB 24-bitModel warna terakhir yang kami gunakan ini, dikenal sebagai model RGB (Merah, Hijau, Biru), adalah yang paling umum Seperti yang kita lihat, model RGB adalah model warna aditif, yang berarti warna primer dicampur bersama untuk membentuk warna lain. Most frequently, the amount of the primary colour added is represented as an integer in the closed range [0, 255] as seen in the example. Oleh karena itu, ada 256 jumlah diskrit dari setiap warna primer yang dapat ditambahkan untuk menghasilkan warna lain. Jumlah jumlah diskrit setiap warna, 256, sesuai dengan jumlah bit yang digunakan untuk menyimpan nilai saluran warna, yaitu delapan (28=256). Karena kami memiliki tiga saluran dengan masing-masing 8 bit (8+8+8=24), ini disebut kedalaman warna 24-bit Setiap warna tertentu dalam model RGB dapat diekspresikan oleh triplet bilangan bulat dalam [0, 255], masing-masing mewakili saluran merah, hijau, dan biru. Jumlah yang lebih besar dalam saluran berarti lebih banyak warna primer yang ada
Setelah menyelesaikan tantangan sebelumnya, kita dapat melihat beberapa contoh warna RGB 24-bit lebih lanjut, secara visual. Gambar dalam tantangan berikutnya menunjukkan beberapa nama warna, nilai triplet RGB 24-bitnya, dan warna itu sendiri
Meskipun kedalaman warna 24-bit adalah umum, ada opsi lain. Kita mungkin memiliki warna 8-bit (3 bit untuk merah dan hijau, tetapi hanya 2 untuk biru, memberikan 8 × 8 × 4 = 256 warna) atau warna 16-bit (4 bit untuk merah, hijau, dan biru, ditambah 4 bit lainnya . Ada kedalaman warna dengan lebih dari delapan bit per saluran, tetapi karena mata manusia hanya dapat membedakan sekitar 10 juta warna berbeda, ini jarang digunakan. Jika Anda menggunakan layar laptop atau monitor LCD lama atau murah untuk melihat gambar, mungkin hanya mendukung warna 18-bit, yang mampu menampilkan 64 × 64 × 64 = 262.144 warna. Gambar berwarna 24-bit akan diubah menjadi 18-bit, dan dengan demikian kualitas warna yang Anda lihat tidak akan cocok dengan apa yang sebenarnya ada di gambar Kami dapat menggabungkan sistem koordinat kami dengan model warna RGB 24-bit untuk mendapatkan pemahaman konseptual tentang gambar yang akan kami kerjakan. Gambar adalah susunan piksel persegi panjang, masing-masing dengan koordinatnya sendiri. Setiap piksel dalam gambar adalah titik persegi cahaya berwarna, di mana warnanya ditentukan oleh triplet RGB 24-bit. Gambar seperti itu adalah contoh grafik raster Format gambarMeskipun gambar yang akan kami manipulasi dalam program kami dikonseptualisasikan sebagai array persegi panjang dari triplet RGB, gambar tersebut tidak harus dibuat, disimpan, atau ditransmisikan dalam format tersebut. Ada beberapa format gambar yang mungkin kita temui, dan kita harus mengetahui dasar-dasarnya setidaknya beberapa di antaranya. Beberapa format yang mungkin kami temui, dan ekstensi filenya, ditampilkan di tabel ini FormatExtensionDevice-Independent Bitmap (BMP). bmpJoint Photographic Experts Group (JPEG). jpg atau. Format File Gambar jpegTag (TIFF). tif atau. bertengkarBMPFormat file yang paling mendekati konseptualisasi gambar kami sebelumnya adalah format file Device-Independent Bitmap, atau BMP. File BMP menyimpan gambar grafik raster sebagai urutan panjang angka yang disandikan biner yang menentukan warna setiap piksel dalam gambar. Since computer files are one-dimensional structures, the pixel colours are stored one row at a time. Yaitu, baris piksel pertama (yang memiliki koordinat y 0) disimpan terlebih dahulu, diikuti oleh baris kedua (yang memiliki koordinat y 1), dan seterusnya. Bergantung pada cara pembuatannya, gambar BMP mungkin memiliki kedalaman warna 8-bit, 16-bit, atau 24-bit Gambar BMP 24-bit memiliki format file yang relatif sederhana, dapat dilihat dan dimuat di berbagai sistem operasi, dan berkualitas tinggi. Namun, gambar BMP tidak dikompresi, menghasilkan ukuran file yang sangat besar untuk resolusi gambar yang berguna Gagasan kompresi gambar penting bagi kami karena dua alasan. pertama, gambar terkompresi memiliki ukuran file yang lebih kecil, sehingga lebih mudah untuk disimpan dan dikirim; . Karena kompresi penting bagi kami, kami harus mengambil jalan memutar singkat dan mendiskusikan konsepnya Kompresi gambarSebelum membahas format tambahan, pemahaman tentang kompresi gambar akan sangat membantu. Mari selidiki subjek itu dengan sebuah tantangan. Untuk tantangan ini, Anda perlu mengetahui tentang bit / byte dan cara penggunaannya untuk menyatakan kapasitas penyimpanan komputer. Jika kamu sudah tahu, kamu bisa langsung ke tantangan di bawah ini
Karena file gambar bisa sangat besar, ada berbagai skema kompresi untuk menyimpan (kira-kira) informasi yang sama sambil menggunakan lebih sedikit ruang. Teknik kompresi ini dapat dikategorikan sebagai lossless atau lossy Kompresi tanpa rugiDalam kompresi gambar lossless, kami menerapkan beberapa algoritme (mis. e. , prosedur terkomputerisasi) ke gambar, menghasilkan file yang secara signifikan lebih kecil daripada setara file BMP yang tidak dikompresi. Kemudian, ketika kami ingin memuat dan melihat atau memproses gambar, program kami membaca file terkompresi, dan membalikkan proses kompresi, menghasilkan gambar yang identik dengan aslinya. Tidak ada yang hilang dalam proses – maka istilah “lossless. ” Ide umum kompresi lossless adalah entah bagaimana mendeteksi pola byte yang panjang dalam file yang berulang-ulang, dan kemudian menetapkan pola bit yang lebih kecil untuk mewakili sampel yang lebih panjang. Kemudian, file terkompresi terdiri dari pola yang lebih kecil, bukan yang lebih besar, sehingga mengurangi jumlah byte yang diperlukan untuk menyimpan file. File terkompresi juga berisi tabel pola pengganti dan aslinya, sehingga ketika file didekompresi dapat dibuat identik dengan aslinya sebelum dikompresi Untuk memberi Anda contoh nyata, pertimbangkan 71. Gambar BMP putih 5 MB dibahas di atas. Ketika dimasukkan melalui utilitas kompresi zip pada Microsoft Windows, hasilnya. zip hanya berukuran 72 KB. Itu adalah. versi zip dari gambar tiga kali lipat lebih kecil dari aslinya, dan dapat didekompresi menjadi file yang byte-untuk-byte sama dengan aslinya. Karena aslinya sangat berulang - hanya triplet warna yang sama diulang 25.000.000 kali - algoritme kompresi dapat secara dramatis mengurangi ukuran file Jika Anda bekerja dengan. zip atau. gz, Anda berurusan dengan kompresi lossless Kompresi kerugianKompresi lossy mengambil gambar asli dan membuang beberapa detail di dalamnya, menghasilkan format file yang lebih kecil. Tujuannya adalah untuk hanya membuang detail yang tidak akan diperhatikan oleh seseorang yang melihat gambar tersebut. Banyak skema kompresi lossy memiliki tingkat kompresi yang dapat disesuaikan, sehingga pembuat gambar dapat memilih jumlah detail yang hilang. Semakin banyak detail yang dikorbankan, file gambar akan semakin kecil - tetapi tentu saja, detail dan kekayaan gambar juga akan semakin rendah Ini mungkin bagus untuk gambar yang ditampilkan di halaman Web atau dicetak pada kertas foto 4 × 6, tetapi mungkin bagus atau tidak untuk karya ilmiah. Anda harus memutuskan apakah hilangnya kualitas dan detail gambar penting untuk pekerjaan Anda, versus penghematan ruang yang diberikan oleh format kompresi lossy Penting untuk dipahami bahwa setelah gambar disimpan dalam format kompresi lossy, detail yang hilang hanya itu - hilang. Saya. e. , tidak seperti format lossless, mengingat gambar disimpan dalam format lossy, tidak ada cara untuk merekonstruksi gambar asli dengan cara byte-by-byte JPEGGambar JPEG mungkin merupakan gambar digital yang paling sering ditemui saat ini. JPEG menggunakan kompresi lossy, dan tingkat kompresi dapat disesuaikan dengan keinginan Anda. Ini mendukung kedalaman warna 24-bit, dan karena format ini digunakan secara luas, gambar JPEG dapat dilihat dan dimanipulasi dengan mudah di semua platform komputasi.
Berikut adalah contoh yang menunjukkan bagaimana kompresi JPEG dapat memengaruhi kualitas gambar. Pertimbangkan gambar beberapa bibit jagung ini (diperkecil di sini dari 11.339 × 11.336 piksel agar sesuai dengan tampilan) Sekarang, mari kita perbesar dan lihat bagian kecil dari label aslinya, pertama dalam format yang tidak terkompresi Ini adalah area gambar yang sama, tetapi dalam format JPEG. Kami menggunakan parameter kompresi yang cukup agresif untuk membuat JPEG, untuk mengilustrasikan masalah yang mungkin Anda temui dengan format tersebut Gambar JPEG memiliki kualitas yang jelas lebih rendah. Ini memiliki variasi warna yang lebih sedikit dan pikselasi yang terlihat. Perbedaan kualitas menjadi lebih nyata ketika seseorang memeriksa histogram warna untuk setiap gambar. Histogram menunjukkan seberapa sering setiap nilai warna muncul dalam gambar. Histogram untuk gambar yang tidak dikompresi (kiri) dan dikompresi (kanan) ditunjukkan di bawah ini Kami belajar bagaimana membuat histogram seperti ini nanti di bengkel. Perbedaan histogram warna bahkan lebih terlihat daripada gambar itu sendiri; Jika pengaturan kualitas untuk gambar JPEG Anda tinggi (dan karena itu tingkat kompresi relatif rendah), kualitas gambar mungkin cukup untuk pekerjaan Anda. It all depends on how much quality you need, and what restrictions you have on image storage space. Pertimbangan lain mungkin di mana gambar disimpan. Misalnya, jika gambar Anda disimpan di cloud dan karena itu harus diunduh ke sistem Anda sebelum Anda menggunakannya, Anda mungkin ingin menggunakan format gambar terkompresi untuk mempercepat waktu transfer file. PNGGambar PNG sangat cocok untuk menyimpan diagram. Ini menggunakan kompresi lossless dan karenanya sering digunakan dalam aplikasi web untuk gambar non-fotografi. Format ini antara lain dapat menyimpan data RGB dan pencahayaan biasa (saluran tunggal, tanpa warna terkait). Data gambar disimpan berdasarkan baris dan kemudian, per baris, filter sederhana, seperti mengambil perbedaan piksel yang berdekatan, dapat diterapkan untuk meningkatkan kompresabilitas data. Data yang disaring kemudian dikompresi pada langkah berikutnya dan ditulis ke disk BERTENGKARGambar TIFF populer di kalangan penerbit, desainer grafis, dan fotografer. Gambar TIFF dapat dikompresi, atau dikompresi menggunakan skema kompresi lossless atau lossy, tergantung pada pengaturan yang digunakan, sehingga gambar TIFF tampaknya memiliki manfaat dari format BMP dan JPEG. Kerugian utama gambar TIFF (selain ukuran gambar dalam format versi tidak terkompresi) adalah bahwa gambar tersebut tidak dapat dibaca secara universal oleh perangkat lunak penampil dan manipulasi gambar. MetadataGambar JPEG dan TIFF mendukung penyertaan metadata dalam gambar. Metadata adalah informasi tekstual yang terkandung dalam file gambar. Metadata menyimpan informasi tentang gambar itu sendiri, seperti kapan gambar diambil, di mana diambil, jenis kamera apa yang digunakan dan dengan pengaturan apa, dll. Kami biasanya tidak melihat metadata ini saat kami melihat gambar, tetapi kami dapat melihatnya secara terpisah jika kami mau (lihat, di bawah). Hal penting yang harus diperhatikan pada tahap ini adalah Anda tidak dapat mengandalkan metadata gambar yang dipertahankan sepenuhnya saat Anda menggunakan perangkat lunak untuk memproses gambar tersebut. Pustaka pembaca/penulis gambar yang kami gunakan selama pelajaran ini, 53, menyertakan metadata saat menyimpan gambar baru, tetapi mungkin gagal menyimpan bidang metadata tertentu. Bagaimanapun, ingat. jika metadata penting bagi Anda, berhati-hatilah untuk selalu mempertahankan file aslinya
Rangkuman format gambar yang digunakan dalam pelajaran iniTabel berikut merangkum karakteristik format gambar BMP, JPEG, dan TIFF FormatCompressionMetadataKeuntungan KerugianBMPNTidak ada Dapat dilihat secara universal, Ukuran file besar kualitas tinggi JPEGLossyYa Dapat dilihat secara universal, Detail mungkin hilang ukuran file lebih kecil PNGLossless Dapat dilihat secara universal, standar terbuka, ukuran file lebih kecilMetadata kurang fleksibel dibandingkan TIFF, hanya RGB
Bekerja dengan skimage
Kami telah membahas banyak tentang bagaimana gambar direpresentasikan dalam perangkat lunak komputer. Dalam episode ini kita akan mempelajari beberapa metode lagi untuk mengakses dan mengubah gambar digital Membaca, menampilkan, dan menyimpan gambarImageio menyediakan fungsi intuitif untuk membaca dan menulis (menyimpan) gambar. Semua format gambar populer, seperti BMP, PNG, JPEG, dan TIFF didukung, bersama dengan beberapa format esoteris lainnya. Periksa dokumen Format yang Didukung untuk daftar semua format. Matplotlib menyediakan banyak koleksi utilitas plotting Mari kita periksa program Python sederhana untuk memuat, menampilkan, dan menyimpan gambar ke format yang berbeda. Inilah beberapa baris pertama _2Pertama, kami mengimpor modul _89 imageio ( 53) sebagai 91 sehingga kami dapat membaca dan menulis gambar. Kemudian, kami menggunakan fungsi _62 untuk membaca gambar JPEG berjudul kursi. jpg. Imageio membaca gambar, mengubahnya dari JPEG menjadi larik NumPy, dan mengembalikan larik; Selanjutnya, kita akan melakukan sesuatu dengan gambar tersebut _3Setelah kami memiliki gambar dalam program, pertama-tama kami memanggil 94 sehingga kami akan memiliki gambar baru dengan satu set sumbu independen dari panggilan kami sebelumnya. Selanjutnya kita memanggil _95 untuk menampilkan gambarSekarang, kami akan menyimpan gambar dalam format lain _4Pernyataan terakhir dalam program, _96, menulis gambar ke file bernama 97 di direktori 74. Fungsi 99 secara otomatis menentukan jenis file, berdasarkan ekstensi file yang kami sediakan. Dalam hal ini, ekstensi _00 menyebabkan gambar disimpan sebagai TIFF
Memanipulasi pikselDalam episode Image Basics, kami secara individual memanipulasi warna piksel dengan mengubah angka yang disimpan dalam larik NumPy gambar. Mari terapkan prinsip-prinsip yang dipelajari di sana bersama dengan beberapa prinsip baru ke contoh dunia nyata Misalkan kita tertarik pada gambar cluster akar jagung ini. Kami ingin dapat memusatkan perhatian program kami pada akar itu sendiri, sambil mengabaikan latar belakang hitam Karena gambar disimpan sebagai larik angka, kita cukup melihat larik untuk nilai warna piksel yang kurang dari beberapa nilai ambang batas. Proses ini disebut thresholding, dan kita akan melihat metode yang lebih ampuh untuk melakukan tugas thresholding di episode Thresholding. Di sini, bagaimanapun, kita akan melihat metode NumPy yang sederhana dan elegan untuk thresholding. Mari kita kembangkan program yang hanya menyimpan nilai warna piksel pada gambar yang memiliki nilai lebih besar atau sama dengan 128. Ini akan menjaga piksel yang lebih terang dari setengah "kecerahan penuh", mis. e. , piksel yang bukan milik latar belakang hitam. Kami akan mulai dengan membaca gambar dan menampilkannya _7Sekarang kita dapat membatasi gambar dan menampilkan hasilnya _8Perintah NumPy untuk mengabaikan semua piksel intensitas rendah adalah 26. Setiap nilai warna piksel dalam seluruh larik 3 dimensi dengan nilai kurang dari 128 diatur ke nol. Dalam hal ini, hasilnya adalah gambar yang detail latar belakangnya telah dihilangkanMengubah gambar berwarna menjadi skala abu-abuSeringkali lebih mudah bekerja dengan gambar skala abu-abu, yang memiliki satu saluran, daripada gambar berwarna, yang memiliki tiga saluran. Skimage menawarkan fungsi _27 untuk mencapai hal ini. Fungsi ini menambahkan tiga saluran warna dengan cara yang sesuai dengan persepsi warna manusia, lihat. Ini mengembalikan gambar skala abu-abu dengan nilai floating point dalam kisaran dari 0 hingga 1. Kita dapat menggunakan fungsi _18 untuk mengubahnya kembali ke tipe data asli dan rentang data kembali 0 hingga 255. Perhatikan bahwa seringkali lebih baik menggunakan nilai gambar yang diwakili oleh nilai floating point, karena menggunakan angka floating point secara numerik lebih stabil
_9Kami juga dapat memuat gambar berwarna sebagai skala abu-abu secara langsung dengan meneruskan argumen 35 ke 62 _0
Akses melalui pengirisanSeperti disebutkan dalam pelajaran sebelumnya, gambar skimage disimpan sebagai larik NumPy, sehingga kita dapat menggunakan pengirisan larik untuk memilih area persegi panjang dari suatu gambar. Kemudian, kita dapat menyimpan pilihan tersebut sebagai gambar baru, mengubah piksel pada gambar, dan seterusnya. Penting untuk diingat bahwa koordinat ditentukan dalam urutan (ry, cx) dan nilai warna ditentukan dalam urutan (r, g, b) saat melakukan manipulasi ini Pertimbangkan gambar papan tulis ini, dan misalkan kita ingin membuat sub-gambar hanya dengan bagian yang bertuliskan "ganjil + genap = ganjil", bersama dengan kotak merah yang digambar di sekitar kata-kata Dengan menggunakan teknik tampilan yang sama yang telah kita gunakan selama kursus ini, kita dapat menentukan koordinat sudut area yang ingin kita ekstrak dengan mengarahkan mouse ke dekat titik perhatian dan mencatat koordinatnya. Jika kita melakukan itu, kita mungkin menetapkan area persegi panjang dengan koordinat kiri atas (135, 60) dan koordinat kanan bawah (480, 150), seperti yang ditunjukkan pada gambar papan tulis versi ini Perhatikan bahwa koordinat pada gambar sebelumnya ditentukan dalam urutan (cx, ry). Sekarang jika seluruh gambar papan tulis kita disimpan sebagai gambar skimage bernama 93, kita dapat membuat gambar baru dari wilayah yang dipilih dengan pernyataan seperti ini _45Pemotongan larik kita menentukan rentang koordinat y atau baris terlebih dahulu, 46, lalu rentang koordinat x atau kolom, 47. Perhatikan bahwa kami melampaui nilai maksimum di setiap dimensi, sehingga seluruh area yang diinginkan dipilih. Bagian ketiga dari irisan, _48, menunjukkan bahwa kita menginginkan ketiga saluran warna di gambar baru kitaSkrip untuk membuat subgambar akan dimulai dengan memuat gambar 4Then we use array slicing to create a new image with our selected area and then display the new image 5We can also change the values in an image, as shown next 6First, we sample a single pixel’s colour at a particular location of the image, saving it in a variable named 29, which creates a 1 × 1 × 3 NumPy array with the blue, green, and red colour values for the pixel located at (ry = 330, cx = 90). Then, with the 50 command, we modify the image in the specified area. From a NumPy perspective, this changes all the pixel values within that range to array saved in the 29 variable. In this case, the command “erases” that area of the whiteboard, replacing the words with a beige colour, as shown in the final image produced by the program
Drawing and Bitwise Operations
The next series of episodes covers a basic toolkit of skimage operators. With these tools, we will be able to create programs to perform simple analyses of images based on changes in colour or shape Drawing on imagesOften we wish to select only a portion of an image to analyze, and ignore the rest. Creating a rectangular sub-image with slicing, as we did in the Image Representation in skimage episode is one option for simple cases. Another option is to create another special image, of the same size as the original, with white pixels indicating the region to save and black pixels everywhere else. Such an image is called a mask. Dalam menyiapkan topeng, terkadang kita harus bisa menggambar bentuk - lingkaran atau persegi panjang, katakanlah - pada gambar hitam. skimage provides tools to do that Consider this image of maize seedlings Now, suppose we want to analyze only the area of the image containing the roots themselves; we do not care to look at the kernels, or anything else about the plants. Further, we wish to exclude the frame of the container holding the seedlings as well. Hovering over the image with our mouse, could tell us that the upper-left coordinate of the sub-area we are interested in is (44, 357), while the lower-right coordinate is (720, 740). These coordinates are shown in (x, y) order A Python program to create a mask to select only that area of the image would start with a now-familiar section of code to open and display the original image 8As before, we first import the 89 submodule of 56 ( 53). We also import the NumPy library, which we need to create the initial mask image. Then, we import the 39 submodule of 32. We load and display the initial image in the same way we have done beforeNumPy allows indexing of images/arrays with “boolean” arrays of the same size. Indexing with a boolean array is also called mask indexing. The “pixels” in such a mask array can only take two values. 65 or 66. When indexing an image with such a mask, only pixel values at positions where the mask is 65 are accessed. But first, we need to generate a mask array of the same size as the image. Luckily, the NumPy library provides a function to create just such an array. The next section of code shows how 9The first argument to the 68 function is the shape of the original image, so that our mask will be exactly the same size as the original. Notice, that we have only used the first two indices of our shape. We omitted the channel dimension. Indexing with such a mask will change all channel values simultaneously. The second argument, 69, indicates that the elements in the array should be booleans - i. e. , values are either 65 or 66. Thus, even though we use 72 to create the mask, its pixel values are in fact not 73 but 65. You could check this, e. g. , by 75Next, we draw a filled, rectangle on the mask 0Here is what our constructed mask looks like. The parameters of the 76 function 77 and 78, are the coordinates of the upper-left ( 79) and lower-right ( 80) corners of a rectangle in (ry, cx) order. The function returns the rectangle as row ( 81) and column ( 82) coordinate arrays
Image modificationAll that remains is the task of modifying the image using our mask in such a way that the areas with 65 pixels in the mask are not shown in the image any more
Now we can write a Python program to use a mask to retain only the portions of our maize roots image that actually contains the seedling roots. We load the original image and create the mask in the same way as before 7Then, we use numpy indexing to remove the portions of the image, where the mask is 65 8Then, we display the masked image 9The resulting masked image should look like this
Creating Histograms
In this episode, we will learn how to use skimage functions to create and display histograms for images Introduction to HistogramsAs it pertains to images, a histogram is a graphical representation showing how frequently various colour values occur in the image. We saw in the Image Basics episode that we could use a histogram to visualise the differences in uncompressed and compressed image formats. If your project involves detecting colour changes between images, histograms will prove to be very useful, and histograms are also quite handy as a preparatory step before performing thresholding Grayscale HistogramsWe will start with grayscale images, and then move on to colour images. We will use this image of a plant seedling as an example. Here we load the image in grayscale instead of full colour, and display it 4Again, we use the 62 function to load our image. The first argument to 62 is the filename of the image. The second argument 35 defines the type and depth of a pixel in the image (e. g. , an 8-bit pixel has a range of 0-255). This argument is forwarded to the 21 backend, for which mode “L” means 8-bit pixels and single-channel (i. e. , grayscale). 21 is a Python imaging library; which backend is used by 62 may be specified (to use 21, you would pass this argument. 25); if unspecified, 62 determines the backend to use based on the image typeThen, we convert the grayscale image of integer dtype, with 0-255 range, into a floating-point one with 0-1 range, by calling the function 27. We will keep working with images in the value range 0 to 1 in this lessonWe now use the function 28 to compute the histogram of our image which, after all, is a NumPy array 5The parameter 29 determines the number of “bins” to use for the histogram. We pass in 30 because we want to see the pixel count for each of the 256 possible values in the grayscale imageThe parameter 31 is the range of values each of the pixels in the image can have. Here, we pass 0 and 1, which is the value range of our input image after transforming it to grayscaleThe first output of the 28 function is a one-dimensional NumPy array, with 256 rows and one column, representing the number of pixels with the intensity value corresponding to the index. I. e. , the first number in the array is the number of pixels found with intensity value 0, and the final number in the array is the number of pixels found with intensity value 255. The second output of 28 is an array with the bin edges and one column and 257 rows (one more than the histogram itself). There are no gaps between the bins, which means that the end of the first bin, is the start of the second and so on. For the last bin, the array also has to contain the stop, so it has one more element, than the histogramNext, we turn our attention to displaying the histogram, by taking advantage of the plotting facilities of the 34 library 6We create the plot with 35, then label the figure and the coordinate axes with 36, 37, and 38 functions. The last step in the preparation of the figure is to set the limits on the values on the x-axis with the 39 function call
Finally, we create the histogram plot itself with 42. Kami menggunakan tepi nampan kiri sebagai posisi-x untuk nilai histogram dengan mengindeks larik 43 untuk mengabaikan nilai terakhir (tepi kanan nampan terakhir). When we run the program on this image of a plant seedling, it produces this histogram
Colour HistogramsWe can also create histograms for full colour images, in addition to grayscale histograms. We have seen colour histograms before, in the Image Basics episode. A program to create colour histograms starts in a familiar way 8We read the original image, now in full colour, and display it Next, we create the histogram, by calling the 28 function three times, once for each of the channels. We obtain the individual channels, by slicing the image along the last axis. For example, we can obtain the red colour channel by calling 52 9We will draw the histogram line for each channel in a different colour, and so we create a tuple of the colours to use for the three lines with the 53line of code. Then, we limit the range of the x-axis with the 40 function callNext, we use the 55 control structure to iterate through the three channels, plotting an appropriately-coloured histogram line for each. This may be new Python syntax for you, so we will take a moment to discuss what is happening in the 55 statementThe Python built-in 57 function takes a list and returns an iterator of tuples, where the first element of the tuple is the index and the second element is the element of the list
In our colour histogram program, we are using a tuple, 61, as the 55 variable. The first time through the loop, the 63 variable takes the value 64, referring to the position of the red colour channel, and the 29 variable contains the string 66. The second time through the loop the values are the green channels index 73 and 68, and the third time they are the blue channel index 69 and 70Inside the 55 loop, our code looks much like it did for the grayscale example. We calculate the histogram for the current channel with the 72function call, and then add a histogram line of the correct colour to the plot with the 73function call. Note the use of our loop variables, 63 and 89Finally we label our axes and display the histogram, shown here
Blurring Images
In this episode, we will learn how to use skimage functions to blur images When processing an image, we are often interested in identifying objects represented within it so that we can perform some further analysis of these objects e. g. by counting them, measuring their sizes, etc. An important concept associated with the identification of objects in an image is that of edges. the lines that represent a transition from one group of similar pixels in the image to another different group. One example of an edge is the pixels that represent the boundaries of an object in an image, where the background of the image ends and the object begins When we blur an image, we make the colour transition from one side of an edge in the image to another smooth rather than sudden. The effect is to average out rapid changes in pixel intensity. A blur is a very common operation we need to perform before other tasks such as thresholding. There are several different blurring functions in the 87 module, so we will focus on just one here, the Gaussian blur
gaussian blurConsider this image of a cat, in particular the area of the image outlined by the white square Now, zoom in on the area of the cat’s eye, as shown in the left-hand image below. When we apply a filter, we consider each pixel in the image, one at a time. In this example, the pixel we are currently working on is highlighted in red, as shown in the right-hand image When we apply a filter, we consider rectangular groups of pixels surrounding each pixel in the image, in turn. Kernel adalah kelompok piksel lain (matriks / gambar kecil terpisah), dengan dimensi yang sama dengan kelompok piksel persegi panjang pada gambar, yang bergerak bersama dengan piksel yang sedang dikerjakan oleh filter. Lebar dan tinggi kernel harus ganjil, sehingga piksel yang dikerjakan selalu berada di tengahnya. In the example shown above, the kernel is square, with a dimension of seven pixels To apply the kernel to the current pixel, an average of the the colour values of the pixels surrounding it is calculated, weighted by the values in the kernel. In a Gaussian blur, the pixels nearest the centre of the kernel are given more weight than those far away from the centre. The rate at which this weight diminishes is determined by a Gaussian function, hence the name Gaussian blur A Gaussian function maps random variables into a normal distribution or “Bell Curve”. https. //en. wikipedia. org/wiki/Gaussian_function#/media/File. Normal_Distribution_PDF. svgThe shape of the function is described by a mean value μ, and a variance value σ². The mean determines the central point of the bell curve on the x axis, and the variance describes the spread of the curve In fact, when using Gaussian functions in Gaussian blurring, we use a 2D Gaussian function to account for X and Y dimensions, but the same rules apply. The mean μ is always 0, and represents the middle of the 2D kernel. Increasing values of σ² in either dimension increases the amount of blurring in that dimension The averaging is done on a channel-by-channel basis, and the average channel values become the new value for the pixel in the filtered image. Larger kernels have more values factored into the average, and this implies that a larger kernel will blur the image more than a smaller kernel To get an idea of how this works, consider this plot of the two-dimensional Gaussian function Imagine that plot laid over the kernel for the Gaussian blur filter. The height of the plot corresponds to the weight given to the underlying pixel in the kernel. I. e. , the pixels close to the centre become more important to the filtered pixel colour than the pixels close to the outer limits of the kernel. The shape of the Gaussian function is controlled via its standard deviation, or sigma. A large sigma value results in a flatter shape, while a smaller sigma value results in a more pronounced peak. The mathematics involved in the Gaussian blur filter are not quite that simple, but this explanation gives you the basic idea To illustrate the blur process, consider the blue channel colour values from the seven-by-seven region of the cat image above The filter is going to determine the new blue channel value for the centre pixel – the one that currently has the value 86. The filter calculates a weighted average of all the blue channel values in the kernel giving higher weight to the pixels near the centre of the kernel This weighted average, the sum of the multiplications, becomes the new value for the centre pixel (3, 3). The same process would be used to determine the green and red channel values, and then the kernel would be moved over to apply the filter to the next pixel in the image
This animation shows how the blur kernel moves along in the original image in order to calculate the colour channel values for the blurred image skimage has built-in functions to perform blurring for us, so we do not have to perform all of these mathematical operations ourselves. Let’s work through an example of blurring an image with the skimage Gaussian blur function First, we load the image, and display it 7Next, we apply the gaussian blur 8The first two parameters to 88 are the image to blur, 93, and a tuple defining the sigma to use in ry- and cx-direction, 90. The third parameter 91 gives the radius of the kernel in terms of sigmas. A Gaussian function is defined from -infinity to +infinity, but our kernel (which must have a finite, smaller size) can only approximate the real function. Therefore, we must choose a certain distance from the centre of the function where we stop this approximation, and set the final size of our kernel. In the above example, we set 91 to 3. 5, which means the kernel size will be 2 * sigma * 3. 5. For example, for a 93 of 1. 0 the resulting kernel size would be 7, while for a 93 of 2. 0 the kernel size would be 14. The default value for 91 in scikit-image is 4. 0The last parameter to 88 tells skimage to interpret our image, that has three dimensions, as a multichannel colour imageFinally, we display the blurred image 9
Other methods of blurringThe Gaussian blur is a way to apply a low-pass filter in skimage. It is often used to remove Gaussian (i. e. , random) noise from the image. For other kinds of noise, e. g. “salt and pepper”, a median filter is typically used. See for a list of available filters
Thresholding
In this episode, we will learn how to use skimage functions to apply thresholding to an image. Thresholding is a type of image segmentation, where we change the pixels of an image to make the image easier to analyze. In thresholding, we convert an image from colour or grayscale into a binary image, i. e. , one that is simply black and white. Most frequently, we use thresholding as a way to select areas of interest of an image, while ignoring the parts we are not concerned with. We have already done some simple thresholding, in the “Manipulating pixels” section of the Image Representation in skimage episode. In that case, we used a simple NumPy array manipulation to separate the pixels belonging to the root system of a plant from the black background. In this episode, we will learn how to use skimage functions to perform thresholding. Then, we will use the masks returned by these functions to select the parts of an image we are interested in Simple thresholdingConsider the image 04 with a series of crudely cut shapes set against a white background 1Now suppose we want to select only the shapes from the image. In other words, we want to leave the pixels belonging to the shapes “on,” while turning the rest of the pixels “off,” by setting their colour channel values to zeros. The skimage library has several different methods of thresholding. We will start with the simplest version, which involves an important step of human input. Specifically, in this simple, fixed-level thresholding, we have to provide a threshold value 05The process works like this. First, we will load the original image, convert it to grayscale, and de-noise it as in the Blurring Images episode 2Next, we would like to apply the threshold 05 such that pixels with grayscale values on one side of 05 will be turned “on”, while pixels with grayscale values on the other side will be turned “off”. How might we do that? Remember that grayscale images contain pixel values in the range from 0 to 1, so we are looking for a threshold 05 in the closed range [0. 0, 1. 0]. We see in the image that the geometric shapes are “darker” than the white background but there is also some light gray noise on the background. One way to determine a “good” value for 05 is to look at the grayscale histogram of the image and try to identify what grayscale ranges correspond to the shapes in the image or the backgroundThe histogram for the shapes image shown above can be produced as in the Creating Histograms episode 3Since the image has a white background, most of the pixels in the image are white. This corresponds nicely to what we see in the histogram. there is a peak near the value of 1. 0. If we want to select the shapes and not the background, we want to turn off the white background pixels, while leaving the pixels for the shapes turned on. So, we should choose a value of 05 somewhere before the large peak and turn pixels above that value “off”. Let us choose 11To apply the threshold 05, we can use the numpy comparison operators to create a mask. Here, we want to turn “on” all pixels which have values smaller than the threshold, so we use the less operator 00 to compare the 14 to the threshold 05. The operator returns a mask, that we capture in the variable 16. It has only one channel, and each of its values is either 0 or 1. The binary mask created by the thresholding operation can be shown with 38, where the 66 entries are shown as black pixels (0-valued) and the 65 entries are shown as white pixels (1-valued) 4You can see that the areas where the shapes were in the original area are now white, while the rest of the mask image is black
We can now apply the 16 to the original coloured image as we have learned in the Drawing and Bitwise Operations episode. What we are left with is only the coloured shapes from the original 5
Automatic thresholdingThe downside of the simple thresholding technique is that we have to make an educated guess about the threshold 05 by inspecting the histogram. There are also automatic thresholding methods that can determine the threshold automatically for us. One such method is Otsu’s method. It is particularly useful for situations where the grayscale histogram of an image has two peaks that correspond to background and objects of interest
Consider the image 33 of a maize root system which we have seen before in the Image Representation in skimage episode 9We use Gaussian blur with a sigma of 1. 0 to denoise the root image. Let us look at the grayscale histogram of the denoised image 0The histogram has a significant peak around 0. 2, and a second, smaller peak very near 1. 0. Thus, this image is a good candidate for thresholding with Otsu’s method. The mathematical details of how this works are complicated (see if you are interested), but the outcome is that Otsu’s method finds a threshold value between the two peaks of a grayscale histogram Fungsi _34 dapat digunakan untuk menentukan ambang batas secara otomatis melalui metode Otsu. Then numpy comparison operators can be used to apply it as before. Here are the Python commands to determine the threshold 05 with Otsu’s method 1 2For this root image and a Gaussian blur with the chosen sigma of 1. 0, nilai ambang yang dihitung adalah 0. 42. No we can create a binary mask with the comparison operator 99. As we have seen before, pixels above the threshold value will be turned on, those below the threshold will be turned off 3Finally, we use the mask to select the foreground 4Application. measuring root massLet us now turn to an application where we can apply thresholding and other techniques we have learned to this point. Consider these four maize root system images, which you can find in the files 37, 38, 39, and 40Suppose we are interested in the amount of plant material in each image, and in particular how that amount changes from image to image. Perhaps the images represent the growth of the plant over time, or perhaps the images show four different maize varieties at the same phase of their growth. The question we would like to answer is, “how much root mass is in each image?” We will first construct a Python program to measure this value for a single image. Our strategy will be this
Our intent is to perform these steps and produce the numeric result - a measure of the root mass in the image - without human intervention. Implementing the steps within a Python function will enable us to call this function for different images Here is a Python function that implements this root-mass-measuring strategy. Since the function is intended to produce numeric output without human interaction, it does not display any of the images. Almost all of the commands should be familiar, and in fact, it may seem simpler than the code we have worked on thus far, because we are not displaying any of the images 5The function begins with reading the original image from the file 41. We use 62 with the optional argument 35 to automatically convert it to grayscale. Next, the grayscale image is blurred with a Gaussian filter with the value of 93 that is passed to the function. Then we determine the threshold 05 with Otsu’s method and create a binary mask just as we did in the previous section. Up to this point, everything should be familiarThe final part of the function determines the root mass ratio in the image. Recall that in the 16, every pixel has either a value of zero (black/background) or one (white/foreground). We want to count the number of white pixels, which can be accomplished with a call to the numpy function 47. Then we determine the width and height of the image by using the elements of 48 (that is, the dimensions of the numpy array that stores the image). Finally, the density ratio is calculated by dividing the number of white pixels by the total number of pixels 49 in the image. The function returns then root density of the imageWe can call this function with any filename and provide a sigma value for the blurring. If no sigma value is provided, the default value 1. 0 will be used. For example, for the file 37 and a sigma value of 1. 5, we would call the function like this 6 7Now we can use the function to process the series of four images shown above. In a real-world scientific situation, there might be dozens, hundreds, or even thousands of images to process. To save us the tedium of calling the function for each image by hand, we can write a loop that processes all files automatically. The following code block assumes that the files are located in the same directory and the filenames all start with the trial- prefix and end with the . jpg suffix 8 9
Connected Component Analysis
ObjectsIn the Thresholding episode we have covered dividing an image into foreground and background pixels. In the shapes example image, we considered the coloured shapes as foreground objects on a white background In thresholding we went from the original image to this version Here, we created a mask that only highlights the parts of the image that we find interesting, the objects. All objects have pixel value of 65 while the background pixels are 66By looking at the mask image, one can count the objects that are present in the image (7). But how did we actually do that, how did we decide which lump of pixels constitutes a single object? Pixel NeighborhoodsIn order to decide which pixels belong to the same object, one can exploit their neighborhood. pixels that are directly next to each other and belong to the foreground class can be considered to belong to the same object Let’s discuss the concept of pixel neighborhoods in more detail. Consider the following mask “image” with 8 rows, and 8 columns. For the purpose of illustration, the digit 64 is used to represent background pixels, and the letter 63 is used to represent object pixels foreground) 4The pixels are organised in a rectangular grid. In order to understand pixel neighborhoods we will introduce the concept of “jumps” between pixels. The jumps follow two rules. First rule is that one jump is only allowed along the column, or the row. Diagonal jumps are not allowed. So, from a centre pixel, denoted with 64, only the pixels indicated with a 73 are reachable 5The pixels on the diagonal (from 64) are not reachable with a single jump, which is denoted by the 67. The pixels reachable with a single jump form the 1-jump neighborhoodThe second rule states that in a sequence of jumps, one may only jump in row and column direction once -> they have to be orthogonal. An example of a sequence of orthogonal jumps is shown below. Starting from 64 the first jump goes along the row to the right. The second jump then goes along the column direction up. After this, the sequence cannot be continued as a jump has already been made in both row and column direction 6All pixels reachable with one, or two jumps form the 2-jump neighborhood. The grid below illustrates the pixels reachable from the centre pixel 64 with a single jump, highlighted with a 73, and the pixels reachable with 2 jumps with a 69 7We want to revisit our example image mask from above and apply the two different neighborhood rules. With a single jump connectivity for each pixel, we get two resulting objects, highlighted in the image with 72’s and 73’s 8In the 1-jump version, only pixels that have direct neighbors along rows or columns are considered connected. Diagonal connections are not included in the 1-jump neighborhood. With two jumps, however, we only get a single object 72 because pixels are also considered connected along the diagonals 9
Connected Component AnalysisIn order to find the objects in an image, we want to employ an operation that is called Connected Component Analysis (CCA). This operation takes a binary image as an input. Usually, the 66 value in this image is associated with background pixels, and the 65 value indicates foreground, or object pixels. Such an image can be produced, e. g. , with thresholding. Given a thresholded image, the connected component analysis produces a new labeled image with integer pixel values. Piksel dengan nilai yang sama, milik objek yang sama. Skimage provides connected component analysis in the function 77. Let us add this function to the already familiar steps of thresholding an image. Here we define a reusable Python function 78 01Note the new import of 79 in order to use the 80 function that performs the CCA. The first four lines of code are familiar from the Thresholding episodeThen we call the 80 function. This function has one positional argument where we pass the 16, i. e. , the binary image to work on. With the optional argument 83, we specify the neighborhood in units of orthogonal jumps. For example, by setting 84 we will consider the 2-jump neighborhood introduced above. The function returns a 85 where each pixel has a unique value corresponding to the object it belongs to. In addition, we pass the optional parameter 86 to return the maximum label index as 87
We can call the above function 78 and display the labeled image like so 04
We can use the function 11 to convert the colours in the image (recall that we already used the 27 function to convert to grayscale). Dengan _11, semua objek diwarnai sesuai dengan daftar warna yang dapat disesuaikan. Kita dapat menggunakan perintah berikut untuk mengonversi dan menampilkan gambar _07
You might wonder why the connected component analysis with 22, and 23 finds 11 objects, whereas we would expect only 7 objects. Where are the four additional objects? With a bit of detective work, we can spot some small objects in the image, for example, near the left borderFor us it is clear that these small spots are artifacts and not objects we are interested in. But how can we tell the computer? One way to calibrate the algorithm is to adjust the parameters for blurring ( 93) and thresholding ( 05), but you may have noticed during the above exercise that it is quite hard to find a combination that produces the right output number. In some cases, background noise gets picked up as an object. And with other parameters, some of the foreground objects get broken up or disappear completely. Therefore, we need other criteria to describe desired properties of the objects that are foundMorphometrics - Describe object features with numbersMorphometrics is concerned with the quantitative analysis of objects and considers properties such as size and shape. For the example of the images with the shapes, our intuition tells us that the objects should be of a certain size or area. So we could use a minimum area as a criterion for when an object should be detected. To apply such a criterion, we need a way to calculate the area of objects found by connected components. Recall how we determined the root mass in the Thresholding episode by counting the pixels in the binary mask. But here we want to calculate the area of several objects in the labeled image. The skimage library provides the function 28 to measure the properties of labeled regions. It returns a list of 29 that describe each connected region in the images. The properties can be accessed using the attributes of the 29 data type. Here we will use the properties 31 and 32. You can explore the skimage documentation to learn about other properties availableWe can get a list of areas of the labeled objects as follows 11This will produce the output 12
Capstone Challenge
In this episode, we will provide a final challenge for you to attempt, based on all the skills you have acquired so far. This challenge will be related to the shape of objects in images (morphometrics) Morphometrics. Bacteria Colony CountingAs mentioned in the workshop introduction, your morphometric challenge is to determine how many bacteria colonies are in each of these images The image files can be found at 82, 83, and 84
|