การหาชนิดของเหรียญด้วยการประมวลผลภาพ (image processing) โดยใช้ภาษา Python
Tags: ai, python
Published: 2023-04-11 03:47:13

เมื่อคุณต้องการนับสิ่งของที่มีขนาดต่างกันจากภาพที่เราถ่ายมา เช่น รูปของใช้ รูปคนที่มีความสูงต่างกัน หรือรูปภาพของเหรียญขนาดที่แตกต่างกัน คุณสามารถทำได้ง่ายๆเพียงแค่ใช้ image processing 

> 
บทความนี้จะมาบอกเคล็ดลับในการใช้ image processing ในการหาขนาดของเหรียญและแสดงชนิดของเหรียญ โดยใช้ภาษา Python และรันโค้ดผ่าน Google Colab
> 

ตัวอย่างรูปภาพ


![ภาพเหรียญขนาดต่างๆ](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ssf344j5n9uzqfqu6w0a.jpg)


_คุณสามารถทำตามขั้นตอนได้ดังนี้_

**ขั้นตอนที่ 1** นำเข้าไลบรารี OpenCV และ Matplotlib

การ import library OpenCV (Open Source Computer Vision Library) เป็น library สำหรับการประมวลผลภาพและวิดีโอ ส่วนการ import module pyplot ซึ่งเป็นส่วนหนึ่งของ library Matplotlib จะเป็น library สำหรับการวาดกราฟและภาพแสดงผลใน Python.
```
import cv2
from matplotlib import pyplot as plt
```


**ขั้นตอนที่ 2** อัปโหลดไฟล์รูปภาพ
อัพโหลดไฟล์จาก local machine เข้าสู่ Google Colaboratory โดยจะมีการเปิดหน้าต่างเลือกไฟล์ขึ้นมาให้เลือก และหลังจากเลือกไฟล์เสร็จเรียบร้อยแล้ว ไฟล์จะถูกอัพโหลดขึ้น Colab และบันทึกไว้ในตัวแปร uploaded ซึ่งจะเป็น dictionary ที่เก็บชื่อไฟล์และข้อมูลไฟล์ของไฟล์ที่ถูกอัพโหลด
```
from google.colab import files
uploaded = files.upload()
```
_ภาพตัวอย่าง_
![ภาพแสดงเมื่อ upload images เสร็จ](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p46u8srkaiweou0j0mfq.jpg)


**ขั้นตอนที่ 3** ประมวลผลภาพ
อ่านภาพที่ชื่อว่า "coin.jpg" ในรูปแบบภาพสีและเก็บไว้ในตัวแปร coin_colorจากนั้นแสดงภาพที่เก็บไว้ในตัวแปร coin_color ที่เป็นภาพสี ด้วย Matplotlib โดยไม่ได้แปลงเป็นภาพขาว-ดำ

```
coin_color = cv2.imread('coin.jpg')
plt.imshow(coin_color)
plt.show()
```
_ภาพตัวอย่าง_

![ภาพโชว์รูปที่นำเข้า](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6xrp6oi042lc9naqo33f.png)

- ใช้ไลบรารี OpenCV แปลงรูปภาพจากสีเป็นโทนเทา (grayscale) และทำการทำ Thresholding บนรูปภาพ 

- 
การกำหนด threshold ที่เหมาะสมจะต้องพิจารณาจากคุณสมบัติของภาพนั้น ๆ เช่น ระดับความเข้มของพื้นหลังและวัตถุที่ต้องการจะเห็น หรือลักษณะของแสงที่เป็นสาเหตุให้เกิดเงาโค้งบนวัตถุ
 

## 
โดยจะกำนหนดสีดำ 235 และสีขาว 255 ใช้ cv2.THRESH_BINARY_INV ซึ่งหมายความว่าจะกลับสีของภาพจากดำเป็นขาว และขาวเป็นดำ และแสดงผลรูปภาพที่ได้หลังจาก Thresholding แล้ว 

```
coin_gray = cv2.cvtColor(coin_color,cv2.COLOR_BGR2GRAY)
ret,coin_th = cv2.threshold(coin_gray,235,255,cv2.THRESH_BINARY_INV)
plt.imshow(coin_th)
plt.show()
```
_ภาพตัวอย่าง_

![ภาพที่ถูกปรับสีเป็นตรงข้าม](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kx521suluqs68948ghkw.png)

ค้นหาเส้น contour บนภาพที่ได้ทำ thresholding ไว้ก่อนหน้านี้ ก็คือ coin_th
```
contours, _ = cv2.findContours(coin_th,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)
```


**ขั้นตอนที่ 4** สร้างตัวแปรและสร้างเงื่อนไข

coin_type =>_กำหนดชนิดของเหรียญ_

- โค้ดจะวนลูปผ่านทุกๆ contour ที่ได้จากการตรวจจับของ OpenCV แสดงผลชนิดของเหรียญ ใช้ขนาดของ contour เป็นตัวกำหนดชนิดของเหรียญ โดยใค้ดนี้ `cv2.putText(coin_color,str(rect[2]),(rect[0],rect[1]),1,cv2.FONT_HERSHEY_PLAIN,(255,0,0),2)`เมื่อเรารู้ขนาดของสิ่งหรือเหรียญที่เราต้องการแล้วให้คอมเม้นต์ไว้เพื่อไม่ให้ค่า contour แสด'
- สร้างเงื่อนไขจากค่า contour ที่ได้มาตามขนาดของเหรียญเพื่อแสดงชนิดของเหรียญและวาดสี่เหลี่ยมล้อมรอบ contour ด้วยสีเขียว และเขียนข้อความระบุชนิดเป็นสีม่วง

```
for cnt in contours:
    rect = cv2.boundingRect(cnt)
    cv2.rectangle(coin_color,rect,(0,255,0),2)
    # cv2.putText(coin_color,str(rect[2]),(rect[0],rect[1]),1,cv2.FONT_HERSHEY_PLAIN,(255,0,0),2)
    
    if(rect[2]>110):
        coin_type = "10 Bath"
    elif(rect[2] >100):
        coin_type = "5 Bath"
    elif(rect[2]>80):
        coin_type = "1 Bath"
    elif(rect[2]>60):
        coin_type = "0.25 Bath"
    else:
        coin_type = " "
    cv2.putText(coin_color,coin_type,(rect[0],rect[1]),1,cv2.FONT_HERSHEY_PLAIN,(0,0,255),1)
```

**ขั้นตอนที่ 5** แสดงผลลัพธ์
 

- จะแสดงภาพ coin_color ซึ่งเป็นภาพที่มีการวาดสี่เหลี่ยมล้อมรอบ contour และเขียนข้อความระบุชนิดของเหรียญที่มีสีม่วง 

- cv2.waitKey(0) เป็นฟังก์ชันที่ใช้รอรับ key input จากผู้ใช้ ถ้าไม่มี key input ใดๆ ระบบจะเข้าสู่สถานะ wait จนกว่าผู้ใช้จะกดปุ่มใดๆ บนคีย์บอร์ด หลังจากผู้ใช้กดปุ่มเรียบร้อยแล้ว ฟังก์ชันจะคืนค่าตาม key code ของปุ่มที่ผู้ใช้กด ถ้าไม่มีการกดปุ่มใดๆ ฟังก์ชันจะคืนค่า -1

```
plt.imshow(coin_color)
plt.show
cv2.waitKey(0)
```

_ภาพตัวอย่าง_

![ภาพแสดงผลลัพธ์](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4y9ome66cjud6g3s9rmm.png)
**สรุผผล**
จะได้ภาพเหรียญที่มีการประมวลผลภาพ (image processing) และแสดงชนิดของเหรียญตามขนาดต่างๆ ด้วยแนวคิดนี้เราสามารถนำไปใช้ในการหาขนาดหรือการนับจำนวนของสิ่งของได้

**REFERENCE**
_ข้อมูลและโค้ดนำมาจากการเรียนการศึกษาในรายวิชาMMI 322
MEDICAL IMAGE PROCESSING_