Xác định gam màu trong MV Nơi này có anh – Sơn Tùng M-TP

color-palettes-noi-nay-co-anh

Lấy cảm hứng từ bài viết NHỮNG GAM MÀU TÌNH YÊU ĐẦY CẢM HỨNG TRONG MV NƠI NÀY CÓ ANH – SƠN TÙNG M-TP. Trong bài viết này, tôi sẽ hướng dẫn nhanh mọi người cách áp dụng kĩ thuật color clustering (image segmentation) để rút ra gam màu chính trong từng cảnh quay của MV. Cụ thể, ta sẽ sử dụng thuật toán k-means clustering. Đây là thuật toán đơn giản đủ để ta thực hiện tác vụ này.

Source code: Github.

Đầu tiên, ta sẽ import các libraries cần thiết.

import argparse
import os

import cv2
import numpy as np
from sklearn.cluster import KMeans

Ta sẽ nhận tham số từ dòng lệnh gồm folder chứa ảnh và số cluster/gam màu cần rút trích.

ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True, help="Path to the image")
ap.add_argument("-c", "--clusters", required=True, type=int, help="# of clusters")
args = vars(ap.parse_args())

Sau đó, ta sẽ đọc các file ảnh từ folder cho trước.

for f in os.listdir(args["image"]):
if f.endswith(".png"):
img_path = args["image"] + "/" + f
img_name = os.path.splitext(f)[0]

# load the image
image = cv2.imread(img_path)

Do k-means clustering đòi hỏi đầu vào là mảng các vector màu nên ta sẽ chuyển đổi ảnh đầu vào thành vector Mx3. Trong đó, M là số lượng pixel trong ảnh, 3 là giá trị màu tương ứng cho Blue, Green, Red (thứ tự màu trong OpenCV là BGR chứ không phải RGB). Chú ý, ta không nhầm lẫn vector màu với vector toạ độ trong ảnh. Ở đây, ta dùng vector gồm 3 giá trị màu, không phải vector gồm 2 giá trị của toạ độ (x, y).

# reshape the image to be a list of pixels
image = image.reshape((image.shape[0] * image.shape[1], 3))

[[212 209 211]
[212 209 211]
[212 209 211]
...,
[ 80  76  84]
[ 26   3  38]
[153 152 155]]

Tiếp đến, ta sẽ gom nhóm các pixel màu này theo số cluster đã xác định.

# cluster the pixel intensities
clt = KMeans(n_clusters=args["clusters"])
clt.fit(image)

Ta tiến hành tạo color palette gồm các gam màu xuất hiện trong ảnh. Mặc định, ta có ảnh 600×100 và chia đều diện tích hiển thị này cho từng cluster. Đối với từng màu đại diện của cluster/centroid, ta hiển thị vùng này bằng màu centroid của cluster đó.

def get_color_palette(k_cluster, centroids, palette_w=600, palette_h=100):
# initialize the color palette
text_y = int(palette_h / 2)
palette = np.zeros((palette_h, palette_w, 3), dtype="uint8")
startX = 0

# loop over the color of each cluster
for color in centroids:
# plot the relative percentage of each cluster
endX = startX + (1.0 / k_cluster * palette_w)
text_x = int(startX + 15)

bgr_code = str(color.astype("uint8").tolist()[0]) + ","
bgr_code += str(color.astype("uint8").tolist()[1]) + ","
bgr_code += str(color.astype("uint8").tolist()[2])

cv2.rectangle(palette, (int(startX), 0), (int(endX), palette_h), color.astype("uint8").tolist(), -1)
cv2.putText(palette, bgr_code, (text_x, text_y), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 200))
startX = endX

# return the palette
return palette

# representing the number of pixels labeled to each color
palette = get_color_palette(args["clusters"], clt.cluster_centers_)

Cuối cùng, ta lưu color pallete đã tìm được vào folder fig_out/

# save color palette
fig_out = "fig_out/color_pallete_" + img_name + ".png"
cv2.imwrite(fig_out, palette)
print("Done", f)

Như vậy, code sau khi hoàn tất sẽ trông như sau

for f in os.listdir(args["image"]):
if f.endswith(".png"):
img_path = args["image"] + "/" + f
img_name = os.path.splitext(f)[0]

# load the image
image = cv2.imread(img_path)

# reshape the image to be a list of pixels
image = image.reshape((image.shape[0] * image.shape[1], 3))

# cluster the pixel intensities
clt = KMeans(n_clusters=args["clusters"])
clt.fit(image)

# representing the number of pixels labeled to each color
palette = get_color_palette(args["clusters"], clt.cluster_centers_)

# save color palette
fig_out = "fig_out/color_pallete_" + img_name + ".png"
cv2.imwrite(fig_out, palette)
print("Done", f)

Để chạy chương trình, ta thực thi dòng lệnh như bên dưới

python color_kmeans.py --image son_tung.png --clusters 5

Như vậy, ta sẽ có bảng màu color palette tương ứng cho từng ảnh.

Sau bài viết này, các bạn có thể áp dụng cho các tập ảnh khác như: lấy gam màu của một trang web, phân đoạn ảnh để xác định một đối tượng nào đó trong ảnh, phát hiện điểm dị biệt trong các thiết bị điện tử, …

Nguồn tham khảo:

Advertisements

Trả lời

Mời bạn điền thông tin vào ô dưới đây hoặc kích vào một biểu tượng để đăng nhập:

WordPress.com Logo

Bạn đang bình luận bằng tài khoản WordPress.com Đăng xuất / Thay đổi )

Twitter picture

Bạn đang bình luận bằng tài khoản Twitter Đăng xuất / Thay đổi )

Facebook photo

Bạn đang bình luận bằng tài khoản Facebook Đăng xuất / Thay đổi )

Google+ photo

Bạn đang bình luận bằng tài khoản Google+ Đăng xuất / Thay đổi )

Connecting to %s