Pemrosesan Gambar OpenCV

Pemrosesan Gambar Opencv



Kami akan mempelajari metode pemrosesan gambar dalam artikel ini. Kami akan memeriksa beberapa topik mendasar namun penting dalam visi komputer dan pembelajaran mesin. Teknik pemrosesan gambar mendasar ini dapat memecahkan masalah yang kompleks, seperti kumpulan data. Akibatnya, ada enam langkah mendasar dalam pemrosesan gambar, yang tercantum di bawah ini:
  1. Terjemahan Gambar
  2. Rotasi Gambar
  3. Aritmatika Gambar
  4. Membalik Gambar
  5. Pemotongan Gambar
  6. Mengubah Ukuran Gambar

Sekarang, kami akan menjelaskan semua topik pemrosesan gambar yang disebutkan di atas secara detail.

1. Terjemahan Gambar

Penerjemahan citra adalah metode pemrosesan citra yang membantu kita memindahkan citra sepanjang sumbu x dan y. Kita dapat memindahkan gambar ke atas, bawah, kanan, kiri, atau kombinasi apapun.







Kita dapat mendefinisikan Matriks Terjemahan dengan simbol M, dan kita dapat merepresentasikannya dalam bentuk matematis, seperti yang ditunjukkan di bawah ini:





Kita dapat memahami konsep gambar terjemahan melalui program ini.





kode python: Kami akan menyimpan nama program berikut sebagai translate.py .

# impor paket yang diperlukan

impor numpy sebagai misalnya

impor argparse

impor imutil

impor cv2

# kami menerapkan parser argumen

ap_obj = argparse. ArgumentParser ( )

ap_obj. add_argument ( '-k' , '--gambar' , yg dibutuhkan = BENAR ,

Tolong = 'lokasi file gambar' )

argumen = yang ( ap_obj. parse_args ( ) )

# muat gambar dan tampilkan di layar

gambar = cv2. imread ( argumen [ 'gambar' ] )

cv2. imshow ( 'Gambar asli' , gambar )

# Penerjemahan gambar adalah matriks NumPy yang diberikan di bawah ini:

# [[1, 0, shiftX], [0, 1, shiftY]]

# Kami akan menggunakan matriks NumPy di ​​atas untuk menggeser gambar di sepanjang

# arah sumbu x dan sumbu y. Untuk ini, kita hanya perlu meneruskan nilai piksel.

# Dalam program ini, kami akan memindahkan gambar 30 piksel ke kanan

# dan 70 piksel ke arah bawah.

translation_mat = misalnya float32 ( [ [ 1 , 0 , 30 ] , [ 0 , 1 , 70 ] ] )

image_translation = cv2. warpAffine ( gambar , translation_mat ,

( gambar. membentuk [ 1 ] , gambar. membentuk [ 0 ] ) )

cv2. imshow ( 'Terjemahan gambar Bawah dan Kanan' , image_translation )

# sekarang, kita akan menggunakan matriks NumPy di ​​atas untuk menggeser gambar di sepanjang

# arah sumbu x (kiri) dan sumbu y (atas).

# Di sini, kita akan memindahkan gambar 50 piksel ke kiri

# dan 90 piksel ke arah atas.

translation_mat = misalnya float32 ( [ [ 1 , 0 , - lima puluh ] , [ 0 , 1 , - 90 ] ] )

image_translation = cv2. warpAffine ( gambar , translation_mat ,

( gambar. membentuk [ 1 ] , gambar. membentuk [ 0 ] ) )

cv2. imshow ( 'Terjemahan gambar Atas dan Kiri' , image_translation )

cv2. waitKey ( 0 )

Baris 1 sampai 5: Kami mengimpor semua paket yang diperlukan untuk program ini, seperti OpenCV, argparser, dan NumPy. Mohon dicatat bahwa ada perpustakaan lain yang imutils. Ini bukan paket OpenCV. Ini hanyalah perpustakaan yang akan dengan mudah menampilkan pemrosesan gambar yang sama.



Library imutils tidak akan disertakan secara otomatis saat kita menginstal OpenCV. Jadi untuk menginstal imutils, kita harus menggunakan cara berikut:

pip install imutils

Baris 8 sampai 15: Kami membuat agrparser kami dan memuat gambar kami.

Baris 24 sampai 25: Bagian program ini adalah tempat terjadinya terjemahan. Matriks terjemahan memberi tahu kita berapa piksel gambar akan dipindahkan ke atas atau ke bawah atau ke kiri atau ke kanan. Karena OpenCV mensyaratkan bahwa nilai matriks berada dalam array floating point, matriks terjemahan mengambil nilai dalam array floating point.

Baris pertama matriks terjemahan terlihat seperti ini:

Baris matriks ini adalah untuk sumbu x. Nilai t x akan memutuskan apakah gambar akan digeser ke sisi kiri atau kanan. Jika kita melewati nilai negatif, maka artinya bayangan akan bergeser ke kiri, dan jika nilainya positif, artinya bayangan akan bergeser ke kanan.

Kami sekarang akan mendefinisikan baris kedua dari matriks sebagai berikut:

Baris matriks ini adalah untuk sumbu y. Nilai t Y akan memutuskan apakah gambar akan digeser ke atas atau ke bawah. Jika kita melewati nilai negatif, maka artinya citra akan bergeser ke atas, dan jika nilainya positif, maka artinya citra akan bergeser ke bawah.

Pada program sebelumnya pada baris 24, kita mendefinisikan t x = 30 dan t Y = 70. Jadi kita memindahkan gambar 30 piksel ke sisi kanan dan 70 piksel ke bawah.

Tetapi proses penerjemahan citra utama terjadi pada baris 25, di mana kita mendefinisikan matriks translasi cv2.warpAffine . Dalam fungsi ini, kita melewatkan tiga parameter: parameter pertama adalah citra, parameter kedua adalah matriks translasi, dan parameter ketiga adalah dimensi citra.

Baris 27: Baris 27 akan menampilkan hasilnya di output.

Sekarang, kami akan mengimplementasikan matriks terjemahan lain untuk kiri dan atas. Untuk ini, kita harus mendefinisikan nilai dalam negatif.

Baris 33 sampai 34: Pada program sebelumnya pada baris 33, kita mendefinisikan t x = -50 dan t Y = -90. Jadi kami memindahkan gambar 50 piksel ke sisi kiri dan 90 piksel ke atas. Tetapi proses penerjemahan citra utama terjadi pada baris 34, di mana kita mendefinisikan matriks translasi cv2.warpAffine .

Baris 36 : Baris 36 akan menampilkan hasil seperti yang ditunjukkan pada output.

Untuk menjalankan kode sebelumnya, kita harus memberikan jalur gambar seperti yang diberikan di bawah ini.

Keluaran: python translate.py –gambar tupai.jpg

Sekarang, kami akan mengimplementasikan program terjemahan gambar yang sama menggunakan imutil Perpustakaan. Library ini sangat mudah digunakan untuk image processing. Di perpustakaan ini, kita tidak perlu memikirkan tentang cv2.warpAffine karena perpustakaan ini akan mengurus ini. Jadi mari terapkan program terjemahan gambar ini menggunakan perpustakaan imutils.

kode python: Kami akan menyimpan nama program berikut sebagai translate_imutils.py .

# impor paket yang diperlukan

impor numpy sebagai misalnya

impor argparse

impor imutil

impor cv2

# Fungsi ini mengimplementasikan terjemahan gambar dan

# mengembalikan gambar yang diterjemahkan ke fungsi panggilan.

def menerjemahkan ( gambar , x , Y ) :

translation_matrix = misalnya float32 ( [ [ 1 , 0 , x ] , [ 0 , 1 , Y ] ] )

image_translation = cv2. warpAffine ( gambar , translation_matrix ,

( gambar. membentuk [ 1 ] , gambar. membentuk [ 0 ] ) )

kembali image_translation

# buat parser argumen dan parsing argumen

ap = argparse. ArgumentParser ( )

ap. add_argument ( '-saya' , '--gambar' , yg dibutuhkan = BENAR , Tolong = 'Jalan ke gambar' )

argumen = yang ( ap. parse_args ( ) )

# muat gambar dan tampilkan di layar

gambar = cv2. imread ( argumen [ 'gambar' ] )

cv2. imshow ( 'Gambar asli' , gambar )

image_translation = imutil. menerjemahkan ( gambar , 10 , 70 )

cv2. imshow ( 'Terjemahan gambar ke kanan dan ke bawah' ,

image_translation )

cv2. waitKey ( 0 )

Baris 9 sampai 13: Bagian program ini adalah tempat terjadinya terjemahan. Matriks terjemahan memberi tahu kita berapa banyak piksel gambar akan dipindahkan ke atas atau ke bawah atau ke kiri atau ke kanan.

Baris-baris ini telah dijelaskan, tetapi sekarang kita akan membangun sebuah fungsi bernama translate() dan mengirim tiga parameter berbeda ke dalamnya. Gambar itu sendiri berfungsi sebagai parameter pertama. Nilai x, dan y matriks terjemahan sesuai dengan parameter kedua dan ketiga.

Catatan : Tidak perlu mendefinisikan fungsi translate ini di dalam program karena sudah termasuk dalam paket library imutils. Saya telah menggunakannya dalam program demi penjelasan langsung. Kita bisa memanggil fungsi ini langsung dengan imutils, seperti yang ditunjukkan pada baris 24.

Baris 24: Program sebelumnya akan menunjukkan bahwa pada baris 24, kita mendefinisikan tx = 10 dan ty = 70. Jadi kita memindahkan gambar 10 piksel ke sisi kanan dan 70 piksel ke bawah.

Dalam program ini, kami tidak mempedulikan fungsi cv2.warpAffine apa pun karena sudah ada di dalam paket pustaka imutils.

Untuk menjalankan kode sebelumnya, kita harus memberikan path gambar, seperti yang diberikan di bawah ini:

Keluaran:

python imutil. py --gambar tupai. jpg

2. Rotasi Gambar

Kami membahas cara menerjemahkan (yaitu, menggeser) gambar ke atas, bawah, kiri, dan kanan di pelajaran sebelumnya (atau kombinasi apa pun). Selanjutnya, kita akan membahas rotasi yang berkaitan dengan pemrosesan gambar.

Gambar diputar oleh sudut, theta, dalam proses yang dikenal sebagai rotasi. Sudut dimana kita memutar gambar akan diwakili oleh theta. Selain itu, saya selanjutnya akan menyediakan fungsi kenyamanan putar untuk membuat gambar berputar lebih mudah.

Mirip dengan translasi, dan mungkin tidak mengherankan, rotasi dengan sudut, theta ditentukan dengan membuat matriks M dalam format berikut:

Matriks ini dapat memutar vektor derajat theta (berlawanan arah jarum jam) di sekitar titik asal yang diberikan (x, y)-bidang Cartesian. Biasanya, dalam skenario ini, titik asal akan menjadi pusat gambar, tetapi pada kenyataannya, kita dapat menetapkan sembarang titik (x, y) acak sebagai pusat rotasi kita.

Gambar R yang diputar kemudian dibuat dari gambar asli I menggunakan perkalian matriks langsung: R = IM

OpenCV, di sisi lain, juga menawarkan kapasitas untuk (1) menskalakan (yaitu, mengubah ukuran) gambar dan (2) menawarkan pusat rotasi acak untuk melakukan rotasi.

Matriks rotasi kami yang dimodifikasi M ditunjukkan di bawah ini:

Mari kita mulai dengan membuka dan membuat file baru bernama rotate.py :

# mengimpor paket yang diperlukan

impor numpy sebagai misalnya

impor argparse

impor imutil

impor cv2

# membuat objek argumentparser dan parsing argumen

apobj = argparse. ArgumentParser ( )

apobj. add_argument ( '-k' , '--gambar' , yg dibutuhkan = BENAR , Tolong = 'jalur gambar' )

argumen = yang ( apobj. parse_args ( ) )

gambar = cv2. imread ( argumen [ 'gambar' ] )

cv2. imshow ( 'Gambar asli' , gambar )

# Hitung pusat gambar menggunakan dimensi gambar.

( tinggi , lebar ) = gambar. membentuk [ : 2 ]

( pusatX , pusatY ) = ( lebar / 2 , tinggi / 2 )

# Sekarang, dengan menggunakan cv2, kita akan memutar gambar sebesar 55 derajat ke

# menentukan matriks rotasi menggunakan getRotationMatrix2D()

rotationMatrix = cv2. getRotationMatrix2D ( ( pusatX , pusatY ) , 55 , 1.0 )

RotatedImage = cv2. warpAffine ( gambar , rotationMatrix , ( lebar , tinggi ) )

cv2. imshow ( 'Memutar gambar sebesar 55 Derajat' , RotatedImage )

cv2. waitKey ( 0 )

# Gambar sekarang akan diputar -85 derajat.

rotationMatrix = cv2. getRotationMatrix2D ( ( pusatX , pusatY ) , - 85 , 1.0 )

RotatedImage = cv2. warpAffine ( gambar , rotationMatrix , ( lebar , tinggi ) )

cv2. imshow ( 'Memutar gambar sebesar -85 Derajat' , RotatedImage )

cv2. waitKey ( 0 )

Baris 1 sampai 5: Kami mengimpor semua paket yang diperlukan untuk program ini, seperti OpenCV, argparser, dan NumPy. Mohon dicatat bahwa ada perpustakaan lain yang imutils. Ini bukan paket OpenCV. Ini hanyalah pustaka yang akan digunakan untuk menampilkan pemrosesan gambar yang sama dengan mudah.

Library imutils tidak akan disertakan secara otomatis saat kita menginstal OpenCV. OpenCV menginstal imutils. Kita harus menggunakan cara berikut:

pip install imutils

Baris 8 sampai 14: Kami membuat agrparser kami dan memuat gambar kami. Dalam argparser ini, kami hanya menggunakan satu argumen gambar, yang akan memberi tahu kami jalur gambar yang akan kami gunakan dalam program ini untuk mendemonstrasikan rotasi.

Saat memutar gambar, kita harus menentukan titik pivot rotasi. Sebagian besar waktu, Anda ingin memutar gambar tentang pusatnya, tetapi OpenCV memungkinkan Anda memilih titik acak sebagai gantinya. Mari kita putar saja gambar di sekitar pusatnya.

Baris 17 sampai 18 ambil masing-masing lebar dan tinggi gambar, lalu bagi setiap dimensi dengan dua untuk menetapkan pusat gambar.

Kami membuat matriks untuk memutar gambar dengan cara yang sama seperti kami mendefinisikan matriks untuk menerjemahkan gambar. Kami hanya akan menelepon cv2.getRotationMatrix2D berfungsi pada Baris 22 daripada membuat matriks secara manual menggunakan NumPy (yang mungkin sedikit rumit).

Itu cv2.getRotationMatrix2D fungsi membutuhkan tiga parameter. Masukan pertama adalah sudut rotasi yang diinginkan (dalam hal ini, bagian tengah gambar). Theta kemudian digunakan untuk menentukan berapa derajat (berlawanan arah jarum jam) kita akan memutar gambar. Di sini, kami akan memutar gambar 45 derajat. Opsi terakhir terkait dengan ukuran gambar.

Terlepas dari fakta bahwa kita belum membahas penskalaan gambar, Anda dapat memberikan angka titik-mengambang di sini dengan 1,0 yang menunjukkan bahwa gambar harus digunakan dalam proporsi aslinya. Namun, jika Anda mengetikkan nilai 2.0, ukuran gambar akan berlipat ganda. Sejumlah 0,5 mengurangi ukuran gambar seperti itu.

Baris 22 sampai 23: Setelah menerima matriks rotasi kami M dari cv2.getRotationMatrix2D fungsi, kami memutar gambar kami menggunakan cv2.warpAffine teknik pada Baris 23. Masukan fungsi pertama adalah gambar yang ingin kita putar. Lebar dan tinggi gambar keluaran kami kemudian ditentukan, bersama dengan matriks rotasi kami M. Pada baris 23, gambar tersebut kemudian diputar 55 derajat.

Anda dapat melihat bahwa gambar kami telah diputar.

Baris 28 sampai 30 merupakan rotasi kedua. Baris 22–23 kode identik, kecuali kali ini kita memutar -85 derajat, bukan 55.

Kami hanya memutar gambar di sekitar pusatnya hingga titik ini. Bagaimana jika kita ingin memutar gambar di sekitar titik acak?

Mari kita mulai dengan membuka dan membuat file baru bernama putar.py:

# mengimpor paket yang diperlukan

impor numpy sebagai misalnya

impor argparse

impor imutil

impor cv2

# membuat objek argumentparser dan parsing argumen

ap_obj = argparse. ArgumentParser ( )

ap_obj. add_argument ( '-k' , '--gambar' , yg dibutuhkan = BENAR , Tolong = 'jalur gambar' )

argumen = yang ( ap_obj. parse_args ( ) )

# muat gambar dan tampilkan di layar

gambar = cv2. imread ( argumen [ 'gambar' ] )

cv2. imshow ( 'Gambar asli' , gambar )

# Hitung pusat gambar menggunakan dimensi gambar.

( tinggi , lebar ) = gambar. membentuk [ : 2 ]

( pusatX , pusatY ) = ( lebar / 2 , tinggi / 2 )

# Sekarang, dengan menggunakan cv2, kita akan memutar gambar sebesar 55 derajat ke

# menentukan matriks rotasi menggunakan getRotationMatrix2D()

rotationMatrix = cv2. getRotationMatrix2D ( ( pusatX , pusatY ) , 55 , 1.0 )

RotatedImage = cv2. warpAffine ( gambar , rotationMatrix , ( lebar , tinggi ) )

cv2. imshow ( 'Memutar gambar sebesar 55 Derajat' , RotatedImage )

cv2. waitKey ( 0 )

# Gambar sekarang akan diputar -85 derajat.

rotationMatrix = cv2. getRotationMatrix2D ( ( pusatX , pusatY ) , - 85 , 1.0 )

RotatedImage = cv2. warpAffine ( gambar , rotationMatrix , ( lebar , tinggi ) )

cv2. imshow ( 'Memutar gambar sebesar -85 Derajat' , RotatedImage )

cv2. waitKey ( 0 )

# Rotasi gambar dari beberapa titik sembarang, bukan dari tengah

rotationMatrix = cv2. getRotationMatrix2D ( ( pusatX - 40 , pusatY - 40 ) , 55 , 1.0 )

RotatedImage = cv2. warpAffine ( gambar , rotationMatrix , ( lebar , tinggi ) )

cv2. imshow ( 'Rotasi gambar dari sembarang titik' , RotatedImage )

cv2. waitKey ( 0 )

Baris 34 sampai 35: Sekarang, kode ini tampaknya cukup umum untuk memutar objek. Untuk memutar gambar di sekitar titik 40 piksel ke kiri dan 40 piksel di atas pusatnya, kami menginstruksikan cv2.getRotationMatrix2D berfungsi untuk memperhatikan parameter pertamanya.

Gambar yang dihasilkan saat kami menerapkan rotasi ini ditunjukkan di bawah ini:

Kita dapat dengan jelas melihat pusat rotasi sekarang menjadi koordinat (x, y), yaitu 40 piksel ke kiri dan 40 piksel di atas pusat gambar yang dihitung.

3. Gambar Aritmatika

Faktanya, aritmatika gambar hanyalah penambahan matriks dengan beberapa batasan tambahan pada tipe data yang akan kita bahas nanti.

Mari luangkan waktu sejenak untuk membahas beberapa dasar aljabar linier yang cantik.

Pertimbangkan menggabungkan dua matriks berikutnya:

Hasil apa yang akan dihasilkan oleh penambahan matriks? Jawaban sederhananya adalah jumlah entri matriks, elemen demi elemen:

Cukup sederhana, bukan?

Kita semua memahami operasi dasar penjumlahan dan pengurangan saat ini. Namun, kita harus memperhatikan batasan yang diberlakukan oleh ruang warna dan tipe data kita saat bekerja dengan gambar.

Piksel dalam gambar RGB, misalnya, berada di antara [0, 255]. Apa yang terjadi jika kita mencoba menambahkan 10 ke piksel dengan intensitas 250 sambil melihatnya?

Kami akan sampai pada nilai 260 jika kami menerapkan prinsip aritmatika standar. 260 bukan nilai yang valid, karena gambar RGB direpresentasikan sebagai bilangan bulat 8-bit yang tidak ditandatangani.

Jadi apa yang seharusnya terjadi? Haruskah kita menjalankan pemeriksaan untuk memastikan tidak ada piksel yang berada di luar rentang [0, 255], memotong setiap piksel agar memiliki nilai antara 0 dan 255?

Atau apakah kita 'membungkus' dan melakukan operasi modulus? Sesuai dengan aturan modulus, menambahkan 10 ke 255 hanya akan menghasilkan nilai 9.

Bagaimana seharusnya penambahan dan pengurangan gambar di luar rentang [0, 255] ditangani?

Sebenarnya tidak ada teknik yang benar atau salah; itu semua tergantung pada bagaimana Anda bekerja dengan piksel Anda dan apa yang ingin Anda capai.

Tapi ingat bahwa ada perbedaan antara penambahan di OpenCV dan penambahan di NumPy. Modulus aritmetika dan 'wrap around' akan dilakukan oleh NumPy. Sebaliknya, OpenCV akan mengeksekusi pemotongan dan memastikan bahwa nilai piksel tidak pernah meninggalkan rentang [0, 255].

Mari kita mulai dengan membuat file baru bernama aritmatika.py dan membukanya:

# python arithmetic.py --image tupai.jpg

# mengimpor paket yang diperlukan

impor numpy sebagai misalnya

impor argparse

impor imutil

impor cv2

# membuat objek argumentparser dan parsing argumen

apObj = argparse. ArgumentParser ( )

apObj. add_argument ( '-k' , '--gambar' , yg dibutuhkan = BENAR , Tolong = 'jalur gambar' )

argumen = yang ( apObj. parse_args ( ) )

gambar = cv2. imread ( argumen [ 'gambar' ] )

cv2. imshow ( 'Gambar asli' , gambar )

'''

Nilai piksel kita akan berada dalam rentang [0, 255]

karena gambar adalah array NumPy, yang disimpan sebagai bilangan bulat 8-bit yang tidak ditandatangani.

Saat menggunakan fungsi seperti cv2.add dan cv2.subtract, nilai akan dipotong

ke kisaran ini bahkan jika mereka ditambahkan atau dikurangi dari luar

[0, 255] jangkauan. Berikut ilustrasinya:

'''


mencetak ( 'maksimal 255: {}' . format ( str ( cv2. menambahkan ( misalnya uint8 ( [ 201 ] ) ,

misalnya uint8 ( [ 100 ] ) ) ) ) )

mencetak ( 'minimal 0: {}' . format ( str ( cv2. mengurangi ( misalnya uint8 ( [ 60 ] ) ,

misalnya uint8 ( [ 100 ] ) ) ) ) )

'''

Saat melakukan operasi aritmatika dengan array ini menggunakan NumPy,

nilainya akan membungkus alih-alih dipotong ke

[0, 255]rentang. Saat menggunakan gambar, sangat penting untuk menyimpannya

dalam pikiran.

'''


mencetak ( 'membungkus: {}' . format ( str ( misalnya uint8 ( [ 201 ] ) + mis. uint8 ( [ 100 ] ) ) ) )

mencetak ( 'membungkus: {}' . format ( str ( misalnya uint8 ( [ 60 ] ) - mis. uint8 ( [ 100 ] ) ) ) )

'''

Mari kalikan kecerahan setiap piksel pada gambar kita dengan 101.

Untuk melakukan ini, kami membuat larik NumPy dengan ukuran yang sama dengan matriks kami,

diisi dengan satu, dan kalikan dengan 101 untuk menghasilkan larik yang terisi

dengan 101s. Akhirnya, kami menggabungkan dua gambar.

Anda akan melihat bahwa gambar sekarang 'lebih cerah'.

'''


Matriks = misalnya satu ( gambar. membentuk , dtype = 'uint8' ) * 101

gambar_ditambahkan = cv2. menambahkan ( gambar , Matriks )

cv2. imshow ( 'Hasil Gambar Ditambahkan' , gambar_ditambahkan )

#Dengan cara yang sama, kami dapat membuat gambar kami lebih gelap dengan mengambil

# 60 dari semua piksel.

Matriks = misalnya satu ( gambar. membentuk , dtype = 'uint8' ) * 60

gambar_dikurangi = cv2. mengurangi ( gambar , Matriks )

cv2. imshow ( 'Hasil Gambar yang Dikurangi' , gambar_dikurangi )

cv2. waitKey ( 0 )

Baris 1 sampai 16 akan digunakan untuk menjalankan proses normal kita, yang memerlukan pengimporan paket kita, mengonfigurasi parser argumen kita, dan memuat gambar kita.

Ingat bagaimana saya sebelumnya membahas perbedaan antara penambahan OpenCV dan NumPy? Sekarang setelah kita membahasnya secara menyeluruh, mari kita lihat kasus tertentu untuk memastikan kita memahaminya.

Dua array NumPy integer 8-bit unsigned didefinisikan pada baris 26 . Nilai 201 adalah satu-satunya elemen dalam larik pertama. Meskipun hanya satu anggota dalam larik kedua, ia memiliki nilai 100. Nilai tersebut kemudian ditambahkan menggunakan fungsi cv2.add OpenCV.

Apa yang Anda antisipasi hasilnya?

Sesuai dengan prinsip aritmatika konvensional, jawabannya harus 301. Tetapi ingat bahwa kita berurusan dengan bilangan bulat tak bertanda 8-bit, yang hanya dapat berada dalam kisaran [0, 255]. Karena kita menggunakan metode cv2.add, OpenCV menangani kliping dan memastikan penambahan hanya mengembalikan hasil maksimal 255.

Baris pertama dari daftar di bawah ini menunjukkan hasil menjalankan kode ini:

hitung. py

maksimal 255 : [ [ 255 ] ]

Jumlah itu memang menghasilkan angka 255.

Setelah itu, baris 26 menggunakan cv2.subtract untuk melakukan pengurangan. Sekali lagi, kita mendefinisikan dua array NumPy integer 8-bit unsigned dengan satu elemen di masing-masingnya. Array pertama bernilai 60, sedangkan array kedua bernilai 100.

Aritmatika kita menyatakan bahwa pengurangan harus menghasilkan nilai -40, tetapi OpenCV menangani pemotongan untuk kita sekali lagi. Kami menemukan bahwa nilainya telah dipangkas menjadi 0. Hasil kami di bawah ini menunjukkan hal ini:

hitung. py

minimal 0 : [ [ 0 ] ]

Menggunakan cv2, kurangi 100 dari 60 kurangi, menghasilkan nilai 0.

Tapi apa yang terjadi jika kita menggunakan NumPy sebagai pengganti OpenCV untuk melakukan perhitungan?

Baris 38 dan 39 mengatasi masalah ini.

Pertama, dua array NumPy integer 8-bit unsigned dengan elemen tunggal masing-masing didefinisikan. Nilai larik pertama adalah 201, sedangkan nilai larik kedua adalah 100. Penjumlahan kita akan dipangkas, dan nilai 255 akan dikembalikan jika kita menggunakan fungsi cv2.add.

NumPy, di sisi lain, 'membungkus' dan melakukan aritmatika modulo daripada memotong. NumPy berputar ke nol setelah nilai 255 tercapai dan kemudian melanjutkan penghitungan hingga 100 langkah tercapai. Ini dikonfirmasi oleh baris keluaran pertama, yang ditunjukkan di bawah ini:

hitung. py
membungkus: [ Empat.Lima ]

Kemudian, dua array NumPy lagi ditentukan, satu dengan nilai 50 dan yang lainnya dengan 100. Pengurangan ini akan dipangkas dengan metode cv2.subtract untuk mengembalikan hasil 0. Namun kami menyadari bahwa alih-alih memotong, NumPy mengeksekusi modulo aritmatika. Sebagai gantinya, prosedur modulo berputar dan mulai menghitung mundur dari 255 setelah 0 tercapai selama pengurangan. Hal ini dapat kita lihat dari output berikut:

hitung. py

membungkus: [ 207 ]

Sekali lagi, keluaran terminal kami menunjukkan perbedaan antara kliping dan pembungkusan:

Sangat penting untuk mengingat hasil yang Anda inginkan saat melakukan aritmatika bilangan bulat. Apakah Anda ingin nilai apa pun di luar rentang [0, 255] dipotong? Gunakan teknik aritmatika gambar bawaan OpenCV setelah itu.

Apakah Anda ingin nilai dibungkus jika berada di luar kisaran [0, 255] dan operasi aritmatika modulus? Array NumPy kemudian ditambahkan dan dikurangi seperti biasa.

Baris 48 mendefinisikan array NumPy satu dimensi dengan dimensi yang sama dengan gambar kita. Sekali lagi, kami memastikan bahwa tipe data kami adalah bilangan bulat tak bertanda 8-bit. Kita hanya mengalikan matriks dengan nilai satu digit dengan 101 untuk mengisinya dengan nilai 101, bukan 1. Terakhir, kita menggunakan fungsi cv2.add untuk menambahkan matriks 100 ke gambar asli. Ini meningkatkan intensitas setiap piksel sebesar 101 sambil juga memastikan bahwa setiap nilai yang berusaha melebihi 255 dipotong ke kisaran [0, 255].

Amati bagaimana gambar terlihat lebih cerah dan tampak lebih 'pudar' daripada aslinya. Ini karena kami mendorong piksel menuju warna yang lebih cerah dengan menaikkan intensitas pikselnya sebesar 101.

Untuk mengurangi 60 dari setiap intensitas piksel gambar, pertama-tama kita membuat larik NumPy kedua pada Baris 54 yang diisi dengan 60-an.

Hasil pengurangan ini digambarkan dalam gambar berikut:

Benda-benda di sekitar kita tampak jauh lebih gelap daripada sebelumnya. Ini karena dengan mengurangkan 60 dari setiap piksel, kami memindahkan piksel dalam ruang warna RGB ke wilayah yang lebih gelap.

4. Pembalikan Gambar

Mirip dengan rotasi, membalik gambar melintasi sumbu x atau y adalah opsi lain yang ditawarkan oleh OpenCV. Bahkan jika operasi flipping tidak sering digunakan, mengetahuinya sangat bermanfaat karena berbagai alasan yang mungkin tidak langsung Anda lihat.

Kami sedang mengembangkan pengklasifikasi pembelajaran mesin untuk perusahaan rintisan kecil yang berupaya mengidentifikasi wajah dalam gambar. Agar sistem kami 'mempelajari' apa itu wajah, kami memerlukan semacam kumpulan data dengan sampel wajah. Sayangnya, perusahaan hanya memberi kami kumpulan data kecil berisi 40 wajah, dan kami tidak dapat mengumpulkan lebih banyak informasi.

Lalu, apa yang kita lakukan?

Karena wajah tetap merupakan wajah baik dicerminkan atau tidak, kami dapat membalik setiap gambar wajah secara horizontal dan menggunakan versi cermin sebagai data pelatihan tambahan.

Contoh ini mungkin tampak bodoh dan dibuat-buat, tetapi sebenarnya tidak. Membalik adalah strategi yang sengaja digunakan oleh algoritme pembelajaran mendalam yang kuat untuk menghasilkan lebih banyak data selama fase pelatihan.

Jelas dari sebelumnya bahwa metode pemrosesan gambar yang Anda pelajari dalam modul ini berfungsi sebagai dasar untuk sistem visi komputer yang lebih besar.

Tujuan:

Menggunakan cv2.flip fungsi, Anda akan belajar cara membalik gambar baik secara horizontal maupun vertikal di sesi ini.

Membalik adalah manipulasi gambar berikutnya yang akan kita pelajari. Sumbu x dan y gambar dapat dibalik atau bahkan keduanya. Sebelum kita masuk ke koding, sebaiknya lihat dulu hasil flip gambar. Lihat gambar yang telah dibalik secara horizontal pada gambar berikut:


Perhatikan bagaimana gambar asli kita berada di sebelah kiri dan bagaimana gambar tersebut dicerminkan secara horizontal di sebelah kanan.

Mari kita mulai dengan membuat file baru bernama membalik.py .

Anda telah melihat contoh pembalikan gambar, jadi mari kita periksa kodenya:

# python flipping.py --image quirrel.jpg

# mengimpor paket yang diperlukan

impor argparse

impor cv2

# membuat objek pengurai argumen dan mengurai argumen

apObj = argparse. ArgumentParser ( )

apObj. add_argument ( '-saya' , '--gambar' , yg dibutuhkan = BENAR , Tolong = 'jalur gambar' )

argumen = yang ( apObj. parse_args ( ) )

gambar = cv2. imread ( argumen [ 'gambar' ] )

cv2. imshow ( 'Asli' , gambar )

# membalik gambar secara horizontal

imageflipped = cv2. Balik ( gambar , 1 )

cv2. imshow ( 'Membalik Gambar Secara Horizontal' , imageflipped )

# membalik gambar secara vertikal

imageflipped = cv2. Balik ( gambar , 0 )

cv2. imshow ( 'Membalik Gambar Secara Vertikal' , imageflipped )

# gambar membalik di sepanjang kedua sumbu

imageflipped = cv2. Balik ( gambar , - 1 )

cv2. imshow ( 'Dibalik Secara Horizontal & Vertikal' , imageflipped )

cv2. waitKey ( 0 )

Langkah-langkah yang kami ambil untuk mengimpor paket kami, mengurai input kami, dan memuat gambar kami dari disk ditangani di l dari 1 sampai 12 .

Dengan mengaktifkan fungsi cv2.flip Baris 15 , mudah untuk membalikkan gambar secara horizontal. Gambar yang ingin kita balik dan kode atau bendera tertentu yang menentukan cara membalik gambar adalah dua argumen yang diperlukan untuk metode cv2.flip.

Nilai kode balik 1 berarti kita akan memutar gambar di sekitar sumbu y untuk membalikkannya secara horizontal ( Baris 15 ). Jika kita menentukan flip code 0, kita ingin memutar gambar terhadap sumbu x ( Baris 19 ). Kode balik negatif ( Baris 23 ) memutar gambar pada kedua sumbu.

Salah satu contoh termudah dalam subjek ini adalah membalikkan gambar, yang merupakan dasar.

Selanjutnya, kita akan membahas memotong gambar dan menggunakan potongan array NumPy untuk mengekstrak bagian gambar tertentu.

5. Pemotongan Gambar

Cropping, sesuai dengan namanya, adalah proses pemilihan dan penghapusan Region of Interest (atau ROI sederhananya) yang merupakan area gambar yang kita minati.

Wajah harus dipotong dari gambar untuk aplikasi deteksi wajah. Selain itu, jika kami membuat skrip Python untuk menemukan anjing dalam gambar, kami mungkin ingin memotong anjing dari gambar saat kami menemukannya.

Sasaran: Tujuan utama kami adalah menjadi terbiasa dan nyaman menggunakan pengirisan array NumPy untuk memotong area dari gambar.

Memangkas : Saat kami memangkas gambar, tujuan kami adalah menghilangkan elemen eksterior yang tidak menarik bagi kami. Proses memilih ROI kami sering disebut sebagai memilih wilayah yang kami minati.

Buat file baru bernama tanaman.py , buka, dan tambahkan kode berikut:

# python potong.py

# mengimpor paket yang diperlukan

impor cv2

# memuat dan menampilkan gambar di layar

gambar = cv2. imread ( 'tupai.jpg' )

mencetak ( gambar. membentuk )

cv2. imshow ( 'Asli' , gambar )

# Irisan array NumPy digunakan untuk memangkas gambar dengan cepat

# kita akan memotong wajah tupai dari gambar

muka tupai = gambar [ 35 : 90 , 35 : 100 ]

cv2. imshow ( 'wajah tupai' , muka tupai )

cv2. waitKey ( 0 )

# Dan sekarang, di sini kita akan memotong seluruh tubuh

# dari tupai

tubuh tupai = gambar [ 35 : 148 , 23 : 143 ]

cv2. imshow ( 'Badan Tupai' , tubuh tupai )

cv2. waitKey ( 0 )

Kami akan menunjukkan pemotongan dengan Python dan OpenCV menggunakan gambar yang kami muat dari disk Baris 5 dan 6 .

Gambar asli yang akan kita potong

Hanya dengan menggunakan teknik pemotongan dasar, kami bertujuan untuk memisahkan wajah tupai dan tubuh tupai dari area sekitarnya.

Kami akan menggunakan pengetahuan kami sebelumnya tentang gambar dan secara manual menyediakan irisan array NumPy di ​​mana tubuh dan wajah berada. Dalam kondisi normal, kami biasanya menggunakan pembelajaran mesin dan algoritme visi komputer untuk mengenali wajah dan tubuh dalam gambar. Tapi mari kita perjelas untuk saat ini dan hindari menggunakan model deteksi apa pun.

Kita dapat mengidentifikasi wajah pada gambar hanya dengan satu baris kode. Baris 13 , Untuk mengekstrak bagian persegi panjang dari gambar, mulai dari (35, 35), kami menyediakan potongan array NumPy (90, 100). Tampaknya membingungkan bahwa kami memberi makan tanaman dengan indeks dalam urutan tinggi-pertama dan lebar-kedua yang kami lakukan, tetapi perlu diingat bahwa OpenCV menyimpan gambar sebagai larik NumPy. Akibatnya, kita harus menyediakan nilai sumbu y sebelum sumbu x.

NumPy membutuhkan empat indeks berikut untuk melakukan pemotongan kami:

Mulai y: Koordinat y di awal. Untuk contoh ini, kita mulai dari y=35.

Akhiri: Koordinat y di bagian akhir. Pangkas kami akan berhenti ketika y = 90.

Mulai x: Koordinat x awal irisan. Pemotongan dimulai pada x=35.

Akhir x: Koordinat sumbu x ujung irisan. Pada x=100, irisan kita selesai.

Demikian pula, kami memotong wilayah (23, 35) dan (143, 148) dari gambar asli untuk mengekstrak seluruh tubuh dari gambar di Baris 19 .

Anda dapat mengamati bahwa gambar telah dipotong untuk hanya menampilkan tubuh dan wajah.

6. Mengubah Ukuran Gambar

Proses menambah atau mengurangi lebar dan tinggi gambar dikenal sebagai penskalaan atau hanya mengubah ukuran. Rasio aspek, yaitu proporsi lebar gambar terhadap tingginya, harus dipertimbangkan saat mengubah ukuran gambar. Mengabaikan rasio aspek dapat mengakibatkan gambar yang telah diskalakan tampak terkompresi dan terdistorsi:

Gambar awal kita ada di sebelah kiri. Di sebelah kanan, Anda akan melihat dua gambar yang telah diskalakan tanpa mempertahankan rasio aspek, mendistorsi proporsi lebar gambar terhadap tingginya. Saat mengubah ukuran gambar, umumnya Anda harus mempertimbangkan rasio aspek.

Teknik interpolasi yang digunakan oleh algoritme pengubahan ukuran kami juga harus mempertimbangkan tujuan fungsi interpolasi untuk menggunakan lingkungan piksel ini untuk menambah atau mengurangi ukuran gambar.

Secara umum, mengecilkan ukuran gambar jauh lebih efektif. Ini karena menghilangkan piksel dari gambar adalah satu-satunya fungsi interpolasi yang perlu dilakukan. Di sisi lain, metode interpolasi perlu “mengisi celah” di antara piksel yang sebelumnya tidak ada jika ukuran gambar ingin diperbesar.

Kami memiliki gambar asli kami di sebelah kiri. Gambar telah diperkecil menjadi setengah dari ukuran aslinya di tengah, tetapi selain itu, tidak ada 'kualitas' gambar yang hilang. Namun demikian, ukuran gambar telah ditingkatkan secara signifikan di sebelah kanan. Sekarang muncul 'meledak' dan 'pixelated.'

Seperti yang saya nyatakan sebelumnya, Anda biasanya ingin memperkecil ukuran gambar daripada memperbesarnya. Dengan mengurangi ukuran gambar, kami menganalisis lebih sedikit piksel dan harus menangani lebih sedikit 'noise', yang membuat algoritme pemrosesan gambar lebih cepat dan lebih akurat.

Terjemahan dan rotasi adalah dua transformasi gambar yang dibahas sejauh ini. Kami sekarang akan memeriksa cara mengubah ukuran gambar.

Tidak mengherankan, kita akan mengubah ukuran gambar kita menggunakan metode cv2.resize. Seperti yang saya tunjukkan sebelumnya, kita harus mempertimbangkan rasio aspek gambar saat menggunakan metode ini. Namun sebelum kita masuk terlalu dalam ke spesifikasinya, izinkan saya memberi Anda sebuah ilustrasi:

# python resize.py --image tupai.jpg

# mengimpor paket yang diperlukan

impor argparse

impor cv2

# membuat objek pengurai argumen dan mengurai argumen

apObj = argparse. ArgumentParser ( )

apObj. add_argument ( '-k' , '--gambar' , yg dibutuhkan = BENAR , Tolong = 'jalur gambar' )

argumen = yang ( apObj. parse_args ( ) )

# muat gambar dan tampilkan di layar

gambar = cv2. imread ( argumen [ 'gambar' ] )

cv2. imshow ( 'Asli' , gambar )

# Untuk mencegah gambar tampak miring, rasio aspek

# harus dipertimbangkan atau dideformasi; oleh karena itu, kami mencari tahu apa

# rasio gambar baru dengan gambar saat ini.

# Mari buat lebar gambar baru kita menjadi 160 piksel.

aspek = 160.0 / gambar. membentuk [ 1 ]

dimensi = ( 160 , int ( gambar. membentuk [ 0 ] * aspek ) )

# baris ini akan menampilkan operasi pengubahan ukuran yang sebenarnya

resizeimage = cv2. mengubah ukuran ( gambar , dimensi , interpolasi = cv2. INTER_AREA )

cv2. imshow ( 'Mengubah ukuran lebar gambar' , resizeimage )

# Bagaimana jika kita ingin mengubah tinggi gambar? - menggunakan

# prinsip yang sama, kita dapat menghitung rasio aspek berdasarkan

# pada tinggi daripada lebar. Mari kita buat skalanya

# tinggi gambar 70 piksel.

aspek = 70.0 / gambar. membentuk [ 0 ]

dimensi = ( int ( gambar. membentuk [ 1 ] * aspek ) , 70 )

# lakukan pengubahan ukuran

resizeimage = cv2. mengubah ukuran ( gambar , dimensi , interpolasi = cv2. INTER_AREA )

cv2. imshow ( 'Mengubah ukuran tinggi gambar' , resizeimage )

cv2. waitKey ( 0 )

Baris 1-14 , Setelah mengimpor paket kami dan mengonfigurasi parser argumen kami, kami akan memuat dan menampilkan gambar kami.

Baris 20 dan 21: Pengkodean yang relevan dimulai pada baris ini . Rasio aspek gambar harus dipertimbangkan saat mengubah ukurannya. Proporsi antara lebar dan tinggi gambar dikenal sebagai rasio aspek.

Tinggi lebar adalah rasio aspek.

Jika kita tidak mempertimbangkan rasio aspek, hasil pengubahan ukuran kita akan terdistorsi.

Pada Baris 20 , perhitungan rasio yang diubah ukurannya dilakukan. Kami memberikan lebar gambar baru kami sebagai 160 piksel di baris kode ini. Kami hanya mendefinisikan rasio (aspektrasi) kami sebagai lebar baru (160 piksel) dibagi dengan lebar lama, yang kami akses menggunakan gambar, untuk menghitung rasio tinggi baru dengan tinggi lama. bentuk[1].

Dimensi baru gambar aktif Baris 21 dapat dihitung sekarang setelah kita mengetahui rasio kita. Sekali lagi, gambar baru akan memiliki lebar 160 piksel. Setelah mengalikan tinggi lama dengan rasio kami dan mengonversi hasilnya menjadi bilangan bulat, tingginya dihitung. Kami dapat mempertahankan rasio aspek asli gambar dengan melakukan operasi ini.

Baris 24 adalah tempat gambar benar-benar diubah ukurannya. Gambar yang ingin kita ubah ukurannya adalah argumen pertama, dan yang kedua adalah dimensi yang kita hitung untuk gambar baru. Metode interpolasi kami, yang merupakan algoritme untuk mengubah ukuran gambar sebenarnya, adalah parameter terakhir.

Akhirnya, aktif Baris 25 , kami menampilkan gambar skala kami.

Kami mendefinisikan kembali rasio (aspektrasi) kami Baris 31 . Ketinggian gambar baru kita akan menjadi 70 piksel. Kami membagi 70 dengan tinggi asli untuk mendapatkan rasio tinggi-ke-tinggi yang baru.

Selanjutnya, kami menetapkan dimensi gambar baru. Gambar baru akan memiliki tinggi 70 piksel, yang sudah diketahui. Sekali lagi kita dapat menjaga rasio aspek asli gambar dengan mengalikan lebar lama dengan rasio untuk menghasilkan lebar baru.

Gambar kemudian benar-benar diubah ukurannya Baris 35 , dan ditampilkan di Baris 36.

Di sini, kita dapat melihat bahwa kita telah mengurangi lebar dan tinggi gambar asli sambil menjaga rasio aspek. Gambar kami akan tampak terdistorsi jika rasio aspek tidak dipertahankan.

Kesimpulan

Di blog ini, kami telah mempelajari berbagai konsep dasar pemrosesan gambar. Kami telah melihat terjemahan gambar dengan bantuan paket OpenCV. Kita telah melihat metode untuk memindahkan gambar ke atas, bawah, kanan, dan kiri. Metode ini sangat berguna ketika kita membuat dataset dari gambar yang mirip untuk diberikan sebagai dataset pelatihan, sehingga mesin akan melihat gambar yang berbeda meskipun sama. Artikel ini juga mengajari Anda cara memutar gambar di sekitar titik mana pun di ruang Cartesian menggunakan matriks rotasi. Kemudian Anda menemukan bagaimana OpenCV memutar gambar menggunakan matriks ini dan melihat beberapa ilustrasi gambar berputar.

Dua operasi aritmatika penjumlahan dan pengurangan gambar yang mendasar (namun signifikan) diperiksa dalam bagian ini. Seperti yang Anda lihat, menambah dan mengurangi matriks dasar adalah semua operasi aritmatika gambar.

Selain itu, kami menggunakan OpenCV dan NumPy untuk menyelidiki kekhasan aritmatika gambar. Pembatasan ini harus diingat, atau Anda berisiko mendapatkan hasil yang tidak terduga saat menjalankan operasi aritmatika pada gambar Anda.

Penting untuk diingat bahwa meskipun NumPy melakukan operasi modulus dan 'memutar', OpenCV menambahkan dan mengurangi nilai pemotongan di luar rentang [0, 255] agar sesuai dengan rentang. Saat mengembangkan aplikasi visi komputer Anda sendiri, mengingat ini akan membantu Anda menghindari memburu bug yang rumit.

Pembalikan gambar tidak diragukan lagi merupakan salah satu ide sederhana yang akan kita telusuri dalam kursus ini. Membalik sering digunakan dalam pembelajaran mesin untuk menghasilkan lebih banyak sampel data pelatihan, menghasilkan pengklasifikasi gambar yang lebih kuat dan andal.

Kami juga belajar bagaimana menggunakan OpenCV untuk mengubah ukuran gambar. Sangat penting untuk mempertimbangkan metode interpolasi yang Anda gunakan dan rasio aspek gambar asli Anda saat mengubah ukurannya sehingga hasilnya tidak tampak terdistorsi.

Terakhir, penting untuk diingat bahwa jika kualitas gambar menjadi masalah, yang terbaik adalah beralih dari gambar yang lebih besar ke gambar yang lebih kecil. Dalam kebanyakan kasus, memperbesar gambar menciptakan artefak dan menurunkan kualitasnya.