สายกราฟฟิก หรือสาย Web designer คนไหนเคยอยากคุมโทนสีตามเรฟที่เป็นรูปภาพ แต่ดูดสีออกมายังไงก็ไม่ได้ดั่งใจไหมคะ? เดี๋ยวเราจะพามาให้รู้จักกับ K-means Algorithm ที่จะทำให้ชีวิตเราง่ายขึ้นเยอะะ เพราะสามารถดูดสีออกมาได้เป๊ะอย่างงี้ 👍🏼💯
บทความนี้เราจะทำการดูดสีรูปภาพโดยใช้ K-mean Clustering ( ในส่วนของ Image Processing ☝🏼🖼️ ) ในการตรวจจับกลุ่มสีต่าง ๆ ในรูป เพื่อนำค่า RGB ของจุดศูนย์กลางของกลุ่มสีนั้น ๆ มาสร้างเป็นโค้ดสี โดยทั้งหมดเราจะรันโค้ดผ่าน Google Colab
✍🏻 ขั้นตอนที่ 1 : Import Libraries
ทำการเรียกใช้ไลบรารีที่จำเป็น ดังนี้
- Scikit-learn ไลบรารีหลักสำหรับ Machine Learning ในภาษา Python ที่มีฟังก์ชันการทำงานที่ครอบคลุม และรองรับอัลกอริธึมที่หลากหลาย ซึ่งแน่นอนว่าการจัดกลุ่ม (Clustering) ก็เป็นหนึ่งในนั้น
- Matplotlib สำหรับสร้างกราฟวงกลม (Pie Chart)
- NumPy (Numerical Python) สำหรับการจัดการ Array
- OpenCV (Open Source Computer Vision Library) สำหรับการจัดการรูปภาพ
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
import numpy as np
import cv2
from collections import Counter
from skimage.color import rgb2lab, deltaE_cie76
import os
%matplotlib inline
✍🏻 ขั้นตอนที่ 2 : นำเข้าข้อมูลรูปภาพ
เลือกรูปที่สนใจมา 1 รูป โดยในตัวอย่างนี้จะใช้เป็นรูปน้องหนูเจอรี่ 🤓👇🏻
เมื่อนำรูปจากไดรฟ์เข้ามาแล้ว จะทำการอ่านและเก็บไว้ในตัวแปร image
from google.colab import drive
drive.mount('/content/drive')
file_path = '/content/drive/MyDrive/hey.JPG'
image = cv2.imread(file_path)
print("The type of this input is {}".format(type(image)))
print("Shape: {}".format(image.shape))
plt.imshow(image)
ผลลัพธ์ที่ได้
แต่เราจะสังเกตได้ว่ารูปที่ได้สีจะเพี้ยนไปจากรูปตัวอย่าง เพราะว่าการอ่านรูปของ OpenCV โดย default ทำให้เราได้รูปออกมาเป็น BGR
ดังนั้น เราจะทำการเปลี่ยนให้เป็น RGB ด้วย
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
plt.imshow(image)
เมื่อสีรูปตรงกับต้นฉบับแล้ว เราก็ไปดูดสีกันได้เลยย 🙌🏼
ขั้นตอนที่ 3 : สร้างฟังก์ชันจำแนกสี
- สร้างฟังก์ชันให้สีที่จำแนกออกมาอยู่ในรูปของค่า hex (โค้ดสี)
def RGB2HEX(color):
return "#{:02x}{:02x}{:02x}".format(int(color[0]), int(color[1]), int(color[2]))
- สร้างฟังก์ชันวิเคราะห์ค่าสีออกมา
def get_colors(image, number_of_colors, show_chart):
modified_image = cv2.resize(image, (600, 400), interpolation = cv2.INTER_AREA)
modified_image = modified_image.reshape(modified_image.shape[0]*modified_image.shape[1], 3)
clf = KMeans(n_clusters = number_of_colors)
labels = clf.fit_predict(modified_image)
counts = Counter(labels)
# sort to ensure correct color percentage
counts = dict(sorted(counts.items()))
center_colors = clf.cluster_centers_
# We get ordered colors by iterating through the keys
ordered_colors = [center_colors[i] for i in counts.keys()]
hex_colors = [RGB2HEX(ordered_colors[i]) for i in counts.keys()]
rgb_colors = [ordered_colors[i] for i in counts.keys()]
if (show_chart):
plt.figure(figsize = (8, 6))
plt.pie(counts.values(), labels = hex_colors, colors = hex_colors)
return rgb_colors
ขั้นตอนที่ 4 : ทดลองนำมาใช้กับรูปตัวอย่าง
get_colors(image, 8, True)
ผลลัพธ์ที่ได้
❔ คำถามชวนคิด ❔
จากผลลัพธ์ข้างต้น คิดว่าถ้าเราสามารถดูดสีจากรูปได้ เราจะสามารถดูดรูปจากสีได้เหมือนกันไหม 🧐
มาลองดูกันน! 😼💪🏻
ขั้นตอนสำหรับการค้นหารูปจากโค้ดสี
- ก่อนอื่นเราจะต้องมีคลังรูปภาพไว้ใน images ก่อน
IMAGE_DIRECTORY = '/content/drive/MyDrive/gallery'
COLORS = {
'RED': [255, 0, 0],
'BLUE': [0, 0, 128],
'YELLOW': [255, 255, 0]
}
images = []
for file in os.listdir(IMAGE_DIRECTORY):
if not file.startswith('.'):
images.append(get_image(os.path.join(IMAGE_DIRECTORY, file)))
ลองแสดงรูปภาพทั้งหมดในแกลลอรี่
plt.figure(figsize=(20, 10))
for i in range(len(images)):
plt.subplot(1, len(images), i+1)
plt.imshow(images[i])
- ต่อมาสร้างฟังก์ชันที่จะเลือกจับคู่สีหลัก ๆ ของรูปภาพมา 10 สี จากนั้นจะเอา 5 สีแรกจากรูปมาคำนวณหาความแตกต่างกับสีที่เราต้องการ
ซึ่งแน่นอนว่าเราไม่สามารถจับคู่ค่าสี (hex) ได้ตรงเป๊ะ ดังนั้น เราจะดูจากสัดส่วนค่าความต่างสี ถ้าน้อยแสดงว่าทั้งสองสีมีความใกล้เคียงกัน เราก็จะแสดงรูปนั้นเลย เพื่อประกาศว่าสีตรงกับรูปนี้นะ
โดยเราจะใช้ rgb2lab
เพื่อแปลงค่าให้สามารถนำมาเปรียบเทียบกันได้ และใช้ deltaE_cie76
สำหรับการหาความต่างสี ได้ดังนี้
def match_image_by_color(image, color, threshold = 60, number_of_colors = 10):
image_colors = get_colors(image, number_of_colors, False)
selected_color = rgb2lab(np.uint8(np.asarray([[color]])))
select_image = False
for i in range(number_of_colors):
curr_color = rgb2lab(np.uint8(np.asarray([[image_colors[i]]])))
diff = deltaE_cie76(selected_color, curr_color)
if (diff < threshold):
select_image = True
return select_image
def show_selected_images(images, color, threshold, colors_to_match):
index = 1
for i in range(len(images)):
selected = match_image_by_color(images[i],
color,
threshold,
colors_to_match)
if (selected):
plt.subplot(1, 5, index)
plt.imshow(images[i])
index += 1
จากนั้นทดลองหารูปที่มีสีแดง ❤️
# Search for RED
plt.figure(figsize = (20, 10))
show_selected_images(images, COLORS['RED'], 60, 5)
ผลลัพธ์ที่ได้
ทดลองหารูปที่มีสีฟ้า💙
# Search for BLUE
plt.figure(figsize = (20, 10))
show_selected_images(images, COLORS['BLUE'], 60, 5)
ผลลัพธ์ที่ได้
ทดลองหารูปที่มีสีเหลือง💛
# Search for YELLOW
plt.figure(figsize = (20, 10))
show_selected_images(images, COLORS['YELLOW'], 60, 5)
สรุปผล 👩🏻🎨🗯️
เราสามารถดึงสีมาจากรูปได้โดยการใช้ K-mean Clustering แต่ในทางกลับกันหากนำโค้ดมาทำการค้นหารูปก็อาจจะไม่สามารถทำได้ดีเท่าที่ควร เห็นได้จากตอนค้นหารูปที่มีสีฟ้า มีการแสดงทุกรูปที่มีออกมาเลย ส่วนนึงเนื่องมาจากการเทียบโค้ดสี hex ให้ตรงกันนั้นเป็นไปได้ยาก จึงง่ายต่อการคลาดเคลื่อน หรือก็คืออาจจะได้รูปที่ไม่ตรงกับสีที่ค้นหา
Reference :
Top comments (0)