هیستوگرام (histogram) یا بافتنگار به نموداری گفته میشود که فراوانی عناصری که در محور افقی آن قرار دارند را در محور عمودی نشان میدهد. ویکی
تصویر زیر یک ماتریس دو بعدی از یک تصویر است که که حاوی اطلاعات از شدت روشنایی است .اگر فرض کنیم، تعداد پیکسلهایی که شدت روشنایی مثلا ۰ دارند ۱۰ تا است، ۱۰ را در محور y و محدوده شدت روشنایی(۰ یا سیاه) را درمحور x نشان میدهد.
یک هیستوگرام مجموعه ای از مناطق مستطیل شکل یا استوانه ای به نام سطل(bin) است. (تعریف دیگر)
اگر بخواهیم این داده ها را به صورت سازمان یافته ببینیم باید چه کنیم؟ با توجه به اینکه محدوده ارزش اطلاعات برای این مورد ۲۵۶ مقدار است، میتوانیم محدوده را به بخشهایی مثل سطل(bins) تقسیم کنیم:
بنابراین می توانیم تعداد پیکسل هایی را که در محدوده هر سطل قرار می گیرند، نگهداریم. برای تصویر بالا، تصویر زیر آماده شده است. محور x همان سطل ها و محور y تعداد پیکسل.
این یک مثال ساده از نحوه عملکرد هیستوگرام و دلیل مفید بودن آن است. هیستوگرام می تواند نه تنها از شدت های رنگ، بلکه از ویژگی های تصویری که می خواهیم اندازه گیری کنیم (مانند شیب، جهت ها و غیره) باشد.
بیایید برخی ورودی های تابع هیستوگرام را شناسایی کنیم:
اگر می خواهید دو ویژگی را حساب کنید چه؟ در این حالت نتیجه شما یک قطعه ۳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 = <span class="stringliteral">'b'</span>) plt.hist(img.flatten(),256,[0,256], color = <span class="stringliteral">'</span><span class="stringliteral">r') plt.xlim([0,256]) plt.legend((<span class="stringliteral">'cdf'</span>,<span class="stringliteral">'histogram'</span>), loc = <span class="stringliteral">'upper left'</span>) plt.show()
در تصویر، مقدار میانگین مقدار متوسط شدت روشنایی تصویر را نشان می دهد و مقدار واریانس، مقدار متوسط کنتراست تصویر را نمایش می دهد.
خیلی ممنون بابت انتقال دانش تون بسیار مفید بودو مشکلی داشتم بر طرف شد.
سلام ممنون میشم در خصوص مقایسه دو تصویر توضیح دهید. فرض کنید یک عکس از شخصی داریم و حالا میخواهیم…
سلام سپاسگزارم
خیلی ممنون از راهنماییتون جال بود صفحه کلید دیگری وصل کردم صفحه کلید لپتابم درست شد
سلام سپاسگزارم