پردازش تصویر با پایتون قسمت بیست و دوم

Histogram in OpenCv

 نمودار هیستوگرام چیست؟

هیستوگرام یا بافت‌نگار به نموداری گفته می‌شود که فراوانی عناصری که در محور افقی آن قرار دارند را در محور عمودی نشان می‌دهد. ویکی

تصویر زیر یک ماتریس دو بعدی از یک تصویر است که که حاوی اطلاعات از شدت روشنایی است .اگر فرض کنیم، تعداد پیکسلهایی که شدت روشنایی مثلا ۰ دارند ۱۰ تا است، ۱۰ را در محور y و محدوده شدت روشنایی(۰ یا سیاه) را درمحور x نشان میدهد.
یک هیستوگرام  مجموعه ای از مناطق مستطیل شکل یا استوانه ای به نام سطل(bin) است. (تعریف دیگر)

 

https://docs.opencv.org

https://docs.opencv.org

اگر بخواهیم این داده ها را به صورت سازمان یافته ببینیم  باید چه کنیم؟ با توجه به اینکه محدوده ارزش اطلاعات برای این مورد ۲۵۶ مقدار است، میتوانیم محدوده را به بخشهایی مثل سطل(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}

 

بنابراین  می توانیم تعداد پیکسل هایی را که در محدوده هر سطل قرار می گیرند، نگهداریم. برای تصویر بالا، تصویر زیر آماده شده است. محور x همان سطل ها و محور y تعداد پیکسل.

../../../../../_images/Histogram_Calculation_Theory_Hist1.jpg

این یک مثال ساده از نحوه عملکرد هیستوگرام و دلیل مفید بودن آن است. هیستوگرام می تواند نه تنها از شدت های رنگ،  بلکه از ویژگی های تصویری که می خواهیم اندازه گیری کنیم (مانند شیب، جهت ها و غیره) باشد. 

بیایید برخی ورودی های تابع  هیستوگرام را شناسایی کنیم:

  • dims: تعداد پارامترهایی که می خواهید اطلاعات را جمع آوری کنید. در مثال ما مقدار این پارامتر ۱ است. چون فقط مقدار شدت روشنایی را در نظر گرفتیم. 
  • bins : تعداد هر مستطیل یا سطل را مشخص میکند. در این مثال bins = 16
  • range: بازه ای از مقادیر [range = [0,255

اگر می خواهید دو ویژگی را حساب کنید چه؟ در این حالت نتیجه شما یک قطعه ۳D است. همین کار را برای ویژگی های بیشتر اعمال می کند (مطمئنا پیچیده تر می شود).

در تمام قسمت ها از تصویر زیر به عنوان ورودی استفاده شده است:

https://en.wikipedia.org/wiki/File:SunLou2.jpg

https://en.wikipedia.org/wiki/File:SunLou2.jpg

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()

hisgray

image_histogram

نکته: نحوه کارکرد تابع ()ravel, همانند (reshape(-1.

>>> import numpy as np
>>> x = np.array([[1, 2, 3], [4, 5, 6]])
>>> print (np.ravel(x))
[۱ ۲ ۳ ۴ ۵ ۶]
>>> x.reshape(-1)
array([1, 2, 3, 4, 5, 6])
>>>

()calcHist

OpenCV از  تابع ()cv2.calcHist  برای هیستوگرام استفاده میکند. بنابراین، زمان آن است که به پارامترهای خاص مربوط به تابع () cv2.calcHist نگاه کنیم:

cv2.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate]])

 

ما به صورت زیر استفاده کردیم:

hist = cv2.calcHist([gray_img],[0],None,[256],[0,256])

پارامتر ها

  1. images: تصویر منبع از نوع uint8 یا float32، باید به عنوان یک لیست ارائه شود. [gray_img]
  2. channels: این مورد نیز به عنوان یک لیست [] داده شده است. این شاخص کانال است که ما با آن هیستوگرام را محاسبه می کنیم. برای مثال، اگر ورودی تصویر سیاه و سفید است، مقدار آن [۰] است. برای تصویر رنگی، می توانید [۰]، [۱] یا [۲] را به ترتیب برای هیستوگرام کانال آبی، سبز یا قرمز محاسبه کنید.
  3. mask:  برای پیدا کردن هیستوگرام  تصویرکامل ، آن را به عنوان None تنظیم شده است. با این حال، اگر ما می خواهیم هیستوگرام منطقه خاص تصویر را دریافت کنیم، باید یک تصویر ماسک برای آن ایجاد کنیم و آن را ماسک کنیم.
  4. histSize:  نشان دهنده شمارش BIN است. باید در [] داده شود. برای مقیاس کامل، ما [۲۵۶]را قرار دادیم .
  5. ranges : به طور معمول، [۰،۲۵۶] است.

 

()NumPy – np.histogram

 

همچنین 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()

hiscolorimage

 

متعادل سازی هیستوگرام


یکی از مشکلاتی که در آستانه گذاری ساده داشتیم، تصاویر ورودی با روشنایی متفاوت، خروجی مناسبی نداشت. برای یکنواختی تصویر میتوانیم قبل از آستانه گیری از متعادل سازی استفاده کنیم. متعادل سازی هیستوگرام  برای بهبود کنتراست و افزایش کیفیت تصویر، استفاده می شود.

یک تصویر را که مقادیر پیکسل(شدت روشنایی) آن،  به رنج کمی از مقادیر،  محدود است را در نظر بگیرید. برای مثال، تصویر روشن تر تمام پیکسل ها را به مقادیر بالا(نزدیک به ۲۵۵) محدود خواهد کرد. اما یک تصویر خوب، پیکسل ها را از تمام نقاط تصویر انتخاب میکند.

بنابراین باید این هیستوگرام را به هر دو انتها ببرید ( تصویر زیر از ویکیپدیا داده شده است) و این همان کاری است که متعادل سازی  هیستوگرام می کند (به صورت ساده).

این عمل، کنتراست تصویر را بهبود می بخشد. 

 

histogram_equalization.png

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()

 

  
 

در تصوير، مقدار ميانگين مقدار متوسط شدت روشنايی تصوير را نشان می دهد و مقدار واريانس، مقدار متوسط کنتراست تصوير را نمايش می دهد.

 
 🆔@image_Process
🌐https://t.me/image_Process

تشخیص پلاک خودروهای های ایرانی توسط کتابخانه OpenCV

بعد از تمام  شدن آموزش مقدماتی پردازش تصویر، پروژه های کوچک وبعد  پروژه تشخیص پلاک خودرو را بررسی میکنیم. 

 

🌟تشخیص حیوانات🌟

g1

2g

🌟تشخیص چهره🌟

g4

🌟تشخیص بارکد🌟

g5

‍ 🌟Credit card OCR🌟

g7

 

 

🌟تشخیص پلاک خودرو🌟

g8

 

 

🆔@image_Process
🌐https://t.me/image_Process

تفاوت حوزه مکانی و فرکانسی

پردازش تصویر با پایتون قسمت بیست و یکم

تفاوت فیلتر کردن حوزه مکان با فرکانس

 

image

مراحل پایه در پردازش تصویر:
۱) پیش پردازش
۲) بخش بندی
۳) توصیف و نمایش

۴)تشخیص و تفسیر

 پردازش تصویر: فرایند دستکاری یا انجام تغییرات مناسب بر رو ی تصویر(سیگنال دو بعدی)، جهت :

۱)  درک بهتر برای انسان
۲)  درک کامپیوتر (بینایی ماشین)

 تصویر خاکستری تابعی از شدت روشنایی است :

f(x,y)= 0-255

ورودی های تابع، مختصات مکانی و خروجی شدت روشنایی است.

 

وقتی تصویر را از ورودی(دوربین) گرفتیم: نمونه برداری میکنیم تا تصویر به پیکسل های جدا از هم تقسیم شود.
برای نمونه برداری جهت دیجیتالی کردن تصویر، اگر ورودی ها را دیجیتالی کنیم به آ ن نمونه برداری میگویند.
اگر خروجی تابع را دیجیتالی کنیم به آن کوانتیزه کردن میگویند.
با ایجاد تصویر دیجیتالی میتوانیم فرض کنیم یک ماتریس دو بعدی داریم.
 پیش پردازش: در این مرحله،  تصویر را با حذف نویز ها یا بالا بردن کنتراست و… ارتقا میدهیم. با بالا رفتن کیفیت تصویر، هم استفاده ی راحتر برای انسان فراهم شده و هم بقیه پردازش ها ، بهتر انجام میشود.

filter2
 برای بهبود و ارتقا کیفیت تصویر ، دو روش داریم:

۱) حوزه مکانی (Spatial Domain)
۲) حوزه فرکانسی

 در حوزه مکان، پردازش ها و عملیات بر روی پیکسلها انجام میشود و یک تصویر با مشاهده سطح خاکستری توصیف میشود که به دو صورت است:

🔶فیلترهای مکانی بر روی ورودیها یا موقعیت مکانی تابع f(x,y) ،که با توجه به پیکسلهای همسایه انجام میشود. فیلتر ها به دو دسته خطی و غیر خطی هستند. فیلترهای مکانی، فیلتر هایی که اندازه تغییرات تصویر را مانند بالاگذر (تغییرات زیاد) یا پایین گذر (تغییرات کم) و … حذف میکنند.
🔸🔸 پایین گذر(مات و نرم کردن): تغییرات زیاد را حذف و تغییرات کم را رد میکند
خطی
۱) فیلتر میانگین: مقدار پیکسل های همسایه جایگزین پیکسل مرکزی میشود.(کانولوشن).
۲)گوسی .

غیرخطی:
۱)میانه
و …
🔸🔸 بالا گذر(تیز و لبه دار کردن) : تغییرا ت کم را حذف و تغییرات زیاد را رد میکند.
۱) لاپلاسین
۲) سوبل
۳)و ….

🔶 تبدیلات بر روی خروجی تابع که نور یا شدت روشنایی نامیده میشود، انجام میشو د. در واقع تبدیلات بدون توجه به پیکسل های همسایه انجام میشود. تبدیلات بر روی شدت روشنایی (تبدیلات مکانی)شامل موارد زیر میباشد:

۱) تعدیل هیستوگرام یا Histogram Equalization
۲) تفریق (subtraction )
و ….

۲) در حوزه فرکانس، تصویر را با استفاده از تبدیل فوریه به حوزه فرکانس میبریم.

تبدیل فوریه دو بعدی، ابتدا روی تمام سطرهای تصویر  انجام میشود و دوبار ه روی تمام ستونهای خروجی مرحله قبلی انجام میشود. 
با تبدیل فوریه هر سیگنالی را میشود با بینهایت موج سینوسی و کسینوسی دقیقا شبیه سازی کرد .
در واقع یک ماتریسی هم اندازه با تصویر بدست می آوریم که نواحی نزدیک به مرکز ماتریس فر کانسهای پایین و نواحی دو ر از مرکز فرکانسهای بالا هستند . اگر فرکانسهای بالا یا دور از مرکز را ۰ کنیم، تصویری خالی از نویز داریم . اگر فر کانس پایین را ۰ کنیم در واقع تصویر لبه دار داریم .

در این حوزه  ما دیگر اطلاعات مکانی نداریم، یعنی نمیتوانیم بگوییم کجا به کجای تصویر مربوط است. ولی یک سری اطلاعات ارزشمند بدست می آوریم.
حوزه فرکانس، تفاوت پیکسلهای کنار همدیگر را به صورت نموداری در نظر میگیرد و توسط یک سری موجهای سینوسی و کسینوسی شبیه سازی میکند.
و همین امر باعث میشود نویز های مانند پریودیک که در حوزه مکان قابل حذف نیستند، حذف شوند. یعنی در حوزه فرکانس به صورت نقاطی سفید دیده میشوند که با ۰ یا سیاه کردن آن نقاط، ازبین میروند.


pri
نکته
** این دو حوزه قابل تبدیل به یکدیگر هستند.
** برخی فیلتر ها در هر دو حوزه قابل اعمال هستند.

🆔@image_Process
🌐https://t.me/image_Process

پردازش تصویر با پایتون قسمت بیستم

Otsu’s Binarization (تقسیم بندی Otsu)

در این روش قرار است از خروجی دوم روش آستانه گیری ساده، retVal استفاده کنیم. چرا ما از این روش استفاده میکنیم؟?؟
در آستانه گیری ساده ما از یک مقدار سراری استفاده کردیم. ولی از کجا بدونیم این مقدار، یک مقدار خوب و بهینه است؟  بله. با آزمون و خطا.

روش آستانه گذاری Otsu ، تصویر را به گونه ای تقسیم بندی میکند که تصویر با بهترین مقدار آستانه به دو کلاس سیاه و سفید یا پیش زمینه و پس زمینه یا پس زمینه و شی تقسیم میشود:

در یک تصویر bimodal (تصویری که هیستوگرام آن دارای دو قله میباشد)، تقریبا در وسط قله ها میتوان آستانه بهینه را انتخاب کرد.

برای همین ما از تابع cv2.threshold() استفاده میکنیم ولی یک فلگ اضافی ، cv2.THRESH_OTSU را داریم . این روش مقدار بهینه آستانه را در retVal قرار میدهد و مقدار threshold برابر ۰ میشود.

 

 

noisy_leaf

تصویر اصلی نویز دار

 

 

otsu

otsu

 

import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('bimodal_hsv_noise.png',0)

# global thresholding
ret1,th1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)

# Otsu's thresholding
ret2,th2 = cv2.threshold(img,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

# Otsu's thresholding after Gaussian filtering
blur = cv2.GaussianBlur(img,(5,5),0)
ret3,th3 = cv2.threshold(blur,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

# plot all the images and their histograms
images = [img, 0, th1,
          img, 0, th2,
          blur, 0, th3]
titles = ['Original Noisy Image','Histogram','Global Thresholding (v=127)',
          'Original Noisy Image','Histogram',"Otsu's Thresholding",
          'Gaussian filtered Image','Histogram',"Otsu's Thresholding"]

for i in xrange(3):
    plt.subplot(3,3,i*3+1),plt.imshow(images[i*3],'gray')
    plt.title(titles[i*3]), plt.xticks([]), plt.yticks([])
    plt.subplot(3,3,i*3+2),plt.hist(images[i*3].ravel(),256)
    plt.title(titles[i*3+1]), plt.xticks([]), plt.yticks([])
    plt.subplot(3,3,i*3+3),plt.imshow(images[i*3+2],'gray')
    plt.title(titles[i*3+2]), plt.xticks([]), plt.yticks([])
plt.show()

تک آستانه، دو سطحی

اینجا پیکسلهای سفید پس زمینه و سیاه، شی یا پیش زمینه را نشان میدهند. در یک تصویر bimodal (تصویری که هیستوگرام آن دارای دو قله میباشد)، تقریبا در وسط قله ها میتوان آستانه بهینه را انتخاب کرد. 

 

 

photo_2018-01-25_15-53-55

آستانه گذاری دوسطحی ، تک آستانه

 

آستانه گذاری دوسطحی یک مقدار آستانه دارد و پیکسلهای تصویر به دو گروه یا کلاس تقسیم میشوند. انتخاب آستانه در این گروه تصاویر بسیار ساده از آستانه گذاری چند سطحی میباشد.

 

 

 

آستانه گذاری چند سطحی با چند آستانه

 

تصویری که بیش از یک آستانه دارد، آستانه گذاری چند سطحی میباشد. 

sample

تصویر اصلی

photo

آستانه گذاری چند سطحی با دو آستانه

import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('sample.jpg',0)
ret1,th1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
ret2,th2 = cv2.threshold(img,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
blur = cv2.GaussianBlur(img,(5,5),0)
ret3,th3 = cv2.threshold(blur,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
images = [img, 0, th1,
img, 0, th2,
blur, 0, th3]
titles = ['Original Noisy Image','Histogram','Global Thresholding (v=127)',
'Original Noisy Image','Histogram',"Otsu's Thresholding",
'Gaussian filtered Image','Histogram',"Otsu's Thresholding"]
for i in xrange(3):
plt.subplot(3,3,i*3+1),plt.imshow(images[i*3],'gray')
plt.title(titles[i*3]), plt.xticks([]), plt.yticks([])
plt.subplot(3,3,i*3+2),plt.hist(images[i*3].ravel(),256)
plt.title(titles[i*3+1]), plt.xticks([]), plt.yticks([])
plt.subplot(3,3,i*3+3),plt.imshow(images[i*3+2],'gray')
plt.title(titles[i*3+2]), plt.xticks([]), plt.yticks([])
plt.show()

🆔@image_Process
https://t.me/image_Process

پردازش تصویر با پایتون قسمت نوزدهم

Adaptive Thresholding

در روش Simple Thresholding،  تصاویری که دارای روشنایی متفاوت در قسمتهای مختلف میباشند خروجی جالبی ندارند. ولی در آستانه گذاری تطبیقی یا سازگاری، بر خلاف آستانه گذاری ساده، مقدار آستانه در هر مکان پیکسل، بستگی به شدت روشنایی پیکسلهای همسایه دارد. در واقع مقدار آستانه برای ناحیه ی کوچکی از تصویر محاسبه میشود و ما دارای آستانه های متفاوت زیادی میباشیم.پیش فرض  این است که مناطق کوچکتر تصویر، احتمال بیشتری برای روشنایی یکنواخت دارند، بنابراین برای آستانه گذاری بیشتر مناسب هستند.

**** برای محاسبه استانه محلی مراحل زیر طی میشود:****

۱) یک بلوک یا ناحیه bxb، اطراف مکان پیکسل توسط کاربر انتخاب میشود.b=3,5,7,…

۲) میانگین وزنی ناحیه bxb را محاسبه میکنیم. Opencv دو روش پیشنهاد میدهد:

— محاسبه میانگین ناحیه پیکسل  ناحیه bxb

— محاسبه میانگین وزنی گوسی مکان پیکسل ناحیه bxb

۳) برای محاسبه مقدار آستانه، میانگین  از یک مقدر ثابت(C) کم میشود:

 T= M- C

توابع ساده و سریع عبارتند از:

میانگین (mean) توزیع شدت محلی:

Eqn:eqnadp1

مقدار میانه(median )

Eqn:eqnadp2

یا میانگین حداقل و حداکثر مقادیر

Eqn:eqnadp3

اندازه همسایگی، باید به اندازه کافی بزرگ باشد تا پیکسل های شی و پس زمینه کافی را پوشش دهد، در غیر این صورت یک آستانه ضعیف انتخاب میشود.از سوی دیگر، انتخاب مناطق که بیش از حد بزرگ هستند می تواند فرض تقریبا یکنواخت را نقض کند.(b)

 

threshold
از آنجا که این تصویر حاوی گرادیان روشنایی قوی است، آستانه سراسری، نتایج بسیار بدی را به وجود می آورد، همانطور که دیده می شود:

import cv2
import numpy as np
img = cv2.imread('sample.jpg')
ret,threshold1 = cv2.threshold(img,127,255,cv2.THRESH_TOZERO_INV)
cv2.imshow('threshold ',threshold1)
cv2.waitKey (0)
cv2.destroyAllWindows ()

ad

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

cv2.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C[, dst]) -> dst

این تابع تنها یک خروجی دارد و ورودی های آن به صورت زیر است:

src: تصویر ورودی

maxval: حداکثر مقدار ، که می تواند به خروجی اختصاص داده شود.

Adaptive Method :  نوع آستانه

cv2.ADAPTIVE_THRESH_MEAN_C: مقدار آستانه،  برای وزن متوسط تنظیم شده است.

cv2.ADAPTIVE_THRESH_GAUSSIAN_C: مقدار آستانه ، مجموعه ای از مقادیر ناحیه ای است که وزن آنها یک پنجره گاوسی است.

blockSize  : اندازه ناحیه ی همسایگی را تعیین میکند.

C: c، یک ثابت است که از میانگین یا میانگین وزنی کم میشود. 

dst :تصویر خروجی(باینری)

 import cv2
 import numpy as np
 from matplotlib import pyplot as plt
img = cv2.imread('sample.jpg',0)
img = cv2.medianBlur(img,5)
ret,th1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
 th2 = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,11,2)
 th3 = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,11,2)
 titles = ['Original Image', 'Global Thresholding (v = 127)','Adaptive Mean Thresholding',
 'Adaptive Gaussian Thresholding']
 images = [img, th1, th2, th3]
 for i in xrange(4):
 plt.subplot(2,2,i+1),plt.imshow(images[i],'gray')
 plt.title(titles[i])
 plt.xticks([]),plt.yticks([])
 plt.show()
Adaptive Thresholding

Thresholdh

تفاوت آستانه ساده با تطبیقی در این تصویر مشهود است.

آستانه گذاری ساده، از آستانه ثابت برای تمام پیکسل های تصویر استفاده می کند، بنابراین، تنها اگر هیستوگرام شدت تصویر ورودی، دارای پیک های جدا شده، مربوط به شی(ها) و پس زمینه مورد نظر باشد، کار می کند. از این رو، نمی تواند با تصاویری که حاوی، gradient روشنایی قوی باشد، مقابله کند.

از سوی دیگر، آستانه گذاری تطبیقی محلی، یک آستانه منحصربه فردی را برای هر پیکسل بر اساس محدوده ای از میزان شدت در همسایگی محلی انتخاب می کند. این آستانه گذاری، برای  تصاویری که هیستوگرام شدت روشنایی، دارای قله های متمایز نباشد(مانند:بخش بندی متن از تصویر)، مناسب است.

این روش در ناحیه اطراف متن نتیجه بخش است. زیرا پیکسل های پیش زمینه وپس زمینه در محدوده همسایگی هر پیکسل به اندازه کافی وجود دارد.
با این حال در margin(ناحیه اطراف متن)،  میانگین ناحیه محلی به عنوان یک آستانه مناسب نیست، زیرا محدوده مقادیر شدت در همسایگی محلی، بسیار کوچک است و میانگین نزدیک به پیکسل مرکزی است. این وضعیت را می توان بهبود داد، اگر آستانه مورد استفاده  mean نباشد مگر  (mean-C)،  که C یک ثابت است.
بنابراین  تمام پیکسلهایی که در محدوده ی یکسان وجود دارند (به عنوان مثال در امتداد حاشیه) به پس زمینه تنظیم میشود.
نتیجه ۷ × ۷ همسایگی و C = 7 نشان داده شده است :

 

11

12

تاثیر انتخاب  cوb های متفاوت در تصویر خروجی.
میتوان به اهمیت این دو ورودی پی برد.

threshold

پردازش تصویر با پایتون قسمت هجدهم

آستانه گذاری ساده

Inverted Threshold to Zero ( type = THRESH_TOZERO_INV)

 

در این نوع آستانه، اگر مقدار پیکسل منبع بیشتر از آستانه باشد، مقدار پیکسل مقصد به مقدار صفر تنظیم می شود . در غير اين صورت آن را به مقدار پيکسل منبع تنظيم ميکنيم. maxValue نادیده گرفته شده است.

الگوریتم:

if src(x,y) > thresh
dst(x,y) =0
else
dst(x,y) =src(x,y)

کد:

import cv2
 import numpy as np
 from matplotlib import pyplot as plt
img = cv2.imread('threshold.png',0)
 ret,thresh1 = cv2.threshold(img,0,255,cv2.THRESH_BINARY)
 ret,thresh2 = cv2.threshold(img,0,127,cv2.THRESH_BINARY_INV)
 ret,thresh3 = cv2.threshold(img,127,255,cv2.THRESH_TRUNC)
 ret,thresh4 = cv2.threshold(img,127,255,cv2.THRESH_TOZERO)
 ret,thresh5 = cv2.threshold(img,127,255,cv2.THRESH_TOZERO_INV)titles
 = ['Original Image','THRESH_BINARY','THRESH_BINARY_INV','THRESH_TRUNC','THRESH_TOZERO','THRESH_TOZERO_INV']
 images = [img, thresh1, thresh2,thresh3,thresh4,thresh5]
 for i in range(6):
plt.subplot(2,3,i+1),plt.imshow(images[i],'gray')
plt.title(titles[i])
 plt.xticks([]),plt.yticks([])plt.show()
th84
threshold

پردازش تصویر با پایتون قسمت هفدهم

آستانه گذاری ساده

Threshold to Zero ( type = THRESH_TOZERO )

 

در این نوع آستانه، اگر مقدار پیکسل منبع بیشتر از آستانه باشد، مقدار پیکسل مقصد به مقدار پیکسل منبع مربوطه تنظیم می شود. در غیر این صورت صفر است. maxValue نادیده گرفته شده است.

الگوریتم:

if src(x,y) > thresh
  dst(x,y) =src(x,y)

else dst(x,y) =>0

کد:

import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('threshold.png',0)
ret,thresh1 = cv2.threshold(img,0,255,cv2.THRESH_BINARY)
ret,thresh2 = cv2.threshold(img,0,127,cv2.THRESH_BINARY_INV)
ret,thresh3 = cv2.threshold(img,127,255,cv2.THRESH_TRUNC)
ret,thresh4 = cv2.threshold(img,127,255,cv2.THRESH_TOZERO)

titles = ['Original Image','THRESH_BINARY','THRESH_BINARY_INV','THRESH_TRUNC','THRESH_TOZERO']
images = [img, thresh1, thresh2,thresh3,thresh4]
for i in range(5):
plt.subplot(2,3,i+1),plt.imshow(images[i],'gray')
plt.title(titles[i])
plt.xticks([]),plt.yticks([])

plt.show()


th85
threshold

پردازش تصویر با پایتون قسمت شانزدهم

آستانه گذاری ساده

( Truncate Thresholding ( type = THRESH_TRUN

در این نوع آستانه، پیکسل مقصد به آستانه (thresh) تنظیم می شود اگر مقدار پیکسل منبع بیشتر از آستانه باشد. در غير اين صورت آن را به مقدار پيکسل منبع تنظيم ميکنيم. maxValue نادیده گرفته شده است.

الگوریتم:

if src(x,y) > thresh
dst(x,y) =thresh
else
dst(x,y) =src(x,y)

توجه داشته باشید که تمام مقادیر بالای آستانه (۱۲۷) به ۱۲۷ تنظیم شده و تمام مقادیر کمتر یا برابر ۱۲۷ بدون تغییر هستند.

maxValue نادیده گرفته شده است

کد:

import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('threshold.png',0)
ret,thresh1 = cv2.threshold(img,0,255,cv2.THRESH_BINARY)
ret,thresh2 = cv2.threshold(img,0,127,cv2.THRESH_BINARY_INV)
ret,thresh3 = cv2.threshold(img,127,255,cv2.THRESH_TRUNC)
titles = ['Original Image','THRESH_BINARY','THRESH_BINARY_INV','THRESH_TRUNC']
images = [img, thresh1, thresh2,thresh3]
for i in range(4):
plt.subplot(2,3,i+1),plt.imshow(images[i],'gray')
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()

th3th5

 

threshold

پردازش تصویر با پایتون قسمت پانزدهم

آستانه گذاری ساده

Inverse Binary Thresholding ( type = THRESH_BINARY_INV )

معکوس کردن آستانه گذاری دوتایی (فقط دو مقار سفید و سیاه را داریم) است.

اگر پیکسل منبع مربوطه بیشتر از آستانه باشد پیکسل مقصد به صفر تنظیم میشود و در غیر این صورت، به maxValue تنظیم میشود.

if  src(x,y) > thresh
dst(x,y) = 0
else
dst(x,y) =maxValue

کد:

import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('threshold.png')
ret,thresh1 = cv2.threshold(img,0,255,cv2.THRESH_BINARY)
ret,thresh2 = cv2.threshold(img,0,128,cv2.THRESH_BINARY_INV)

titles = ['Original Image','THRESH_BINARY','THRESH_BINARY_INV']
images = [img, thresh1, thresh2]
for i in range(3):
    plt.subplot(2,3,i+1),plt.imshow(images[i],'gray')
    plt.title(titles[i])
    plt.xticks([]),plt.yticks([])

plt.show()
th3

 

پردازش تصویر با پایتون- قسمت چهاردهم

آستانه  گذاری ساده

 

مرسوم ترین خصوصیت تصویر برای  آستانه گذاری، سطح  خاکستری پیکسل است:
اگر T آستانه باشد

g(x,y) = ۰ if f(x,y) < T  و g(x,y) = ۱ if f(x,y) ≥ T

اگر دو تا آستانه داشته باشیم  T1 < T1  :

g(x,y) = ۰ if f(x,y) < T1 OR f(x,y) > T2 and g(x,y) = ۱ if T1 ≤ f(x,y) ≤ T2

th8

https://www.cs.auckland.ac.nz

 

مشکل اصلی این است که  چگونه یک یا تعدادی آستانه مناسب، برای جدا کردن یک یا چند شی دلخواه از پس زمینه، انتخاب کنیم. 

در بسیاری از موارد عملی، آستانه گذاری ساده، قادر به جداسازی اشیاء مد نظر نیست، همانطور که در تصاویر بالا نشان داده شده است.

تابع استفاده شده، cv2.threshold است.

 

cv2.threshold(src, thresh, maxval, type[, dst]) → retval, dst

پارامترها

src : آرایه ورودی همان تصویر ورودی( تک کاناله(خاکستری )، ۸ بیتی یا ۳۲ بیتی شناور)

dst : آرایه یا تصویر خروجی که هم اندازه و هم نوع با تصویر ورودی است.

thresh : مقدار آستانه

maxval : حداکثر مقدار برای استفاده دو نو آستانه گذاری ساده THRESH_BINARY و THRESH_BINARY_INV .

type  : نوع آستانه گذاری

 

OpenCV سبک های مختلف آستانه گذاری ساده  را فراهم می کند و توسط پارامتر چهارم تابع تعیین می شود:

  • cv2.THRESH_BINARY
  • cv2.THRESH_BINARY_INV
  • cv2.THRESH_TRUNC
  • cv2.THRESH_TOZERO
  • cv2.THRESH_TOZERO_INV
threshold ture

https://docs.opencv.org/2.4/modules/imgproc/doc/miscellaneous_transformations.html#cv2.threshold

 

ساده ترین شکل آستانه گذاری ، آستانه گذاری باینری نامیده می شود.

اگر (src (x، y بزرگتر از thresh باشد، مقدار (dst (x، y(تصویر مقصد) به maxValue تنظیم میشود، در غیر اینصورت آن را صفر تنظیم می کند.

ifsrc(x,y) > thresh
dst(x,y) =maxValue
else
dst(x,y)  =0
thresholded
 

مشخص است. اگر مقدار پیکسل بیشتر از یک مقدار آستانه باشد، مقدار (ممکن است سفید باشد) تعیین می شود، در غیر اینصورت یک مقدار دیگر (ممکن است سیاه باشد) تعیین می شود.

 دو خروجی به دست می آید.یکی از آنها retval  است که بعدا توضیح داده خواهد شد.خروجی دوم تصویر آستانه ای است. بنابراین حتما باید از دو متغیر استفاده کنیم. 

threshold

https://www.learnopencv.com

کد:

import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('threshold.png')
#thresh = ۰ و maxValue = ۲۵۵٫
ret,thresh1 = cv2.threshold(img,0,255,cv2.THRESH_BINARY)
#با تغییر آستانه به ۳۵، شدت نور بالاتر از  ۳۵ نمایش داده میشود. 
ret,thresh2 = cv2.threshold(img,35,255,cv2.THRESH_BINARY)
ret,thresh3 = cv2.threshold(img,65,255,cv2.THRESH_BINARY)
#با آستانه ۱۲۷ و بیشترین مقدار ۱۲۵ ، شدت نور بالاتر از ۱۲۷ و با رنگ ۱۲۸ نمایش داده میشود. 
ret,thresh4 = cv2.threshold(img,127,128,cv2.THRESH_BINARY)
ret,thresh5 = cv2.threshold(img,0,128,cv2.THRESH_BINARY)

titles = ['Original Image','THRESH1','THRESH12','THRESH3','THRESH4','THRESH6']
images = [img, thresh1, thresh2, thresh3, thresh4, thresh5]

for i in range(6):
 plt.subplot(2,3,i+1),plt.imshow(images[i],'gray')
 plt.title(titles[i])
 plt.xticks([]),plt.yticks([])

plt.show()

th1
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('threshold.png')
ret,thresh1 = cv2.threshold(img,0,255,cv2.THRESH_BINARY)
# تغییر بیشترین مقدار به ۱۲۸، مقدار بخش آستانه گذاری شده را به ۱۲۸ تنظیم می کند.
ret,thresh2 = cv2.threshold(img,0,128,cv2.THRESH_BINARY)
ret,thresh3 = cv2.threshold(img,0,201,cv2.THRESH_BINARY)
ret,thresh4 = cv2.threshold(img,0,66,cv2.THRESH_BINARY)
ret,thresh5 = cv2.threshold(img,0,33,cv2.THRESH_BINARY)
titles = ['Original Image','THRESH255','THRESH128','THRESH201','THRESH6','THRESH33']
images = [img, thresh1, thresh2, thresh3, thresh4, thresh5]
for i in range(6):
plt.subplot(2,3,i+1),plt.imshow(images[i],'gray')
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()
th33