دسته بندی رنگ های تصویر توسط الگوریتم K-Means
به نام خدا و با لام
در این مطلب قصد دارم کدی برای دسته بندی پیکسل های یک تصویر بنویسم. برای این کار از الگوریتم های مربوط به یادگیری ماشین استفاده خواهم کرد. ممکنه افرادی که تا به حال یادگیری ماشین انجام نداده اند با شنیدن این موضوع ناراحت بشوند. خب هیچ جای نگرانی نیست چون خودم هم بلد نیستم :))
به خاطر همین از پکیج آماده برای این منظور استفاده خواهیم کرد. K-means یک الگوریتم برای دسته بندی است. این الگوریتم، N داده را در K دسته مرتب می کند؛ بدین صورت که هر داده ای که به میانگین دسته ای نزدیک تر باشد، به آن دسته تعلق خواهد گرفت.
برای استفاده از این الگوریتم، تصویر را به حالت RGB تبدیل می کنیم. هر تصویر دارای M*N پیکسل است که هر کدام دارای سه المان Red و Geen و Blue خواهند بود. پس داده های ما برای دسته بندی، M*N پیکسل خواهد بود. برای اطلاعات بیشتر در مورد الگوریتم K-means و همچنین پکیج مربوط به آن (sklearn) توصیه می کند نگاهی به این صفحه بیاندازید. خب حرف زدن کافیه بریم سراغ کد نویسی.
1 2 3 4 5 |
# import the necessary packages from sklearn.cluster import KMeans import matplotlib.pyplot as plt import numpy as np import cv2 |
ابتدا پکیج های مورد نیاز را وارد می کنیم. sklearn.cluster برای الگوریتم K-means است. توجه داشته باشید که باید این پکیج را دانلود و نصب نمایید. از پکیج matplotlib برای رسم تصاویر استفاده خواهیم کرد. و در آخر پکیج های numpy و cv2 به ترتیب برای Numerical Processing و OpenCV هستند.
1 2 3 4 5 6 7 8 9 |
# load the image and convert it from BGR to RGB so that # we can dispaly it with matplotlib image = cv2.imread("Halo.jpg") image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # show our image plt.figure() plt.axis("off") plt.imshow(image) |
در این قسمت لازم است تا تصویر مورد نظر را بارگذاری کرده و آن را از حالت BGR به RGB تبدیل کنیم. علت این امر آن است که الگوریتم K-means براساس کانال های RGB عمل می کند و نه BGR. در پایان تصویر اصلی را نشان می دهیم..
1 2 |
# reshape the image to be a list of pixels image = image.reshape((image.shape[0] * image.shape[1], 3)) |
همان طوری که پیشتر اشاره شد داده های برنامه M*N پیکسل هستند. برای دست یابی به این لیست ضروری است که ابعاد تصویر مورد نظر را تغییر دهیم. با این کار تصویر (که آرایه ای از numpy است) به لستی از یکسل های RGB تبدیل خواهد شد.
1 2 3 |
# cluster the pixel intensities clt = KMeans(n_clusters=5) clt.fit(image) |
این دو خط از برنامه تمامی الگوریتم K-means را اجرا خواهند کرد (به همین سادگی!!). خط اول تعداد دسته ها را وارد می کنیم. با وارد کردن عدد ۵، تعداد دسته ها پنج عدد خواهد بود. با اعمال دستور fit، الگوریتم K-means را به تصویر اعمال می کنیم.
کار تمام شد!! اما اجازه بدهید برای نمایش بهتر خروجی یک چارت تولید کنیم تا خروجی زیباتر نشان داده شود.
1 2 3 4 5 6 7 8 9 10 11 12 |
def centroid_histogram(clt): # grab the number of different clusters and create a histogram # based on the number of pixels assigned to each cluster numLabels = np.arange(0, len(np.unique(clt.labels_)) + 1) (hist, _) = np.histogram(clt.labels_, bins = numLabels) # normalize the histogram, such that it sums to one hist = hist.astype("float") hist /= hist.sum() # return the histogram return hist |
تابع centroid_histogram را به منظور تولید هیستوگرام (Histogram) خروجی الگوریتم K-means می نویسیم. این تابع تنها یک ورودی دارد.
بدین منظور ابتدا تعداد دسته ها و پیکسل هایی که به هر دسته اختصاص یافته را بدست می آوریم. سپس هستورام هر دسته را محاسبه می کنیم.
در پایان هستوگرام محاسبه شده را نرمالیزه کرده و به عنوان خروجی این تابع برمی گردانیم.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
def plot_colors(hist, centroids): # initialize the bar chart representing the relative frequency # of each of the colors bar = np.zeros((50, 300, 3), dtype = "uint8") startX = 0 # loop over the percentage of each cluster and the color of # each cluster for (percent, color) in zip(hist, centroids): # plot the relative percentage of each cluster endX = startX + (percent * 300) cv2.rectangle(bar, (int(startX), 0), (int(endX), 50), color.astype("uint8").tolist(), -1) startX = endX # return the bar chart return bar |
تابع دیگری به منظور رسم نمودار رنگ ها تعریف می کنیم. این تابع دارای دو ورودی برای هیستوگرام و مرکز هر دسته و نام این تابع plot_colors است. در ابتدا آرایه ای به ابعاد ۳۰۰*۵۰ می سازیم.
سپس با تعریف حلقه ای برحسب هستوگرام هر دسته محدوده ای برای آنها برحسب درصد (در اینجا طول آرایه bar) تعیین می کنیم. در اخر bar را برمی گردانیم.
1 2 3 4 5 6 7 8 9 10 |
# build a histogram of clusters and then create a figure # representing the number of pixels labeled to each color hist = centroid_histogram(clt) bar = plot_colors(hist, clt.cluster_centers_) # show our color bart plt.figure() plt.axis("off") plt.imshow(bar) plt.show() |
در پایان، از این دو تابع استفاده خواهیم کرد تا هیستوگرام و چارت دسته ها را بدست بیاوریم و نمایش بدهیم. در تایع plot_colors، ورودی دوم مرکز هر دسته است. شکل زیر نتیجه را برای تعداد دسته ۳ نشان می دهد.
و شکل زیر نتیجه را با تعداد دسته ۵ نشان می دهد.
در پایان می توانید از لینک زیر کد و تصاویر را دانلود نمایید.
منبع:با تشکراز اقای خوش نظر