آشنایی با histogram
هیستوگرام تصویر چیست؟
هیستوگرام یک گراف یا یک طرح است که نشان دهنده توزیع شدت (پراکندگی رنگ) پیکسل در یک تصویر است. در این بخش ما قصد داریم روی فضای رنگ RGB تمرکز کنیم (در اینجا اگر توضیحات در مورد تفاوت میان برخی از فضاهای رنگی مانند RGB و Lab را بخواهید، به این ترتیب شدت یک پیکسل در محدوده [0، 255 ] هنگام ترسیم هیستوگرام، شدت پیکسل در محور X و فرکانس در محور Y است. هیستوگرام را می توان برای هر دو تصویر سیاه و سفید و برای تصویر رنگی محاسبه کرد. در مورد اول ما یک کانال تک رنگ با بازه رنگ grayscale را داریم، از این رو یک هیستوگرام تنها خواهد بود. در مورد دوم ما سه کانال داریم، از این رو سه هیستوگرام تولید خواهد شد. محاسبه هیستوگرام یک تصویر بسیار مفید است زیرا به برخی از خواص (feature) تصویر مانند محدوده تونال، کنتراست و روشنایی می توان پی برد.
محاسبه هیستوگرام
حالا ببینید چگونه می توان هیستوگرام هر تصویر داده شده را با استفاده از OpenCV محاسبه کرد و آنها را با استفاده از matplotlib نمایش داد.OpenCV تابع cv2.calcHist را برای محاسبه هیستوگرام یک تصویر فراهم می کند. که به شکل زیر است:
cv2.calcHist(images, channels, mask, bins, ranges)
که در اینجا:
- images - تصویری است که میخواهیم هیستوگرام پیچیده شده را به عنوان یک لیست محاسبه کنیم، بنابراین اگر تصویر ما در تصویر متغیر باشد، تصویر [تصویر] منتقل خواهد شد
- channels - فهرست کانال هایی است که در نظر گرفته شده اند (0) برای تصاویر سیاه و سفید مانند یک کانال و [0]، [1] و یا [2] برای تصاویر رنگی اگر ما می خواهیم در نظر بگیریم کانال سبز، آبی یا قرمز به ترتیب)،
- mask - یک ماسک است که در تصویر می شود اگر ما بخواهیم فقط یک منطقه خاص را در نظر بگیریم (ما این را در این پست نادیده می گیریم)
- bins - لیستی است که حاوی تعداد سطل های استفاده شده برای هر کانال است
- ranges - محدوده مقادیر احتمال پیکسل است که [0، 256] در مورد فضای رنگی RGB (جایی که 256 شامل نیست) است.
ما می توانیم این رابط را ساده تر کنیم با قرار دادن آن در یک تابع که علاوه بر محاسبه هیستوگرام که آن را نیز ترسیم می کند و مقدار پیش فرض bins را بر روی 256 تنظیم می کنیم.
نمایش هیستوگرام
دو راه برای این وجود دارد
- روش کوتاه: استفاده از توابع نقشه برداری Matplotlib
- راه طولانی: از توابع طراحی OpenCV استفاده کنید
تصویر نمونه مورد استفاده
1. با استفاده از Matplotlib
Matplotlib با یک تابع ترسیم هیستوگرام همراه است: matplotlib.pyplot.hist ()
این مستقیما هیستوگرام را پیدا می کند و آن را طرح کرده و نمایش می دهد. برای پیدا کردن هیستوگرام لازم نیست از تابع calcHist ()
یا np.histogram ()
استفاده کنید. کد زیر را ببینید:
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('Sample.jpg',0)
cv2.imshow("Sample",img)
plt.hist(img.ravel(),256,[0,256])
plt.show()
که خروجی آن به شکل زیر خواهد بود:
یا می توانید از نمودار طبیعی matplotlib استفاده کنید ، که برای طرح BGR خوب است. برای این منظور ، ابتدا باید داده های هیستوگرام را پیدا کنید. کد زیر را امتحان کنید:
import numpy as np
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('Sample.jpg')
cv2.imshow("Sample",img)
color = ('b','g','r')
for i,col in enumerate(color):
histr = cv2.calcHist([img],[i],None,[256],[0,256])
plt.plot(histr,color = col)
plt.xlim([0,256])
plt.show()
که خروجی زیر را به شما نمایش خواهد داد:
می توانید از نمودار بالا دریابید که ، رنگ قرمز دارای برخی مناطق با ارزش بالا در تصویر است.
2. با استفاده از opencv
خوب ، در اینجا شما می توانید مقادیر هیستوگرام را به همراه مقادیر bin آن تنظیم کنید تا مانند x ، y مختصات باشد تا بتوانید آن را با استفاده از تابع cv.line () یا cv.polyline () ترسیم کنید تا همان تصویر بالا را تولید کند.
کاربرد ماسک
ما از cv.calcHist () برای یافتن هیستوگرام تصویر کامل استفاده کردیم. اگر می خواهید هیستوگرام برخی از مناطق یک تصویر را پیدا کنید ، چه می کنید؟ فقط کافی است یک تصویر ماسک با رنگ سفید بر روی منطقه ای که می خواهید هیستوگرام و سیاه پیدا کنید ایجاد کنید. سپس این را به عنوان ماسک عبور دهید.
import numpy as np
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('Sample.jpg',0)
# create a mask
mask = np.zeros(img.shape[:2], np.uint8)
mask[100:300, 100:400] = 255
masked_img = cv2.bitwise_and(img,img,mask = mask)
# Calculate histogram with mask and without mask
# Check third argument for mask
hist_full = cv2.calcHist([img],[0],None,[256],[0,256])
hist_mask = cv2.calcHist([img],[0],mask,[256],[0,256])
plt.subplot(221), plt.imshow(img, 'gray')
plt.subplot(222), plt.imshow(mask,'gray')
plt.subplot(223), plt.imshow(masked_img, 'gray')
plt.subplot(224), plt.plot(hist_full), plt.plot(hist_mask)
plt.xlim([0,256])
plt.show()
نتیجه را ببینید در نمودار هیستوگرام ، خط آبی هیستوگرام تصویر کامل را نشان می دهد در حالی که خط نارنجی هیستوگرام ناحیه پوشیده شده را نشان می دهد.