Ikhtisar metode segmentasi gambar di pustaka scikit-image

Ambang batas


Ini adalah cara termudah untuk memisahkan objek dari latar belakang dengan memilih piksel di atas atau di bawah ambang tertentu. Ini biasanya berguna ketika kita akan mengelompokkan objek berdasarkan latar belakangnya. Anda dapat membaca lebih lanjut tentang ambang di sini .

Orang yang akrab dengan film Terminator mungkin akan setuju bahwa ini adalah film fiksi ilmiah terbesar di zaman itu. Dalam film itu, James Cameron memperkenalkan konsep efek visual yang menarik, yang memungkinkan pemirsa bersembunyi di balik mata cyborg bernama Terminator. Efek ini telah dikenal sebagai "Visi Terminator" (Visi Terminator Inggris). Dalam arti tertentu, ia memisahkan siluet orang-orang dari latar belakang. Ini mungkin kedengarannya sangat tidak pantas saat itu, tetapi segmentasi gambar adalah bagian penting dari banyak teknik pemrosesan gambar saat ini.

Segmentasi gambar


Ada sejumlah perpustakaan yang ditulis untuk analisis gambar. Pada artikel ini, kita akan membahas scikit-image, pustaka pemrosesan gambar Python, secara terperinci.

Gambar-scikit


gambar

Scikit-image adalah pustaka Python untuk pemrosesan gambar.

Instalasi


scikit-image diinstal sebagai berikut:

pip install -U scikit-image(Linux and OSX) pip install scikit-image(Windows) # For Conda-based distributions conda install scikit-image 



Tinjauan Gambar Python


Sebelum kita sampai pada aspek teknis segmentasi gambar, penting untuk sedikit mengenal ekosistem gambar Scikit dan bagaimana memproses gambar.

Impor Gambar GrayScale dari perpustakaan skimage


Modul data skimage berisi beberapa contoh set data bawaan, yang biasanya disimpan dalam format jpeg atau png.

 from skimage import data import numpy as np import matplotlib.pyplot as plt image = data.binary_blobs() plt.imshow(image, cmap='gray') 

Impor gambar warna dari pustaka skimage


 from skimage import data import numpy as np import matplotlib.pyplot as plt image = data.astronaut() plt.imshow(image) 



Impor gambar dari sumber eksternal


 # The I/O module is used for importing the image from skimage import data import numpy as np import matplotlib.pyplot as plt from skimage import io image = io.imread('skimage_logo.png') plt.imshow(image); 



Unduh banyak gambar


 images = io.ImageCollection('../images/*.png:../images/*.jpg') print('Type:', type(images)) images.files Out[]: Type: <class 'skimage.io.collection.ImageCollection'> 

Menyimpan Gambar


 #Saving file as 'logo.png' io.imsave('logo.png', logo) 

Segmentasi gambar


Sekarang kami memiliki gagasan scikit-image, kami menawarkan untuk mempertimbangkan detail segmentasi gambar. Segmentasi gambar adalah proses membagi gambar digital menjadi beberapa segmen untuk menyederhanakan dan / atau mengubah representasi gambar menjadi sesuatu yang lebih bermakna dan lebih mudah dianalisis.

Dalam artikel ini, kami akan mempertimbangkan algoritma untuk model yang diajarkan dengan guru (diawasi) dan tanpa guru (tidak diawasi).


Beberapa algoritma segmentasi tersedia di pustaka scikit-image.

Segmentasi dengan seorang guru: beberapa pengetahuan awal, mungkin dari input manusia, digunakan untuk memandu algoritma.

Segmentasi tanpa guru: pengetahuan sebelumnya tidak diperlukan. Algoritma ini mencoba untuk secara otomatis membagi gambar menjadi area yang signifikan. Pengguna masih dapat mengonfigurasi parameter tertentu untuk mendapatkan hasil yang diinginkan.

Mari kita coba ini pada gambar tutorial yang dilengkapi dengan dataset scikit-image yang telah ditentukan.

Impor reguler


 import numpy as np import matplotlib.pyplot as plt import skimage.data as data import skimage.segmentation as seg import skimage.filters as filters import skimage.draw as draw import skimage.color as color 

Fitur pencitraan sederhana

 def image_show(image, nrows=1, ncols=1, cmap='gray'): fig, ax = plt.subplots(nrows=nrows, ncols=ncols, figsize=(14, 14)) ax.imshow(image, cmap='gray') ax.axis('off') return fig, ax 

Gambar


 text = data.page() image_show(text) 



Gambar ini sedikit lebih gelap, tapi mungkin kita masih bisa memilih nilai yang akan memberi kita segmentasi yang wajar tanpa algoritma yang rumit. Sekarang, untuk membantu kami memilih nilai ini, kami akan menggunakan histogram.

Dalam hal ini, histogram menunjukkan jumlah piksel dalam gambar dengan intensitas berbeda yang ditemukan dalam gambar ini. Sederhananya, histogram adalah grafik di mana sumbu X menunjukkan semua nilai yang ada dalam gambar, dan sumbu Y menunjukkan frekuensi dari nilai-nilai ini.

 fig, ax = plt.subplots(1, 1) ax.hist(text.ravel(), bins=32, range=[0, 256]) ax.set_xlim(0, 256); 



Contoh kami ternyata adalah gambar 8-bit, jadi kami memiliki 256 kemungkinan nilai di sepanjang sumbu X. Histogram menunjukkan bahwa ada konsentrasi piksel yang cukup cerah (0: hitam, 255: putih). Ini kemungkinan besar latar belakang teks kami yang cukup ringan, tetapi sisanya agak kabur. Histogram segmentasi yang ideal adalah bimodal sehingga kita dapat memilih angka tepat di tengah. Sekarang mari kita coba membuat beberapa gambar tersegmentasi berdasarkan nilai ambang batas yang sederhana.

Ambang batas terkontrol


Karena kita sendiri yang memilih nilai ambang, kami menyebutnya nilai ambang terkendali.

 text_segmented = text > (value concluded from histogram ie 50,70,120 ) image_show(text_segmented); 


Kiri: teks> 50 | Pertengahan: teks> 70 | Kanan: teks> 120

Kami tidak mendapatkan hasil yang sempurna, karena bayangan di sebelah kiri menimbulkan masalah. Mari kita coba dengan ambang batas tanpa pengawasan sekarang.

Ambang tak terkendali


Ambang tak terkendali Scikit-image memiliki sejumlah metode penentuan ambang otomatis yang tidak memerlukan input saat memilih ambang optimal. Berikut adalah beberapa metode: otsu, li, lokal.

 text_threshold = filters.threshold_ # Hit tab with the cursor after the underscore to get all the methods. image_show(text < text_threshold); 


Otsu kiri || Benar: li

Dalam kasus lokal, kita juga perlu menentukan block_size. Offset membantu menyesuaikan gambar untuk hasil yang lebih baik.

 text_threshold = filters.threshold_local(text,block_size=51, offset=10) image_show(text > text_threshold); 



Metode ini memberikan efek yang cukup bagus. Untuk sebagian besar, orang dapat menyingkirkan daerah yang bising.

Segmentasi dengan algoritma untuk model dengan guru


Thresholding adalah proses segmentasi yang sangat sederhana, dan itu tidak akan berfungsi dengan baik pada gambar kontras tinggi, yang membutuhkan alat yang lebih canggih.

Pada bagian ini, kita akan menggunakan contoh gambar yang tersedia secara bebas dan mencoba untuk membagi bagian kepala menggunakan metode dengan guru.

 # import the image from skimage import io image = io.imread('girl.jpg') plt.imshow(image); 



Sebelum melakukan segmentasi gambar apa pun, disarankan untuk menghilangkan noise dari sana menggunakan beberapa filter.

Namun, dalam kasus kami, gambar tidak memiliki noise yang signifikan, jadi kami akan menerimanya apa adanya. Langkah selanjutnya adalah mengubah gambar menjadi skala abu-abu menggunakan rgb2gray.

 image_gray = color.rgb2gray(image) image_show(image_gray); 



Kami akan menggunakan dua metode segmentasi yang bekerja pada prinsip yang sangat berbeda.

Segmentasi kontur aktif


Segmentasi jalur aktif juga disebut ular dan diinisialisasi menggunakan jalur yang ditentukan pengguna atau garis di sekitar wilayah yang diminati, dan kemudian jalur ini secara perlahan dikompresi dan ditarik atau ditolak oleh cahaya dan tepian.

Sebagai contoh gambar kita, mari gambarkan lingkaran di sekitar kepala manusia untuk menginisialisasi ular.

 def circle_points(resolution, center, radius): """ Generate points which define a circle on an image.Centre refers to the centre of the circle """ radians = np.linspace(0, 2*np.pi, resolution) c = center[1] + radius*np.cos(radians)#polar co-ordinates r = center[0] + radius*np.sin(radians) return np.array([c, r]).T # Exclude last point because a closed path should not have duplicate points points = circle_points(200, [80, 250], 80)[:-1] 

Perhitungan di atas menghitung koordinat x dan y dari titik-titik di pinggiran lingkaran. Karena kami memberikan resolusi 200, itu akan menghitung 200 poin tersebut.

 fig, ax = image_show(image) ax.plot(points[:, 0], points[:, 1], '--r', lw=3) 



Algoritme kemudian mengelompokkan wajah orang tersebut dari sisa gambar, menyesuaikan kurva tertutup ke tepi wajah.



Kami dapat mengkonfigurasi parameter yang disebut alpha dan beta. Nilai alpha yang lebih tinggi menyebabkan kurva berkontraksi lebih cepat, sementara beta membuat kurva lebih halus.

 snake = seg.active_contour(image_gray, points,alpha=0.06,beta=0.3) fig, ax = image_show(image) ax.plot(points[:, 0], points[:, 1], '--r', lw=3) ax.plot(snake[:, 0], snake[:, 1], '-b', lw=3); 



Segmentasi walker acak


Dalam metode ini, segmentasi dilakukan menggunakan pelabelan interaktif, yang disebut label. Dengan menggambar setiap piksel ke label yang probabilitas tertingginya dihitung, Anda bisa mendapatkan segmentasi gambar berkualitas tinggi. Rincian lebih lanjut tentang metode ini dapat ditemukan dalam pekerjaan ini .

Selanjutnya, kita akan kembali menggunakan nilai sebelumnya dari contoh kita. Kita bisa melakukan inisialisasi yang berbeda, tetapi untuk kesederhanaan mari kita berpegang pada prinsip lingkaran.

 image_labels = np.zeros(image_gray.shape, dtype=np.uint8) 

Algoritma Pass Acak menerima label sebagai input. Dengan demikian, kita akan memiliki lingkaran besar yang menutupi seluruh wajah orang tersebut, dan lingkaran kecil lainnya di dekat bagian tengah wajah.

 indices = draw.circle_perimeter(80, 250,20)#from here image_labels[indices] = 1 image_labels[points[:, 1].astype(np.int), points[:, 0].astype(np.int)] = 2 image_show(image_labels); 


Sekarang mari kita gunakan Random Walker dan lihat apa yang terjadi.

 image_segmented = seg.random_walker(image_gray, image_labels) # Check our results fig, ax = image_show(image_gray) ax.imshow(image_segmented == 1, alpha=0.3); 



Hasilnya bukan yang terbaik, ujung-ujung wajah tetap tidak terjangkau. Untuk memperbaiki situasi ini, kita dapat menyesuaikan parameter bagian sampai kita mendapatkan hasil yang diinginkan. Setelah beberapa upaya, kami menetapkan nilainya menjadi 3000, yang berfungsi cukup baik.

 image_segmented = seg.random_walker(image_gray, image_labels, beta = 3000) # Check our results fig, ax = image_show(image_gray) ax.imshow(image_segmented == 1, alpha=0.3); 



Ini semua untuk segmentasi dengan guru, di mana kami harus memberikan data input tertentu, serta mengkonfigurasi beberapa parameter. Namun, tidak selalu mungkin bagi seseorang untuk melihat gambar dan kemudian memutuskan kontribusi apa yang akan diberikan dan di mana untuk memulai. Untungnya, untuk situasi seperti itu, kami memiliki metode segmentasi yang tidak terkendali.

Segmentasi tanpa guru


Segmentasi tanpa guru tidak membutuhkan pengetahuan sebelumnya. Pertimbangkan gambar yang sangat besar sehingga tidak mungkin melihat semua piksel sekaligus. Jadi, dalam kasus seperti itu, segmentasi tanpa guru dapat membagi gambar menjadi beberapa subkawasan, jadi alih-alih jutaan piksel, Anda memiliki puluhan atau ratusan area. Mari kita lihat dua algoritma berikut:

Simple Linear Iterative Clustering


Metode ini (English Simple Linear Iterative Clustering atau SLIC) menggunakan algoritma pembelajaran mesin yang disebut K-Means. Dibutuhkan semua nilai piksel gambar dan mencoba membaginya menjadi jumlah subdomain tertentu. Baca karya ini untuk informasi terperinci.

SLIC bekerja dengan warna yang berbeda, jadi kami akan menggunakan gambar asli.

 image_slic = seg.slic(image,n_segments=155) 

Yang perlu kita lakukan hanyalah menetapkan nilai rata-rata untuk setiap segmen yang kita temukan, yang membuatnya lebih mirip gambar.

 # label2rgb replaces each discrete label with the average interior color image_show(color.label2rgb(image_slic, image, kind='avg')); 



Kami mengurangi gambar ini dari 512 * 512 = 262.000 piksel menjadi 155 segmen.

Felzenszwalb


Metode ini juga menggunakan algoritma pembelajaran mesin yang disebut pengelompokan pohon rentang minimum. Felzenszwaib tidak memberi tahu kami jumlah cluster yang tepat di mana gambar akan dibagi. Dia akan menghasilkan banyak cluster sesuai keinginannya.

 image_felzenszwalb = seg.felzenszwalb(image) image_show(image_felzenszwalb); 



Ada terlalu banyak daerah dalam gambar. Mari kita hitung jumlah segmen unik.

 np.unique(image_felzenszwalb).size 3368 

Sekarang mari kita warnai kembali menggunakan nilai rata-rata di atas segmen, seperti yang kita lakukan pada algoritma SLIC.

 image_felzenszwalb_colored = color.label2rgb(image_felzenszwalb, image, kind='avg') image_show(image_felzenszwalb_colored); 

Sekarang kami mendapatkan lebih sedikit segmen. Jika kami menginginkan segmen yang lebih sedikit lagi, kami dapat mengubah parameter skala. Pendekatan ini kadang-kadang disebut segmentasi berlebihan.



Ini lebih seperti gambar posterized, yang pada dasarnya hanya pengurangan jumlah warna. Untuk menggabungkannya lagi (RAG).

Kesimpulan


Segmentasi gambar adalah langkah yang sangat penting dalam pemrosesan gambar. Ini adalah area penelitian aktif dengan beragam aplikasi, mulai dari visi komputer hingga gambar medis, lalu lintas, dan pengawasan video. Python menyediakan pustaka gambar scikit-kuat dengan sejumlah besar algoritma pemrosesan gambar. Ini tersedia secara gratis dan tanpa batasan, yang didukung oleh komunitas yang aktif. Saya sarankan Anda membaca dokumentasinya. Artikel asli dapat ditemukan di sini .

Source: https://habr.com/ru/post/id441006/


All Articles