۱- نمودار هیستوگرام چیست؟
۱-۲- هیستوگرام برای تصاویر رنگی
۱-۳- متعادل سازی هیستوگرام
قبل از پرداخت به هیستوگرام در پردازش تصویر، ببینیم این نمودار به چه دردی میخوره.
حتما با این عبارت آشنایی دارید که میگن تصویر کیفیت نداره . به وسیله هیستوگرام اطلاعات بیشتری از عکس بدست میاوریم تا بتوانیم یک تصویری با بهترین نور دهی داشه باشیم.
باید گفت که شفافیت یک عکس، کار کنتراست است که یکی از کاربردهای هیستگرام است. از طرفی کنتراست، بر تفاوت بین سیاهترین(تعداد پیکسل ها به سمت ۰) و روشنترین( تعداد پیکسل ها به سمت ۲۵۵) قسمت های یک عکس تاثیر میگذارد.
بالا بودن کنتراست نشان از کیفیت تصویر است. یعنی ما هم روشنایی ها را داریم و هم تاریکی ها را داریم. یک جورایی نمودار ما پهن میباشد . ولی در کنتراست پایین که وضوح عکس پایین میاد، نمودار باریک است. در اینجا جزئیات کمتری داریم.
و درک این مسئله با نمودار هیستوگرام بسیار آسانتر خواهد بود.
هیستوگرام یا بافتنگار، به زبان خیلی ساده به نموداری گفته میشود که به ما بگوید به عنوان مثال چند تا عدد ۹ داریم . عدد ۹ که روی محور x قرار میگیرد و اگر تعداد آن ۱۸ باشد با محور y مشخص میشود.
تصویر زیر یک ماتریس دو بعدی از یک تصویر است که که حاوی اطلاعات از شدت روشنایی است .اگر فرض کنیم، تعداد پیکسلهایی که شدت روشنایی مثلا ۰ دارند ۱۰ تا است، ۱۰ را در محور y و محدوده شدت روشنایی(۰ یا سیاه) را درمحور x نشان میدهد.
یک هیستوگرام مجموعه ای از مناطق مستطیل شکل یا استوانه ای به نام سطل(bin) است. (تعریف دیگر)
اگر بخواهیم این داده ها را به صورت سازمان یافته ببینیم باید چه کنیم؟ با توجه به اینکه محدوده ارزش اطلاعات برای این مورد ۲۵۶ مقدار است، میتوانیم محدوده را به بخشهایی مثل سطل(bins) تقسیم کنیم:
![\begin{array}{l} [0, 255] = { [0, 15] \cup [16, 31] \cup ....\cup [240,255] } \\ range = { bin_{1} \cup bin_{2} \cup ....\cup bin_{n = 15} } \end{array}](https://docs.opencv.org/2.4/_images/math/13273dd42ab0362196b14ee3b0970f7f00a6b010.png)
بنابراین می توانیم تعداد پیکسل هایی را که در محدوده هر سطل قرار می گیرند، نگهداریم. برای تصویر بالا، تصویر زیر آماده شده است. محور x همان سطل ها و محور y تعداد پیکسل.

Histogram
این یک مثال ساده از نحوه عملکرد هیستوگرام و دلیل مفید بودن آن است. هیستوگرام می تواند نه تنها از شدت های رنگ، بلکه از ویژگی های تصویری که می خواهیم اندازه گیری کنیم (مانند شیب، جهت ها و غیره) باشد.
بیایید برخی ورودی های تابع هیستوگرام را شناسایی کنیم:
اگر می خواهید دو ویژگی را حساب کنید چه؟ در این حالت نتیجه شما یک قطعه ۳D است. همین کار را برای ویژگی های بیشتر اعمال می کند (مطمئنا پیچیده تر می شود).
در تمام قسمت ها از تصویر زیر به عنوان ورودی استفاده شده است:
import cv2
import numpy as np
from matplotlib import pyplot as plt
gray_img = cv2.imread('images_histogram.png', cv2.IMREAD_GRAYSCALE)#histogram tasvir tak kanale
cv2.imshow('GoldenGate',gray_img)
hist = cv2.calcHist([gray_img],[0],None,[256],[0,256])
plt.hist(gray_img.ravel(),256,[0,256])
plt.title('Histogram for gray scale picture')
plt.show()
while True:
k = cv2.waitKey(0) & 0xFF
if k == 27: break # ESC key to exit
cv2.destroyAllWindows()
نکته: نحوه کارکرد تابع ()ravel, همانند (reshape(-1.
import numpy as np x = np.array([[1, 2, 3], [4, 5, 6]]) print (np.ravel(x)) [1 2 3 4 5 6] x.reshape(-1) array([1, 2, 3, 4, 5, 6])
OpenCV از تابع ()cv2.calcHist برای هیستوگرام استفاده میکند. بنابراین، زمان آن است که به پارامترهای خاص مربوط به تابع () cv2.calcHist نگاه کنیم:
cv2.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate]])
ما به صورت زیر استفاده کردیم:
hist = cv2.calcHist([gray_img],[0],None,[256],[0,256])
پارامتر ها
همچنین NumPy یک تابع برای هیستوگرام، که ()np.histogram است را فراهم می کند. بنابراین، ما می توانیم به جای تابع OpenCV از NumPy استفاده کنیم:
import cv2
import numpy as np
from matplotlib import pyplot as plt
gray_img = cv2.imread('hisimage.jpg', cv2.IMREAD_GRAYSCALE)
cv2.imshow('GoldenGate',gray_img)
#hist = cv2.calcHist([gray_img],[0],None,[256],[0,256])
hist,bins = np.histogram(gray_img,256,[0,256])
plt.hist(gray_img.ravel(),256,[0,256])
plt.title('Histogram for gray scale picture')
plt.show()
while True:
k = cv2.waitKey(0) & 0xFF
if k == 27: break # ESC key to exit
cv2.destroyAllWindows()
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('images/GoldenGateSunset.png', -1)
cv2.imshow('GoldenGate',img)
color = ('b','g','r')
for channel,col in enumerate(color):
histr = cv2.calcHist([img],[channel],None,[256],[0,256])
plt.plot(histr,color = col)
plt.xlim([0,256])
plt.title('Histogram for color scale picture')
plt.show()
while True:
k = cv2.waitKey(0) & 0xFF
if k == 27: break # ESC key to exit
cv2.destroyAllWindows()
یکی از مشکلاتی که در آستانه گذاری ساده داشتیم، تصاویر ورودی با روشنایی متفاوت، خروجی مناسبی نداشت. برای یکنواختی تصویر میتوانیم قبل از آستانه گیری از متعادل سازی استفاده کنیم. متعادل سازی هیستوگرام برای بهبود کنتراست و افزایش کیفیت تصویر، استفاده می شود.
یک تصویر را که مقادیر پیکسل(شدت روشنایی) آن، به رنج کمی از مقادیر، محدود است را در نظر بگیرید. برای مثال، تصویر روشن تر تمام پیکسل ها را به مقادیر بالا(نزدیک به ۲۵۵) محدود خواهد کرد. اما یک تصویر خوب، پیکسل ها را از تمام نقاط تصویر انتخاب میکند.
بنابراین باید این هیستوگرام را به هر دو انتها ببرید ( تصویر زیر از ویکیپدیا داده شده است) و این همان کاری است که متعادل سازی هیستوگرام می کند (به صورت ساده).
این عمل، کنتراست تصویر را بهبود می بخشد.

متعادل سازی هیستوگرام
importcv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('wiki.jpg',0)
hist,bins = np.histogram(img.flatten(),256,[0,256])
cdf = hist.cumsum()
cdf_normalized = cdf * hist.max()/ cdf.max()
plt.plot(cdf_normalized, color = 'b')
plt.hist(img.flatten(),256,[0,256], color = 'r')
plt.xlim([0,256])
plt.legend(('cdf','histogram'), loc = 'upper left')
plt.show()
در تصویر، مقدار میانگین مقدار متوسط شدت روشنایی تصویر را نشان می دهد و مقدار واریانس، مقدار متوسط کنتراست تصویر را نمایش می دهد.