پردازش تصویر در OpenCV
هیستوگرام - 3: هیستوگرام دوبُعدی (2D Histograms)
هدف#
در این فصل، یاد میگیریم که چگونه هیستوگرامهای دوبُعدی را محاسبه و رسم کنیم. این موضوع در فصلهای آینده مفید خواهد بود.
مقدمه#
در اولین مقاله، هیستوگرام یکبُعدی را محاسبه و رسم کردیم. آن را یکبُعدی مینامیم زیرا فقط یک ویژگی را در نظر میگیریم، یعنی مقدار شدت روشنایی در مقیاس خاکستری پیکسل. اما در هیستوگرامهای دوبُعدی، دو ویژگی را در نظر میگیریم. این روش معمولاً برای یافتن هیستوگرامهای رنگی استفاده میشود که در آن دو ویژگی مقادیر رنگ (Hue) و اشباع (Saturation) هر پیکسل هستند.
یک نمونه پایتون (samples/python/color_histogram.py) برای یافتن هیستوگرامهای رنگی از قبل موجود است. سعی میکنیم نحوه ایجاد چنین هیستوگرام رنگی را درک کنیم و این برای درک موضوعات بیشتر مانند بازتاب هیستوگرام (Histogram Back-Projection) مفید خواهد بود.
هیستوگرام دوبُعدی در OpenCV#
این کار کاملاً ساده است و با همان تابع cv.calcHist() محاسبه میشود. برای هیستوگرامهای رنگی، باید تصویر را از BGR به HSV تبدیل کنیم. (به یاد داشته باشید که برای هیستوگرام یکبُعدی، از BGR به Grayscale تبدیل کردیم). برای هیستوگرامهای دوبُعدی، پارامترها به صورت زیر تغییر میکنند:
- channels = [0,1] زیرا باید هر دو صفحه H و S را پردازش کنیم.
- bins = [180,256] 180 برای صفحه H و 256 برای صفحه S.
- range = [0,180,0,256] مقدار رنگ (Hue) بین 0 و 180 و اشباع (Saturation) بین 0 و 256 قرار دارد.
اکنون کد زیر را بررسی کنید:
import numpy as np
import cv2 as cv
img = cv.imread('home.jpg')
assert img is not None, "file could not be read, check with os.path.exists()"
hsv = cv.cvtColor(img,cv.COLOR_BGR2HSV)
hist = cv.calcHist([hsv], [0, 1], None, [180, 256], [0, 180, 0, 256])
همین.
هیستوگرام دوبُعدی در Numpy#
Numpy نیز یک تابع خاص برای این منظور دارد: np.histogram2d(). (به یاد داشته باشید که برای هیستوگرام یکبُعدی از np.histogram() استفاده کردیم).
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('home.jpg')
assert img is not None, "file could not be read, check with os.path.exists()"
hsv = cv.cvtColor(img,cv.COLOR_BGR2HSV)
hist, xbins, ybins = np.histogram2d(h.ravel(),s.ravel(),[180,256],[[0,180],[0,256]])
آرگومان اول صفحه H، دومی صفحه S، سومی تعداد binها برای هر کدام و چهارمی بازه آنها است.
اکنون میتوانیم نحوه رسم این هیستوگرام رنگی را بررسی کنیم.
رسم هیستوگرامهای دوبُعدی#
روش ۱: استفاده از cv.imshow()#
نتیجهای که به دست میآوریم یک آرایه دوبُعدی به اندازه ۱۸۰×۲۵۶ است. پس میتوان آن را مانند حالت معمول با تابع cv.imshow() نمایش داد. این یک تصویر در مقیاس خاکستری خواهد بود و ایده روشنی از اینکه چه رنگهایی وجود دارند نمیدهد، مگر اینکه مقادیر Hue رنگهای مختلف را بدانید.
روش ۲: استفاده از Matplotlib#
میتوانیم از تابع matplotlib.pyplot.imshow() برای رسم هیستوگرام دوبُعدی با نگاشتهای رنگی مختلف استفاده کنیم. این روش ایده بهتری از چگالیهای مختلف پیکسل به ما میدهد. اما این روش هم در نگاه اول ایده روشنی از اینکه چه رنگی وجود دارد نمیدهد، مگر اینکه مقادیر Hue رنگهای مختلف را بدانید. با این حال، این روش را ترجیح میدهم. ساده و بهتر است.
کد را در نظر بگیرید:
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('home.jpg')
assert img is not None, "file could not be read, check with os.path.exists()"
hsv = cv.cvtColor(img,cv.COLOR_BGR2HSV)
hist = cv.calcHist( [hsv], [0, 1], None, [180, 256], [0, 180, 0, 256] )
plt.imshow(hist,interpolation = 'nearest')
plt.show()
در زیر تصویر ورودی و نمودار هیستوگرام رنگی آن آمده است. محور X مقادیر S و محور Y مقادیر Hue را نشان میدهد.

در هیستوگرام، میتوانید مقادیر بالایی در نزدیکی H = 100 و S = 200 ببینید. این مربوط به آبی آسمان است. به همین ترتیب، قله دیگری در نزدیکی H = 25 و S = 100 دیده میشود. این مربوط به زرد کاخ است. میتوانید آن را با هر ابزار ویرایش تصویری مانند GIMP تأیید کنید.
روش ۳: سبک نمونه OpenCV!#
یک نمونه کد برای هیستوگرام رنگی در نمونههای OpenCV-Python وجود دارد (samples/python/color_histogram.py). اگر کد را اجرا کنید، میتوانید ببینید که هیستوگرام رنگ متناظر را هم نشان میدهد. به عبارتی دیگر، خروجی یک هیستوگرام رنگبندیشده است. نتیجه آن بسیار خوب است (هرچند نیاز به اضافه کردن چند خط بیشتر دارید).
در آن کد، نویسنده یک نگاشت رنگی در فضای HSV ایجاد کرده است. سپس آن را به BGR تبدیل کرده است. تصویر هیستوگرام حاصل با این نگاشت رنگی ضرب میشود. او همچنین از برخی مراحل پیشپردازش برای حذف پیکسلهای منزوی کوچک استفاده میکند که منجر به یک هیستوگرام خوب میشود.
این کار را به خوانندگان واگذار میکنم که کد را اجرا کرده، آن را تحلیل کنند و راهحلهای خود را بیابند. در زیر خروجی آن کد برای همان تصویر بالا آمده است:

میتوانید به وضوح در هیستوگرام ببینید که چه رنگهایی وجود دارند؛ آبی هست، زرد هست و کمی سفید به دلیل صفحه شطرنج هم وجود دارد. عالی!