บันทึก training data science EP 12: skimage – ภาพจำยังชัดเจน
ตอนก่อนหน้า: บันทึก training data science EP 11: NLP & Spacy – สอนภาษารัก
ความสามารถอีกแขนงนึงของ Data Science คือการวิเคราะห์รูปภาพนะฮะ และแน่นอน Python มี Library ให้เราใช้งานเกี่ยวกับการประมวลผลภาพฮะ
ก่อนอื่นต้องเข้าใจก่อนว่า รูปภาพเนี่ยมันถูกประมวลผลในคอมพิวเตอร์เป็นตัวเลข รูปภาพสีโดยทั่วไปก็เป็น 24 บิตมาจาก 3 สี (RGB = Red, Green ,Blue) ซึ่งเป็นระบบสีแบบนึง คูณกับจำนวน 8 บิตต่อ 1 pixel ในรูปขาวดำฮะ ดังนั้นในหนึ่งจุด pixel เล็กๆ เนี่ย ข้อมูลรูปภาพที่เป็นสีนั้นจึงมีขนาดเท่ากับ 24 บิตหรือ 3 ไบท์ ( 1 ไบท์เท่ากับ 8 บิต) นั่นเอง
ทีนี้ในสเกลสีของระบบ RGB ก็จะแบ่งย่อยๆ เป็น 256 ระดับ นับตั้งแต่ 0 จนถึง 255 ตัวอย่างเช่น
ถ้าเราเน้นสีแดงจนเด่นไปเลยค่าเดียว สีที่ได้ก็จะเป็นสีแดงแป๊ด (255, 0, 0) แต่ถ้าเราเติมสีเขียวไป เราจะได้สีผสม นั่นก็คือสีเหลืองฮะ (255, 255, 0) แต่ถ้าเราลดค่าลง เราจะได้สีที่มืดลง จนถึงสีดำที่มีค่า (0, 0, 0) กลับกัน สีขาวก็มีค่า (255, 255, 255) นั่นเองฮะ
skimage
คือ Library ตัวที่ว่านั่นแหละฮะ มันสามารถคำนวณรูปภาพมาได้ เพื่อประมวลผลในงานอื่นๆ เราติดตั้งโดยดูจากลิงก์นี้ได้เลยฮะ https://scikit-image.org/docs/stable/install.html
และแน่นอน เราก็ต้อง import skimage
กันก่อน และเราก็มี matplotlib.pyplot
เพื่อแสดงผลภาพได้จาก Jupyter notebook โดยตรงฮะ
เปิดรูปที่มี
ใช้คำสั่งนี้เพื่อเปิดไฟล์รูปฮะ
lynx = skimage.io.imread(img)
plt.imshow(lynx)
ตัวแปร lynx เนี่ยจะเก็บข้อมูลเป็น array of integers ตามค่าสีที่ได้เล่าไปข้างบนแล้วนะฮะ ด้วยความเป็น array นี่เอง เราก็ใช้คำสั่ง .shape
เพื่อดูขนาดไฟล์ได้ด้วยแหละ ตามรูปเลย ไฟล์นี้มีความสูง (หรือก็คือจำนวนแถว) เป็น 423 pixel ความยาว (จำนวนคอลัมน์) เท่ากับ 640 pixel ส่วนเลข 3 นั่นคือแม่สีทั้งสามฮะ
และเมื่อมันเป็นตัวเลข เราก็เอาตัวเลขอะไรไปแปะเพื่อเปลี่ยนสีมันได้ ตามรูปข้างล่างฮะ
for i in range(30, 60):
for j in range(60, 90):
lynx[i,j] = [60, 60, 60]
plt.imshow(lynx)
คุมโทนสีให้เป็นขาวดำ
ใช้คำสั่งนี้เพื่อเปลี่ยนรูปสีให้เป็นขาวดำคุมโทนได้ง่ายๆ เลยฮะ
import skimage.color
plt.imshow(skimage.color.rgb2gray(lynx), cmap='gray')
ย่อขยายได้ตามใจ
คำสั่ง skimage.transform.resize()
ทำให้รูปที่ออกมามีขนาดตามที่เราต้องการ แบบยืดหดขยายอะไรแบบนั้นฮะ โดยสังเกตว่า เราใช้ .shape[0] * 2
เพื่อให้ความสูงเพิ่มขึ้นสองเท่า และ .shape[1] * 1.5
เพื่อให้ความยาวเพิ่มขึ้นอีกครึ่งนึงฮะ
import skimage.transform
plt.imshow(
skimage.transform.resize(lynx, (lynx.shape[0] * 2, lynx.shape[1] * 1.5))
)
สร้างรูปทรงเรขาคณิต
เมื่อเรา import skimage.morphology
เราจะมีฟังก์ชันสร้างรูปเรขาคณิตฮะ ดังตัวอย่างข้างล่างนี่เลย
star
diamond
rectangle
disk
เพิ่มฟิลเตอร์เบลอๆ
เราจะใช้ skimage.filter
เพื่อเพิ่มรูปเรขาคณิตไปแปะบนรูปนะฮะ ผลคือรูปจะดูเบลอๆ ตามตัวอย่างข้างล่างนี้เลยฮะ
skimage.filter.median()
+ disk(5)
skimage.filter.median()
+ disk(10)
skimage.filter.median()
+ diamond(10)
skimage.filter.threshold_local()
และมันมีฟังก์ชัน .try_all_threshold()
เพื่อดูผลของฟิลเตอร์หลายๆ แบบฮะ
skimage.filters.try_all_threshold(skimage.color.rgb2gray(lynx))
เทียบความแตกต่าง
สมมติเรามีรูปอยู่สามรูปดังนี้ฮะ
“latest”
“latest_2nd”
“first”
เราสามารถวัดความแตกต่างระหว่างสองรูปได้แบบนี้ฮะ
import skimage.metrics
skimage.metrics.mean_squared_error(a, b)
.mean_squared_error()
ใช้สำหรับวัดค่า Mean-Squared Error (MSE) โดยพิจารณาที่ข้อมูล pixel ฮะ ยิ่งมีค่ามาก แปลว่าสองรูปนี้แตกต่างกันมากฮะ
import skimage.metrics
skimage.metrics.structural_similarity(a, b, multichannel=True)
.structural_similarity()
คำนวณค่า Structural Similarity Index Measure (SSIM) ซึ่งคำนวณไปถึงค่า noise และ brightness ด้วยฮะ ยิ่งมีค่ามาก แปลว่าสองรูปนี้คล้ายกันมากฮะ
เราจะกำหนดรูปสามรูปไว้ดังนี้นะฮะ
จากรูปข้างบนจะเห็นได้เลยฮะว่า เทียบที่ค่า MSE และ SSIM แล้วนั้น รูป “latest” คล้ายกับรูป “latest_2nd” มากกว่ารูป “first” ฮะ
ความแตกต่างอย่างโดดเด่น
จากการคำนวณหาความแตกต่างระหว่างสองรูปแล้ว คราวนี้เราจะมาลองหาว่าจุดไหนของรูปที่ต่างกันให้เราเห็นชัดๆ บ้างฮะ
เราจะหาด้วยวิธีง่ายๆ นั่นคือ หา pixel ตำแหน่งเดียวกัน แต่มีค่าที่ต่างกันของรูปสองรูปน้อยกว่าค่าที่กำหนด ในที่นี้คือ 0.1 ฮะ ซึ่งรอบนี้เราจะใช้สองรูปแรกฮะ นั่นคือ “latest” กับ “latest_2nd”
change_px = np.abs(latest_gray - latest_2nd_gray) < 0.1
plt.imshow(change_px, cmap='gray')
ต่อมาเราก็จะลบ "รู" ที่มีขนาดเล็กกว่าค่าที่กำหนด นั่นคือ "area_threshold" ซึ่งในที่นี้เป็นค่า 400 pixel นั่นเองฮะ
ถึงตรงนี้ เราพอจะมองออกแล้วนะฮะว่าสองรูปนั้นต่างกันตรง "ถนน" นั่นเองฮะ เพราะถนนในรูปมีการเปลี่ยนแปลงจากรถต่างๆ
road = skimage.morphology.remove_small_holes(change_px, area-threshole=400)
และสุดท้ายเราก็ตกแต่ง "ถนน" โดยปรับค่าสีของ pixel ให้กลืนสีสว่างของ pixel ใกล้ๆ เป็นสีมืดฮะ
road = skimage.morphology.erosion(road)
Reference links:
- https://scikit-image.org/docs/stable/api/api.html
- http://scipy-lectures.org/packages/scikit-image/index.html
นี่ก็เป็นความสามารถเล็กๆ น้อยๆ ของ library skimage ตัวนี้นะฮะ
เจอกันใหม่ บล็อกหน้าฮะ
บาย~
ตอนต่อไป: บันทึก training data science EP 13: Regularization – Optimization ด้วย Regularization