نوشته‌ها

Histogram in OpenCv

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

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

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

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

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

 

مرسوم ترین خصوصیت تصویر برای  آستانه گذاری، سطح  خاکستری پیکسل است:
اگر 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

Image Segmentation

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

OpenCV Threshold

بخشبندی تصویر (Image Segmentation)

هدف پردازش تصویر دیجیتال، استخراج اطلاعات مفید(آبجکت، شی، ۲۵۵، ۱، روشن) از تصاویر، بدون کمک انسان است.

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

 

 

خروجی بخشبندی

 

۱) پیکسلهای لبه یا مرز یک بخش. کاربرد:  گوشه ها یا حالت  ناحیه ی مد نظر  را مشخص میکند.

۲) تمام پیکسلهای درون یک بخش. کاربرد: ویژگیهای درونی بخش های تصویر مثل بافت، رنگ و … را مشخص میکند.

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

 

تکنیکهای بخشبندی

۱)  contextual (بخش بندی بر اساس لبه ها):  تصویر،  با آشکار کردن نقاط یا مرزهایی که در محل آنها،  تغییرات سریع سطوح خاکستری وجود دارند، بخش بندی میشود. 

Contexuall

۲) non-contextual (بخش بندی بر اساس نواحی): بر اساس شباهت سطوح خاکستری ، تصویر،  در ابتدا با آستانه گذاری، ناحیه را گسترش داده و با ادغام کردن  بخش ها، بخشبندی میشود. همین جا اشاره کنم که آستانه گذاری از نوع non-contextual میباشد.(ماسکهای آشکار ساز لبه ها، همانند فیلتر بالاگذر حوزه فرکانس  که در قسمتهای بعدی توضیح داده میشوند، میباشند.)

non

 

کاربرد بخشبندی

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

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

 

آستانه‌گذاری  مناسب‌ترین و ساده ترین تکنیک بخش بندی non-contextual است.
با اعمال آستانه‌گذاری بر روی تصویر در مقیاس خاکستری، تصویری باینری(۰و۱) بدست می‌آید که تصویر به دو بخش کاملا جدا از هم تقسیم میشود.یکی از آنها حاوی پیکسل هایی با مقادیر داده ورودی کوچکتر از آستانه و دیگری مربوط به مقادیر ورودی است که برابر آستانه یا بیشتراز آن هستند. مناطق اول و دوم معمولا به ترتیب با برچسب صفر (۰) و غیر صفر (۱) برچسب گذاری می شوند. آستانه گذاری ، ممکن است دارای چند آستانه باشد که تصویر را به چند بخش مجزا تقسیم میکنند.

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

به عبارت دیگر آستانه گذاری شامل تقسیم یک تصویر به دو منطقه است: یک منطقه آبجکت و یک منطقه پس زمینه.
threshold e

تصویر زیر را با دقت مشاهده کنید:

threshold

https://www.learnopencv.com

چند عدد می بینید؟
اکثر شما اعداد زیر را می بینید:
۳۲ (آه، بله، به دقت نگاه کنید)، ۶۴، ۱۰۰، ۱۲۸، ۱۸۰، ۲۰۰ و ۲۵۵٫ اما در تصویر، اعداد بیشتری وجود دارد که به چشم نمیاد.

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

در حقیقت تمام اعداد در تصویر اصلی یک مقدار خاکستری  برابر با عدد دارند. بنابراین ۲۵۵ روشنترین و ۵ تاریک ترین است.

 خواندن اعداد در تصویر آستانه گذاری شده  آسان تر از خواندن اعداد در تصویر اصلی است. جای تعجب نیست که یک الگوریتم  تصویر آستانه گذاری شده، بسیار ساده تر از تصویر اصلی،  پردازش می کند.
تمام الگوریتم های آستانه گذاری، یک تصویر منبع (src) و مقدار آستانه (thresh) به عنوان ورودی میگیرند، و با مقایسه مقادیر پیکسل در پیکسل  تصویر منبع (x، y) با آستانه،  یک تصویر خروجی (dst) تولید می کند. اگر src (x، y)> thresh باشد، سپس (dst (x، y یک مقدار را تعیین می کند. در غیر این صورت، (dst (x، y مقدار دیگری را ایجادمی کند.

سه روش آستانه ‘گذاری داریم که در قسمتهای بعدی توضیح داده خواهند شد:
+ Simple thresholding
+ Adaptive thresholding
+ Otsu’s thresholding

 

background-subtraction

به دست آوردن تفریق دو تصویر با دستور BackgroundSubtractorMOG در پایتون

تفریق تصویر

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

چندین الگوریتم برای این منظور معرفی شدند. OpenCV سه الگوریتم را اجرا کرده است که بسیار آسان است. ما آنها را توسط فیلم زیر،  یک به یک می بینیم.

https://github.com/opencv/opencv/blob/master/samples/data/vtest.avi

 

BackgroundSubtractorMOG

import numpy as np
import cv2
cap = cv2.VideoCapture('vtest.avi')
fgbg = cv2.createBackgroundSubtractorMOG()
while(1):
    ret, frame = cap.read()
    fgmask = fgbg.apply(frame)
    cv2.imshow('frame',fgmask)
    k = cv2.waitKey(30) &amp; 0xff
    if k == 27:
        break
cap.release()
cv2.destroyAllWindows()
Background Subtraction

Background Subtraction

 

BackgroundSubtractorMOG2

import numpy as np
import cv2
cap = cv2.VideoCapture('vtest.avi')
fgbg = cv2.createBackgroundSubtractorMOG2()
while(1):
    ret, frame = cap.read()
    fgmask = fgbg.apply(frame)
    cv2.imshow('frame',fgmask)
    k = cv2.waitKey(30) &amp; 0xff
    if k == 27:
        break
cap.release()
cv2.destroyAllWindows()
Background Subtraction

https://docs.opencv.org.html

BackgroundSubtractorGMG

import numpy as np
import cv2
cap = cv2.VideoCapture('vtest.avi')
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3))
fgbg = cv2.createBackgroundSubtractorGMG()
while(1):
    ret, frame = cap.read()
    fgmask = fgbg.apply(frame)
    fgmask = cv2.morphologyEx(fgmask, cv2.MORPH_OPEN, kernel)
    cv2.imshow('frame',fgmask)
    k = cv2.waitKey(30) &amp; 0xff
    if k == 27:
        break
cap.release()
cv2.destroyAllWindows()
 
Background Subtraction

Background Subtraction



۱-پردازش تصویر با پایتون-OpenCV
۲-آموزش نصب pip در پایتون
۳-
کتابخانه های مورد نیاز پردازش تصویر
۴ – خواندن و نمایش فرمت تصویر در پایتون
۵- نمایش تصویرRGB با Matplotlib و تابع تبدیل ()cvtColor در OpenCv

۶-تغییر فضاهای رنگ- opencv

۷-تقسیم و ادغام کانال های تصویری با opencv

۸-بخشبندی تصویر (Image Segmentation)

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

۱۰- هیستوگرام در پردازش تصویر


image -processing-python-opencv

نمایش تصویرRGB با Matplotlib و تابع تبدیل ()cvtColor در OpenCv

.

۱- نمایش تصویرRGB با Matplotlib
۱- ۲خواندن و نمایش تصویر فقط با opencv
۱- ۳خواندن و نمایش تصویر فقط با matplotlib
۱- ۴ خواندن تصویر با opencv و نمایش آن توسط matplotlib
۲- تابع تبدیل ()cvtColor در OpenCv

 

 


نمایش تصویرRGB با Matplotlib

 


می دانیم که کتابخانه  matplotlib ، برای کار با نمودارها و ارقام است. اما اگر خواستیم یک تصویر ساده RGB را نمایش دهیم چه؟ آیا می توانیم با matplotlib انجام دهیم؟

در این قسمت مابه شما نشان می دهیم که چگونه یک تصویر RGB  را با matplotlib فقط در چند خط کد  میشه نشان داد و هرگونه ابهاماتی را که هنگام استفاده از OpenCV و matplotlib وقتی با هم اجرا میشوند، مواجه می شوید روشن کنید.

یک تصویر RGB، که گاهی اوقات به عنوان یک تصویر رنگی واقعی نامیده می شود، به صورت یک آرایه سه بعدی  داده m × n × ۳ ذخیره می شود که کانالهای قرمز، سبز و آبی رنگ را برای هر پیکسل تعریف می کند. رنگ هر پیکسل با ترکیبی از فرمت های فایل های گرافیکی تصاویر RGB، به عنوان تصاویر ۲۴(۸*۳) بیتی ذخیره می شود، حال آنکه هر کدام از کانالهای قرمز، سبز و آبی ۸ بیت هستند.

 

نمایش تصویرRGB توسط Matplotlib

تصویر اصلی

 

خواندن و نمایش تصویر فقط با opencv

کد زیر فقط از opencv برای خواندن و نمایش تصویر استفاده  کرده است. توجه داشته باشید که فرمت رنگ پیش فرض در OpenCV  BGR است (بایت ها معکوس می شوند).

import numpy as np
import cv2
img = cv2.imread('test.png')
cv2.imshow('opencv',img)
cv2.waitKey (0)
cv2.destroyAllWindows ()

خروجی:

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

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

 

خواندن و نمایش تصویر فقط با matplotlib

در کد زیر هم فقط از matplotlib برای خواندن و نمایش تصویر  استفاده شده است.

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
image = mpimg.imread(&amp;quot;img2.png&amp;quot;)
plt.imshow(image)
plt.show()

اولین کاری که ما انجام می دهیم این است که کتابخانه matplotlib را وارد کنیم.

ولی ما فقط از یک قسمتی از این کتابخانه مربوط به خواندن تصویر است به عنوان mpimg  ، که جایگزین  matplotlib.image،  همچنین از plt که جایگزین matplotlib.pyplot است  برای نمایش استفاده کردیم.
ما می توانیم تصویر زیر را ببینیم:

 

نمایش تصویر با استفاده از matplotlib با محور دور تصویر

نمایش تصویر با استفاده از matplotlib با محور دور تصویر

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

plt.axis(“off”)
plt.imshow(image)
plt.show()
 
 

خواندن تصویر با opencv و نمایش آن توسط matplotlib

import cv2
import matplotlib.pyplot as plt
image = cv2.imread(&amp;quot;img2.png&amp;quot;)
plt.axis(&amp;quot;off&amp;quot;)
plt.imshow(image)
plt.show()

 

اما نتیجه انتظار نمی رفت تصویر زیر باشد:

خواندن تصویر با opencv و نمایش آن توسط matplotlib

خواندن تصویر با opencv و نمایش آن توسط matplotlib

 

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

پاسخ به عنوان یک نکته در opencv نهفته است.

 

نکته

OpenCV تصاویر RGB را به عنوان آرایه های چند بعدی Numpy معرفی می کند … اما به ترتیب معکوس! به این معنی که تصاویر در واقع در BGR به جای RGB نشان داده شده است!

پس چگونه این مسئله را حل کنیم؟

 

 تصویر را از BGR به RGB   تبدیل   کنیم:


تابع تبدیل ()cvtColor در OpenCv 


این تابع یک تصویر ورودی را از یک فضای رنگی به یکی دیگر تبدیل می کند.  در صورت تغییر به-از فضای رنگ RGB، منظور از کانال ها باید صریح مشخص شود (RGB یا BGR).

cv2.cvtColor(src, code[, dst[, dstCn]]) → dst

پارامتر ها

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

۸-bit unsigned, 16-bit unsigned ( CV_16UC… )

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

code : کد تبدیل فضای رنگ

dstCn – تعداد کانال ها در تصویر مقصد؛ اگر پارامتر ۰ باشد، تعداد کانال ها به صورت خودکار از src و کد به دست می آید.

چرا در OpenCV  فضای رنگ BGR  است؟

 توجه داشته باشید که فرمت رنگ پیش فرض در OpenCV اغلب به عنوان RGB نامیده می شود اما در واقع BGR است (بایت ها معکوس می شوند).

  بنابراین بایت اول یک تصویر استاندارد ۲۴ بیتی،  8 بیتی،  آبی ، بایت دوم سبز  و بایت سوم قرمز خواهد بود. بایت های چهارم، پنجم و ششم پیکسل دوم (آبی، سپس سبز، سپس قرمز)، و غیره

محدوده  معمول برای مقادیر کانال R، G و B عبارتند از:

۰ to 255 for CV_8U images

۰ to 65535 for CV_16U images

۰ to 1 for CV_32F images

CV_8U  – یعنی یک پیکسل می تواند مقادیر ۰-۲۵۵ داشته باشد، این محدوده طبیعی برای اکثر فرمت های تصویری و فیلم است.

CV_32F – پیکسل می تواند هر مقدار بین ۰-۱٫۰ داشته باشد، برای برخی از مجموعه محاسبات در داده ها مفید است – اما باید آن را به ۸ بیت برای ذخیره یا نمایش با ضرب کردن هر پیکسل به ۲۵۵ تبدیل کنید.

CV_8U: یک عدد صحیح بدون علامت ۱ بایت (unsigned char).
CV_32S عدد صحیح علامت دار (int).
CV_32F: نقطه شناور ۴ بایت.

 

import numpy as np
import matplotlib.pyplot as plt
import cv2
img = cv2.imread('img2.png')
temp = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
plt.imshow(temp)
plt.axis('off')
plt.show()

 

نتیجه اسکریپت ما نشان می دهد که رنگ های تصویر ما درست است.

 



۱-پردازش تصویر با پایتون-OpenCV
۲-آموزش نصب pip در پایتون
۳-
کتابخانه های مورد نیاز پردازش تصویر
۴ – خواندن و نمایش فرمت تصویر در پایتون
۵- نمایش تصویرRGB با Matplotlib و تابع تبدیل ()cvtColor در OpenCv

۶-تغییر فضاهای رنگ- opencv

۷-تقسیم و ادغام کانال های تصویری با opencv

۸-بخشبندی تصویر (Image Segmentation)

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


آموزش قبلی

https://sufra.ir/2017/12/%D9%BE%D8%B1%D8%AF%D8%A7%D8%B2%D8%B4-%D8%AA%D8%B5%D9%88%DB%8C%D8%B1%D8%A8%D8%A7-%D9%BE%D8%A7%DB%8C%D8%AA%D9%88%D9%86/

 

آموزش بعدی

 

 

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

آستانه گذاری ساده-تطبیقی -Otsu

۱- آستانه  گذاری ساده
۱-۲- cv2.threshold
۱-۳- آستانه گذاری باینری
۱-۴- آستانه گذاری باینری معکوس
۱-۵- Truncate Thresholding ( type = THRESH_TRUN
۱-۶- Inverted Threshold to Zero
۲- Adaptive Thresholding
۳- Otsu’s Binarization


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

مرسوم ترین خصوصیت تصویر برای  آستانه گذاری، سطح  خاکستری پیکسل است:
اگر 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

Simple Thresholding

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
Simple Thresholding

https://docs.opencv.org

 

 

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

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

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

ifsrc(x,y) &amp;amp;gt; thresh
dst(x,y) =maxValue
else
dst(x,y)  =0

Simple Thresholding

Simple Thresholding

 

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

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

Simple Thresholding

https://www.learnopencv.com

کد:

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

img = cv2.imread('threshold.png')
#&amp;amp;lt;strong&amp;amp;gt;thresh&amp;amp;nbsp;&amp;amp;lt;/strong&amp;amp;gt;= 0 و&amp;amp;nbsp;&amp;amp;lt;strong&amp;amp;gt;maxValue&amp;amp;lt;/strong&amp;amp;gt;&amp;amp;nbsp;= 255.
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()
THRESH_BINARY

THRESH_BINARY

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

آستانه گذاری باینری معکوس

Inverse Binary Thresholding ( type = THRESH_BINARY_INV )
معکوس کردن آستانه گذاری دوتایی (فقط دو مقار سفید و سیاه را داریم) است.

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

if  src(x,y) &amp;gt; 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()
THRESH_BINARY_INV

“THRESH_BINARY_INV

( Truncate Thresholding ( type = THRESH_TRUN

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

الگوریتم:

if src(x,y) &amp;amp;gt; 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()
Truncate Thresholding

Truncate Thresholding

Truncate Thresholding

Truncate Thresholding

Threshold to Zero ( type = THRESH_TOZERO )

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

الگوریتم:

if src(x,y) &amp;gt; thresh
  dst(x,y) =src(x,y)
else dst(x,y) =&amp;gt;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()

THRESH_TOZERO

THRESH_TOZERO

Inverted Threshold to Zero ( type = THRESH_TOZERO_INV)

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

الگوریتم:

if src(x,y) &amp;gt; 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()
THRESH_TOZERO_INV

THRESH_TOZERO_INV

 

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)

 

Adaptive Thresholding

Adaptive Thresholding

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

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

 

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

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

Adaptive Thresholding

Adaptive Thresholding

Adaptive Thresholding

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

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

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

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

Adaptive Thresholding

Adaptive Thresholding

Adaptive Thresholding

Adaptive Thresholding


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

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

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

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

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

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

Otsu’s Binarization

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

Otsu’s Binarization

Otsu’s Binarization

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 (تصویری که هیستوگرام آن دارای دو قله میباشد)، تقریبا در وسط قله ها می توان آستانه بهینه را انتخاب کرد. 

Otsu’s Binarization

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

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

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

 

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

Otsu’s Binarization

تصویر اصلی

Otsu’s Binarization

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

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



۱-پردازش تصویر با پایتون-OpenCV
۲-آموزش نصب pip در پایتون
۳-
کتابخانه های مورد نیاز پردازش تصویر
۴ – خواندن و نمایش فرمت تصویر در پایتون
۵- نمایش تصویرRGB با Matplotlib و تابع تبدیل ()cvtColor در OpenCv

۶-تغییر فضاهای رنگ- opencv

۷-تقسیم و ادغام کانال های تصویری با opencv

۸-بخشبندی تصویر (Image Segmentation)

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

۱۰- هیستوگرام در پردازش تصویر


 

image -processing-python-opencv

تغییر فضاهای رنگ- opencv

۱- تغییر فضاهای رنگ- opencv
۲- HSV
۲-۱ Hue
۲-۳ Value
۲-۴ Saturation or intensity
۲-۵ HSV چه کاربردی دارد؟
۲-۵ استخراج سه شی رنگی از تصویر
۲-۵ برای پیدا کردن مقادیر HSV چکار باید کرد؟
۳- Grayscale


تغییر فضاهای رنگ

 

در این آموزش،  نحوه ی  تبدیل تصاویر از یک فضای رنگی به دیگری را  یاد خواهیم گرفت. مانند: BGR \leftrightarrowGray, BGR \leftrightarrow HSV. علاوه بر این، یک برنامه ایجاد می کنیم که ۳ شیء رنگی را از یک تصویر استخراج کند، و در ادامه به تصاویر خاکستری می پردازیم. در OpenCV، بیش از ۱۵۰ روش تبدیل فضای رنگ وجود دارد. اما تنها دو مورد که بیشتر مورد استفاده قرار می گیرند، به BGR ↔ Gray و BGR ↔ HSV را توضیح می دهیم .


برای تبدیل رنگ، از تابع (cv2.cvtColor (input_image، flag استفاده می کنیم که در آن پرچم، نوع تبدیل را تعیین می کند.

برای تبدیل  BGR →Gray،   از پرچم cv2.COLOR_BGR2GRAY و برای BGR → HSV، از پرچم cv2.COLOR_BGR2HSV استفاده می کنیم. .
برای دریافت پرچم های دیگر، فقط دستورات زیر را در ترمینال پایتون خود اجرا کنید:

import cv2
flags = [i for i in dir(cv2) if i.startswith('COLOR_')]
print flags

 (HSV)

یک فضای رنگی مناسب، مدل رنگی HSV است. همانطور که گفتم قراره اشیاء داخل یک تصویر را  از آن جدا کنیم. تشخیص یا استخراج اشیاء در خیلی جاها از جمله کنترل وسایل نقلیه و  ترافیک کاربرد دارد. در واقع در این مدل، دو ویژگی روشنایی و شدت نور، کمک زیادی می کند. این مدل، دارای سه ویژگی متمایز است:

Hue


نام رنگ (زرد، سبز، صورتی و..) . 

Value

 

روشنایی یا تیرگی رنگ (خاکستری)



Saturation or intensity

 اشباع یا شدت نور  : خلوص رنگ، روشنایی یا تاریکی ( طیف رنگی قرمز).

 

نکته

در فضای رنگ HSV، محدوده رنگ [۰،۱۷۹]، محدوده اشباع [۰،۲۵۵] و محدوده مقدار [۰،۲۵۵] است. نرم افزار های مختلف از مقیاس های مختلف استفاده می کنند. بنابراین اگر مقادیر OpenCV را با آنها مقایسه کنید، باید این محدوده ها را نرمال کنید.

مدل رنگ HSV چه کاربردی دارد؟

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

در HSV، رنگ آمیزی ساده تر از BGR رنگی است. 

 

 

hsv

 

hsv
hsv
hsv

HSV

 

استخراج سه شی رنگی از تصویر

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

  1. برنامه،  تصویر را بگیرد
  2. تبدیل از فضای رنگ BGR به HSV انجام دهد.

 

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

در حال حاضر تنها ۳ شیء آبی و سبز و قرمز را استخراج می کنیم، می توانیم هر آنچه را که می خواهیم انجام دهیم.
کد:

 

import cv2
import numpy as np
img = cv2.imread('bgrtohsv.png')
#تبدیل فضای رنگ bgr to hsv
hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV )

lower_blue = np.array([110,50,50])
upper_blue = np.array([120,255,255])

lower_green = np.array([50,50,50])
upper_green = np.array([60,255,255])

lower_red = np.array([0,50,50])
upper_red = np.array([0,255,255])
#آستانه گیری(cv2.inRange())
maskb = cv2.inRange(hsv, lower_blue, upper_blue)
maskg = cv2.inRange(hsv, lower_green, upper_green)
maskr = cv2.inRange(hsv, lower_red, upper_red)
# and تصویر اصلی با ماسک
#میشود (cv2.bitwise_and())
resb = cv2.bitwise_and(img,img, mask= maskb)
resg = cv2.bitwise_and(img,img, mask= maskg)
resr = cv2.bitwise_and(img,img, mask= maskr)

cv2.imshow('original image',img)
cv2.imshow('maskb',maskb)
cv2.imshow('maskg',maskg)
cv2.imshow('maskr',maskr)

cv2.imshow('resb',resb)
cv2.imshow('resg',resg)
cv2.imshow('resr',resr)

cv2.waitKey()
cv2.destroyAllWindows()

rgb-hsv

استخراج سه شی رنگی از تصویر

 

نکته

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

 

برای پیدا کردن مقادیر HSV چکار باید کرد؟

بسیار ساده است و شما می توانید از همان تابع ()cv2.cvtColor  استفاده کنید.

برای مثال، برای پیدا کردن مقدار HSV سبز، دستورات زیر را در ترمینال پایتون امتحان کنید:

green = np.uint8([[[0,255,0 ]]])
hsv_green = cv2.cvtColor(green,cv2.COLOR_BGR2HSV)
print hsv_green
[[[ ۶۰ ۲۵۵ ۲۵۵]]]

اکنون شما می توانید [H-10، ۱۰۰،۱۰۰] و [H + 10، ۲۵۵، ۲۵۵] را به ترتیب پایین تر و بالاتر محدوده رنگ  قرار دهید.

به غیر از این روش، می توانید از هر ابزار ویرایش عکس مانند GIMP یا هر مبدل آنلاین برای پیدا کردن این ارزش ها استفاده کنید.

اما فراموش نکنید که محدوده های HSV را تنظیم کنید.

 

تصاویر Grayscale(خاکستری)

دوربین های قدیمی فقط  قادر به نمایش تصاویر مونوکروم  یا تک رنگ  بودند. درکل سنسور دوربین تنها شدت نور را ثبت میکند که شدت نور طیفی خاکستری ایجاد میکند.

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

Grayscale

http://hamamatsu.magnet.fsu.edu

تصاویر خاکستری فقط دارای یک کانال رنگی(۸بیتی) در مقیاس ۰ تا ۲۵۵ هستند که نشان دهنده روشنایی آن پیکسل است، ۰ کاملا تاریک (سیاه) و ۲۵۵ کاملا روشن (سفید) است.

Grayscale

Grayscale

 

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

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

مثلا به رنگ سبز دقت کنید، فقط قسمتی که رنگ سبز داریم سفید وبقیه قسمت ها سیاه است. کانال سبز  یک کانال ۸ بیتی که به صورت   [0,255,0]:rgb مقدار دهی می شود و نشان دهنده ی این است که هر چه شدت نور به سمت ۲۵۵ باشد رنگ سبز بیشتر و هر چه به سمت ۰ باشد رنگ سبز کمتری داریم و در مورد کانال های دیگر هم همین استدلال را میشه کرد.

Grayscale

Grayscale

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

import numpy as np
import cv2
import matplotlib.pyplot as pltimg = cv2.imread('test.jpg')
gray_img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
#تصویر خاکستری به عنوان آراه ای دوبعدیprint(gray_img)
[[۲۵۰ ۲۵۰ ۲۵۰ ..., ۲۵۰ ۲۵۰ ۲۵۰]
[۲۵۰ ۲۵۰ ۲۵۰ ..., ۲۵۰ ۲۵۰ ۲۵۰]
[۲۵۰ ۲۵۰ ۲۵۰ ..., ۲۵۰ ۲۵۰ ۲۵۰]
...,
[۲۵۰ ۲۵۰ ۲۵۰ ..., ۲۵۰ ۲۵۰ ۲۵۰]
[۲۵۰ ۲۵۰ ۲۵۰ ..., ۲۵۰ ۲۵۰ ۲۵۰]
[۲۵۰ ۲۵۰ ۲۵۰ ..., ۲۵۰ ۲۵۰ ۲۵۰]]
print (gray_img.shape)&amp;amp;lt;/span&amp;amp;gt;
(۶۴۰, ۶۴۰)
print (img.dtype)
uint8

و در نهایت تبدیل به تصویر خاکستری:

import numpy as np
import cv2
import matplotlib.pyplot as plt
img = cv2.imread('test.jpg')
gray_img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
plt.imshow(cv2.cvtColor(gray_img, cv2.COLOR_GRAY2RGB))
plt.show()
grayscale

تبدیل به تصویر خاکستری

 



۱-پردازش تصویر با پایتون-OpenCV
۲-آموزش نصب pip در پایتون
۳-
کتابخانه های مورد نیاز پردازش تصویر
۴ – خواندن و نمایش فرمت تصویر در پایتون
۵- نمایش تصویرRGB با Matplotlib و تابع تبدیل ()cvtColor در OpenCv

۶-تغییر فضاهای رنگ- opencv
۷-تقسیم و ادغام کانال های تصویری با opencv

 


image -processing-python-opencv

خواندن و نمایش و نوشتن تصویر در پایتون

۱- پردازش تصویر چیست؟
۲- فرمت تصویر
۳ – نمایش فرمت تصویر
۴ – کانال
۵- خواندن یا وارد کردن تصویر
۶ – نمایش تصویر در OpenCv
۷ – نوشتن یا ذخیره تصویر در OpenCV
۷-۱ – فشرده سازی تصویر
۷-۲ – تصاویر رستری
۷-۳ – تصاویر برداری


پردازش تصویر چیست؟

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

شروع کار پردازش تصویر  با  ایمپورت ها است. ما از کتابخانه های  cv2، numpy و کمی از matplotlib (اغلب به عنوان یک روش راحت برای نمایش تصاویر) استفاده می کنیم .

matplotlib : کتابخانه ای برای رسم نمودارها

matplotlib.pyplot: هر تابع pyplot باعث تغییراتی در شکل می شود: به عنوان مثال شکلی را  می گیرد،  یک منطقه ترسیم در شکل ایجاد می کند،   چند خط در یک منطقه  از شکل ترسیم میکند،  شکل را با برچسب و غیره تزئین می کند و … .

NumPy : کتابخانه ای  برای محاسبات علمی با پایتون است. این شامل موارد زیر است:
۱) یک آبجکت آرایه n بعدی قدرتمند

۲) ابزاری برای ادغام C / C ++ و کد Fortran 

۳) …..

import cv2,matplotlib
import numpy as np
import matplotlib.pyplot as plt

فرمت تصویر

بسيار خوب! ما نیاز داریم تصاویر را بخوانیم تا فرمتی که آنها نشان میدهند را بفهمیم.در OpenCv تصاویر به صورت زیر آرایه ۳ بعدی numpy نمایش داده می شوند. یک تصویر رنگی  از ردیف های پیکسل تشکیل شده و هر پیکسل با آرایه ای از مقادیر رنگ نمایش داده می شود.

BGR

BGR

نمایش فرمت تصویر

(اساسا یک آرایه ۳ بعدی از اطلاعات رنگ پیکسل، در قالب BGR):

print( img)
[[[۱۸۳ ۱۸۳ ۱۸۳][۱۰۲ ۱۰۲ ۱۰۲][۱۰۲ ۱۰۲ ۱۰۲]..., [۱۰۲ ۱۰۲ ۱۰۲][۱۰۲ ۱۰۲ ۱۰۲][۱۰۲ ۱۰۲ ۱۰۲]]

[[۱۰۲ ۱۰۲ ۱۰۲][۱۹۳ ۱۹۳ ۱۹۳][۲۵۳ ۲۵۳ ۲۵۳]..., [۱۶۸ ۱۶۸ ۱۶۸][۲۵۴ ۲۵۴ ۲۵۴][۱۹۳ ۱۹۳ ۱۹۳]]
[[۲۵۳ ۲۵۳ ۲۵۳][۲۵۲ ۲۵۲ ۲۵۲][۲۵۲ ۲۵۲ ۲۵۲]..., [۱۶۷ ۱۶۷ ۱۶۷][۲۵۳ ۲۵۳ ۲۵۳][۲۵۲ ۲۵۲ ۲۵۱]]
..., [[۲۵۵ ۲۵۵ ۲۴۷][۲۵۵ ۲۵۵ ۲۴۷][۲۵۴ ۲۵۴ ۲۵۱]..., [ ۶۸ ۶۲ ۵۶][۲۰۲ ۱۹۷ ۱۹۱][۱۳۶ ۱۲۳ ۱۰۹]]
[[۲۵۵ ۲۵۵ ۲۴۷][۲۵۵ ۲۵۵ ۲۴۶][۲۵۵ ۲۵۵ ۲۵۰]..., [۱۲۱ ۱۱۶ ۱۱۱][۱۸۶ ۱۷۹ ۱۷۳][۱۲۱ ۱۱۰ ۹۷]]
[[۲۵۵ ۲۵۵ ۲۴۴][۲۵۵ ۲۵۵ ۲۴۳][۲۵۵ ۲۵۵ ۲۴۶]..., [۱۷۸ ۱۷۲ ۱۶۶][۱۴۵ ۱۳۶ ۱۲۷][۱۰۷ ۹۶ ۸۴]]]

اینجا [ ۱۴۵ ۱۳۶ ۱۲۷] و… ، مقادیر یک پیکسل، آبی، قرمز و سبز (BGR) هستند. توجه داشته باشید که OpenCV به طور پیش فرض یک تصویر را در قالب BGR بارگذاری می کند.

کانال 

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


خواندن یا وارد کردن تصویر(imread )

BGR-RGB

تصویر اصلی

import numpy as np
import cv2
img = cv2.imread('test.jpg')
print(img)

برای خواندن تصویر در opencv، از تابع imread استفاده می کنیم. آرگومان این تابع آدرس محل ذخیره تصویر است. 

cv2.imread(filename[, flags])&amp;amp;amp;amp;amp;amp;amp;amp;amp;nbsp;→ retval
cv2.imread('test.jpg',0 or 1 or -1)

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

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

۱) cv2.IMREAD_COLOR: تصویر رنگی را بارگیری می کند و هر گونه شفافیت تصویر را نادیده می گیرد. این پرچم پیش فرض است:

پرچم بزرگتر از ۰ تصویر رنگی سه کاناله(قرمز، سبز،آبی)  و عمق ۸ بیتی برمیگرداند. BGR

cv2.imread('test.jpg')
or
cv2.imread('test.jpg',1)
or
cv2.imread('test.jpg',cv2.IMREAD_COLOR)

۲) cv2.IMREAD_GRAYSCALE: بارگیری تصویر در حالت خاکستری یک کانال و عمق ۸ بیتی:

cv2.imread('test.jpg',0)

۳) cv2.IMREAD_UNCHANGED: تصویر را به عنوان  کانال آلفا بارگیری می کند:

اگر پرچم کوچکتر از ۰ باشد تصویر ۴ کاناله برمیگرداند. تابع وقتی تصویر ۱۶/۳۲ بیتی برمیگرداند که تصویر ورودی دارای یک همچین عمقی باشد وگرنه آ ن را به ۸ بیتی تبدیل میکند

cv2.imread('test.jpg',-1)
or
cv2.imread('test.jpg',cv2.IMREAD_UNCHANGED)

نکته

به جای این سه پرچم، به سادگی می توانید عدد صحیح ۱، ۰ یا -۱ را منتقل کنید.

کد زیر را ببینید:

&amp;amp;amp;amp;amp;amp;amp;amp;amp;nbsp;import numpy as np
import cv2
img = cv2.imread('test.jpg',0)

همانطور که در قطعه کد بالا  ملاحظه میکنید بعد از خواندن تصویر آن را در متغییری به نام img قرار میدهیم. از این متغیر برای نمایش تصویر، نوشتن تصویر و … استفاده میکنیم.

هشدار

حتی اگر مسیر تصویر اشتباه باشد، خطایی نخواهد داشت، اما img  چاپ نمیشود.

img = cv2.imread('test.jpg')

 نمایش تصویر(imshow) در  OpenCv

 cv2.imshow()

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

import cv2
img = cv2.imread('test.png')
cv2.imshow('opencv',img)
c = cv2.waitKey(0)
cv2.destroyAllWindows()
11

cv2.imshow()

 

 

 

Waits for a pressed key(منتظر برای فشار دادن یک کلید ازصفحه کلید).  یک تابع اتصال به  صفحه کلید است. یک آرگومان دارد که زمان در میلی ثانیه است.

cv2.waitKey([delay]) → retval

پارامتر ها

delay 

تاخیرزمان به میلی ثانیه . ۰ به عنوان آرگوان ورودی مقدار ویژه ای است به معنای “بی وقفه” است.

اگر  (\texttt{delay}\leq 0 ) باشد یعنی پنجره برای مدت نامحدودی منتظر می ماند تا زمانی یک کلید از صفحه کلید را فشار دهیم و آن بسته شود. 

اگر مقدار delay  مثبت باشد مثلا ۱۰۰۰، بعد از یک ثانیه پنجره به صورت خودکار بسته میشود. 

این تابع یا کد کلید فشار داده شده از صفحه کلید را بر میگرداند یا -۱(یعنی کلیدی  قبل از زمان مشخص فشار داده نشده . برای من ۲۵۵ بر میگرداند.) 

نکته

این تابع زمانی کار میکند که  حداقل یک پنجره

در حالی که OpenCV برای استفاده در برنامه های کاربردی تمام عیار طراحی شده است و می تواند در چارچوب های عملکردی غنی از UI (مانند Qt *، WinForms * یا Cocoa *) یا بدون استفاده از رابط کاربری مورد استفاده قرار گیرد، گاهی اوقات لازم است که سرعت عمل را امتحان و نتایج را تصور کنید. این همان چیزی است که ماژول HighGUI برای آن طراحی شده است.

destroyAllWindows

تابع destroyAllWindows تمام پنجره های باز شده HighGUI را از بین می برد.

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

import cv2
def sufra():
img = cv2.imread('test.png')
cv2.imshow('image', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
print (&amp;amp;amp;amp;amp;amp;amp;amp;quot;waitkey&amp;amp;amp;amp;amp;amp;amp;amp;quot;)

if __name__ == '__main__':
sufra()

waitkey

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

۱۰۶ کد اسکی حرف h  میباشد.

import cv2
def sufra():
img = cv2.imread('test.png')
cv2.imshow('image', img)
key=cv2.waitKey(1000)
cv2.destroyAllWindows()
print (key)
print (&amp;amp;amp;amp;amp;amp;amp;amp;quot;waitkey&amp;amp;amp;amp;amp;amp;amp;amp;quot;)

if __name__ == '__main__':
sufra()

۲۵۵
waitkey
۱۰۴
waitKey

در کد  از دستور if استفاده کردیم که فقط با  فشار دادن کلید q،پنجره بسته میشود. 

ord()

تابع ()ord یک رشته یا کاراکتر میگرد و کد اسکی آن را بر میگرداند.

import cv2
def sufra():
img = cv2.imread('test.png')
while True:
cv2.imshow('image', img)
if cv2.waitKey(1)  == ord('q'):
cv2.destroyAllWindows()
print (&amp;amp;amp;amp;amp;amp;amp;amp;quot;q&amp;amp;amp;amp;amp;amp;amp;amp;quot;)
break;

if __name__ == '__main__':
sufra()

waitKey

() cv2.destroyAllWindows

به راحتی تمامی پنجره هایی که ایجاد کردیم  را از بین می برد. اگر می خواهید پنجره خاصی را از بین ببرید، از تابع ()cv2.destroyWindow  استفاده کنید.

cv2.destroyAllWindows() → None

نکته

یک مورد خاص وجود دارد که شما قبلا می توانید یک پنجره ایجاد کنید و تصویر را بعدا بارگذاری کنید. در این صورت، می توانید مشخص کنید که آیا پنجره قابل اندازه بندی مجدد است یا نه.
  این کار توسط تابع () cv2.namedWindow انجام می شود. به طور پیش فرض، پرچم cv2.WINDOW_AUTOSIZE است.اما اگر شما پرچم را به عنوان cv2.WINDOW_NORMAL مشخص کنید،می توانید پنجره را تغییر دهید. هنگامی که تصویر در ابعاد بزرگ، مفید خواهد بود: 

cv2.namedWindow(winname[, flags]) → None

پارامترها

name : نامی برای پنجره که ممکنه به عنوان شناسه هم استفاه شود

flags(پرچم های پنجره):

WINDOW_NORMAL  :   اگر تنظیم شده باشد، کاربر می تواند پنجره را تغییر دهد (بدون محدودیت).
WINDOW_AUTOSIZE  : اگر تنظیم شده باشد، اندازه پنجره به صورت خودکار براساس تصویر نمایش داده می شود ، و شما نمی توانید اندازه پنجره را به صورت دستی تغییر دهید.
WINDOW_OPENGL اگر  : تنظیم شده باشد، پنجره با پشتیبانی OpenGL ایجاد خواهد شد.

import cv2
img = cv2.imread('test.png')
cv2.namedWindow('image', cv2.WINDOW_NORMAL)
cv2.imshow('image',img)
cv2.waitKey(0)
k=cv2.destroyAllWindows()
print(k)
None

نوشتن یا ذخیره تصویر(imwrite  ) در OpenCV 

 

cv2.imwrite()


از تابع ()cv2.imwrite  برای ذخیره یک تصویر در یک فایل مشخص شده استفاده میشود.

cv2.imwrite(filename, img[, params]) → retval

پارامتر ها

 

filename : نام  برای فایل انتخاب یکنیم 

image: تصویر  برای ذخیره شدن

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

 

فشرده سازی تصویر

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

تصاویر رستری 

ساخته شده از پیکسل
تغییر اندازه باعث تغییر در کیفیت تصویر میشد.

فرمت های رایج: jpg، png، gif، tif، bmp

تصاویر برداری

ساخته شده از اشیاء بردار (نه مبتنی بر پیکسل)
می تواند به هر اندازه ای تغییر کند بدون عوض کاه یا افزایش کیفیت
• فرمت های رایج: ai، eps، ps، svg، wmf، pdf

 

vector-raster

Bitmap-vector-raster

https://commons.wikimedia.org/wiki/File:Bitmap_VS_SVG.svg

 

 در پردازش تصویر، تصاویر رستری به کار میرود.

 با استفاده از تابع imwrite،  می توان فقط تصاویر  8 بیتی (یا ۱۶ بیت بدون امضای (CV_16U) در حالت تک کانال یا ۳ کانال ( BGR) را ذخیره کرد). ( مانند PNG، JPEG 2000 و TIFF) 

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

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

import numpy as np
import cv2
img = cv2.imread('test.png')
cv2.imshow('image',img)
k = cv2.waitKey(0)
# را فشار بدیم Escاگر
#پنجره بسته میشود
if k == 27:&amp;amp;amp;amp;amp;amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;/span&amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;
cv2.destroyAllWindows()
#اگر این حرف را فشار بدهیم تصویر با نام انتخابی ذخیره میشود.
elif k == ord('s'):&amp;amp;amp;amp;amp;amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;/span&amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;
cv2.imwrite('save.jpg',img)&amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;/span&amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;
cv2.destroyAllWindows()&amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;/span&amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;


۱-پردازش تصویر با پایتون-OpenCV
۲-آموزش نصب pip در پایتون
۳-
کتابخانه های مورد نیاز پردازش تصویر
۴ – خواندن و نمایش فرمت تصویر در پایتون
۵- نمایش تصویرRGB با Matplotlib و تابع تبدیل ()cvtColor در OpenCv

۶-تغییر فضاهای رنگ- opencv
۷-تقسیم و ادغام کانال های تصویری با opencv


آموزش قبلی

آموزش بعدی

image -processing-python-opencv

نمایش تصویرRGB با Matplotlib و تابع تبدیل ()cvtColor در OpenCv

.

۱- نمایش تصویرRGB با Matplotlib</a
۱- ۲خواندن و نمایش تصویر فقط با opencv
۱- ۳خواندن و نمایش تصویر فقط با matplotlib
۱- ۴ خواندن تصویر با opencv و نمایش آن توسط matplotlib
۲- تابع تبدیل ()cvtColor در OpenCv

 

 


نمایش تصویرRGB با Matplotlib

 


می دانیم که کتابخانه  matplotlib ، برای کار با نمودارها و ارقام است. اما اگر خواستیم یک تصویر ساده RGB را نمایش دهیم چه؟ آیا می توانیم با matplotlib انجام دهیم؟

در این قسمت مابه شما نشان می دهیم که چگونه یک تصویر RGB  را با matplotlib فقط در چند خط کد  میشه نشان داد و هرگونه ابهاماتی را که هنگام استفاده از OpenCV و matplotlib وقتی با هم اجرا میشوند، مواجه می شوید روشن کنید.

یک تصویر RGB، که گاهی اوقات به عنوان یک تصویر رنگی واقعی نامیده می شود، به صورت یک آرایه سه بعدی  داده m × n × ۳ ذخیره می شود که کانالهای قرمز، سبز و آبی رنگ را برای هر پیکسل تعریف می کند. رنگ هر پیکسل با ترکیبی از فرمت های فایل های گرافیکی تصاویر RGB، به عنوان تصاویر ۲۴(۸*۳) بیتی ذخیره می شود، حال آنکه هر کدام از کانالهای قرمز، سبز و آبی ۸ بیت هستند.

 

تصویر اصلی

 

خواندن و نمایش تصویر فقط با opencv

کد زیر فقط از opencv برای خواندن و نمایش تصویر استفاده  کرده است. توجه داشته باشید که فرمت رنگ پیش فرض در OpenCV  BGR است (بایت ها معکوس می شوند).

import numpy as np
import cv2
img = cv2.imread('test.png')
cv2.imshow('opencv',img)
cv2.waitKey (0)
cv2.destroyAllWindows ()

خروجی:

11

 

خواندن و نمایش تصویر فقط با matplotlib

در کد زیر هم فقط از matplotlib برای خواندن و نمایش تصویر  استفاده شده است.

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
image = mpimg.imread("img2.png")
plt.imshow(image)
plt.show()

اولین کاری که ما انجام می دهیم این است که کتابخانه matplotlib را وارد کنیم.

ولی ما فقط از یک قسمتی از این کتابخانه مربوط به خواندن تصویر است به عنوان mpimg  ، که جایگزین  matplotlib.image،  همچنین از plt که جایگزین matplotlib.pyplot است  برای نمایش استفاده کردیم.
ما می توانیم تصویر زیر را ببینیم:

 

12

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

plt.axis(“off”)
plt.imshow(image)
plt.show()
 
 

خواندن تصویر با opencv و نمایش آن توسط matplotlib

import cv2
import matplotlib.pyplot as plt
image = cv2.imread("img2.png") 
 plt.axis("off") 
plt.imshow(image)
plt.show() 

 

اما نتیجه انتظار نمی رفت تصویر زیر باشد:

13

 

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

پاسخ به عنوان یک نکته در opencv نهفته است.

 

نکته

OpenCV تصاویر RGB را به عنوان آرایه های چند بعدی Numpy معرفی می کند … اما به ترتیب معکوس! به این معنی که تصاویر در واقع در BGR به جای RGB نشان داده شده است!

پس چگونه این مسئله را حل کنیم؟

 

 تصویر را از BGR به RGB   تبدیل   کنیم:


تابع تبدیل ()cvtColor در OpenCv 


این تابع یک تصویر ورودی را از یک فضای رنگی به یکی دیگر تبدیل می کند.  در صورت تغییر به-از فضای رنگ RGB، منظور از کانال ها باید صریح مشخص شود (RGB یا BGR).

cv2.cvtColor(src, code[, dst[, dstCn]]) → dst

پارامتر ها

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

۸-bit unsigned, 16-bit unsigned ( CV_16UC… )

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

code : کد تبدیل فضای رنگ

dstCn – تعداد کانال ها در تصویر مقصد؛ اگر پارامتر ۰ باشد، تعداد کانال ها به صورت خودکار از src و کد به دست می آید.

چرا در OpenCV  فضای رنگ BGR  است؟

 توجه داشته باشید که فرمت رنگ پیش فرض در OpenCV اغلب به عنوان RGB نامیده می شود اما در واقع BGR است (بایت ها معکوس می شوند).

  بنابراین بایت اول یک تصویر استاندارد ۲۴ بیتی،  ۸ بیتی،  آبی ، بایت دوم سبز  و بایت سوم قرمز خواهد بود. بایت های چهارم، پنجم و ششم پیکسل دوم (آبی، سپس سبز، سپس قرمز)، و غیره

محدوده  معمول برای مقادیر کانال R، G و B عبارتند از:

۰ to 255 for CV_8U images

۰ to 65535 for CV_16U images

۰ to 1 for CV_32F images

CV_8U  – یعنی یک پیکسل می تواند مقادیر ۰-۲۵۵ داشته باشد، این محدوده طبیعی برای اکثر فرمت های تصویری و فیلم است.

CV_32F – پیکسل می تواند هر مقدار بین ۰-۱٫۰ داشته باشد، برای برخی از مجموعه محاسبات در داده ها مفید است – اما باید آن را به ۸ بیت برای ذخیره یا نمایش با ضرب کردن هر پیکسل به ۲۵۵ تبدیل کنید.

CV_8U: یک عدد صحیح بدون علامت ۱ بایت (unsigned char).
CV_32S عدد صحیح علامت دار (int).
CV_32F: نقطه شناور ۴ بایت.

 

import numpy as np
 import matplotlib.pyplot as plt
 import cv2
img = cv2.imread('img2.png')
temp = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
plt.imshow(temp)
plt.axis('off')
plt.show()

 

نتیجه اسکریپت ما نشان می دهد که رنگ های تصویر ما درست است.