Pemprosesan Imej OpenCV

Pemprosesan Imej Opencv



Kami akan mengkaji kaedah pemprosesan imej dalam artikel ini. Kami akan mengkaji beberapa topik asas tetapi kritikal dalam penglihatan komputer dan pembelajaran mesin. Teknik pemprosesan imej asas ini boleh menyelesaikan masalah yang kompleks, seperti set data. Hasilnya, terdapat enam langkah asas dalam pemprosesan imej, yang disenaraikan di bawah:
  1. Terjemahan Imej
  2. Putaran Imej
  3. Aritmetik Imej
  4. Membalikkan Imej
  5. Pemotongan Imej
  6. Saiz Semula Imej

Sekarang, kami akan menerangkan semua topik pemprosesan imej yang dinyatakan di atas secara terperinci.

1. Terjemahan Imej

Terjemahan imej ialah kaedah pemprosesan imej yang membantu kita menggerakkan imej di sepanjang paksi-x dan y. Kita boleh menggerakkan imej ke atas, bawah, kanan, kiri atau mana-mana gabungan.







Kita boleh mentakrifkan Matriks Terjemahan dengan simbol M, dan kita boleh mewakilinya dalam bentuk matematik, seperti yang ditunjukkan di bawah:





Kita boleh memahami konsep imej terjemahan melalui program ini.





Kod Python: Kami akan mengekalkan nama program berikut sebagai translate.py .

# import pakej yang diperlukan

import numpy sebagai cth.

import argparse

import imutil

import cv2

# kami melaksanakan penghurai hujah

ap_obj = argparse. ArgumentParser ( )

ap_obj. tambah_argumen ( '-k' , '--gambar' , diperlukan = betul ,

membantu = 'lokasi fail imej' )

args = yang ( ap_obj. parse_args ( ) )

# muatkan imej dan tunjukkan pada skrin

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

cv2. tayangan ( 'Imej_asli' , gambar )

# Terjemahan imej ialah matriks NumPy yang diberikan di bawah:

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

# Kami akan menggunakan matriks NumPy di ​​atas untuk mengalihkan imej di sepanjang

# arah paksi-x dan paksi-y. Untuk ini, kita hanya perlu lulus nilai piksel.

# Dalam program ini, kami akan mengalihkan imej 30 piksel ke kanan

# dan 70 piksel ke arah bawah.

translation_mat = cth. terapung32 ( [ [ 1 , 0 , 30 ] , [ 0 , 1 , 70 ] ] )

terjemahan_gambar = cv2. warpAffine ( gambar , translation_mat ,

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

cv2. tayangan ( 'Terjemahan imej ke Bawah dan Kanan' , terjemahan_gambar )

# sekarang, kita akan menggunakan matriks NumPy di ​​atas untuk mengalihkan imej di sepanjang

# arah paksi-x (kiri) dan paksi-y (atas).

# Di sini, kita akan mengalihkan imej 50 piksel ke kiri

# dan 90 piksel ke arah atas.

translation_mat = cth. terapung32 ( [ [ 1 , 0 , - lima puluh ] , [ 0 , 1 , - 90 ] ] )

terjemahan_gambar = cv2. warpAffine ( gambar , translation_mat ,

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

cv2. tayangan ( 'Terjemahan imej Atas dan Kiri' , terjemahan_gambar )

cv2. waitKey ( 0 )

Baris 1 hingga 5: Kami mengimport semua pakej yang diperlukan untuk program ini, seperti OpenCV, argparser dan NumPy. Sila ambil perhatian bahawa terdapat perpustakaan lain iaitu imutils. Ini bukan pakej OpenCV. Ini hanyalah perpustakaan yang akan memaparkan pemprosesan imej yang sama dengan mudah.



Imutils perpustakaan tidak akan disertakan secara automatik apabila kami memasang OpenCV. Jadi untuk memasang imutil, kita perlu menggunakan kaedah berikut:

pip pasang imutils

Baris 8 hingga 15: Kami mencipta agrparser kami dan memuatkan imej kami.

Baris 24 hingga 25: Bahagian program ini adalah tempat terjemahan berlaku. Matriks terjemahan memberitahu kita berapa banyak piksel imej akan dialihkan ke atas atau ke bawah atau ke kiri atau kanan. Oleh kerana OpenCV memerlukan nilai matriks berada dalam tatasusunan titik terapung, matriks terjemahan mengambil nilai dalam tatasusunan titik terapung.

Baris pertama matriks terjemahan kelihatan seperti ini:

Baris matriks ini adalah untuk paksi-x. Nilai t x akan memutuskan sama ada imej akan dialihkan ke sebelah kiri atau kanan. Jika kita melepasi nilai negatif, maka ia bermakna imej akan dianjakkan ke sebelah kiri, dan jika nilainya positif, maka ia bermakna imej akan dialihkan ke sebelah kanan.

Kami kini akan mentakrifkan baris kedua matriks seperti berikut:

Baris matriks ini adalah untuk paksi-y. Nilai t Y akan memutuskan sama ada imej akan dianjakkan ke atas atau bawah. Jika kita melepasi nilai negatif, maka ia bermakna imej akan dianjakkan ke atas, dan jika nilainya positif, maka ia bermakna imej akan beralih ke bahagian bawah.

Dalam program sebelumnya di baris 24, kami mentakrifkan t x = 30 dan t Y = 70. Jadi kita sedang menggerakkan imej 30 piksel ke arah sebelah kanan dan 70 piksel ke bawah.

Tetapi proses terjemahan imej utama berlaku di baris 25, di mana kami mentakrifkan matriks terjemahan cv2.warpAffine . Dalam fungsi ini, kami menghantar tiga parameter: parameter pertama ialah imej, parameter kedua ialah matriks terjemahan, dan parameter ketiga ialah dimensi imej.

Baris 27: Baris 27 akan memaparkan hasil dalam output.

Sekarang, kami akan melaksanakan satu lagi matriks terjemahan untuk kiri dan atas. Untuk ini, kita perlu menentukan nilai dalam negatif.

Baris 33 hingga 34: Dalam program sebelumnya pada baris 33, kami mentakrifkan t x = -50 dan t Y = -90. Jadi kami mengalihkan imej 50 piksel ke arah sebelah kiri dan 90 piksel ke atas. Tetapi proses terjemahan imej utama berlaku di baris 34, di mana kami mentakrifkan matriks terjemahan cv2.warpAffine .

Baris 36 : Baris 36 akan memaparkan keputusan seperti yang ditunjukkan dalam output.

Untuk menjalankan kod sebelumnya, kita perlu memberikan laluan imej seperti yang diberikan di bawah.

Pengeluaran: python translate.py –image squirrel.jpg

Sekarang, kami akan melaksanakan program terjemahan imej yang sama menggunakan imutil perpustakaan. Perpustakaan ini sangat mudah digunakan untuk pemprosesan imej. Di perpustakaan ini, kita tidak perlu memikirkan tentang cv2.warpAffine kerana perpustakaan ini akan menguruskan perkara ini. Jadi mari kita laksanakan program terjemahan imej ini menggunakan perpustakaan imutils.

Kod Python: Kami akan mengekalkan nama program berikut sebagai translate_imutils.py .

# import pakej yang diperlukan

import numpy sebagai cth.

import argparse

import imutil

import cv2

# Fungsi ini melaksanakan terjemahan imej dan

# mengembalikan imej yang diterjemahkan kepada fungsi panggilan.

def menterjemah ( gambar , x , Y ) :

matriks_terjemahan = cth. terapung32 ( [ [ 1 , 0 , x ] , [ 0 , 1 , Y ] ] )

terjemahan_gambar = cv2. warpAffine ( gambar , matriks_terjemahan ,

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

kembali terjemahan_gambar

# bina hurai hujah dan hurai hujah

ap = argparse. ArgumentParser ( )

ap. tambah_argumen ( '-saya' , '--gambar' , diperlukan = betul , membantu = 'Laluan ke imej' )

args = yang ( ap. parse_args ( ) )

# muatkan imej dan paparan pada skrin

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

cv2. tayangan ( 'Imej_asli' , gambar )

terjemahan_gambar = imutil. menterjemah ( gambar , 10 , 70 )

cv2. tayangan ( 'Terjemahan imej ke kanan dan bahagian bawah' ,

terjemahan_gambar )

cv2. waitKey ( 0 )

Baris 9 hingga 13: Bahagian program ini adalah tempat terjemahan berlaku. Matriks terjemahan memberitahu kami dengan bilangan piksel imej akan dialihkan ke atas atau ke bawah atau ke kiri atau kanan.

Baris ini telah dijelaskan, tetapi kini kita akan membina fungsi yang dipanggil translate () dan menghantar tiga parameter berbeza ke dalamnya. Imej itu sendiri berfungsi sebagai parameter pertama. Nilai x, dan y matriks terjemahan sepadan dengan parameter kedua dan ketiga.

Nota : Tidak perlu mentakrifkan fungsi terjemah ini di dalam program kerana ia sudah disertakan dalam pakej perpustakaan imutils. Saya telah menggunakannya dalam program demi penjelasan yang jelas. Kita boleh memanggil fungsi ini secara langsung dengan imutil, seperti yang ditunjukkan dalam baris 24.

Baris 24: Program sebelumnya akan menunjukkan bahawa pada baris 24, kami mentakrifkan tx = 10 dan ty = 70. Jadi kami mengalihkan imej 10 piksel ke arah sebelah kanan dan 70 piksel ke bawah.

Dalam program ini, kami tidak mengambil berat tentang mana-mana fungsi cv2.warpAffine kerana ia sudah berada di dalam pakej perpustakaan imutils.

Untuk menjalankan kod sebelumnya, kita perlu memberikan laluan imej, seperti yang diberikan di bawah:

Pengeluaran:

python imutils. py --gambar tupai. jpg

2. Putaran Imej

Kami telah melalui cara untuk menterjemah (iaitu, menganjak) imej ke atas, bawah, kiri dan kanan dalam pelajaran sebelumnya (atau sebarang gabungan). Seterusnya, kita akan membincangkan putaran kerana ia berkaitan dengan pemprosesan imej.

Gambar diputar oleh sudut, theta, dalam proses yang dikenali sebagai putaran. Sudut di mana kita memutar imej akan diwakili oleh theta. Selain itu, saya kemudiannya akan menyediakan fungsi kemudahan putar untuk menjadikan imej berputar lebih mudah.

Sama seperti terjemahan, dan mungkin tidak menghairankan, putaran mengikut sudut, theta ditentukan dengan membina matriks M dalam format berikut:

Matriks ini boleh memutarkan darjah theta vektor (lawan arah jam) di sekeliling asalan yang diberi (x, y)-satah Cartes. Biasanya, dalam senario ini, asal akan menjadi pusat gambar, tetapi sebenarnya, kami mungkin menetapkan mana-mana titik rawak (x, y) sebagai pusat putaran kami.

Gambar R yang diputar kemudian dicipta daripada imej asal I menggunakan pendaraban matriks mudah: R = IM

OpenCV, sebaliknya, juga menawarkan kapasiti untuk (1) skala (iaitu, mengubah saiz) imej dan (2) menawarkan pusat putaran sewenang-wenangnya untuk menjalankan putaran sekeliling.

Matriks putaran diubah suai kami M ditunjukkan di bawah:

Mari mulakan dengan membuka dan menjana fail baharu yang dipanggil rotate.py :

# mengimport pakej yang diperlukan

import numpy sebagai cth.

import argparse

import imutil

import cv2

# mencipta objek argumentparser dan hujah parsing

apobj = argparse. ArgumentParser ( )

apobj. tambah_argumen ( '-k' , '--gambar' , diperlukan = betul , membantu = 'laluan imej' )

hujah = yang ( apobj. parse_args ( ) )

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

cv2. tayangan ( 'Imej_asli' , gambar )

# Kira pusat imej menggunakan dimensi imej.

( ketinggian , lebar ) = gambar. bentuk [ : 2 ]

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

# Sekarang, menggunakan cv2, kami akan memutarkan imej sebanyak 55 darjah ke

# tentukan matriks putaran menggunakan getRotationMatrix2D()

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

diputarImej = cv2. warpAffine ( gambar , rotationMatrix , ( lebar , ketinggian ) )

cv2. tayangan ( 'Memutar imej sebanyak 55 Darjah' , diputarImej )

cv2. waitKey ( 0 )

# Imej kini akan diputar sebanyak -85 darjah.

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

diputarImej = cv2. warpAffine ( gambar , rotationMatrix , ( lebar , ketinggian ) )

cv2. tayangan ( 'Memutar imej sebanyak -85 Darjah' , diputarImej )

cv2. waitKey ( 0 )

Baris 1 hingga 5: Kami mengimport semua pakej yang diperlukan untuk program ini, seperti OpenCV, argparser dan NumPy. Sila ambil perhatian bahawa terdapat perpustakaan lain iaitu imutils. Ini bukan pakej OpenCV. Ini hanyalah perpustakaan yang akan digunakan untuk menunjukkan pemprosesan imej yang sama dengan mudah.

Imutils perpustakaan tidak akan disertakan secara automatik apabila kami memasang OpenCV. OpenCV memasang imutils. Kita perlu menggunakan kaedah berikut:

pip pasang imutils

Baris 8 hingga 14: Kami mencipta agrparser kami dan memuatkan imej kami. Dalam argparser ini, kami hanya menggunakan satu hujah imej, yang akan memberitahu kami laluan imej yang akan kami gunakan dalam program ini untuk menunjukkan putaran.

Apabila memutar imej, kita mesti menentukan titik pangsi putaran. Selalunya, anda perlu memutarkan imej tentang pusatnya, tetapi OpenCV membenarkan anda memilih mana-mana titik rawak sebaliknya. Mari kita putarkan imej di sekeliling pusatnya.

Baris 17 hingga 18 ambil lebar dan tinggi imej, masing-masing, dan kemudian bahagikan setiap dimensi dengan dua untuk mewujudkan pusat imej.

Kami membina matriks untuk memutar imej dengan cara yang sama kami mentakrifkan matriks untuk menterjemah imej. Kami hanya akan memanggil cv2.getRotationMatrix2D berfungsi pada Baris 22 dan bukannya mencipta matriks secara manual menggunakan NumPy (yang mungkin sedikit menyusahkan).

The cv2.getRotationMatrix2D fungsi memerlukan tiga parameter. Input pertama ialah sudut putaran yang dikehendaki (dalam kes ini, pusat imej). Theta kemudiannya digunakan untuk menentukan berapa banyak (lawan arah jam) darjah yang akan kita putarkan imej. Di sini, kami akan memutarkan imej 45 darjah. Pilihan terakhir adalah berkaitan dengan saiz imej.

Terlepas dari fakta bahawa kita belum lagi membincangkan penskalaan imej, anda boleh memberikan nombor titik terapung di sini dengan 1.0 yang menandakan bahawa imej itu harus digunakan dalam perkadaran asalnya. Walau bagaimanapun, jika anda menaip nilai 2.0, saiz imej akan berganda. Sebilangan 0.5 mengurangkan saiz imej seperti itu.

Baris 22 hingga 23: Selepas menerima matriks putaran kami M dari cv2.getRotationMatrix2D fungsi, kami memutar imej kami menggunakan cv2.warpAffine teknik pada Baris 23. Input pertama fungsi ialah imej yang ingin kita putar. Lebar dan ketinggian imej keluaran kami kemudiannya ditakrifkan, bersama-sama dengan matriks putaran kami M. Pada baris 23, imej kemudiannya diputar sebanyak 55 darjah.

Anda dapat melihat bahawa imej kami telah diputar.

Baris 28 hingga 30 membentuk putaran kedua. Baris 22–23 kod adalah sama, kecuali kali ini kita berputar sebanyak -85 darjah berbanding 55.

Kami hanya memutarkan imej di sekeliling pusatnya sehingga ke tahap ini. Bagaimana jika kita ingin memutarkan imej di sekeliling titik rawak?

Mari mulakan dengan membuka dan menjana fail baharu yang dipanggil rotate.py:

# mengimport pakej yang diperlukan

import numpy sebagai cth.

import argparse

import imutil

import cv2

# mencipta objek argumentparser dan hujah parsing

ap_obj = argparse. ArgumentParser ( )

ap_obj. tambah_argumen ( '-k' , '--gambar' , diperlukan = betul , membantu = 'laluan imej' )

hujah = yang ( ap_obj. parse_args ( ) )

# muatkan imej dan paparan pada skrin

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

cv2. tayangan ( 'Imej_asli' , gambar )

# Kira pusat imej menggunakan dimensi imej.

( ketinggian , lebar ) = gambar. bentuk [ : 2 ]

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

# Sekarang, menggunakan cv2, kami akan memutarkan imej sebanyak 55 darjah ke

# tentukan matriks putaran menggunakan getRotationMatrix2D()

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

diputarImej = cv2. warpAffine ( gambar , rotationMatrix , ( lebar , ketinggian ) )

cv2. tayangan ( 'Memutar imej sebanyak 55 Darjah' , diputarImej )

cv2. waitKey ( 0 )

# Imej kini akan diputar sebanyak -85 darjah.

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

diputarImej = cv2. warpAffine ( gambar , rotationMatrix , ( lebar , ketinggian ) )

cv2. tayangan ( 'Memutar imej sebanyak -85 Darjah' , diputarImej )

cv2. waitKey ( 0 )

# putaran imej dari beberapa titik sewenang-wenangnya, bukan dari tengah

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

diputarImej = cv2. warpAffine ( gambar , rotationMatrix , ( lebar , ketinggian ) )

cv2. tayangan ( 'Putaran imej dari titik sewenang-wenangnya' , diputarImej )

cv2. waitKey ( 0 )

Baris 34 hingga 35: Sekarang, kod ini sepatutnya kelihatan biasa untuk memutar objek. Untuk memutarkan imej di sekitar titik 40 piksel ke kiri dan 40 piksel di atas pusatnya, kami mengarahkan cv2.getRotationMatrix2D berfungsi untuk memberi perhatian kepada parameter pertamanya.

Imej yang dihasilkan apabila kita menggunakan putaran ini ditunjukkan di bawah:

Kita boleh melihat dengan jelas pusat putaran kini ialah koordinat (x, y), iaitu 40 piksel ke kiri dan 40 piksel di atas pusat pengiraan gambar.

3. Aritmetik Imej

Sebenarnya, aritmetik imej hanyalah penambahan matriks dengan beberapa sekatan tambahan pada jenis data yang akan kami bincangkan kemudian.

Mari kita luangkan sedikit masa untuk membincangkan beberapa asas algebra linear yang cantik.

Pertimbangkan untuk menggabungkan dua matriks seterusnya:

Apakah keputusan yang akan dihasilkan oleh penambahan matriks? Jawapan mudah ialah jumlah entri matriks, elemen demi elemen:

Cukup mudah, bukan?

Kita semua memahami operasi asas tambah dan tolak pada masa ini. Walau bagaimanapun, kita mesti mengambil kira sekatan yang dikenakan oleh ruang warna dan jenis data kita semasa bekerja dengan imej.

Piksel dalam imej RGB, misalnya, berada di antara [0, 255]. Apakah yang berlaku jika kita cuba menambah 10 pada piksel dengan keamatan 250 semasa melihatnya?

Kami akan mencapai nilai 260 jika kami menggunakan prinsip aritmetik piawai. 260 bukan nilai yang sah, kerana imej RGB diwakili sebagai integer tidak bertanda 8-bit.

Jadi apa yang patut berlaku? Patutkah kita menjalankan semakan untuk memastikan tiada piksel melebihi julat [0, 255], memotong setiap piksel untuk mempunyai nilai antara 0 dan 255?

Atau adakah kita 'membungkus' dan melakukan operasi modulus? Selaras dengan peraturan modulus, penambahan 10 hingga 255 hanya akan menghasilkan nilai 9.

Bagaimanakah penambahan dan penolakan pada imej di luar julat [0, 255] harus dikendalikan?

Sebenarnya tidak ada teknik yang betul atau salah; semuanya bergantung pada cara anda bekerja dengan piksel anda dan perkara yang anda ingin capai.

Tetapi ingat bahawa terdapat perbezaan antara penambahan dalam OpenCV dan penambahan dalam NumPy. Modulus aritmetik dan 'bungkus' akan dilakukan oleh NumPy. Sebaliknya, OpenCV akan melaksanakan keratan dan memastikan bahawa nilai piksel tidak pernah meninggalkan julat [0, 255].

Mari mulakan dengan mencipta fail baharu bernama aritmetik.py dan membukanya:

# python arithmetic.py --image squirrel.jpg

# mengimport pakej yang diperlukan

import numpy sebagai cth.

import argparse

import imutil

import cv2

# mencipta objek argumentparser dan hujah parsing

apObj = argparse. ArgumentParser ( )

apObj. tambah_argumen ( '-k' , '--gambar' , diperlukan = betul , membantu = 'laluan imej' )

hujah = yang ( apObj. parse_args ( ) )

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

cv2. tayangan ( 'Imej_asli' , gambar )

'''

Nilai piksel kami akan berada dalam julat [0, 255]

memandangkan imej ialah tatasusunan NumPy, yang disimpan sebagai integer 8-bit yang tidak ditandatangani.

Apabila menggunakan fungsi seperti cv2.add dan cv2.tolak, nilai akan dipotong

kepada julat ini walaupun ia ditambah atau ditolak dari luar

julat [0, 255]. Berikut adalah ilustrasi:

'''


cetak ( 'maksimum 255: {}' . format ( str ( cv2. Tambah ( cth. uint8 ( [ 201 ] ) ,

cth. uint8 ( [ 100 ] ) ) ) ) )

cetak ( 'minimum 0: {}' . format ( str ( cv2. tolak ( cth. uint8 ( [ 60 ] ) ,

cth. uint8 ( [ 100 ] ) ) ) ) )

'''

Apabila melakukan operasi aritmetik dengan tatasusunan ini menggunakan NumPy,

nilai akan membungkus dan bukannya dipotong ke

[0, 255]julat. Apabila menggunakan imej, penting untuk menyimpannya

dalam fikiran.

'''


cetak ( 'membungkus: {}' . format ( str ( cth. uint8 ( [ 201 ] ) + cth. uint8 ( [ 100 ] ) ) ) )

cetak ( 'membungkus: {}' . format ( str ( cth. uint8 ( [ 60 ] ) - cth. uint8 ( [ 100 ] ) ) ) )

'''

Mari kita darabkan kecerahan setiap piksel dalam imej kita dengan 101.

Untuk melakukan ini, kami menjana tatasusunan NumPy dengan saiz yang sama dengan matriks kami,

diisi dengan satu, dan darabkannya dengan 101 untuk menghasilkan tatasusunan yang diisi

dengan 101s. Akhirnya, kami menggabungkan kedua-dua imej.

Anda akan perhatikan bahawa imej itu kini 'lebih cerah.'

'''


Matriks = cth. satu ( gambar. bentuk , dtype = 'uint8' ) * 101

imej_tambah = cv2. Tambah ( gambar , Matriks )

cv2. tayangan ( 'Hasil Imej Ditambah' , imej_tambah )

#Dengan cara yang sama, kita boleh menjadikan imej kita lebih gelap dengan mengambil

# 60 jauh daripada semua piksel.

Matriks = cth. satu ( gambar. bentuk , dtype = 'uint8' ) * 60

imej_tolak = cv2. tolak ( gambar , Matriks )

cv2. tayangan ( 'Hasil Imej Tolak' , imej_tolak )

cv2. waitKey ( 0 )

Baris 1 hingga 16 akan digunakan untuk menjalankan proses biasa kami, yang memerlukan pengimportan pakej kami, mengkonfigurasi penghurai hujah kami dan memuatkan imej kami.

Ingat bagaimana saya sebelum ini membincangkan perbezaan antara penambahan OpenCV dan NumPy? Memandangkan kita telah membincangkannya dengan teliti, mari kita lihat kes tertentu untuk memastikan kita memahaminya.

Dua tatasusunan NumPy integer tidak bertanda 8-bit ditakrifkan pada baris 26 . Nilai 201 ialah satu-satunya elemen dalam tatasusunan pertama. Walaupun hanya seorang ahli berada dalam tatasusunan kedua, ia mempunyai nilai 100. Nilai tersebut kemudiannya ditambah menggunakan fungsi cv2.add OpenCV.

Apakah yang anda jangkakan hasilnya?

Selaras dengan prinsip aritmetik konvensional, jawapannya hendaklah 301. Tetapi ingat bahawa kita berurusan dengan integer tidak bertanda 8-bit, yang hanya boleh berada dalam julat [0, 255]. Kerana kami menggunakan kaedah cv2.add, OpenCV mengendalikan keratan dan memastikan penambahan itu hanya mengembalikan hasil maksimum 255.

Baris pertama penyenaraian di bawah menunjukkan hasil menjalankan kod ini:

aritmetik. py

maksimum daripada 255 : [ [ 255 ] ]

Jumlah itu sememangnya menghasilkan sejumlah 255.

Berikutan itu, baris 26 menggunakan cv2.tolak untuk mencapai penolakan. Sekali lagi, kami mentakrifkan dua tatasusunan NumPy integer tidak bertanda 8-bit dengan satu elemen dalam setiap satu. Nilai tatasusunan pertama ialah 60, manakala nilai tatasusunan kedua ialah 100.

Aritmetik kami menentukan bahawa penolakan harus menghasilkan nilai -40, tetapi OpenCV mengendalikan keratan untuk kami sekali lagi. Kami mendapati bahawa nilai telah dipangkas kepada 0. Keputusan kami di bawah menunjukkan ini:

aritmetik. py

minimum daripada 0 : [ [ 0 ] ]

Menggunakan cv2, tolak 100 daripada 60 tolak, menghasilkan nilai 0.

Tetapi apa yang berlaku jika kita menggunakan NumPy sebagai ganti OpenCV untuk menjalankan pengiraan?

Baris 38 dan 39 menangani isu ini.

Pertama, dua tatasusunan NumPy integer tidak bertanda 8-bit dengan satu elemen setiap satu ditakrifkan. Nilai tatasusunan pertama ialah 201, manakala nilai tatasusunan kedua ialah 100. Penambahan kami akan dipangkas dan nilai 255 akan dikembalikan jika kami menggunakan fungsi cv2.add.

NumPy, sebaliknya, 'membalut' dan melakukan aritmetik modulo dan bukannya menggunting. NumPy membungkus kepada sifar apabila nilai 255 dicapai dan kemudian menyambung mengira sehingga 100 langkah telah dicapai. Ini disahkan oleh baris pertama output, yang ditunjukkan di bawah:

aritmetik. py
membungkus: [ Empat lima ]

Kemudian, dua lagi tatasusunan NumPy ditakrifkan, satu dengan nilai 50 dan satu lagi dengan 100. Penolakan ini akan dipangkas dengan kaedah cv2.tolak untuk mengembalikan hasil 0. Tetapi kami sedar bahawa bukannya keratan, NumPy melaksanakan aritmetik modulo. Sebaliknya, prosedur modulo membalut dan mula mengira ke belakang dari 255 apabila 0 dicapai semasa penolakan. Kita boleh melihat ini daripada output berikut:

aritmetik. py

membungkus: [ 207 ]

Sekali lagi, output terminal kami menunjukkan perbezaan antara keratan dan pembalut:

Adalah penting untuk mengingati hasil yang anda inginkan semasa melakukan aritmetik integer. Adakah anda mahu sebarang nilai di luar julat [0, 255] dipotong? Gunakan teknik aritmetik imej terbina dalam OpenCV selepas itu.

Adakah anda mahu nilai dililitkan jika ia berada di luar julat [0, 255] dan operasi aritmetik modulus? Tatasusunan NumPy kemudiannya hanya ditambah dan ditolak seperti biasa.

Baris 48 mentakrifkan tatasusunan NumPy satu dimensi dengan dimensi yang sama seperti imej kami. Sekali lagi, kami memastikan bahawa jenis data kami ialah integer tidak bertanda 8-bit. Kami hanya mendarabkan matriks nilai satu digit kami dengan 101 untuk mengisinya dengan nilai 101 dan bukannya 1. Akhir sekali, kami menggunakan fungsi cv2.add untuk menambah matriks 100s kami kepada imej asal. Ini meningkatkan keamatan setiap piksel sebanyak 101 sambil juga memastikan bahawa sebarang nilai yang cuba melebihi 255 dipotong ke julat [0, 255].

Perhatikan bagaimana imej kelihatan lebih terang dan kelihatan lebih 'dicuci' daripada yang asal. Ini kerana kami memacu piksel ke arah warna yang lebih cerah dengan meningkatkan keamatan pikselnya sebanyak 101.

Untuk menolak 60 daripada setiap keamatan piksel imej, kami mula-mula mewujudkan tatasusunan NumPy kedua pada Baris 54 yang diisi dengan 60-an.

Hasil penolakan ini digambarkan dalam imej berikut:

Barang-barang di sekeliling kita kelihatan lebih gelap dengan ketara berbanding sebelum ini. Ini kerana dengan menolak 60 daripada setiap piksel, kami mengalihkan piksel dalam ruang warna RGB ke kawasan yang lebih gelap.

4. Membalikkan Imej

Sama seperti putaran, membalikkan imej merentasi paksi-x atau y adalah pilihan lain yang ditawarkan oleh OpenCV. Walaupun operasi membalikkan tidak digunakan sekerap, mengetahuinya adalah sangat berfaedah atas pelbagai sebab yang mungkin tidak anda lihat dengan segera.

Kami sedang membangunkan pengelas pembelajaran mesin untuk syarikat permulaan kecil yang ingin mengenal pasti wajah dalam imej. Untuk sistem kami 'mempelajari' apa itu wajah, kami memerlukan beberapa jenis set data dengan contoh muka. Malangnya, syarikat itu hanya memberikan kami set data kecil 40 muka dan kami tidak dapat mengumpulkan lebih banyak maklumat.

Lalu, apa yang kita lakukan?

Memandangkan wajah kekal sebagai wajah sama ada ia dicerminkan atau tidak, kami dapat membalikkan secara mendatar setiap imej wajah dan menggunakan versi yang dicerminkan sebagai data latihan tambahan.

Contoh ini mungkin kelihatan bodoh dan buatan, tetapi tidak. Flipping ialah strategi yang sengaja digunakan oleh algoritma pembelajaran mendalam yang kuat untuk menghasilkan lebih banyak data semasa fasa latihan.

Jelas daripada sebelumnya bahawa kaedah pemprosesan imej yang anda pelajari dalam modul ini berfungsi sebagai asas untuk sistem penglihatan komputer yang lebih besar.

Objektif:

Menggunakan cv2.flip fungsi, anda akan belajar cara membalikkan imej secara mendatar dan menegak dalam sesi ini.

Flipping ialah manipulasi imej seterusnya yang akan kami kaji. Paksi-x dan y imej boleh diterbalikkan atau kedua-duanya sekali. Sebelum kita menyelami pengekodan, sebaiknya lihat dahulu hasil flip imej. Lihat imej yang telah diterbalikkan secara mendatar dalam imej berikut:


Ambil perhatian tentang bagaimana imej asal kami berada di sebelah kiri dan bagaimana imej itu telah dicerminkan secara mendatar di sebelah kanan.

Mari mulakan dengan mencipta fail baharu bernama flipping.py .

Anda telah melihat contoh flip imej, jadi mari kita periksa kod tersebut:

# python flipping.py --image quirrel.jpg

# mengimport pakej yang diperlukan

import argparse

import cv2

# mencipta objek penghurai hujah dan menghuraikan hujah

apObj = argparse. ArgumentParser ( )

apObj. tambah_argumen ( '-saya' , '--gambar' , diperlukan = betul , membantu = 'laluan imej' )

hujah = yang ( apObj. parse_args ( ) )

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

cv2. tayangan ( 'Asal' , gambar )

# terbalikkan imej secara mendatar

imej terbalik = cv2. flip ( gambar , 1 )

cv2. tayangan ( 'Imej Terbalik Secara Mendatar' , imej terbalik )

# terbalikkan imej secara menegak

imej terbalik = cv2. flip ( gambar , 0 )

cv2. tayangan ( 'Imej Terbalik Secara Menegak' , imej terbalik )

# imej terbalik di sepanjang kedua-dua paksi

imej terbalik = cv2. flip ( gambar , - 1 )

cv2. tayangan ( 'Terbalik secara Mendatar & Menegak' , imej terbalik )

cv2. waitKey ( 0 )

Langkah-langkah yang kami ambil untuk mengimport pakej kami, menghuraikan input kami dan memuatkan imej kami dari cakera dikendalikan dalam l ines 1 hingga 12 .

Dengan memanggil fungsi cv2.flip dihidupkan Baris 15 , adalah mudah untuk membalikkan imej secara mendatar. Imej yang ingin kami selak dan kod atau bendera tertentu yang menyatakan cara menyelak imej ialah dua hujah yang diperlukan untuk kaedah cv2.flip.

Nilai kod flip 1 bermakna kita akan memutarkan imej di sekeliling paksi-y untuk membalikkannya secara mendatar ( Baris 15 ). Jika kami menentukan kod flip 0, kami ingin memutarkan imej tentang paksi-x ( Baris 19 ). Kod flip negatif ( Baris 23 ) memutarkan imej pada kedua-dua paksi.

Salah satu contoh paling mudah dalam subjek ini ialah menyelak imej, yang merupakan asas.

Seterusnya, kami akan membincangkan pemangkasan imej dan menggunakan hirisan tatasusunan NumPy untuk mengekstrak bahagian imej tertentu.

5. Pemotongan Imej

Pemangkasan, seperti namanya, ialah proses memilih dan mengalih keluar Wilayah Minat (atau ringkasnya ROI), iaitu kawasan imej yang menarik minat kami.

Wajah itu perlu dipangkas daripada imej untuk aplikasi pengesanan muka. Selain itu, jika kami mencipta skrip Python untuk mencari anjing dalam imej, kami mungkin mahu memangkas anjing itu daripada imej apabila kami mencarinya.

Matlamat: Matlamat utama kami adalah untuk membiasakan diri dan selesa menggunakan susunan NumPy menghiris untuk memangkas kawasan daripada imej.

Penanaman : Apabila kami memangkas imej, matlamat kami adalah untuk menghapuskan elemen luaran yang tidak menarik minat kami. Proses memilih ROI kami sering dirujuk sebagai memilih kawasan yang diminati kami.

Buat fail baharu bernama crop.py , bukanya dan tambah kod berikut:

# python crop.py

# mengimport pakej yang diperlukan

import cv2

# muatkan imej dan paparan pada skrin

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

cetak ( gambar. bentuk )

cv2. tayangan ( 'Asal' , gambar )

# Kepingan tatasusunan NumPy digunakan untuk memangkas imej dengan cepat

# kita akan memangkas muka tupai daripada imej

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

cv2. tayangan ( 'Muka tupai' , muka tupai )

cv2. waitKey ( 0 )

# Dan sekarang, di sini kita akan memangkas seluruh badan

# tupai

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

cv2. tayangan ( 'Badan Tupai' , badan tupai )

cv2. waitKey ( 0 )

Kami akan menunjukkan pemangkasan dalam Python dan OpenCV menggunakan imej yang kami muatkan dari cakera Baris 5 dan 6 .

Imej asal yang akan kami pangkas

Dengan hanya menggunakan teknik asas tanaman, kami menyasarkan untuk mengasingkan muka tupai dan badan tupai dari kawasan sekeliling.

Kami akan menggunakan pengetahuan terdahulu kami tentang imej dan membekalkan hirisan tatasusunan NumPy secara manual di mana badan dan muka wujud. Dalam keadaan biasa, kami biasanya menggunakan pembelajaran mesin dan algoritma penglihatan komputer untuk mengecam muka dan badan dalam imej. Tetapi mari kita pastikan perkara itu mudah buat masa ini dan elakkan menggunakan sebarang model pengesanan.

Kita boleh mengenal pasti wajah dalam imej dengan hanya satu baris kod. Baris 13 , Untuk mengekstrak bahagian segi empat tepat imej, bermula pada (35, 35), kami menyediakan hirisan tatasusunan NumPy (90, 100). Nampaknya mengelirukan bahawa kami menyuapkan tanaman dengan indeks dalam susunan ketinggian pertama dan lebar saat yang kami lakukan, tetapi perlu diingat bahawa OpenCV menyimpan imej sebagai tatasusunan NumPy. Akibatnya, kita mesti membekalkan nilai untuk paksi-y sebelum paksi-x.

NumPy memerlukan empat indeks berikut untuk menjalankan pemangkasan kami:

Mulakan: Koordinat-y pada permulaan. Untuk contoh ini, kita bermula pada y=35.

Tamat y: Koordinat y pada penghujung. Tanaman kami akan berhenti apabila y = 90.

Mula x: Permulaan hirisan x koordinat. Tanaman dimulakan pada x=35.

Tamat x: Koordinat paksi x hujung hirisan. Pada x=100, kepingan kami telah selesai.

Begitu juga, kami memangkas kawasan (23, 35) dan (143, 148) daripada imej asal untuk mengekstrak isi penuh daripada imej pada Baris 19 .

Anda boleh melihat bahawa imej telah dipangkas untuk hanya mempamerkan badan dan muka.

6. Saiz Semula Imej

Proses menambah atau mengurangkan lebar dan ketinggian imej dikenali sebagai penskalaan atau hanya mengubah saiz. Nisbah aspek, iaitu perkadaran lebar imej kepada ketinggiannya, harus dipertimbangkan apabila mengubah saiz imej. Mengabaikan nisbah bidang boleh menyebabkan imej yang telah diskalakan kelihatan dimampatkan dan diherotkan:

Imej awal kami berada di sebelah kiri. Di sebelah kanan, anda akan melihat dua imej yang telah diskalakan tanpa mengekalkan nisbah bidang, memutarbelitkan perkadaran lebar imej kepada ketinggiannya. Apabila mengubah saiz imej anda, anda harus mempertimbangkan nisbah bidang secara amnya.

Teknik interpolasi yang digunakan oleh algoritma saiz semula kami juga mesti mempertimbangkan objektif fungsi interpolasi untuk menggunakan kejiranan piksel ini sama ada untuk menambah atau mengurangkan saiz imej.

Secara umum, mengecilkan saiz imej adalah jauh lebih berkesan. Ini kerana mengalih keluar piksel daripada imej adalah semua fungsi interpolasi yang perlu dilakukan. Sebaliknya, kaedah interpolasi perlu 'mengisi jurang' antara piksel yang tidak wujud sebelum ini jika saiz imej ingin ditingkatkan.

Kami mempunyai imej asal kami di sebelah kiri. Imej telah dikecilkan kepada separuh saiz asalnya di tengah, tetapi selain daripada itu, tidak ada kehilangan 'kualiti' imej. Namun begitu, saiz imej telah dipertingkatkan dengan ketara di sebelah kanan. Ia kini kelihatan 'diletupkan' dan 'berpiksel.'

Seperti yang saya nyatakan sebelum ini, anda biasanya mahu mengecilkan saiz imej dan bukannya meningkatkannya. Dengan mengecilkan saiz imej, kami menganalisis lebih sedikit piksel dan perlu menangani lebih sedikit 'bunyi' yang menjadikan algoritma pemprosesan imej lebih pantas dan lebih tepat.

Terjemahan dan putaran ialah dua transformasi imej yang ditangani setakat ini. Kami kini akan mengkaji cara mengubah saiz imej.

Tidak mengejutkan, kami akan mengubah saiz imej kami menggunakan kaedah cv2.resize. Seperti yang saya nyatakan sebelum ini, kita mesti mempertimbangkan nisbah bidang imej apabila menggunakan kaedah ini. Tetapi sebelum kita masuk terlalu mendalam ke dalam spesifik, izinkan saya memberi anda ilustrasi:

# python resize.py --image squirrel.jpg

# mengimport pakej yang diperlukan

import argparse

import cv2

# mencipta objek penghurai hujah dan menghuraikan hujah

apObj = argparse. ArgumentParser ( )

apObj. tambah_argumen ( '-k' , '--gambar' , diperlukan = betul , membantu = 'laluan imej' )

hujah = yang ( apObj. parse_args ( ) )

# muatkan imej dan paparan pada skrin

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

cv2. tayangan ( 'Asal' , gambar )

# Untuk mengelakkan imej daripada kelihatan condong, nisbah aspek

# mesti dipertimbangkan atau cacat; oleh itu, kami memikirkan apa

# nisbah imej baharu kepada imej semasa.

# Mari jadikan lebar imej baharu kami 160 piksel.

aspek = 160.0 / gambar. bentuk [ 1 ]

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

# baris ini akan menunjukkan operasi ubah saiz sebenar

ubah saiz imej = cv2. ubah saiz ( gambar , dimensi , interpolasi = cv2. INTER_AREA )

cv2. tayangan ( 'Saiz semula lebar imej' , ubah saiz imej )

# Bagaimana jika kita ingin menukar ketinggian imej? - menggunakan

# prinsip yang sama, kita boleh mengira nisbah aspek berdasarkan

# pada ketinggian dan bukannya lebar. Mari buat skala

# ketinggian imej 70 piksel.

aspek = 70.0 / gambar. bentuk [ 0 ]

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

# lakukan ubah saiz

ubah saiz imej = cv2. ubah saiz ( gambar , dimensi , interpolasi = cv2. INTER_AREA )

cv2. tayangan ( 'Saiz semula ketinggian imej' , ubah saiz imej )

cv2. waitKey ( 0 )

Baris 1-14 , Selepas mengimport pakej kami dan mengkonfigurasi penghurai hujah kami, kami akan memuatkan dan memaparkan imej kami.

Baris 20 dan 21: Pengekodan yang berkaitan bermula dalam baris ini . Nisbah bidang imej mesti diambil kira semasa mengubah saiznya. Perkadaran antara lebar dan tinggi imej dikenali sebagai nisbah bidang.

Ketinggian kelebaran ialah nisbah aspek.

Jika kita tidak mengambil kira nisbah bidang, keputusan saiz semula kita akan menjadi herot.

hidup Baris 20 , pengiraan nisbah saiz semula dilakukan. Kami menyediakan lebar imej baharu kami sebagai 160 piksel dalam baris kod ini. Kami hanya mentakrifkan nisbah (aspectratio) kami sebagai lebar baharu (160 piksel) dibahagikan dengan lebar lama, yang kami akses menggunakan imej, untuk mengira nisbah ketinggian baharu kepada ketinggian lama. bentuk[1].

Dimensi baharu imej dihidupkan Baris 21 boleh dikira sekarang bahawa kita tahu nisbah kita. Sekali lagi, imej baharu akan mempunyai lebar 160 piksel. Selepas mendarab ketinggian lama dengan nisbah kami dan menukar hasilnya kepada integer, ketinggian dikira. Kita boleh mengekalkan nisbah aspek asal imej dengan menjalankan operasi ini.

Baris 24 ialah tempat imej benar-benar diubah saiznya. Imej yang kami mahu ubah saiz ialah hujah pertama, dan yang kedua ialah dimensi yang kami hitung untuk imej baharu. Kaedah interpolasi kami, yang merupakan algoritma untuk mengubah saiz imej sebenar, ialah parameter terakhir.

Akhirnya, pada Baris 25 , kami memaparkan imej berskala kami.

Kami mentakrifkan semula nisbah (aspectratio) kami pada Baris 31 . Ketinggian imej baharu kami ialah 70 piksel. Kami membahagikan 70 dengan ketinggian asal untuk mendapatkan nisbah ketinggian kepada asal baharu.

Seterusnya, kami mewujudkan dimensi imej baharu. Imej baharu akan mempunyai ketinggian 70 piksel, yang sudah diketahui. Kita boleh sekali lagi mengekalkan nisbah aspek asal imej dengan mendarab lebar lama dengan nisbah untuk menghasilkan lebar baharu.

Imej itu kemudiannya diubah saiznya Baris 35 , dan ia dipaparkan pada Baris 36.

Di sini, kita dapat melihat bahawa kita telah mengurangkan lebar dan ketinggian imej asal kita sambil mengekalkan nisbah bidang. Imej kami akan kelihatan herot jika nisbah bidang tidak dikekalkan.

Kesimpulan

Dalam blog ini, kami telah mengkaji konsep asas pemprosesan imej yang berbeza. Kami telah melihat terjemahan imej dengan bantuan pakej OpenCV. Kami telah melihat kaedah untuk menggerakkan imej ke atas, bawah, kanan, dan kiri. Kaedah ini sangat berguna apabila kami mencipta set data imej yang serupa untuk diberikan sebagai set data latihan, jadi mesin akan melihat imej yang berbeza walaupun ia adalah sama. Artikel ini juga mengajar anda cara memutar imej di sekeliling mana-mana titik dalam ruang Cartes menggunakan matriks putaran. Kemudian anda menemui cara OpenCV memutar imej menggunakan matriks ini dan melihat beberapa ilustrasi imej berputar.

Dua operasi aritmetik imej asas (tetapi penting) bagi penambahan dan penolakan telah diperiksa dalam bahagian ini. Seperti yang anda lihat, menambah dan menolak matriks asas adalah semua operasi aritmetik imej memerlukan.

Selain itu, kami menggunakan OpenCV dan NumPy untuk menyiasat keanehan aritmetik imej. Sekatan ini mesti diingat, atau anda berisiko mendapat hasil yang tidak dijangka apabila melaksanakan operasi aritmetik pada imej anda.

Adalah penting untuk diingat bahawa walaupun NumPy melakukan operasi modulus dan 'membungkus', penambahan OpenCV dan nilai potong penolakan melebihi julat [0, 255] untuk dimuatkan dalam julat. Apabila membangunkan aplikasi penglihatan komputer anda sendiri, mengingati ini akan membantu anda mengelak daripada memburu pepijat rumit.

Membalikkan imej sudah pasti salah satu idea yang lebih mudah yang akan kami terokai dalam kursus ini. Flipping sering digunakan dalam pembelajaran mesin untuk menghasilkan lebih banyak sampel data latihan, menghasilkan pengelas imej yang lebih kuat dan boleh dipercayai.

Kami juga mempelajari cara menggunakan OpenCV untuk mengubah saiz imej. Adalah penting untuk mempertimbangkan kedua-dua kaedah interpolasi yang anda gunakan dan nisbah bidang imej asal anda apabila mengubah saiz imej supaya hasilnya tidak kelihatan herot.

Akhir sekali, adalah penting untuk diingat bahawa jika kualiti imej menjadi isu, adalah lebih baik untuk menukar daripada imej yang lebih besar kepada yang lebih kecil. Dalam kebanyakan kes, membesarkan imej menghasilkan artifak dan merendahkan kualitinya.