Site icon UNYDeveloperNetwork

Membuat Penghitung Koin Sederhana Dengan OpenCV

Reading Time: 9 minutes

Selamat datang di Blogs UNYDeveloperNetwork. Pada postingan kali ini, Saya ingin berbagi dengan Anda sebuah projectr membuat program penghitung koin sederhana dengan menggunakan OpenCV. Bahasa pemrograman yang kita gunakan dalam project ini adalah Python. Tidak perlu berlama – lama lagi, baca post ini lebih lanjut untuk memulai project program penghitung koin sederhana dengan OpenCV.

Sebelum memulai project ini, alangkah baiknya kita mulai dengan tool dan library apa sajakah yang Saya gunakan dalam project ini.

  1. Python versi 2.7.18
  2. OpenCV versi 4.1.0.25
  3. PyCharm Community Edition

Setelah semua tool dan library siap, mari kita langsung mulai saja. Di sini, Saya asumsikan Anda sudah paham menggunakan PyCharm. Sehingga kita bisa langsung melewati tahap membuat project baru dengan menggunakan PyCharm.

Langkah Pertama.  Adalah membuat project baru. Oleh karena itu, buatlah satu project baru dengan nama coinCounter.

Langkah Kedua. Setelah project selesai dibuat, langkah selanjutnya adalah memasukkan gambar ke dalam project. Gambar yang digunakan dapat diunduh melalui tautan berikut ini.

Gambar koin yang akan digunakan dalam project

Berikan nama gambar yang diimport ke dalam project: coin_test.jpeg.

Gambar koin yang sudah disisipkan ke dalam project

Langkah Ketiga. Buat script Python baru dengan nama coin_counter.py dan letakkan satu direktori dengan gambar yang baru saja diimport.

Script coin_counter.py diletakkan di dalam project.

Setelah kita menyelesaikan ketiga tahap di atas, kita siap untuk membuat program penghitung koin sederhana kita.

Memuat Gambar Ke Program

Pertama, kita harus mengimport library openCV ke dalam script kita. Ketikkan kode berikut ini ke dalam script.

import cv2 as cv

Selanjutnya, kita muat gambar yang sudah diimport ke dalam project dengan menggunakan fungsi imread().

img = cv.imread("coin_test.jpeg")

Kemudian kita coba tampilkan gambar yang sudah dimuat tadi dengan menggunakan fungsi imshow(). 

cv.imshow("Show Images", img)

Terakhir, kita tambahkan fungsi waitKey() dan destroyAllWindows() untuk menghandle visibilitas window.

cv.waitKey(0)
cv.destroyAllWindows()

Pada akhir tahap ini, bentuk script kita adalah seperti ini:

import cv2 as cv

img = cv.imread("coin_test.jpeg")
cv.imshow("Original Images", img)

cv.waitKey(0)
cv.destroyAllWindows()

Ketika script tersebut dijalankan, maka akan tampak seperti tangkapan layar di bawah ini.

Gambar Koin yang berhasil dimuat dengan openCV

Dapat kita lihat pada tangkapan layar di atas, gambar koin yang dimuat masih terlalu besar. Oleh karena itu, pada tahap berikutnya kita akan melakukan resize terhadap gambar tersebut.

Mengubah Dimensi Gambar

Pada tahap ini kita akan mengubah dimensi gambar supaya gambar tidak terlalu besar ketika ditampilkan di layar monitor. Untuk mengubah dimensi gambar, kita akan menggunakan fungsi resize(). Namun, sebelum kita dapat menggunakan fungsi ini, terlebih dahulu kita harus mendapat image properties yang berupa width dan height. Setelah kita mendapatkan image properties tersebut, kita dapat mengubah dimensi gambar menjadi lebih besar atau lebih kecil. Untuk memperoleh image properties ini, kita menggunakan fungsi shape().

Kita buat terlebih dahulu variabel untuk menyimpan height dan width dari gambar, baru kemudian dengan menggunakan fungsi shape(), kita ekstrak informasi height dan width dari gambar. Ketikkan kode berikut ini untuk melakukannya.

height, width = img.shape[:2]

Dengan menggunakan kode di atas kita sudah bisa mendapatkan nilai height dan width dari sebuah gambar. Selanjutnya, kita akan mengubah dimensi gambar menjadi lebih kecil dari gambar sebelumnya. Hasil ubahan dimensi gambar tersebut juga kita simpan sebagai variabel yang nantinya akan kita gunakan di tahap – tahap selanjutnya. Gunakan kode berikut untuk melakukannya.

res = cv.resize(img,(width/2, height/2), interpolation = cv.INTER_LINEAR)

Pada kode di atas, Saya mengubah dimensi gambar menjadi setengah lebih kecil dari gambar asilnya serta untuk flags interpolationnya, saya set ke INTER_LINEAR yang merupakan interpolation standar untuk mengubah dimensi lebih besar atau lebih kecil.

Untuk melihat hasil pengubahan dimensi ini, tambahkan satu kode imshow() untuk menampilkan hasilnya. Sehingga kondisi akhir script adalah seperti di bawah ini.

import cv2 as cv

img = cv.imread("coin_test.jpeg")
cv.imshow("Original Images", img)

height, width = img.shape[:2]
res = cv.resize(img,(width/2, height/2), interpolation = cv.INTER_LINEAR)
cv.imshow("Resized Images", res)

cv.waitKey(0)
cv.destroyAllWindows()

Ketika kita jalankan script di atas, hasilnya adalah seperti tangkapan layar di bawah ini.

Dua buah penampil gambar dengan ukuran yang berbeda

Setelah kita berhasil mengubah ukuran dimensi gambar, langkah selanjutnya adalah proses untuk menghilangkan kontur gambar. Ada beberapa langkah yang akan dilakukan dan mari kita simak satu persatu.

Mengubah Color Space gambar menjadi Grayscale

Langkah pertama dalam proses menghilangkan kontur gambar adalah mengubah gambar yang tadinya berwarna menjadi grayscale. Untuk melakukannya, kita akan menggunakan fungsi cvtColor(). Gambar yang digunakan pun adalah gambar hasil resize. Sehingga kode untuk mengubah gambar menjadi grayscale adalah.

grey = cv.cvtColor(res, cv.COLOR_BGR2GRAY)

Dapat kita lihat pada kode di atas, kita sudah menggunakan res sebagai sumber gambar karena gambar ini sudah diubah dimensinya menjadi lebih kecil.  Untuk dapat melihat hasilnya, tambahkan fungsi imshow() sehingga hasil akhir script sampai di tahap ini adalah.

import cv2 as cv

img = cv.imread("coin_test.jpeg")

height, width = img.shape[:2]
res = cv.resize(img,(width/2, height/2), interpolation = cv.INTER_LINEAR)
cv.imshow("Resized Images", res)

grey = cv.cvtColor(res, cv.COLOR_BGR2GRAY)
cv.imshow("Grayscale Images", grey)

cv.waitKey(0)
cv.destroyAllWindows()

Dari kode di atas, kira dapat melihat bahwa Saya menghapus imshow() untuk menampilkan gambar original. Mengapa? Karena gambar tersebut sudah dapat diwakili oleh imshow() pada gambar yang sudah diresize, dan juga ukuran gambar yang sudah diresize lebih kecil daripada gambar originalnya.

Ketika script di atas dijalankan, maka hasilnya adalah seperti tangkapan layar di bawah ini.

Hasil gambar setelah diubah menjadi grayscale

Setelah gambar menjadi grayscale, langkah selanjutnya untuk lebih menghilangkan kontur pada gambar, kita akan memblur gambar tersebut. Oleh karena itu, langkah selanjutnya adalah memberikan efek blur pada gambar.

Memberikan Filter Blur Pada Gambar

Tujuan dari langkah ini adalah “makin membuat buram” gambar sehingga akan menyisakan kontur terluarnya saja. Sehingga, untuk melakukannya kita harus menggunakan filter blur. Ada beberapa filter blur yang dapat kita gunakan, namun khusus pada kasus ini kita gunakan filter GaussianBlur(). Untuk memberikan efek blur ini, ketikkan kode berikut.

blurred = cv.GaussianBlur(grey, (17, 17), 0)

Masing-masing flags pada parameter filter GaussianBlur memiliki arti tersendiri yang akan kita bahas di postingan yang lain. Karena jika kita bahas di postingan ini, ditakutkan post akan semakin panjang.

Dapat kita lihat pada baris kode di atas, bahwa gambar hasi pemberian filter blur disimpan di dalam sebuah variabel. Mengapa? Ya, karena gambar hasil “pembluran” ini akan diproses lebih lanjut hingga script dapat mendeteksi obyek dan menghitungnya. Namun, jika kita ingin menampilkannya secara terpisah, maka kita bisa menggunakan fungsi imshow() seperti halnya langkah-langkah sebelumnya.

Hasil akhir script hingga tahap ini adalah sebagai berikut.

import cv2 as cv

img = cv.imread("coin_test.jpeg")

height, width = img.shape[:2]
res = cv.resize(img,(width/2, height/2), interpolation = cv.INTER_LINEAR)
cv.imshow("Resized Images", res)

grey = cv.cvtColor(res, cv.COLOR_BGR2GRAY)
cv.imshow("Grayscale Images", grey)

blurred = cv.GaussianBlur(grey, (17, 17), 0)
cv.imshow("Blurred Images", blurred)

cv.waitKey(0)
cv.destroyAllWindows()

Sekarang, mari kita coba jalankan script di atas. Ketika script di atas dijalankan, maka menghasilkan seperti tangkapan layar di bawah ini.

Hasil gambar setelah diberikan filter GaussianBlur

Dari tangkapan layar di atas, kita dapat melihat hasil tiga gambar yang berbeda. Pada tampilan gambar pertama, merupakan gambar asli yang di ubah dimensinya, pada tampilan gambar kedua, merupakan gambar yang telah diubah menjadi gambar grayscale, dan pada tampilan gambar ketiga, merupakan gambar yang telah diberikan filter GaussianBlur.

Apakah langkah-langkahnya hanya sampai di sini saja? Tidak, belum selesai. Bahkan kita juga belum bisa mendeteksi keberadaan “uang koin” di dalam gambar ini. Oleh karena itu, kita akan berlanjut ke tahapan selanjutnya yakni mendeteksi kontur untuk menentukan tepi obyek.

Mendeteksi Contour / Edge

Pada tahapan ini, kita akan mencoba mendeteksi kontur untuk menemukan tepian obyek. Idenya adalah, semakin sederhana bentuk suatu obyek (misal berbentuk lingkaran atau kotak) maka, kontur yang terdeteksi pun sederhana, Sehingga dapat dihitung ada berapa shape yang terdeteksi di dalam gambar tersebut. Untuk dapat melakukan hal ini, kita akan menggunakan fungsi canny() dan findContours(). Pertama, kita mencari outline dari objek yang sudah kita blur tadi. Pada tahap ini kita menggunakan fungsi canny(). Oleh karena itu, tambahkan baris kode berikut ke dalam script.

outline = cv.Canny(blurred, 30, 150)

Setelah kita tambahkan baris kode di atas, kita sudah dapat menambahkan outline pada obyek yang sudah kita blur. Tujuannya untuk menemukan shape paling sederhana dari obyek. Namun, sampai di sini, belum cukup. Kita harus mencari kontur outline hasil dari fungsi canny(). Untuk itu, kita gunakan fungsi findContours(). Tambahkan kode berikut ke dalam script.

(cnts, _) = cv.findContours(outline, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)

Dari fungsi di atas, kita mencoba mencari kontur terluar suatu obyek yang sudah dideteksi oleh fungsi canny() dan menggunakan pendekatan pencarian kontur paling sederhana untuk mempercepat proses.

Nah, sampai di sini, kita sudah bisa memperoleh ada berapa koin yang terdeteksi pada gambar tersebut. Untuk mengetahui berapa jumlah koin yang terdeteksi, kita panggil fungsi print untk mencetak panjang variabel cnts.

print("Jumlah koin: %i " % len(cnts))

Sehingga, sampai di tahap ini script yang sudah kita buat adalah seperti di bawah ini.

import cv2 as cv

img = cv.imread("coin_test.jpeg")

height, width = img.shape[:2]
res = cv.resize(img,(width/2, height/2), interpolation = cv.INTER_LINEAR)
cv.imshow("Resized Images", res)

grey = cv.cvtColor(res, cv.COLOR_BGR2GRAY)
cv.imshow("Grayscale Images", grey)

blurred = cv.GaussianBlur(grey, (17, 17), 0)
cv.imshow("Blurred Images", blurred)

outline = cv.Canny(blurred, 30, 150)
(cnts, _) = cv.findContours(outline, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)

print("Jumlah koin: %i " % len(cnts))

cv.waitKey(0)
cv.destroyAllWindows()

Apabila kita jalankan, maka pada console akan menampilkan jumlah koin seperti tangkapan layar di bawah ini.

Jumlah koin ditampilkan melalui console

Sampai di tahap ini, sebenarnya program kita sudah jadi. Namun, kita belum mengetahuo bagaimana program mendeteksi koin. Untuk itu, kita lanjutkan ke tahap selanjutnya yakni menggambar garis pada kontur.

Menggambar Garis

Pada tahap ini, kita akan lebih menyempurnakan program yang sudah kita buat. Menyempurnakan di sini maksudnya adalah menambahkan satu baris kode lagi yang memungkinkan kita untuk melihat hasil akhir dari program ini. Pada tahapan sebelumnya kita memang sudah mendapatkan hasil akhir berupa jumlah koin yang terdeteksi pada suatu gambar. Namun, kita belum benar – benar mengetahui apa yang terjadi pada gambar yang sudah diolah dengan menggunakan openCV hingga program dapat menghitung koin yang terdapat pada gambar. Oleh karena itu, di tahap ini kita akan menambahkan satu tampilan lagi yang isinya adalah berupa gambar hasil filter Gaussian Blur ditambah dengan garis tampak yang mengikuti kontur sederhana dari fungsi findContours(). Tambahkan satu baris berikut ini pada script.

res = cv.drawContours(res, cnts, -1, (0, 255, 0), 2)

Sehingga pada tahap ini, kode pada script sudah menjadi seperti ini.

import cv2 as cv

img = cv.imread("coin_test.jpeg")

height, width = img.shape[:2]
res = cv.resize(img,(width/2, height/2), interpolation = cv.INTER_LINEAR)
cv.imshow("Resized Images", res)

grey = cv.cvtColor(res, cv.COLOR_BGR2GRAY)
cv.imshow("Grayscale Images", grey)

blurred = cv.GaussianBlur(grey, (17, 17), 0)
cv.imshow("Blurred Images", blurred)

outline = cv.Canny(blurred, 30, 150)
(cnts, _) = cv.findContours(outline, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)

res = cv.drawContours(res, cnts, -1, (0, 255, 0), 2)
cv.imshow("Final Results", res)

print("Jumlah koin: %i " % len(cnts))

cv.waitKey(0)
cv.destroyAllWindows()

Dapat Anda lihat, pada script di atas, saya menambahkan fungsi drawContours() yang berfungsi untuk menggambar garis disekitar kontur sederhana yang sudah ditemukan dan digambar secara maya oleh fungsi findContours(). Warna yang digunakan untuk garis tersebut adalah RGB hijau sehingga kontras dengan warna gambar yang diolah. Ketika script di atas dijalankan, maka hasilnya adalah seperti tangkapan layar di bawah ini.

Setelah diberikan garis warna hijau, kini tampak hasil akhir koin yang terdeteksi

Nah, sampai di sini nih, program kita sudah makin sempurna. Tapi, kita akan menyempurnakannya lagi yakni dengan menambahkan teks hasil deteksi koin ke dalam gambarnya langsung. Bagaimana caranya? Ikuti tahap selanjutnya.

Menuliskan Teks Pada Gambar

Pada langkah ini, kita hanya akan secara khusus menambahkan teks pada gambar. Bagaimana caranya? tambahkan kode di bawah ini pada script. Letakkan sebelum imshow() terakhir.

res = cv.putText(res, "Jumlah koin: %i " % len(cnts), (10,30), cv.FONT_HERSHEY_SIMPLEX, 1, (0,0,0), 2, cv.LINE_AA)

Sehingga script terakhir pada tahap ini adalah sebagai berikut.

import cv2 as cv

img = cv.imread("coin_test.jpeg")

height, width = img.shape[:2]
res = cv.resize(img,(width/2, height/2), interpolation = cv.INTER_LINEAR)
cv.imshow("Resized Images", res)

grey = cv.cvtColor(res, cv.COLOR_BGR2GRAY)
cv.imshow("Grayscale Images", grey)

blurred = cv.GaussianBlur(grey, (17, 17), 0)
cv.imshow("Blurred Images", blurred)

outline = cv.Canny(blurred, 30, 150)
(cnts, _) = cv.findContours(outline, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)

res = cv.drawContours(res, cnts, -1, (0, 255, 0), 2)
res = cv.putText(res, "Jumlah koin: %i " % len(cnts), (10,30), cv.FONT_HERSHEY_SIMPLEX, 1, (0,0,0), 2, cv.LINE_AA)
cv.imshow("Final Results", res)

print("Jumlah koin: %i " % len(cnts))

cv.waitKey(0)
cv.destroyAllWindows()

Kemudian, apabila script di atas kita jalankan maka tampilannya akan menjadi seperti tangkapan layar di bawah ini.

Tampilan hasil program setelah ditambah script menulis teks pada gambar

Akhirnya kita hampir tiba di tahap yang benar – benar akhir. Yakni merapikan program. Untuk itu, kita lanjutkan ke tahap selanjutnya.

Merapikan Program

Pada tahap terakhir ini, selain kita akan merapikan program, kita juga akan menyimpan gambar hasil analisis ke dalam komputer kita. Pertama, kita akan merapikan program terlebih dahulu. Untuk itu, kita akan menghapus seluruh fungsi imshow() kecuali fungsi imshow() paling akhir. Kita juga akan menghapus fungsi print() sehingga tidak ada lagi pesan yang ditampilkan di console. Hasil akhir script setelah dirapikan adalah sebagai berikut.

import cv2 as cv

img = cv.imread("coin_test.jpeg")

height, width = img.shape[:2]
res = cv.resize(img,(width/2, height/2), interpolation = cv.INTER_LINEAR)

grey = cv.cvtColor(res, cv.COLOR_BGR2GRAY)

blurred = cv.GaussianBlur(grey, (17, 17), 0)

outline = cv.Canny(blurred, 30, 150)
(cnts, _) = cv.findContours(outline, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)

res = cv.drawContours(res, cnts, -1, (0, 255, 0), 2)
res = cv.putText(res, "Jumlah koin: %i " % len(cnts), (10,30), cv.FONT_HERSHEY_SIMPLEX, 1, (0,0,0), 2, cv.LINE_AA)
cv.imshow("Final Results", res)

cv.waitKey(0)
cv.destroyAllWindows()

Selanjutnya, kita akan menyimpan hasil akhir analisis gambar ke dalam komputer kita. Oleh karena itu, kita memerlukan satu fungsi yakni imwrite(). Tambahkan kode berikut sebelum fungsi imshow().

cv.imwrite('hasildeteksi.jpeg', res)

Sehingga, secara utuh, script kita menjadi seperti di bawah ini.

import cv2 as cv

img = cv.imread("coin_test.jpeg")

height, width = img.shape[:2]
res = cv.resize(img,(width/2, height/2), interpolation = cv.INTER_LINEAR)

grey = cv.cvtColor(res, cv.COLOR_BGR2GRAY)

blurred = cv.GaussianBlur(grey, (17, 17), 0)

outline = cv.Canny(blurred, 30, 150)
(cnts, _) = cv.findContours(outline, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)

res = cv.drawContours(res, cnts, -1, (0, 255, 0), 2)
res = cv.putText(res, "Jumlah koin: %i " % len(cnts), (10,30), cv.FONT_HERSHEY_SIMPLEX, 1, (0,0,0), 2, cv.LINE_AA)
cv.imwrite('hasildeteksi.jpeg', res)
cv.imshow("Final Results", res)

cv.waitKey(0)
cv.destroyAllWindows()

Terakhir, ketika script di atas dijalankan, maka akan diperoleh tampilan seperti tangkapan layar di bawah ini.

Hasil akhir program pendeteksi dan penghitung koin sederhana

Pada tangkapan layar di atas, kita dapat melihat juga bahwa ada satu file gambar baru yang dihasilkan. Yakni hasildeteksi.jpeg. Apabila file tersebut kita buka, maka ditampilkan file gambar asli lengkap dengan hasil analisisnya.

Gambar hasildeteksi.jpeg

Baiklah, sampai di sini program kita telah selesai dibuat.


Demikian postingan saya tentang Membuat Penghitung Koin Sederhana Dengan OpenCV. Semoga postingan ini bermanfaat bagi Anda yang ingin belajar tentang OpenCV. Apabila Anda masih menemukan kendala dalam membuat program ini, Anda dapat meninggalkan pertanyan di kolom komentar. Jika Anda ingin mencuplik sebagian teks dari artikel ini, Saya mohon jangan lupa sertakan sumber dan penulisnya.

Terima Kasih…. ^_^


DOWNLOAD

Exit mobile version