Cara menggunakan python untuk menggambar

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 Penelitian

Pemrosesan 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

  • pencitraan Lubang Hitam
  • memperkirakan populasi Penguin Kaisar
  • analisis keanekaragaman plankton laut skala global
  • segmentasi hati dan pembuluh darah dari gambar CT

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

Morphometrics

Morphometrics 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

Cara menggunakan python untuk menggambar

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

Cara menggunakan python untuk menggambar

Why write a program to do that?

Note that you can easily manually count the number of bacteria colonies shown in the morphometric example above. Why should we learn how to write a Python program to do a task we could easily perform with our own eyes? There are at least two reasons to learn how to perform tasks like these with Python and skimage

  1. What if there are many more bacteria colonies in the Petri dish? For example, suppose the image looked like this

    Cara menggunakan python untuk menggambar

    Manually counting the colonies in that image would present more of a challenge. A Python program using skimage could count the number of colonies more accurately, and much more quickly, than a human could

  2. What if you have hundreds, or thousands, of images to consider? Imagine having to manually count colonies on several thousand images like those above. A Python program using skimage could move through all of the images in seconds; how long would a graduate student require to do the task? Which process would be more accurate and repeatable?

As you can see, the simple image processing / computer vision techniques you will learn during this workshop can be very valuable tools for scientific research

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

Key Points

  • Simple Python and skimage (scikit-image) techniques can be used to solve genuine image analysis problems

  • Masalah morfometrik menyangkut jumlah, bentuk, dan/atau ukuran objek dalam suatu citra


Image Basics

Overview

Teaching. 20 min
Exercises. 5 menit

Questions

  • Bagaimana gambar direpresentasikan dalam format digital?

Tujuan

  • Define the terms bit, byte, kilobyte, megabyte, etc

  • Explain how a digital image is composed of pixels

  • Recommend using imageio (resp. skimage) for I/O (resp. image processing) tasks

  • Explain how images are stored in NumPy arrays

  • Explain the left-hand coordinate system used in digital images

  • Explain the RGB additive colour model used in digital images

  • Explain the order of the three colour values in skimage images

  • Explain the characteristics of the BMP, JPEG, and TIFF image formats

  • Explain the difference between lossy and lossless compression

  • Explain the advantages and disadvantages of compressed image formats

  • Jelaskan informasi apa yang dapat dimuat dalam metadata gambar

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

Pixels

It 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

Cara menggunakan python untuk menggambar

Now, if we zoomed in close enough to see the pixels in the red box, we would see something like this

Cara menggunakan python untuk menggambar

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 Pixels

As 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

Matrices, arrays, images and pixels

The matrix is mathematical concept - numbers evenly arranged in a rectangle. This can be a two dimensional rectangle, like the shape of the screen you’re looking at now. Or it could be a three dimensional equivalent, a cuboid, or have even more dimensions, but always keeping the evenly spaced arrangement of numbers. In computing, array refers to a structure in the computer’s memory where data is stored in evenly-spaced elements. This is strongly analogous to a matrix. A

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
33 array is a type of variable (a simpler example of a type is an integer). For our purposes, the distinction between matrices and arrays is not important, we don’t really care how the computer arranges our data in its memory. The important thing is that the computer stores values describing the pixels in images, as arrays. And the terms matrix and array can be used interchangeably

First, the necessary imports

"""
 * Python libraries for learning and performing image processing.
 *
"""
import numpy as np
import matplotlib.pyplot as plt
import ipympl
import imageio.v3 as iio
import skimage

Import Statements in Python

In Python, the

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
34 statement is used to load additional functionality into a program. This is necessary when we want our code to do something more specialised, which cannot easily be achieved with the limited set of basic tools and data structures available in the default Python environment

Additional functionality can be loaded as a single function or object, a module defining several of these, or a library containing many modules. You will encounter several different forms of

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
34 statement

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np

Further Explanation

In the example above, form 1 loads the entire

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
32 library into the program as an object. Individual modules of the library are then available within that object, e. g. , to access the
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
37 function used in the drawing episode, you would write
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
38

Form 2 loads only the

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
39 module of
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
32 into the program. When we run the code, the program will take less time and use less memory because we will not load the whole
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
32 library. The syntax needed to use the module remains unchanged. to access the
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
37 function, we would use the same function call as given for form 1

To further reduce the time and memory requirements for your program, form 3 can be used to import only a specific function/class from a library/module. Unlike the other forms, when this approach is used, the imported function or class can be called by its name only, without prefixing it with the name of the module/library from which it was loaded, i. e. ,

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
43 instead of
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
38 using the example above. One hazard of this form is that importing like this will overwrite any object with the same name that was defined/imported earlier in the program, i. e. , the example above would replace any existing object called
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
37 with the
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
37 function from
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
47

Finally, the

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
48 keyword can be used when importing, to define a name to be used as shorthand for the library/module being imported. This name is referred to as an alias. Typically, using an alias (such as
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
49 for the NumPy library) saves us a little typing. Anda mungkin melihat
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
48 digabungkan dengan salah satu dari tiga bentuk pertama pernyataan
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
34 lainnya

Bentuk mana yang digunakan seringkali bergantung pada ukuran dan jumlah alat tambahan yang dimuat ke dalam program

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

%matplotlib widget

Dengan itu, mari muat data gambar kita dari disk menggunakan fungsi

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
52 dari modul
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
53 dan tampilkan menggunakan fungsi
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
54 dari modul
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
55.
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
_56 adalah pustaka Python untuk membaca dan menulis data gambar.
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
_53 menentukan bahwa kami ingin menggunakan versi 3 dari
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
56. Versi ini memiliki manfaat mendukung data gambar nD (multidimensi) secara asli (pikirkan volume, film)

Mengapa tidak menggunakan import skimage # form 1, load whole skimage library import skimage.draw # form 2, load skimage.draw module only from skimage.draw import disk # form 3, load only the disk function import numpy as np # form 4, load all of numpy into an object called np _59

Perpustakaan

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
32 memiliki fungsinya sendiri untuk membaca gambar, jadi Anda mungkin bertanya mengapa kami tidak menggunakannya di sini. Sebenarnya,
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
_59 menggunakan
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
62 secara internal saat memuat gambar ke Python. Ini tentu sesuatu yang dapat Anda gunakan sesuai keinginan Anda dalam kode Anda sendiri. Dalam pelajaran ini, kami menggunakan perpustakaan
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
_56 untuk membaca atau menulis (menyimpan) gambar, sedangkan
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
32 didedikasikan untuk melakukan operasi pada gambar. Menggunakan
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
_56 memberi kami lebih banyak fleksibilitas, terutama dalam menangani metadata

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)

Cara menggunakan python untuk menggambar

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

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
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

print(image.shape)
print(image)

(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]

Jadi jika kita memiliki alat yang memungkinkan kita memanipulasi susunan angka ini, kita dapat memanipulasi gambar. Pustaka

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
33 dapat sangat berguna di sini, jadi mari kita coba menggunakan
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
33 pengirisan array. Perhatikan bahwa perilaku default dari fungsi
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
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 nol

To 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

zero = iio.imread(uri="data/eight.tif")
zero[2,1]= 1.0
"""
The follwing line of code creates a new figure for imshow to use in displaying our output. Without it, plt.imshow() would overwrite our previous image in the cell above
"""
fig, ax = plt.subplots()
plt.imshow(zero)
print(zero)

[[0. 0. 0.]
 [0. 1. 0.]
 [0. 1. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]

Cara menggunakan python untuk menggambar

Sistem koordinasi

Saat kami memproses gambar, kami dapat mengakses, memeriksa, dan / atau mengubah warna piksel apa pun yang kami inginkan. Untuk melakukan ini, kami memerlukan beberapa konvensi tentang cara mengakses piksel satu per satu;

Cara paling umum untuk melakukan ini, dan yang akan kita gunakan dalam program kita, adalah menetapkan sistem koordinat Cartesian yang dimodifikasi ke gambar. Sistem koordinat yang biasa kita lihat dalam matematika memiliki sumbu x horizontal dan sumbu y vertikal, seperti ini

Cara menggunakan python untuk menggambar

Sistem koordinat yang dimodifikasi yang digunakan untuk gambar kita hanya akan memiliki koordinat positif, titik asal berada di pojok kiri atas, bukan di tengah, dan nilai koordinat y akan semakin besar saat turun, bukan naik, seperti ini

Cara menggunakan python untuk menggambar

Ini disebut sistem koordinat kiri. Jika Anda memegang tangan kiri Anda di depan wajah Anda dan mengarahkan ibu jari Anda ke lantai, jari telunjuk Anda yang terulur akan sesuai dengan sumbu x sedangkan ibu jari Anda mewakili sumbu y

Cara menggunakan python untuk menggambar

Sampai Anda telah bekerja dengan gambar untuk sementara waktu, kesalahan paling umum yang akan Anda buat dengan koordinat adalah lupa bahwa koordinat y menjadi lebih besar saat turun, bukan naik seperti dalam sistem koordinat Cartesian normal. Konsekuensinya, mungkin berguna untuk berpikir dalam hal menghitung mundur baris (r) untuk sumbu y dan melintasi kolom (c) untuk sumbu x. Ini dapat sangat membantu dalam kasus di mana Anda perlu mengubah urutan data penampil gambar yang disediakan dalam format x,y ke format y,x. Jadi, kami akan menggunakan cx dan ry jika perlu untuk membantu menjembatani kedua pendekatan ini

Mengubah Nilai Piksel (5 mnt)

Muat salinan lain dari delapan bernama lima, lalu ubah nilai piksel sehingga Anda memiliki tampilan seperti 5, bukan 8. Tampilkan gambar dan cetak matriksnya juga

Larutan

Ada banyak solusi yang mungkin, tetapi satu metode adalah. .

five = iio.imread(uri="data/eight.tif")
five[1,2]= 1.0
five[3,0]= 1.0
fig, ax = plt.subplots()
plt.imshow(five)
print(five)

[[0. 0. 0.]
 [0. 1. 1.]
 [0. 0. 0.]
 [1. 1. 0.]
 [0. 0. 0.]]

Cara menggunakan python untuk menggambar

Lebih banyak warna

Sampai 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

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
0

Cara menggunakan python untuk menggambar

Kami 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

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
_1

Cara menggunakan python untuk menggambar

Di 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 Warna

Ini 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

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
_2

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
_3

Cara menggunakan python untuk menggambar

Sebelumnya 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]

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
_4

Ini 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.

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
5

Cara menggunakan python untuk menggambar

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
_6

Cara menggunakan python untuk menggambar

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
_7

Cara menggunakan python untuk menggambar

Jika 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-bit

Model 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

Memikirkan tentang warna RGB (5 mnt)

Misalkan kita merepresentasikan warna sebagai tripel (r, g, b), di mana masing-masing r, g, dan b adalah bilangan bulat dalam [0, 255]. Warna apa yang diwakili oleh masing-masing tiga kali lipat ini? . )

  1. (255, 0, 0)
  2. (0, 255, 0)
  3. (0, 0, 255)
  4. (255, 255, 255)
  5. (0, 0, 0)
  6. (128, 128, 128)

Larutan

  1. (255, 0, 0) mewakili merah, karena saluran merah dimaksimalkan, sedangkan dua saluran lainnya memiliki nilai minimum
  2. (0, 255, 0) melambangkan hijau
  3. (0, 0, 255) mewakili warna biru
  4. (255, 255, 255) sedikit lebih sulit. Saat kami mencampur nilai maksimum dari ketiga saluran warna, kami melihat warna putih
  5. (0, 0, 0) menunjukkan tidak adanya semua warna, atau hitam
  6. (128, 128, 128) mewakili warna abu-abu sedang. Perhatikan bahwa model warna RGB 24-bit menyediakan setidaknya 254 warna abu-abu, bukan hanya lima puluh

Perhatikan bahwa model warna RGB mungkin bertentangan dengan pengalaman Anda, terutama jika Anda telah mencampur warna primer cat untuk menciptakan warna baru. Dalam model RGB, ketiadaan warna apa pun adalah hitam, sedangkan jumlah maksimum masing-masing warna primer adalah putih. Dengan cat fisik, kita mungkin mulai dengan dasar putih, lalu menambahkan cat lain dalam jumlah yang berbeda untuk menghasilkan warna yang lebih gelap

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

Tabel warna RGB (opsional, tidak termasuk dalam pengaturan waktu)

Cara menggunakan python untuk menggambar

Kami tidak bisa menyediakan tabel lengkap. Untuk mengetahui alasannya, jawab pertanyaan ini. Berapa banyak kemungkinan warna yang dapat direpresentasikan dengan model RGB 24-bit?

Larutan

Ada total 24 bit dalam warna RGB jenis ini, dan setiap bit dapat dihidupkan atau dimatikan, sehingga ada 224 = 16.777.216 kemungkinan warna dengan model warna RGB 24-bit aditif kami

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 gambar

Meskipun 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. bertengkar

BMP

Format 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 gambar

Sebelum 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

Bit dan byte

Sebelum kita berbicara secara khusus tentang gambar, pertama-tama kita perlu memahami bagaimana angka disimpan di komputer digital modern. Ketika kita memikirkan sebuah angka, kita melakukannya dengan menggunakan desimal, atau sistem bilangan nilai tempat berbasis 10. Misalnya, angka seperti 659 adalah 6 × 102 + 5 × 101 + 9 × 100. Setiap angka pada bilangan dikalikan dengan pangkat 10, berdasarkan tempat terjadinya, dan terdapat 10 angka yang dapat terjadi pada setiap posisi (0, 1, 2, 3, 4, 5, 6, 7, 8, 9

Pada prinsipnya, komputer dapat dibangun untuk merepresentasikan angka dengan cara yang persis sama. Namun, sirkuit elektronik di dalam komputer jauh lebih mudah dibuat jika kita membatasi basis numerik hanya menjadi dua, bukan 10. (Lebih mudah bagi sirkuit untuk mengetahui perbedaan antara dua level tegangan daripada membedakan di antara 10 level. ) Jadi, nilai-nilai di komputer disimpan menggunakan sistem bilangan biner, atau basis-2 nilai tempat

Dalam sistem ini, setiap simbol dalam angka disebut bit, bukan digit, dan hanya ada dua nilai untuk setiap bit (0 dan 1). Kita mungkin membayangkan bilangan biner empat bit, 1101. Dengan menggunakan perluasan nilai tempat yang sama seperti yang kita lakukan di atas untuk 659, kita melihat bahwa 1101 = 1 × 23 + 1 × 22 + 0 × 21 + 1 × 20, yang jika kita hitung adalah 8 + 4 + 0 +

Secara internal, komputer memiliki jumlah bit minimum yang dapat digunakan pada waktu tertentu. delapan. Sekelompok delapan bit disebut byte. Jumlah memori (RAM) dan ruang drive yang dimiliki komputer kita dihitung dengan istilah seperti Megabyte (MB), Gigabyte (GB), dan Terabyte (TB). Tabel berikut memberikan definisi yang lebih formal untuk istilah-istilah ini

UnitAbbreviationSizeKilobyteKB1024 bytesMegabyteMB1024 KBGigabyteGB1024 MBTerabyteTB1024 GB

Ukuran gambar BMP (opsional, tidak termasuk dalam pengaturan waktu)

Bayangkan kita memiliki gambar yang cukup besar, tetapi sangat membosankan. gambar 5.000 × 5.000 piksel yang hanya terdiri dari piksel putih. Jika kami menggunakan format gambar yang tidak dikompresi seperti BMP, dengan model warna RGB 24-bit, berapa banyak penyimpanan yang diperlukan untuk file tersebut?

Larutan

Dalam gambar seperti itu, ada 5.000 × 5.000 = 25.000.000 piksel, dan 24 bit untuk setiap piksel, menghasilkan 25.000.000 × 24 = 600.000.000 bit, atau 75.000.000 byte (71. 5MB). Itu cukup banyak ruang untuk gambar yang sangat tidak menarik

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 rugi

Dalam 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 kerugian

Kompresi 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

JPEG

Gambar 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.

Memeriksa ukuran gambar sebenarnya (opsional, tidak termasuk dalam pengaturan waktu)

Mari kita lihat efek kompresi gambar pada ukuran gambar dengan gambar sebenarnya. Skrip berikut membuat gambar putih persegi 5000 X 5000 piksel, lalu menyimpannya sebagai gambar BMP dan sebagai gambar JPEG

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
_8

Periksa ukuran file dari dua file keluaran,

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
70 dan
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
71. Apakah ukuran gambar BMP sesuai dengan prediksi kami sebelumnya?

Larutan

File BMP,

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
_70, berukuran 75.000.054 byte, yang sangat cocok dengan prediksi kami. File JPEG,
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
_71, berukuran 392.503 byte, dua kali lipat lebih kecil dari versi bitmap

Membandingkan kompresi lossless versus lossy (opsional, tidak termasuk dalam pengaturan waktu)

Mari kita lihat contoh langsung dari kompresi lossless versus lossy. Sekali lagi, buka terminal dan arahkan ke direktori ________0______74. Dua gambar keluaran,

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
70 dan
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
71, harus tetap berada di direktori, bersama dengan gambar lain,
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
77

Kami dapat menerapkan kompresi lossless ke file apa pun dengan menggunakan perintah

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
78. Ingatlah bahwa file
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
_70 berisi 75.000.054 byte. Terapkan kompresi lossless ke gambar ini dengan menjalankan perintah berikut.
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
_80. Perintah ini memberi tahu komputer untuk membuat file terkompresi baru,
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
81, dari gambar bitmap asli. Jalankan perintah serupa pada file pohon JPEG.
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
_82

Setelah membuat file terkompresi, gunakan perintah ________0______83 untuk menampilkan isi direktori. Seberapa besar file yang dikompresi?

Larutan

Berikut adalah sebagian daftar direktori, menunjukkan ukuran file yang relevan di sana

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
_9

Kita dapat melihat bahwa keteraturan gambar bitmap (ingat, ini adalah gambar berukuran 5.000 x 5.000 piksel yang hanya berisi piksel putih) memungkinkan skema kompresi lossless untuk mengompres file dengan cukup efektif. Di sisi lain, mengompresi

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
77 tidak menghasilkan file yang jauh lebih kecil;

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)

Cara menggunakan python untuk menggambar

Sekarang, mari kita perbesar dan lihat bagian kecil dari label aslinya, pertama dalam format yang tidak terkompresi

Cara menggunakan python untuk menggambar

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

Cara menggunakan python untuk menggambar

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

Cara menggunakan python untuk menggambar

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.

PNG

Gambar 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

BERTENGKAR

Gambar 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.

Metadata

Gambar 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,

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
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

Mengakses Metadata

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
_53 menyediakan cara untuk menampilkan atau menjelajahi metadata yang terkait dengan gambar. Metadata disajikan secara terpisah dari data piksel

%matplotlib widget
_0

%matplotlib widget
_1

Ada perangkat lunak lain yang dapat membantu Anda menangani metadata, mis. g. , Fiji dan ImageMagick. Anda mungkin ingin menjelajahi opsi ini jika perlu bekerja dengan metadata gambar Anda

Rangkuman format gambar yang digunakan dalam pelajaran ini

Tabel 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

Key Points

  • Gambar digital direpresentasikan sebagai array persegi panjang dari piksel persegi

  • Citra digital menggunakan sistem koordinat tangan kiri, dengan titik asal di pojok kiri atas, sumbu x berjalan ke kanan, dan sumbu y berjalan ke bawah. Beberapa pelajar mungkin lebih suka berpikir dalam hal menghitung mundur baris untuk sumbu y dan melintasi kolom untuk sumbu x. Oleh karena itu, kami akan berusaha untuk mengizinkan kedua pendekatan tersebut dalam penyajian pelajaran kami

  • Paling sering, gambar digital menggunakan model RGB tambahan, dengan delapan bit untuk saluran merah, hijau, dan biru

  • gambar skimage disimpan sebagai array NumPy multi-dimensi

  • Dalam gambar skimage, saluran merah ditentukan terlebih dahulu, lalu hijau, lalu biru, i. e. , RGB

  • Kompresi lossless mempertahankan semua detail dalam gambar, tetapi kompresi lossy menyebabkan hilangnya beberapa detail gambar asli

  • Gambar BMP tidak terkompresi, artinya memiliki kualitas tinggi tetapi juga ukuran filenya besar

  • Gambar JPEG menggunakan kompresi lossy, artinya ukuran filenya lebih kecil, tetapi kualitas gambar mungkin menurun

  • Gambar TIFF dapat dikompresi atau dikompresi dengan kompresi lossy atau lossless

  • Bergantung pada kamera atau sensornya, berbagai informasi berguna dapat disimpan dalam file gambar, dalam metadata gambar


Bekerja dengan skimage

Overview

Pengajaran. 70 mnt
Latihan. 50 mnt

Questions

  • Bagaimana pustaka visi komputer skimage Python dapat digunakan untuk bekerja dengan gambar?

Tujuan

  • Baca dan simpan gambar dengan imageio

  • Tampilkan gambar dengan matplotlib

  • Ubah ukuran gambar dengan skimage

  • Perform simple image thresholding with NumPy array operations

  • Ekstrak sub-gambar menggunakan irisan array

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 gambar

Imageio 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

%matplotlib widget
_2

Pertama, kami mengimpor modul

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
_89 imageio (
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
53) sebagai
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
91 sehingga kami dapat membaca dan menulis gambar. Kemudian, kami menggunakan fungsi
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
_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

%matplotlib widget
_3

Setelah kami memiliki gambar dalam program, pertama-tama kami memanggil

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
94 sehingga kami akan memiliki gambar baru dengan satu set sumbu independen dari panggilan kami sebelumnya. Selanjutnya kita memanggil
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
_95 untuk menampilkan gambar

Sekarang, kami akan menyimpan gambar dalam format lain

%matplotlib widget
_4

Pernyataan terakhir dalam program,

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
_96, menulis gambar ke file bernama
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
97 di direktori
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
74. Fungsi
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
99 secara otomatis menentukan jenis file, berdasarkan ekstensi file yang kami sediakan. Dalam hal ini, ekstensi
%matplotlib widget
_00 menyebabkan gambar disimpan sebagai TIFF

Metadata, ditinjau kembali

Ingat, seperti yang disebutkan di bagian sebelumnya, gambar yang disimpan dengan

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
99 tidak akan mempertahankan semua metadata yang terkait dengan gambar asli yang dimuat ke dalam Python. Jika metadata gambar penting bagi Anda, pastikan untuk selalu menyimpan salinan gambar asli yang tidak berubah

Ekstensi tidak selalu menentukan jenis file

Fungsi

%matplotlib widget
_02 secara otomatis menggunakan jenis file yang kami tentukan dalam ekstensi parameter nama file. Perhatikan bahwa ini tidak selalu terjadi. Misalnya, jika kami mengedit dokumen di Microsoft Word, dan kami menyimpan dokumen sebagai
%matplotlib widget
03 alih-alih
%matplotlib widget
04, file tersebut tidak disimpan sebagai dokumen PDF

Argumen bernama versus argumen posisional

Saat kita memanggil fungsi dengan Python, ada dua cara untuk menentukan argumen yang diperlukan. Kita dapat menentukan argumen secara posisional, i. e. , dalam urutan parameter muncul dalam definisi fungsi, atau kita dapat menggunakan argumen bernama

Misalnya, definisi fungsi

%matplotlib widget
_02 menentukan dua parameter, sumber daya untuk menyimpan gambar (e. g. , nama file, alamat http) dan image untuk menulis ke disk. Jadi, kita bisa menyimpan gambar kursi di contoh kode di atas menggunakan argumen posisional seperti ini

%matplotlib widget
_06

Karena fungsi mengharapkan argumen pertama menjadi nama file, tidak ada kebingungan tentang apa artinya

%matplotlib widget
07. Hal yang sama berlaku untuk argumen kedua

Gaya yang akan kita gunakan dalam lokakarya ini adalah memberi nama setiap argumen, seperti ini

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
_96

Gaya ini akan memudahkan Anda mempelajari cara menggunakan berbagai fungsi yang akan kami bahas dalam lokakarya ini

Mengubah ukuran gambar (10 mnt)

Tambahkan

%matplotlib widget
_09 dan
%matplotlib widget
10 ke daftar impor Anda. Menggunakan gambar
%matplotlib widget
_11 yang terletak di folder data, tulis skrip Python untuk membaca gambar Anda ke dalam variabel bernama
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
93. Then, resize the image to 10 percent of its current size using these lines of code

%matplotlib widget
_5

Seperti yang digunakan di sini, parameter ke fungsi

%matplotlib widget
13 adalah gambar yang akan diubah,
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
93, dimensi yang kita inginkan untuk dimiliki gambar baru,
%matplotlib widget
15

Perhatikan bahwa nilai piksel pada gambar baru merupakan perkiraan dari nilai aslinya dan tidak boleh dikacaukan dengan data aktual yang diamati. Ini karena

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
_32 menginterpolasi nilai piksel saat memperkecil atau menambah ukuran gambar.
%matplotlib widget
_17 memiliki sejumlah parameter opsional yang memungkinkan pengguna untuk mengontrol interpolasi ini. Anda dapat menemukan detail lebih lanjut di

File gambar pada disk biasanya disimpan sebagai bilangan bulat untuk efisiensi ruang, tetapi transformasi dan operasi matematika lainnya sering menghasilkan konversi ke angka floating point. Menggunakan metode

%matplotlib widget
_18 mengubahnya kembali menjadi bilangan bulat sebelum kita menyimpannya kembali ke disk. Jika kami tidak mengonversinya sebelum menyimpan,
%matplotlib widget
02 mungkin tidak mengenalinya sebagai data gambar

Selanjutnya, tulis gambar yang diubah ukurannya ke file baru bernama

%matplotlib widget
20 di direktori data Anda. Terakhir, gunakan
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
_95 dengan masing-masing variabel gambar Anda untuk menampilkan kedua gambar di buku catatan Anda. Jangan lupa gunakan
%matplotlib widget
_22 agar tidak menimpa gambar pertama dengan gambar kedua. Gambar mungkin tampak berukuran sama di jupyter, tetapi Anda dapat melihat perbedaan ukuran dengan membandingkan skala masing-masing gambar. Anda juga dapat melihat perbedaan ukuran penyimpanan file pada disk dengan mengarahkan kursor mouse ke file asli dan file baru di browser file jupyter, menggunakan
%matplotlib widget
23 di shell Anda, atau browser file OS jika dikonfigurasi untuk menampilkan ukuran file

Larutan

Berikut tampilan skrip Python Anda

%matplotlib widget
_6

Skrip mengubah ukuran gambar

%matplotlib widget
_24 dengan faktor 10 di kedua dimensi, menyimpan hasilnya ke file
%matplotlib widget
25, dan menampilkan yang asli dan diubah ukurannya untuk perbandingan

Memanipulasi piksel

Dalam 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

Cara menggunakan python untuk menggambar

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

%matplotlib widget
_7

Sekarang kita dapat membatasi gambar dan menampilkan hasilnya

%matplotlib widget
_8

Perintah NumPy untuk mengabaikan semua piksel intensitas rendah adalah

%matplotlib widget
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 dihilangkan

Cara menggunakan python untuk menggambar

Mengubah gambar berwarna menjadi skala abu-abu

Seringkali lebih mudah bekerja dengan gambar skala abu-abu, yang memiliki satu saluran, daripada gambar berwarna, yang memiliki tiga saluran. Skimage menawarkan fungsi

%matplotlib widget
_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
%matplotlib widget
_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

Warna dan %matplotlib widget _29

The Carpentries umumnya lebih suka ejaan Inggris Inggris, itulah sebabnya kami menggunakan "warna" dalam teks penjelasan pelajaran ini. Namun,

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
_32 berisi banyak modul dan fungsi yang menyertakan ejaan bahasa Inggris AS,
%matplotlib widget
29. Ejaan yang tepat penting di sini, e. g. Anda akan menemukan kesalahan jika Anda mencoba menjalankan ________22______32. Untuk menjelaskan hal ini, kita akan menggunakan ejaan Bahasa Inggris AS,
%matplotlib widget
29, dalam contoh kode Python selama pelajaran. Anda akan menemukan pendekatan serupa dengan "pusat" dan
%matplotlib widget
34

%matplotlib widget
_9

Kami juga dapat memuat gambar berwarna sebagai skala abu-abu secara langsung dengan meneruskan argumen

%matplotlib widget
35 ke
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
62

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
_0

Menyimpan hanya piksel intensitas rendah (10 mnt)

Beberapa saat sebelumnya, kami menunjukkan bagaimana kami dapat menggunakan Python dan skimage untuk mengaktifkan hanya piksel berintensitas tinggi dari sebuah gambar, sambil mematikan semua piksel berintensitas rendah. Now, you can practice doing the opposite - keeping all the low intensity pixels while changing the high intensity ones

File

%matplotlib widget
_37 adalah gambar RGB dari teka-teki sudoku

Cara menggunakan python untuk menggambar

Tugas Anda adalah mengubah semua piksel putih pada gambar menjadi warna abu-abu muda, katakanlah dengan intensitas setiap piksel putih sebelumnya disetel ke 0. 75. Hasilnya akan terlihat seperti ini

Cara menggunakan python untuk menggambar

Petunjuk. ini adalah contoh di mana sangat membantu untuk mengubah gambar dari RGB ke skala abu-abu

Larutan

Pertama, muat file gambar dan ubah menjadi skala abu-abu

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
_1

Kemudian, ubah semua nilai piksel intensitas tinggi (> 0. 75) sampai 0. 75

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
_2

Terakhir, tampilkan gambar yang dimodifikasi

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
_3

Merencanakan gambar saluran tunggal (cmap, vmin, vmax)

Dibandingkan dengan gambar berwarna, gambar skala abu-abu hanya berisi satu nilai intensitas per piksel. Saat kami memplot gambar seperti itu dengan

%matplotlib widget
_38, matplotlib menggunakan peta warna, untuk menetapkan setiap nilai intensitas warna. Peta warna default disebut "viridis" dan memetakan nilai rendah ke ungu dan nilai tinggi ke kuning. Kita dapat menginstruksikan matplotlib untuk memetakan nilai rendah ke hitam dan nilai tinggi ke putih sebagai gantinya, dengan memanggil
%matplotlib widget
38 dengan
%matplotlib widget
40. Dokumentasi berisi ikhtisar peta warna yang telah ditentukan sebelumnya

Selanjutnya, matplotlib menentukan nilai minimum dan maksimum peta warna secara dinamis dari gambar, secara default. Artinya, dalam sebuah gambar, di mana minimumnya adalah 0. 25 dan maksimumnya adalah 0. 75, nilai tersebut masing-masing akan dipetakan menjadi hitam dan putih (dan bukan abu-abu tua dan abu-abu muda seperti yang Anda duga). Jika ada nilai minimum dan maksimum yang ditentukan, Anda dapat menentukannya melalui

%matplotlib widget
41 dan
%matplotlib widget
42 untuk mendapatkan hasil yang diinginkan

Jika Anda melupakannya, ini dapat menyebabkan hasil yang tidak terduga. Coba hapus parameter

%matplotlib widget
_42 dari sudoku challenge solution dan lihat apa yang terjadi

Akses melalui pengirisan

Seperti 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

Cara menggunakan python untuk menggambar

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

Cara menggunakan python untuk menggambar

Perhatikan bahwa koordinat pada gambar sebelumnya ditentukan dalam urutan (cx, ry). Sekarang jika seluruh gambar papan tulis kita disimpan sebagai gambar skimage bernama

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
93, kita dapat membuat gambar baru dari wilayah yang dipilih dengan pernyataan seperti ini

%matplotlib widget
_45

Pemotongan larik kita menentukan rentang koordinat y atau baris terlebih dahulu,

%matplotlib widget
46, lalu rentang koordinat x atau kolom,
%matplotlib widget
47. Perhatikan bahwa kami melampaui nilai maksimum di setiap dimensi, sehingga seluruh area yang diinginkan dipilih. Bagian ketiga dari irisan,
%matplotlib widget
_48, menunjukkan bahwa kita menginginkan ketiga saluran warna di gambar baru kita

Skrip untuk membuat subgambar akan dimulai dengan memuat gambar

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
4

Then we use array slicing to create a new image with our selected area and then display the new image

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
5

We can also change the values in an image, as shown next

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
6

First, we sample a single pixel’s colour at a particular location of the image, saving it in a variable named

%matplotlib widget
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
%matplotlib widget
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
%matplotlib widget
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

Cara menggunakan python untuk menggambar

Practicing with slices (10 min - optional, not included in timing)

Using the techniques you just learned, write a script that creates, displays, and saves a sub-image containing only the plant and its roots from “data/maize-root-cluster. jpg”

Larutan

Here is the completed Python program to select only the plant and roots in the image

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
7

Key Points

  • Images are read from disk with the

    import skimage                 # form 1, load whole skimage library
    import skimage.draw            # form 2, load skimage.draw module only
    from skimage.draw import disk  # form 3, load only the disk function
    import numpy as np             # form 4, load all of numpy into an object called np
    
    62 function

  • We create a window that automatically scales the displayed image with matplotlib and calling

    %matplotlib widget
    
    53 on the global figure object

  • Colour images can be transformed to grayscale using

    %matplotlib widget
    
    27 or, in many cases, be read as grayscale directly by passing the argument
    %matplotlib widget
    
    35 to
    import skimage                 # form 1, load whole skimage library
    import skimage.draw            # form 2, load skimage.draw module only
    from skimage.draw import disk  # form 3, load only the disk function
    import numpy as np             # form 4, load all of numpy into an object called np
    
    62

  • We can resize images with the

    %matplotlib widget
    
    13 function

  • NumPy array commands, such as

    %matplotlib widget
    
    26, can be used to manipulate the pixels of an image

  • Array slicing can be used to extract sub-images or modify areas of images, e. g. ,

    %matplotlib widget
    
    59

  • Metadata is not retained when images are loaded as skimage images


Drawing and Bitwise Operations

Overview

Teaching. 45 min
Exercises. 45 min

Questions

  • How can we draw on skimage images and use bitwise operations and masks to select certain parts of an image?

Tujuan

  • Create a blank, black skimage image

  • Draw rectangles and other shapes on skimage images

  • Explain how a white shape on a black background can be used as a mask to select specific parts of an image

  • Use bitwise operations to apply a mask to an image

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 images

Often 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

Cara menggunakan python untuk menggambar

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

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
8

As before, we first import the

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
89 submodule of
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
56 (
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
53). We also import the NumPy library, which we need to create the initial mask image. Then, we import the
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
39 submodule of
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
32. We load and display the initial image in the same way we have done before

NumPy 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.

%matplotlib widget
65 or
%matplotlib widget
66. When indexing an image with such a mask, only pixel values at positions where the mask is
%matplotlib widget
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

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
9

The first argument to the

%matplotlib widget
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,
%matplotlib widget
69, indicates that the elements in the array should be booleans - i. e. , values are either
%matplotlib widget
65 or
%matplotlib widget
66. Thus, even though we use
%matplotlib widget
72 to create the mask, its pixel values are in fact not
%matplotlib widget
73 but
%matplotlib widget
65. You could check this, e. g. , by
%matplotlib widget
75

Next, we draw a filled, rectangle on the mask

print(image.shape)
print(image)
0

Here is what our constructed mask looks like.

Cara menggunakan python untuk menggambar

The parameters of the

%matplotlib widget
76 function
%matplotlib widget
77 and
%matplotlib widget
78, are the coordinates of the upper-left (
%matplotlib widget
79) and lower-right (
%matplotlib widget
80) corners of a rectangle in (ry, cx) order. The function returns the rectangle as row (
%matplotlib widget
81) and column (
%matplotlib widget
82) coordinate arrays

Check the documentation

When using an skimage function for the first time - or the fifth time - it is wise to check how the function is used, via the skimage documentation or other usage examples on programming-related sites such as Stack Overflow. Basic information about skimage functions can be found interactively in Python, via commands like

%matplotlib widget
83 or
%matplotlib widget
84. Take notes in your lab notebook. And, it is always wise to run some test code to verify that the functions your program uses are behaving in the manner you intend

Variable naming conventions

You may have wondered why we called the return values of the rectangle function

%matplotlib widget
81 and
%matplotlib widget
82?. You may have guessed that
%matplotlib widget
87 is short for
%matplotlib widget
88 and
%matplotlib widget
89 is short for
%matplotlib widget
90. However, the rectangle function returns mutiple rows and columns; thus we used a convention of doubling the letter
%matplotlib widget
87 to
%matplotlib widget
81 (and
%matplotlib widget
89 to
%matplotlib widget
82) to indicate that those are multiple values. In fact it may have even been clearer to name those variables
%matplotlib widget
95 and
%matplotlib widget
96; however this would have been also much longer. Whatever you decide to do, try to stick to some already existing conventions, such that it is easier for other people to understand your code

Other drawing operations (15 min)

There are other functions for drawing on images, in addition to the

%matplotlib widget
97 function. We can draw circles, lines, text, and other shapes as well. These drawing functions may be useful later on, to help annotate images that our programs produce. Practice some of these functions here

Circles can be drawn with the

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
38 function, which takes two parameters. the (ry, cx) point of the centre of the circle, and the radius of the circle. There is an optional
%matplotlib widget
99 parameter that can be supplied to this function. It will limit the output coordinates for cases where the circle dimensions exceed the ones of the image

Lines can be drawn with the

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
00 function, which takes four parameters. the (ry, cx) coordinate of one end of the line, and the (ry, cx) coordinate of the other end of the line

Other drawing functions supported by skimage can be found in

First let’s make an empty, black image with a size of 800x600 pixels

print(image.shape)
print(image)
1

Sekarang tugas Anda adalah menggambar beberapa bentuk dan garis berwarna lain pada gambar, mungkin seperti ini

Cara menggunakan python untuk menggambar

Larutan

Menggambar lingkaran

print(image.shape)
print(image)
2

Menggambar garis

print(image.shape)
print(image)
3

print(image.shape)
print(image)
4

Kita dapat memperluas solusi ini, jika kita mau, menggambar persegi panjang, lingkaran, dan garis pada posisi acak di dalam kanvas hitam kita. Untuk melakukan ini, kita bisa menggunakan modul python

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
_01, dan fungsi
image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
02, yang dapat menghasilkan angka acak dalam rentang tertentu

Mari menggambar 15 lingkaran yang ditempatkan secara acak

print(image.shape)
print(image)
5

We could expand this even further to also randomly choose whether to plot a rectangle, a circle, or a square. Again, we do this with the

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
01 module, now using the function
image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
04 that returns a random number between 0. 0 and 1. 0

print(image.shape)
print(image)
6

Image modification

All that remains is the task of modifying the image using our mask in such a way that the areas with

%matplotlib widget
65 pixels in the mask are not shown in the image any more

How does a mask work? (optional, not included in timing)

Now, consider the mask image we created above. The values of the mask that corresponds to the portion of the image we are interested in are all

%matplotlib widget
66, while the values of the mask that corresponds to the portion of the image we want to remove are all
%matplotlib widget
65

How do we change the original image using the mask?

Larutan

When indexing the image using the mask, we access only those pixels at positions where the mask is

%matplotlib widget
65. So, when indexing with the mask, one can set those values to 0, and effectively remove them from the image

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

print(image.shape)
print(image)
7

Then, we use numpy indexing to remove the portions of the image, where the mask is

%matplotlib widget
65

print(image.shape)
print(image)
8

Then, we display the masked image

print(image.shape)
print(image)
9

The resulting masked image should look like this

Cara menggunakan python untuk menggambar

Masking an image of your own (optional, not included in timing)

Now, it is your turn to practice. Using your mobile phone, tablet, webcam, or digital camera, take an image of an object with a simple overall geometric shape (think rectangular or circular). Copy that image to your computer, write some code to make a mask, and apply it to select the part of the image containing your object. For example, here is an image of a remote control

Cara menggunakan python untuk menggambar

And, here is the end result of a program masking out everything but the remote

Cara menggunakan python untuk menggambar

Larutan

Here is a Python program to produce the cropped remote control image shown above. Of course, your program should be tailored to your image

(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
0

Masking a 96-well plate image (30 min)

Consider this image of a 96-well plate that has been scanned on a flatbed scanner

(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
1

Cara menggunakan python untuk menggambar

Suppose that we are interested in the colours of the solutions in each of the wells. We do not care about the colour of the rest of the image, i. e. , the plastic that makes up the well plate itself

Your task is to write some code that will produce a mask that will mask out everything except for the wells. To help with this, you should use the text file

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
10 that contains the (cx, ry) coordinates of the centre of each of the 96 wells in this image. You may assume that each of the wells has a radius of 16 pixels

Your program should produce output that looks like this

Cara menggunakan python untuk menggambar

Larutan

(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
_2

Masking a 96-well plate image, take two (optional, not included in timing)

If you spent some time looking at the contents of the

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
10 file from the previous challenge, you may have noticed that the centres of each well in the image are very regular. Assuming that the images are scanned in such a way that the wells are always in the same place, and that the image is perfectly oriented (i. e. , it does not slant one way or another), we could produce our well plate mask without having to read in the coordinates of the centres of each well. Assume that the centre of the upper left well in the image is at location cx = 91 and ry = 108, and that there are 70 pixels between each centre in the cx dimension and 72 pixels between each centre in the ry dimension. Each well still has a radius of 16 pixels. Write a Python program that produces the same output image as in the previous challenge, but without having to read in the
image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
12 file. Hint. use nested for loops

Larutan

Here is a Python program that is able to create the masked image without having to read in the

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
12 file

(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
3

Key Points

  • We can use the NumPy

    image = iio.imread(uri="data/eight.tif")
    plt.imshow(image)
    
    14 function to create a blank, black image

  • We can draw on skimage images with functions such as

    %matplotlib widget
    
    97,
    import skimage                 # form 1, load whole skimage library
    import skimage.draw            # form 2, load skimage.draw module only
    from skimage.draw import disk  # form 3, load only the disk function
    import numpy as np             # form 4, load all of numpy into an object called np
    
    38,
    image = iio.imread(uri="data/eight.tif")
    plt.imshow(image)
    
    00, and more

  • The drawing functions return indices to pixels that can be set directly


Creating Histograms

Overview

Teaching. 40 min
Exercises. 40 min

Questions

  • How can we create grayscale and colour histograms to understand the distribution of colour values in an image?

Tujuan

  • Explain what a histogram is

  • Load an image in grayscale format

  • Create and display grayscale and colour histograms for entire images

  • Create and display grayscale and colour histograms for certain areas of images, via masks

In this episode, we will learn how to use skimage functions to create and display histograms for images

Introduction to Histograms

As 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 Histograms

We will start with grayscale images, and then move on to colour images. We will use this image of a plant seedling as an example.

Cara menggunakan python untuk menggambar

Here we load the image in grayscale instead of full colour, and display it

(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
4

Cara menggunakan python untuk menggambar

Again, we use the

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
62 function to load our image. The first argument to
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
62 is the filename of the image. The second argument
%matplotlib widget
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
image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
21 backend, for which mode “L” means 8-bit pixels and single-channel (i. e. , grayscale).
image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
21 is a Python imaging library; which backend is used by
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
62 may be specified (to use
image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
21, you would pass this argument.
image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
25); if unspecified,
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
62 determines the backend to use based on the image type

Then, 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

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
27. We will keep working with images in the value range 0 to 1 in this lesson

We now use the function

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
28 to compute the histogram of our image which, after all, is a NumPy array

(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
5

The parameter

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
29 determines the number of “bins” to use for the histogram. We pass in
image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
30 because we want to see the pixel count for each of the 256 possible values in the grayscale image

The parameter

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
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 grayscale

The first output of the

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
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
image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
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 histogram

Next, we turn our attention to displaying the histogram, by taking advantage of the plotting facilities of the

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
34 library

(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
6

We create the plot with

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
35, then label the figure and the coordinate axes with
image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
36,
image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
37, and
image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
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
image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
39 function call

Variable-length argument lists

Note that we cannot used named parameters for the

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
40 or
image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
41 functions. This is because these functions are defined to take an arbitrary number of unnamed arguments. The designers wrote the functions this way because they are very versatile, and creating named parameters for all of the possible ways to use them would be complicated

Finally, we create the histogram plot itself with

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
42. Kami menggunakan tepi nampan kiri sebagai posisi-x untuk nilai histogram dengan mengindeks larik
image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
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

Cara menggunakan python untuk menggambar

Histograms in matplotlib

Matplotlib provides a dedicated function to compute and display histograms.

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
44. Kami tidak akan menggunakannya dalam pelajaran ini untuk memahami cara menghitung histogram secara lebih detail. In practice, it is a good idea to use this function, because it visualises histograms more appropriately than
image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
41. Here, you could use it by calling
image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
46 instead of
image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
47 and
image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
41 (
image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
49 is a numpy function that converts our two-dimensional image into a one-dimensional array)

Using a mask for a histogram (15 min)

Looking at the histogram above, you will notice that there is a large number of very dark pixels, as indicated in the chart by the spike around the grayscale value 0. 12. That is not so surprising, since the original image is mostly black background. What if we want to focus more closely on the leaf of the seedling? That is where a mask enters the picture

First, hover over the plant seedling image with your mouse to determine the (x, y) coordinates of a bounding box around the leaf of the seedling. Then, using techniques from the Drawing and Bitwise Operations episode, create a mask with a white rectangle covering that bounding box

After you have created the mask, apply it to the input image before passing it to the

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
28 function

Larutan

(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
7

Your histogram of the masked area should look something like this

Cara menggunakan python untuk menggambar

Colour Histograms

We 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

(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
8

We read the original image, now in full colour, and display it

Next, we create the histogram, by calling the

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
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
image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
52

(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
9

We 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

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
53

line of code. Then, we limit the range of the x-axis with the

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
40 function call

Next, we use the

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
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
image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
55 statement

The Python built-in

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
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

Iterators, tuples, and image = iio.imread(uri="data/eight.tif") plt.imshow(image) 57

In Python, an iterator, or an iterable object, is something that can be iterated over with the

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
55 control structure. A tuple is a sequence of objects, just like a list. However, a tuple cannot be changed, and a tuple is indicated by parentheses instead of square brackets. The
image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
57 function takes an iterable object, and returns an iterator of tuples consisting of the 0-based index and the corresponding object

For example, consider this small Python program

zero = iio.imread(uri="data/eight.tif")
zero[2,1]= 1.0
"""
The follwing line of code creates a new figure for imshow to use in displaying our output. Without it, plt.imshow() would overwrite our previous image in the cell above
"""
fig, ax = plt.subplots()
plt.imshow(zero)
print(zero)
0

Executing this program would produce the following output

zero = iio.imread(uri="data/eight.tif")
zero[2,1]= 1.0
"""
The follwing line of code creates a new figure for imshow to use in displaying our output. Without it, plt.imshow() would overwrite our previous image in the cell above
"""
fig, ax = plt.subplots()
plt.imshow(zero)
print(zero)
1

In our colour histogram program, we are using a tuple,

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
61, as the
image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
55 variable. The first time through the loop, the
image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
63 variable takes the value
image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
64, referring to the position of the red colour channel, and the
%matplotlib widget
29 variable contains the string
image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
66. The second time through the loop the values are the green channels index
%matplotlib widget
73 and
image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
68, and the third time they are the blue channel index
image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
69 and
image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
70

Inside the

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
55 loop, our code looks much like it did for the grayscale example. We calculate the histogram for the current channel with the

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
72

function call, and then add a histogram line of the correct colour to the plot with the

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
73

function call. Note the use of our loop variables,

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
63 and
%matplotlib widget
89

Finally we label our axes and display the histogram, shown here

Cara menggunakan python untuk menggambar

Colour histogram with a mask (25 min)

We can also apply a mask to the images we apply the colour histogram process to, in the same way we did for grayscale histograms. Consider this image of a well plate, where various chemical sensors have been applied to water and various concentrations of hydrochloric acid and sodium hydroxide

zero = iio.imread(uri="data/eight.tif")
zero[2,1]= 1.0
"""
The follwing line of code creates a new figure for imshow to use in displaying our output. Without it, plt.imshow() would overwrite our previous image in the cell above
"""
fig, ax = plt.subplots()
plt.imshow(zero)
print(zero)
2

Cara menggunakan python untuk menggambar

Suppose we are interested in the colour histogram of one of the sensors in the well plate image, specifically, the seventh well from the left in the topmost row, which shows Erythrosin B reacting with water

Hover over the image with your mouse to find the centre of that well and the radius (in pixels) of the well. Then create a circular mask to select only the desired well. Then, use that mask to apply the colour histogram operation to that well

Your masked image should look like this

Cara menggunakan python untuk menggambar

And, the program should produce a colour histogram that looks like this

Cara menggunakan python untuk menggambar

Larutan

zero = iio.imread(uri="data/eight.tif")
zero[2,1]= 1.0
"""
The follwing line of code creates a new figure for imshow to use in displaying our output. Without it, plt.imshow() would overwrite our previous image in the cell above
"""
fig, ax = plt.subplots()
plt.imshow(zero)
print(zero)
3

Key Points

  • In many cases, we can load images in grayscale by passing the

    %matplotlib widget
    
    35 argument to the
    import skimage                 # form 1, load whole skimage library
    import skimage.draw            # form 2, load skimage.draw module only
    from skimage.draw import disk  # form 3, load only the disk function
    import numpy as np             # form 4, load all of numpy into an object called np
    
    62 function

  • We can create histograms of images with the

    image = iio.imread(uri="data/eight.tif")
    plt.imshow(image)
    
    28 function

  • We can separate the RGB channels of an image using slicing operations

  • We can display histograms using the

    image = iio.imread(uri="data/eight.tif")
    plt.imshow(image)
    
    79
    image = iio.imread(uri="data/eight.tif")
    plt.imshow(image)
    
    80,
    image = iio.imread(uri="data/eight.tif")
    plt.imshow(image)
    
    81,
    image = iio.imread(uri="data/eight.tif")
    plt.imshow(image)
    
    82,
    image = iio.imread(uri="data/eight.tif")
    plt.imshow(image)
    
    83,
    image = iio.imread(uri="data/eight.tif")
    plt.imshow(image)
    
    84,
    image = iio.imread(uri="data/eight.tif")
    plt.imshow(image)
    
    85, and
    %matplotlib widget
    
    53 functions


Blurring Images

Overview

Teaching. 35 min
Exercises. 25 min

Questions

  • How can we apply a low-pass blurring filter to an image?

Tujuan

  • Explain why applying a low-pass blurring filter to an image is beneficial

  • Apply a Gaussian blur filter to an image using skimage

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

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
87 module, so we will focus on just one here, the Gaussian blur

Filters

In the day-to-day, macroscopic world, we have physical filters which separate out objects by size. A filter with small holes allows only small objects through, leaving larger objects behind. This is a good analogy for image filters. A high-pass filter will retain the smaller details in an image, filtering out the larger ones. A low-pass filter retains the larger features, analogous to what’s left behind by a physical filter mesh. High- and low-pass, here, refer to high and low spatial frequencies in the image. Details associated with high spatial frequencies are small, a lot of these features would fit across an image. Features associated with low spatial frequencies are large - maybe a couple of big features per image

Blurring

Blurring is to make something less clear or distinct. This could be interpreted quite broadly in the context of image analysis - anything that reduces or distorts the detail of an image might apply. Applying a low pass filter, which removes detail occurring at high spatial frequencies, is perceived as a blurring effect. A Gaussian blur is a filter that makes use of a Gaussian kernel

Kernels

A kernel can be used to implement a filter on an image. A kernel, in this context, is a small matrix which is combined with the image using a mathematical technique. convolution. Different sizes, shapes and contents of kernel produce different effects. The kernel can be thought of as a little image in itself, and will favour features of a similar size and shape in the main image. On convolution with an image, a big, blobby kernel will retain big, blobby, low spatial frequency features

gaussian blur

Consider this image of a cat, in particular the area of the image outlined by the white square

Cara menggunakan python untuk menggambar

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

Cara menggunakan python untuk menggambar

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. svg

The 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

Cara menggunakan python untuk menggambar

https. //commons. wikimedia. org/wiki/File. Gaussian_2D. png

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

Cara menggunakan python untuk menggambar

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

Cara menggunakan python untuk menggambar

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

Cara menggunakan python untuk menggambar

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

Image edges

Something different needs to happen for pixels near the outer limits of the image, since the kernel for the filter may be partially off the image. For example, what happens when the filter is applied to the upper-left pixel of the image? Here are the blue channel pixel values for the upper-left pixel of the cat image, again assuming a seven-by-seven kernel

zero = iio.imread(uri="data/eight.tif")
zero[2,1]= 1.0
"""
The follwing line of code creates a new figure for imshow to use in displaying our output. Without it, plt.imshow() would overwrite our previous image in the cell above
"""
fig, ax = plt.subplots()
plt.imshow(zero)
print(zero)
4

The upper-left pixel is the one with value 4. Since the pixel is at the upper-left corner, there are no pixels underneath much of the kernel; here, this is represented by x’s. So, what does the filter do in that situation?

The default mode is to fill in the nearest pixel value from the image. For each of the missing x’s the image value closest to the x is used. If we fill in a few of the missing pixels, you will see how this works

zero = iio.imread(uri="data/eight.tif")
zero[2,1]= 1.0
"""
The follwing line of code creates a new figure for imshow to use in displaying our output. Without it, plt.imshow() would overwrite our previous image in the cell above
"""
fig, ax = plt.subplots()
plt.imshow(zero)
print(zero)
5

Another strategy to fill those missing values is to reflect the pixels that are in the image to fill in for the pixels that are missing from the kernel

zero = iio.imread(uri="data/eight.tif")
zero[2,1]= 1.0
"""
The follwing line of code creates a new figure for imshow to use in displaying our output. Without it, plt.imshow() would overwrite our previous image in the cell above
"""
fig, ax = plt.subplots()
plt.imshow(zero)
print(zero)
6

A similar process would be used to fill in all of the other missing pixels from the kernel. Other border modes are available; you can learn more about them in the skimage documentation

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

Cara menggunakan python untuk menggambar

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

zero = iio.imread(uri="data/eight.tif")
zero[2,1]= 1.0
"""
The follwing line of code creates a new figure for imshow to use in displaying our output. Without it, plt.imshow() would overwrite our previous image in the cell above
"""
fig, ax = plt.subplots()
plt.imshow(zero)
print(zero)
7

Cara menggunakan python untuk menggambar

Next, we apply the gaussian blur

zero = iio.imread(uri="data/eight.tif")
zero[2,1]= 1.0
"""
The follwing line of code creates a new figure for imshow to use in displaying our output. Without it, plt.imshow() would overwrite our previous image in the cell above
"""
fig, ax = plt.subplots()
plt.imshow(zero)
print(zero)
8

The first two parameters to

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
88 are the image to blur,
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
93, and a tuple defining the sigma to use in ry- and cx-direction,
image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
90. The third parameter
image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
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
image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
91 to 3. 5, which means the kernel size will be 2 * sigma * 3. 5. For example, for a
image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
93 of 1. 0 the resulting kernel size would be 7, while for a
image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
93 of 2. 0 the kernel size would be 14. The default value for
image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
91 in scikit-image is 4. 0

The last parameter to

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
88 tells skimage to interpret our image, that has three dimensions, as a multichannel colour image

Finally, we display the blurred image

zero = iio.imread(uri="data/eight.tif")
zero[2,1]= 1.0
"""
The follwing line of code creates a new figure for imshow to use in displaying our output. Without it, plt.imshow() would overwrite our previous image in the cell above
"""
fig, ax = plt.subplots()
plt.imshow(zero)
print(zero)
9

Cara menggunakan python untuk menggambar

Experimenting with sigma values (10 min)

The size and shape of the kernel used to blur an image can have a significant effect on the result of the blurring and any downstream analysis carried out on the blurred image. The next two exercises ask you to experiment with the sigma values of the kernel, which is a good way to develop your understanding of how the choice of kernel can influence the result of blurring

First, try running the code above with a range of smaller and larger sigma values. Generally speaking, what effect does the sigma value have on the blurred image?

Larutan

Generally speaking, the larger the sigma value, the more blurry the result. A larger sigma will tend to get rid of more noise in the image, which will help for other operations we will cover soon, such as thresholding. However, a larger sigma also tends to eliminate some of the detail from the image. So, we must strike a balance with the sigma value used for blur filters

Experimenting with kernel shape (10 min - optional, not included in timing)

Now, what is the effect of applying an asymmetric kernel to blurring an image? Try running the code above with different sigmas in the ry and cx direction. For example, a sigma of 1. 0 in the ry direction, and 6. 0 in the cx direction

Larutan

[[0. 0. 0.]
 [0. 1. 0.]
 [0. 1. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
0

Cara menggunakan python untuk menggambar

These unequal sigma values produce a kernel that is rectangular instead of square. The result is an image that is much more blurred in the x direction than the y direction. For most use cases, a uniform blurring effect is desirable and this kind of asymmetric blurring should be avoided. However, it can be helpful in specific circumstances e. g. when noise is present in your image in a particular pattern or orientation, such as vertical lines, or when you want to remove uniform noise without blurring edges present in the image in a particular orientation

Other methods of blurring

The 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

Key Points

  • Applying a low-pass blurring filter smooths edges and removes noise from an image

  • Blurring is often used as a first step before we perform thresholding or edge detection

  • Gaussian blur dapat diterapkan pada gambar dengan fungsi

    image = iio.imread(uri="data/eight.tif")
    plt.imshow(image)
    
    88

  • Nilai sigma yang lebih besar dapat menghilangkan lebih banyak noise, tetapi juga akan menghilangkan detail dari suatu gambar


Thresholding

Overview

Teaching. 60 min
Latihan. 50 mnt

Questions

  • How can we use thresholding to produce a binary image?

Tujuan

  • Explain what thresholding is and how it can be used

  • Use histograms to determine appropriate threshold values to use for the thresholding process

  • Apply simple, fixed-level binary thresholding to an image

  • Jelaskan perbedaan antara menggunakan operator

    image = iio.imread(uri="data/eight.tif")
    plt.imshow(image)
    
    99 atau operator
    print(image.shape)
    print(image)
    
    00 untuk membatasi gambar yang diwakili oleh larik numpy

  • Jelaskan bentuk citra biner yang dihasilkan oleh thresholding melalui

    image = iio.imread(uri="data/eight.tif")
    plt.imshow(image)
    
    99 atau
    print(image.shape)
    print(image)
    
    00

  • Explain when Otsu’s method for automatic thresholding is appropriate

  • Terapkan ambang batas otomatis ke gambar menggunakan metode Otsu

  • Use the

    print(image.shape)
    print(image)
    
    03 function to count the number of non-zero pixels in an image

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 thresholding

Consider the image

print(image.shape)
print(image)
04 with a series of crudely cut shapes set against a white background

[[0. 0. 0.]
 [0. 1. 0.]
 [0. 1. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
1

Cara menggunakan python untuk menggambar

Now 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

print(image.shape)
print(image)
05

The 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

[[0. 0. 0.]
 [0. 1. 0.]
 [0. 1. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
2

Cara menggunakan python untuk menggambar

Next, we would like to apply the threshold

print(image.shape)
print(image)
05 such that pixels with grayscale values on one side of
print(image.shape)
print(image)
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
print(image.shape)
print(image)
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
print(image.shape)
print(image)
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 background

The histogram for the shapes image shown above can be produced as in the Creating Histograms episode

[[0. 0. 0.]
 [0. 1. 0.]
 [0. 1. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
3

Cara menggunakan python untuk menggambar

Since 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

print(image.shape)
print(image)
05 somewhere before the large peak and turn pixels above that value “off”. Let us choose
print(image.shape)
print(image)
11

To apply the threshold

print(image.shape)
print(image)
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
print(image.shape)
print(image)
00 to compare the
print(image.shape)
print(image)
14 to the threshold
print(image.shape)
print(image)
05. The operator returns a mask, that we capture in the variable
print(image.shape)
print(image)
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
%matplotlib widget
38, where the
%matplotlib widget
66 entries are shown as black pixels (0-valued) and the
%matplotlib widget
65 entries are shown as white pixels (1-valued)

[[0. 0. 0.]
 [0. 1. 0.]
 [0. 1. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
4

Cara menggunakan python untuk menggambar

You 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

What makes a good threshold?

As is often the case, the answer to this question is “it depends”. In the example above, we could have just switched off all the white background pixels by choosing

print(image.shape)
print(image)
20, but this would leave us with some background noise in the mask image. On the other hand, if we choose too low a value for the threshold, we could lose some of the shapes that are too bright. You can experiment with the threshold by re-running the above code lines with different values for
print(image.shape)
print(image)
05. In practice, it is a matter of domain knowledge and experience to interpret the peaks in the histogram so to determine an appropriate threshold. The process often involves trial and error, which is a drawback of the simple thresholding method. Below we will introduce automatic thresholding, which uses a quantitative, mathematical definition for a good threshold that allows us to determine the value of
print(image.shape)
print(image)
05 automatically. It is worth noting that the principle for simple and automatic thresholding can also be used for images with pixel ranges other than [0. 0, 1. 0]. For example, we could perform thresholding on pixel intensity values in the range [0, 255] as we have already seen in the Image Representation in skimage episode

We can now apply the

print(image.shape)
print(image)
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

[[0. 0. 0.]
 [0. 1. 0.]
 [0. 1. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
5

Cara menggunakan python untuk menggambar

More practice with simple thresholding (15 min)

Now, it is your turn to practice. Suppose we want to use simple thresholding to select only the coloured shapes (in this particular case we consider grayish to be a colour, too) from the image

print(image.shape)
print(image)
24

Cara menggunakan python untuk menggambar

First, plot the grayscale histogram as in the Creating Histogram episode and examine the distribution of grayscale values in the image. What do you think would be a good value for the threshold

print(image.shape)
print(image)
05?

Larutan

The histogram for the

print(image.shape)
print(image)
24 image can be shown with

[[0. 0. 0.]
 [0. 1. 0.]
 [0. 1. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
6

Cara menggunakan python untuk menggambar

We can see a large spike around 0. 3, and a smaller spike around 0. 7. The spike near 0. 3 represents the darker background, so it seems like a value close to

print(image.shape)
print(image)
27 would be a good choice

Next, create a mask to turn the pixels above the threshold

print(image.shape)
print(image)
05 on and pixels below the threshold
print(image.shape)
print(image)
05 off. Note that unlike the image with a white background we used above, here the peak for the background colour is at a lower gray level than the shapes. Therefore, change the comparison operator less
print(image.shape)
print(image)
00 to greater
image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
99 to create the appropriate mask. Then apply the mask to the image and view the thresholded image. If everything works as it should, your output should show only the coloured shapes on a black background

Larutan

Here are the commands to create and view the binary mask

[[0. 0. 0.]
 [0. 1. 0.]
 [0. 1. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
7

Cara menggunakan python untuk menggambar

And here are the commands to apply the mask and view the thresholded image

[[0. 0. 0.]
 [0. 1. 0.]
 [0. 1. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
8

Cara menggunakan python untuk menggambar

Automatic thresholding

The downside of the simple thresholding technique is that we have to make an educated guess about the threshold

print(image.shape)
print(image)
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

Denoising an image before thresholding

In practice, it is often necessary to denoise the image before thresholding, which can be done with one of the methods from the Blurring Images episode

Consider the image

print(image.shape)
print(image)
33 of a maize root system which we have seen before in the Image Representation in skimage episode

[[0. 0. 0.]
 [0. 1. 0.]
 [0. 1. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
9

Cara menggunakan python untuk menggambar

We 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

five = iio.imread(uri="data/eight.tif")
five[1,2]= 1.0
five[3,0]= 1.0
fig, ax = plt.subplots()
plt.imshow(five)
print(five)
0

Cara menggunakan python untuk menggambar

The 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

print(image.shape)
print(image)
_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
print(image.shape)
print(image)
05 with Otsu’s method

five = iio.imread(uri="data/eight.tif")
five[1,2]= 1.0
five[3,0]= 1.0
fig, ax = plt.subplots()
plt.imshow(five)
print(five)
1

five = iio.imread(uri="data/eight.tif")
five[1,2]= 1.0
five[3,0]= 1.0
fig, ax = plt.subplots()
plt.imshow(five)
print(five)
2

For 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

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
99. As we have seen before, pixels above the threshold value will be turned on, those below the threshold will be turned off

five = iio.imread(uri="data/eight.tif")
five[1,2]= 1.0
five[3,0]= 1.0
fig, ax = plt.subplots()
plt.imshow(five)
print(five)
3

Cara menggunakan python untuk menggambar

Finally, we use the mask to select the foreground

five = iio.imread(uri="data/eight.tif")
five[1,2]= 1.0
five[3,0]= 1.0
fig, ax = plt.subplots()
plt.imshow(five)
print(five)
4

Cara menggunakan python untuk menggambar

Application. measuring root mass

Let 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

print(image.shape)
print(image)
37,
print(image.shape)
print(image)
38,
print(image.shape)
print(image)
39, and
print(image.shape)
print(image)
40

Cara menggunakan python untuk menggambar

Suppose 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

  1. Read the image, converting it to grayscale as it is read. For this application we do not need the colour image
  2. Blur the image
  3. Use Otsu’s method of thresholding to create a binary image, where the pixels that were part of the maize plant are white, and everything else is black
  4. Save the binary image so it can be examined later
  5. Count the white pixels in the binary image, and divide by the number of pixels in the image. This ratio will be a measure of the root mass of the plant in the image
  6. Output the name of the image processed and the root mass ratio

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

five = iio.imread(uri="data/eight.tif")
five[1,2]= 1.0
five[3,0]= 1.0
fig, ax = plt.subplots()
plt.imshow(five)
print(five)
5

The function begins with reading the original image from the file

print(image.shape)
print(image)
41. We use
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
62 with the optional argument
%matplotlib widget
35 to automatically convert it to grayscale. Next, the grayscale image is blurred with a Gaussian filter with the value of
image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
93 that is passed to the function. Then we determine the threshold
print(image.shape)
print(image)
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 familiar

The final part of the function determines the root mass ratio in the image. Recall that in the

print(image.shape)
print(image)
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
print(image.shape)
print(image)
47. Then we determine the width and height of the image by using the elements of
print(image.shape)
print(image)
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
print(image.shape)
print(image)
49 in the image. The function returns then root density of the image

We 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

print(image.shape)
print(image)
37 and a sigma value of 1. 5, we would call the function like this

five = iio.imread(uri="data/eight.tif")
five[1,2]= 1.0
five[3,0]= 1.0
fig, ax = plt.subplots()
plt.imshow(five)
print(five)
6

five = iio.imread(uri="data/eight.tif")
five[1,2]= 1.0
five[3,0]= 1.0
fig, ax = plt.subplots()
plt.imshow(five)
print(five)
7

Now 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

five = iio.imread(uri="data/eight.tif")
five[1,2]= 1.0
five[3,0]= 1.0
fig, ax = plt.subplots()
plt.imshow(five)
print(five)
8

five = iio.imread(uri="data/eight.tif")
five[1,2]= 1.0
five[3,0]= 1.0
fig, ax = plt.subplots()
plt.imshow(five)
print(five)
9

Ignoring more of the images – brainstorming (10 min)

Let us take a closer look at the binary masks produced by the

print(image.shape)
print(image)
51 function

Cara menggunakan python untuk menggambar

You may have noticed in the section on automatic thresholding that the thresholded image does include regions of the image aside of the plant root. the numbered labels and the white circles in each image are preserved during the thresholding, because their grayscale values are above the threshold. Therefore, our calculated root mass ratios include the white pixels of the label and white circle that are not part of the plant root. Those extra pixels affect how accurate the root mass calculation is

How might we remove the labels and circles before calculating the ratio, so that our results are more accurate? Think about some options given what we have learned so far

Larutan

One approach we might take is to try to completely mask out a region from each image, particularly, the area containing the white circle and the numbered label. If we had coordinates for a rectangular area on the image that contained the circle and the label, we could mask the area out easily by using techniques we learned in the Drawing and Bitwise Operations episode

However, a closer inspection of the binary images raises some issues with that approach. Since the roots are not always constrained to a certain area in the image, and since the circles and labels are in different locations each time, we would have difficulties coming up with a single rectangle that would work for every image. We could create a different masking rectangle for each image, but that is not a practicable approach if we have hundreds or thousands of images to process

Another approach we could take is to apply two thresholding steps to the image. Look at the graylevel histogram of the file

print(image.shape)
print(image)
37 shown above again. Notice the peak near 1. 0? Recall that a grayscale value of 1. 0 corresponds to white pixels. the peak corresponds to the white label and circle. So, we could use simple binary thresholding to mask the white circle and label from the image, and then we could use Otsu’s method to select the pixels in the plant portion of the image

Note that most of this extra work in processing the image could have been avoided during the experimental design stage, with some careful consideration of how the resulting images would be used. For example, all of the following measures could have made the images easier to process, by helping us predict and/or detect where the label is in the image and subsequently mask it from further processing

  • Using labels with a consistent size and shape
  • Placing all the labels in the same position, relative to the sample
  • Using a non-white label, with non-black writing

Ignoring more of the images – implementation (30 min - optional, not included in timing)

Implement an enhanced version of the function

print(image.shape)
print(image)
51 that applies simple binary thresholding to remove the white circle and label from the image before applying Otsu’s method

Larutan

We can apply a simple binary thresholding with a threshold

print(image.shape)
print(image)
54 to remove the label and circle from the image. We use the binary mask to set the pixels in the blurred image to zero (black)

[[0. 0. 0.]
 [0. 1. 1.]
 [0. 0. 0.]
 [1. 1. 0.]
 [0. 0. 0.]]
0

The output of the improved program does illustrate that the white circles and labels were skewing our root mass ratios

[[0. 0. 0.]
 [0. 1. 1.]
 [0. 0. 0.]
 [1. 1. 0.]
 [0. 0. 0.]]
1

Here are the binary images produced by the additional thresholding. Note that we have not completely removed the offending white pixels. Outlines still remain. However, we have reduced the number of extraneous pixels, which should make the output more accurate

Cara menggunakan python untuk menggambar

Thresholding a bacteria colony image (15 min)

In the images directory

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
74, you will find an image named
print(image.shape)
print(image)
56

Cara menggunakan python untuk menggambar

This is one of the images you will be working with in the morphometric challenge at the end of the workshop

  1. Plot and inspect the grayscale histogram of the image to determine a good threshold value for the image
  2. Create a binary mask that leaves the pixels in the bacteria colonies “on” while turning the rest of the pixels in the image “off”

Larutan

Here is the code to create the grayscale histogram

[[0. 0. 0.]
 [0. 1. 1.]
 [0. 0. 0.]
 [1. 1. 0.]
 [0. 0. 0.]]
2

Cara menggunakan python untuk menggambar

The peak near one corresponds to the white image background, and the broader peak around 0. 5 corresponds to the yellow/brown culture medium in the dish. The small peak near zero is what we are after. the dark bacteria colonies. A reasonable choice thus might be to leave pixels below

print(image.shape)
print(image)
57 on

Here is the code to create and show the binarized image using the

print(image.shape)
print(image)
00 operator with a threshold
print(image.shape)
print(image)
57

[[0. 0. 0.]
 [0. 1. 1.]
 [0. 0. 0.]
 [1. 1. 0.]
 [0. 0. 0.]]
3

Cara menggunakan python untuk menggambar

When you experiment with the threshold a bit, you can see that in particular the size of the bacteria colony near the edge of the dish in the top right is affected by the choice of the threshold

Key Points

  • Thresholding produces a binary image, where all pixels with intensities above (or below) a threshold value are turned on, while all other pixels are turned off

  • Gambar biner yang dihasilkan oleh thresholding disimpan dalam array NumPy dua dimensi, karena hanya memiliki satu saluran nilai warna. Mereka adalah boolean, karenanya mengandung nilai 0 (mati) dan 1 (aktif)

  • Thresholding can be used to create masks that select only the interesting parts of an image, or as the first step before edge detection or finding contours


Connected Component Analysis

Overview

Pengajaran. 70 mnt
Exercises. 55 min

Questions

  • How to extract separate objects from an image and describe these objects quantitatively

Tujuan

  • Understand the term object in the context of images

  • Learn about pixel connectivity

  • Pelajari cara kerja Analisis Komponen Terhubung (CCA).

  • Gunakan CCA untuk menghasilkan gambar yang menyorot setiap objek dengan warna berbeda

  • Characterise each object with numbers that describe its appearance

Objects

In 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

Cara menggunakan python untuk menggambar

In thresholding we went from the original image to this version

Cara menggunakan python untuk menggambar

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

%matplotlib widget
65 while the background pixels are
%matplotlib widget
66

By 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 Neighborhoods

In 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

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
64 is used to represent background pixels, and the letter
print(image.shape)
print(image)
63 is used to represent object pixels foreground)

[[0. 0. 0.]
 [0. 1. 1.]
 [0. 0. 0.]
 [1. 1. 0.]
 [0. 0. 0.]]
4

The 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

print(image.shape)
print(image)
64, only the pixels indicated with a
%matplotlib widget
73 are reachable

[[0. 0. 0.]
 [0. 1. 1.]
 [0. 0. 0.]
 [1. 1. 0.]
 [0. 0. 0.]]
5

The pixels on the diagonal (from

print(image.shape)
print(image)
64) are not reachable with a single jump, which is denoted by the
print(image.shape)
print(image)
67. The pixels reachable with a single jump form the 1-jump neighborhood

The 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

print(image.shape)
print(image)
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

[[0. 0. 0.]
 [0. 1. 1.]
 [0. 0. 0.]
 [1. 1. 0.]
 [0. 0. 0.]]
6

All pixels reachable with one, or two jumps form the 2-jump neighborhood. The grid below illustrates the pixels reachable from the centre pixel

print(image.shape)
print(image)
64 with a single jump, highlighted with a
%matplotlib widget
73, and the pixels reachable with 2 jumps with a
image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
69

[[0. 0. 0.]
 [0. 1. 1.]
 [0. 0. 0.]
 [1. 1. 0.]
 [0. 0. 0.]]
7

We 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

print(image.shape)
print(image)
72’s and
print(image.shape)
print(image)
73’s

[[0. 0. 0.]
 [0. 1. 1.]
 [0. 0. 0.]
 [1. 1. 0.]
 [0. 0. 0.]]
8

In 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

print(image.shape)
print(image)
72 because pixels are also considered connected along the diagonals

[[0. 0. 0.]
 [0. 1. 1.]
 [0. 0. 0.]
 [1. 1. 0.]
 [0. 0. 0.]]
9

Object counting (optional, not included in timing)

How many objects with 1 orthogonal jump, how many with 2 orthogonal jumps?

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
00

1 jump

a) 1 b) 5 c) 2

Larutan

b) 5

2 jumps

a) 2 b) 3 c) 5

Larutan

a) 2

Jumps and neighborhoods

We have just introduced how you can reach different neighboring pixels by performing one or more orthogonal jumps. We have used the terms 1-jump and 2-jump neighborhood. There is also a different way of referring to these neighborhoods. the 4- and 8-neighborhood. With a single jump you can reach four pixels from a given starting pixel. Hence, the 1-jump neighborhood corresponds to the 4-neighborhood. When two orthogonal jumps are allowed, eight pixels can be reached, so the 2-jump neighborhood corresponds to the 8-neighborhood

Connected Component Analysis

In 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

%matplotlib widget
66 value in this image is associated with background pixels, and the
%matplotlib widget
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
print(image.shape)
print(image)
77. Let us add this function to the already familiar steps of thresholding an image. Here we define a reusable Python function
print(image.shape)
print(image)
78

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
01

Note the new import of

print(image.shape)
print(image)
79 in order to use the
print(image.shape)
print(image)
80 function that performs the CCA. The first four lines of code are familiar from the Thresholding episode

Then we call the

print(image.shape)
print(image)
80 function. This function has one positional argument where we pass the
print(image.shape)
print(image)
16, i. e. , the binary image to work on. With the optional argument
print(image.shape)
print(image)
83, we specify the neighborhood in units of orthogonal jumps. For example, by setting
print(image.shape)
print(image)
84 we will consider the 2-jump neighborhood introduced above. The function returns a
print(image.shape)
print(image)
85 where each pixel has a unique value corresponding to the object it belongs to. In addition, we pass the optional parameter
print(image.shape)
print(image)
86 to return the maximum label index as
print(image.shape)
print(image)
87

Optional parameters and return values

The optional parameter

print(image.shape)
print(image)
88 changes the data type that is returned by the function
print(image.shape)
print(image)
80. The number of labels is only returned if
print(image.shape)
print(image)
88 is True. Otherwise, the function only returns the labeled image. This means that we have to pay attention when assigning the return value to a variable. If we omit the optional parameter
print(image.shape)
print(image)
88 or pass
print(image.shape)
print(image)
92, we can call the function as

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
02

If we pass

print(image.shape)
print(image)
86, the function returns a tuple and we can assign it as

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
03

If we used the same assignment as in the first case, the variable

print(image.shape)
print(image)
85 would become a tuple, in which
print(image.shape)
print(image)
95 is the image and
print(image.shape)
print(image)
96 is the number of labels. This could cause confusion if we assume that
print(image.shape)
print(image)
85 only contains the image and pass it to other functions. If you get an
print(image.shape)
print(image)
98 or similar, check if you have assigned the return values consistently with the optional parameters

We can call the above function

print(image.shape)
print(image)
78 and display the labeled image like so

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
04

Color mappings

Here you might get a warning

(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
00 or just see an all black image (Note. this behavior might change in future versions or not occur with a different image viewer)

What went wrong? When you hover over the black image, the pixel values are shown as numbers in the lower corner of the viewer. You can see that some pixels have values different from

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
64, so they are not actually pure black. Let’s find out more by examining
print(image.shape)
print(image)
85. Properties that might be interesting in this context are
(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
03, the minimum and maximum value. We can print them with the following lines

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
05

Examining the output can give us a clue why the image appears black

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
06

(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
_03 dari
print(image.shape)
print(image)
85 adalah
(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
06. This means that values in this image range from
(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
07 to
(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
08. Those are really big numbers. From this available space we only use the range from
image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
64 to
(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
10. When showing this image in the viewer, it squeezes the complete range into 256 gray values. Therefore, the range of our numbers does not produce any visible change

Fortunately, the skimage library has tools to cope with this situation

We can use the function

(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
11 to convert the colours in the image (recall that we already used the
%matplotlib widget
27 function to convert to grayscale). Dengan
(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
_11, semua objek diwarnai sesuai dengan daftar warna yang dapat disesuaikan. Kita dapat menggunakan perintah berikut untuk mengonversi dan menampilkan gambar

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
_07

Cara menggunakan python untuk menggambar

Berapa banyak objek dalam gambar tersebut (15 menit)

Sekarang, giliran Anda untuk berlatih. Menggunakan fungsi

print(image.shape)
print(image)
_78, temukan dua cara untuk mencetak jumlah objek yang ditemukan pada gambar

Berapa jumlah objek yang Anda harapkan?

Bagaimana mengubah nilai

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
93 dan
(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
16 memengaruhi hasil?

Larutan

Seperti yang sudah Anda duga, nilai pengembalian

print(image.shape)
print(image)
87 sudah berisi jumlah gambar yang ditemukan. Jadi itu bisa dicetak dengan mudah

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
_08

Namun ada juga cara untuk mendapatkan jumlah objek yang ditemukan dari gambar berlabel itu sendiri. Ingatlah bahwa semua piksel milik satu objek diberi nilai integer yang sama. Algoritma komponen terhubung menghasilkan angka berurutan. Latar belakang mendapatkan nilai

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
_64, objek pertama mendapatkan nilai
%matplotlib widget
73, objek kedua mendapatkan nilai
image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
69, dan seterusnya. Artinya dengan mencari objek dengan nilai maksimum, kita juga mengetahui berapa banyak objek yang ada di dalam citra. Dengan demikian kita dapat menggunakan fungsi
(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
_21 dari Numpy untuk menemukan nilai maksimum yang sama dengan jumlah objek yang ditemukan

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
_09

Memanggil fungsi dengan

(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
_22, dan
(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
23, kedua metode akan dicetak

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
_10

Menurunkan ambang batas akan menghasilkan objek yang lebih sedikit. Semakin tinggi ambang batas yang ditetapkan, semakin banyak objek yang ditemukan. More and more background noise gets picked up as objects. Larger sigmas produce binary masks with less noise and hence a smaller number of objects. Setting sigma too high bears the danger of merging objects

You might wonder why the connected component analysis with

(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
22, and
(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
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 border

Cara menggunakan python untuk menggambar

For 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 (

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
93) and thresholding (
print(image.shape)
print(image)
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 found

Morphometrics - Describe object features with numbers

Morphometrics 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

(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
28 to measure the properties of labeled regions. It returns a list of
(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
29 that describe each connected region in the images. The properties can be accessed using the attributes of the
(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
29 data type. Here we will use the properties
(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
31 and
(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
32. You can explore the skimage documentation to learn about other properties available

We can get a list of areas of the labeled objects as follows

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
11

This will produce the output

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
12

Plot a histogram of the object area distribution (10 min)

Similar to how we determined a “good” threshold in the Thresholding episode, it is often helpful to inspect the histogram of an object property. For example, we want to look at the distribution of the object areas

  1. Create and examine a histogram of the object areas obtained with
    (5, 3)
    [[0. 0. 0.]
     [0. 1. 0.]
     [0. 0. 0.]
     [0. 1. 0.]
     [0. 0. 0.]]
    
    28
  2. What does the histogram tell you about the objects?

Larutan

The histogram can be plotted with

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
13

Cara menggunakan python untuk menggambar

The histogram shows the number of objects (vertical axis) whose area is within a certain range (horizontal axis). The height of the bars in the histogram indicates the prevalence of objects with a certain area. The whole histogram tells us about the distribution of object sizes in the image. It is often possible to identify gaps between groups of bars (or peaks if we draw the histogram as a continuous curve) that tell us about certain groups in the image

In this example, we can see that there are four small objects that contain less than 50000 pixels. Then there is a group of four (1+1+2) objects in the range between 200000 and 400000, and three objects with a size around 500000. For our object count, we might want to disregard the small objects as artifacts, i. e, we want to ignore the leftmost bar of the histogram. We could use a threshold of 50000 as the minimum area to count. In fact, the

(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
34 list already tells us that there are fewer than 200 pixels in these objects. Therefore, it is reasonable to require a minimum area of at least 200 pixels for a detected object. Dalam praktiknya, menemukan ambang batas yang “tepat” bisa rumit dan biasanya melibatkan tebakan berdasarkan pengetahuan domain

Filter objects by area (10 min)

Now we would like to use a minimum area criterion to obtain a more accurate count of the objects in the image

  1. Find a way to calculate the number of objects by only counting objects above a certain area

Larutan

One way to count only objects above a certain area is to first create a list of those objects, and then take the length of that list as the object count. This can be done as follows

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
14

Another option is to use Numpy arrays to create the list of large objects. We first create an array

(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
34 containing the object areas, and an array
(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
36 containing the object labels. The labels of the objects are also returned by
(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
28. We have already seen that we can create boolean arrays using comparison operators. Here we can use
(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
38 to produce an array that has the same dimension as
(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
36. It can then used to select the labels of objects whose area is greater than
(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
40 by indexing

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
15

The advantage of using Numpy arrays is that

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
55 loops and
(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
42 statements in Python can be slow, and in practice the first approach may not be feasible if the image contains a large number of objects. In that case, Numpy array functions turn out to be very useful because they are much faster

In this example, we can also use the

print(image.shape)
print(image)
47 function that we have seen earlier together with the
image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
99 operator to count the objects whose area is above
(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
40

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
16

For all three alternatives, the output is the same and gives the expected count of 7 objects

Using functions from Numpy and other Python packages

Functions from Python packages such as Numpy are often more efficient and require less code to write. It is a good idea to browse the reference pages of

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
33 and
import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
32 to look for an availabe function that can solve a given task

Remove small objects (20 min)

We might also want to exclude (mask) the small objects when plotting the labeled image

  1. Enhance the
    print(image.shape)
    print(image)
    
    78 function such that it automatically removes objects that are below a certain area that is passed to the function as an optional parameter

Larutan

To remove the small objects from the labeled image, we change the value of all pixels that belong to the small objects to the background label 0. One way to do this is to loop over all objects and set the pixels that match the label of the object to 0

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
17

Here Numpy functions can also be used to eliminate

image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
55 loops and
(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
42 statements. Like above, we can create an array of the small object labels with the comparison
(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
51. We can use another Numpy function,
(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
52, to set the pixels of all small objects to 0.
(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
52 takes two arrays and returns a boolean array with values
%matplotlib widget
65 if the entry of the first array is found in the second array, and
%matplotlib widget
66 otherwise. This array can then be used to index the
print(image.shape)
print(image)
85 and set the entries that belong to small objects to
image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
64

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
18

An even more elegant way to remove small objects from the image is to leverage the

(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
58 module. It provides a function
(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
59 that does exactly what we are looking for. It can be applied to a binary image and returns a mask in which all objects smaller than
(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
40 are excluded, i. e, their pixel values are set to
%matplotlib widget
66. We can then apply
print(image.shape)
print(image)
80 to the masked image

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
19

Using the

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
32 features, we can implement the
(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
64 as follows

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
20

We can now call the function with a chosen

(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
40 and display the resulting labeled image

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
21

Cara menggunakan python untuk menggambar

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
_22

Perhatikan bahwa benda-benda kecil "hilang" dan kami memperoleh jumlah yang benar dari 7 benda dalam gambar

Colour objects by area (optional, not included in timing)

Terakhir, kami ingin menampilkan gambar dengan objek yang diwarnai sesuai dengan luasnya. Dalam praktiknya, ini dapat digunakan dengan properti lain untuk memberikan isyarat visual dari properti objek

Larutan

We already know how to get the areas of the objects from the

(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
66. We just need to insert a zero area value for the background (to colour it like a zero size object). The background is also labeled
image = iio.imread(uri="data/eight.tif")
plt.imshow(image)
64 in the
print(image.shape)
print(image)
85, so we insert the zero area value in front of the first element of
(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
34 with
(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
70. Then we can create a
(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
71 where we assign each pixel value the area by indexing the
(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
34 with the label values in
print(image.shape)
print(image)
85

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
23

Cara menggunakan python untuk menggambar

You may have noticed that in the solution, we have used the

print(image.shape)
print(image)
85 to index the array
(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
34. Ini adalah contoh dari Hasilnya adalah array dengan bentuk yang sama dengan
print(image.shape)
print(image)
85 yang nilai pikselnya dipilih dari
(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
34 sesuai dengan label objek. Karenanya objek akan diwarnai berdasarkan area saat hasilnya ditampilkan. Note that advanced indexing with an integer array works slightly different than the indexing with a Boolean array that we have used for masking. While Boolean array indexing returns only the entries corresponding to the
%matplotlib widget
65 values of the index, integer array indexing returns an array with the same shape as the index. Anda dapat membaca lebih lanjut tentang pengindeksan lanjutan di

Key Points

  • We can use

    print(image.shape)
    print(image)
    
    80 to find and label connected objects in an image

  • We can use

    (5, 3)
    [[0. 0. 0.]
     [0. 1. 0.]
     [0. 0. 0.]
     [0. 1. 0.]
     [0. 0. 0.]]
    
    28 to measure properties of labeled objects

  • We can use

    (5, 3)
    [[0. 0. 0.]
     [0. 1. 0.]
     [0. 0. 0.]
     [0. 1. 0.]
     [0. 0. 0.]]
    
    59 to mask small objects and remove artifacts from an image

  • We can display the labeled image to view the objects coloured by label


Capstone Challenge

Overview

Teaching. 10 min
Exercises. 40 min

Questions

  • How can we automatically count bacterial colonies with image analysis?

Tujuan

  • Bring together everything you’ve learnt so far to count bacterial colonies in 3 images

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 Counting

As mentioned in the workshop introduction, your morphometric challenge is to determine how many bacteria colonies are in each of these images

Cara menggunakan python untuk menggambar

Cara menggunakan python untuk menggambar

Cara menggunakan python untuk menggambar

The image files can be found at

(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
82,
(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
83, and
(5, 3)
[[0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]
 [0. 1. 0.]
 [0. 0. 0.]]
84

Morfometri untuk koloni bakteri

Write a Python program that uses skimage to count the number of bacteria colonies in each image, and for each, produce a new image that highlights the colonies. The image should look similar to this one

Cara menggunakan python untuk menggambar

Additionally, print out the number of colonies for each image

Use what you have learnt about histograms, thresholding and connected component analysis. Try to put your code into a re-usable function, so that it can be applied easily to any image file

Larutan

First, let’s work through the process for one image

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
24

Cara menggunakan python untuk menggambar

Next, we need to threshold the image to create a mask that covers only the dark bacterial colonies. This is easier using a grayscale image, so we convert it here

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
25

Cara menggunakan python untuk menggambar

Next, we blur the image and create a histogram

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
26

Cara menggunakan python untuk menggambar

In this histogram, we see three peaks - the left one (i. e. the darkest pixels) is our colonies, the central peak is the yellow/brown culture medium in the dish, and the right one (i. e. the brightest pixels) is the white image background. Therefore, we choose a threshold that selects the small left peak

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
27

Cara menggunakan python untuk menggambar

This mask shows us where the colonies are in the image - but how can we count how many there are? This requires connected component analysis

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
28

Terakhir, kami membuat gambar ringkasan koloni berwarna di atas gambar skala abu-abu

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
_29

Cara menggunakan python untuk menggambar

Sekarang kita telah menyelesaikan tugas untuk satu gambar, kita perlu mengulanginya untuk dua gambar yang tersisa. Ini adalah poin yang bagus untuk mengumpulkan baris di atas menjadi fungsi yang dapat digunakan kembali

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
_30

Sekarang kita dapat dengan mudah melakukan analisis ini pada semua gambar melalui for loop

import skimage                 # form 1, load whole skimage library
import skimage.draw            # form 2, load skimage.draw module only
from skimage.draw import disk  # form 3, load only the disk function
import numpy as np             # form 4, load all of numpy into an object called np
_31

Cara menggunakan python untuk menggambar
Cara menggunakan python untuk menggambar
Cara menggunakan python untuk menggambar

You’ll notice that for the images with more colonies, the results aren’t perfect. For example, some small colonies are missing, and there are likely some small black spots being labelled incorrectly as colonies. You could expand this solution to, for example, use an automatically determined threshold for each image, which may fit each better. Also, you could filter out colonies below a certain size (as we did in the Connected Component Analysis episode). You’ll also see that some touching colonies are merged into one big colony. This could be fixed with more complicated segmentation methods (outside of the scope of this lesson) like watershed

Key Points

  • Using thresholding, connected component analysis and other tools we can automatically segment images of bacterial colonies

    Can I use Python to draw?

    Getting to Know the Python turtle Library turtle is a pre-installed Python library that enables users to create pictures and shapes by providing them with a virtual canvas . The onscreen pen that you use for drawing is called the turtle and this is what gives the library its name.

    How to draw graphics in Python?

    Langkah-langkah membuat grafik dengan Python. Features of Graphic Window. Creating different types of Graphic objects. .
    Import all libraries from the graphics Class
    Create a Window object
    Draw the objects in the created window
    Close the window

    How to draw object in Python?

    Object-oriented Programming in Python. Create Your Own Adventure Game .
    from shapes import Paper, Triangle, Rectangle, Oval
    paper = Paper()
    rect1 = Rectangle()
    rect1. set_width(200) rect1. set_height(100) rect1. .
    rect1. draw()
    paper. display()
    # put the code to create the 2nd Rectangle here paper. display()

    How do I turn a picture into a drawing?

    Anda dapat mengonversi foto menjadi sketsa di ponsel dengan mudah menggunakan aplikasi foto ke sketsa Fotor . Unduh di perangkat smartphone Android atau iOS Anda secara gratis. Unggah gambar Anda di aplikasi dan pilih filter sketsa dari perpustakaan. Terapkan ke gambar, dan voila.