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

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

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

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

 

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

 

Grayscale(خاکستری)

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

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

http://hamamatsu.magnet.fsu.edu

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


87

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

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

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

Capture

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

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)
(۶۴۰, ۶۴۰)
>>> 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

هدف

در این آموزش،  نحوه تبدیل تصاویر از یک فضای رنگی به دیگری را  یاد خواهیم گرفت، مانند: BGR \leftrightarrowGray, BGR \leftrightarrow HSV  ، 
علاوه بر این، یک برنامه ایجاد می کنیم که ۳ شیء رنگی را از یک تصویر استخراج کند، و با توابع زیر آشنا خواهید شد:
()cv2.cvtColor () ، cv2.inRange  .

 

در 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

 

hsv2

hsv3hsv4
  بنابراین در اینجا روش به شکل زیر است:

برنامه،  تصویر را بگیرد
تبدیل از فضای رنگ 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()
 

rgbtohsv

 

نکته

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

 

برای پیدا کردن مقادیر 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 را تنظیم کنید.

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

 

هدف

عملیات اساسی و پایه بر روی تصاویر

دسترسی به مقادیر پیکسل و تغییر آنها

دسترسی به مشخصات تصویر
تنظیم قسمت موردنظر در تصویر ((ROI)Region of Interes)

تقسیم و ادغام تصاویر
تقریبا تمام عملیات در این بخش به طور عمده به Numpy بیشتر از  OpenCV مربوط می شود. دانش خوبی از Numpy برای نوشتن کد بهینه سازی بهتر با OpenCV لازم است.

* (نمونه ها در ترمینال پایتون نشان داده می شوند، زیرا اکثر آنها فقط کدهای خطی هستند)

 

دسترسی و تغییر مقادیر پیکسل – opencv

[gap height=”19″]

[gap height=”19″]
اجازه دهید یک تصویر رنگی را بار اول بگذاریم:

 

>>> import cv2
>>>import numpy as np
>>>img = cv2.imread('img2.png')
>>>

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

px = img[100,100]
 >>> print (px)
 [۲۴۷ ۲۵۳ ۲۳۴]
>>> blue = img[100,100,0]
 >>> print (blue)
 ۲۴۷
 >>> green = img[100,100,1]
 >>> print(green)
 ۲۵۳
>>> red = img[100,100,2]
 >>> print(red)
 ۲۳۴
 >>>

شما می توانید مقادیر پیکسل را به همین شیوه تغییر دهید. به عنوان مثال :


>>> img[20,20] = [0,0,0]
 >>> print (img[20,20])
 [۰ ۰ ۰]
 >>>
point

تغییر مقدار پیکسل

 

هشدار

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

نکته

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

برای دسترسی به پیکسل های تکی، متدهای  آرایهNumpy ،  () و array.itemset () array.item   بهتر است در نظر گرفته شود. اما همیشه یک اسکالر را برمیگرداند. بنابراین اگر میخواهید به تمام مقادیر B، G، R  دسترسی داشته باشید، باید با استفاده از array.item () به طور جداگانه برای همه صدا بزنید.

روش دسترسی و ویرایش بهتر پیکسل:

>>> img.item(20,20,2)
 ۰
>>> img.item(10,10,2)
 ۲۳۵
 >>> img.itemset((20,20,2),100)
 >>> img.item(20,20,2)
 ۱۰۰
 >>>

دسترسی به ویژگی های تصویر(img.shape)

خواص تصویر شامل تعداد ردیف ها، ستون ها و کانال ها، نوع داده های تصویر، تعداد پیکسل ها و غیره

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

>>> print (img.shape)
 (۶۴۰, ۶۴۰, ۳)
>>>

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

تعداد کل پیکسل ها توسط img.size قابل دسترسی است:

>>> print (img.size)
 ۱۲۲۸۸۰۰
 >>>

نوع داده تصویر توسط img.dtype بدست می آید:

>>> print (img.dtype)
 uint8
 >>>

نکته

توجه داشته باشید img.dtype بسیار مهم است در اشکال زدایی، زیرا تعداد زیادی از خطا در کد OpenCV-Python ناشی از نوع داده معتبر است.

 

Image ROI

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

در اینجا من با انتخاب الله در تصویر و کپی کردن،  آن را به یک منطقه دیگر در تصویر منتقل کردم:

import cv2
import numpy as np
img = cv2.imread('img2.PNG')
allah = img[105:190,435:521]
img[79:164,1:87] = allah
img[544:623,115:194] = [0,255,0]
img[544:623,17:96] = [255,0,0]
img[544:623,212:290] = [0,0,255]
cv2.namedWindow('My Image', cv2.WINDOW_NORMAL)
cv2.imshow('My Image',img)
cv2.waitKey(0)
roi

 

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

گاهی اوقات شما باید جداگانه در کانال های B، G، R کار کنید. سپس شما نیاز دارید برای تقسیم تصاویر BGR به یک تک کاناله:


b,g,r = cv2.split(img)
blue =cv2.split(img)[0]
green=cv2.split(img)[1]
red = cv2.split(img)[2]

import cv2
import numpy
import matplotlib.pyplot
image = cv2.imread("img2.png",1)
print(image.shape)
b,g,r = cv2.split(image) # the order is not r,g,b
cv2.namedWindow("Image", cv2.WINDOW_NORMAL)
cv2.imshow("Image",image)
cv2.namedWindow("ImageR", cv2.WINDOW_NORMAL)
cv2.imshow("ImageR",r)
cv2.namedWindow("ImageG", cv2.WINDOW_NORMAL)
cv2.imshow("ImageG",g)
cv2.namedWindow("ImageB", cv2.WINDOW_NORMAL)
cv2.imshow("ImageB",b)
cv2.waitKey(0)
cv2.destroyAllWindows()

rgb7

یا بعضی وقتها، ممکن است نیاز به پیوستن این کانال های فردی و تبدیل آن به  تصویر BGR باشید:

 

img = cv2.merge((b,g,r))

یا

b = img[:,:,0]

فرض کنید شما می خواهید تمام پیکسل های قرمز را صفر کنید
شما نیازی به تقسیم کردن این کار ندارید و آن را برابر صفر قرار دهید. شما می توانید به راحتی از Indexing Numpy استفاده کنید و سریع تر است.

img[:,:,2] = 0

 

شما می توانید تبدیل رنگ قرمز به سیاه را  به سادگی انجام دهید:

 

>>> import cv2
import numpy as np
img = cv2.imread('img2.PNG')
b,g,r = cv2.split(img)
img = cv2.merge((b,g,r))
b = img[:,:,0]
img[:,:,2] = 0
cv2.namedWindow('My Image', cv2.WINDOW_NORMAL)
cv2.imshow('My Image',img)
cv2.waitKey(0)
b

 

 

هشدار

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

 

ساخت مرز و حاشیه برای تصاویر

 

اگر می خواهید حاشیه ای در اطراف تصویر ایجاد کنید، چیزی شبیه یک قاب عکس، شما می توانید از تابع ()cv2.copyMakeBorder  استفاده کنید. اما این تابع کاربردهای بیشتری برای عملیات کانولوشن، صفر کردن و غیره دارد. این تابع با استفاده از آرگومانهای های زیر عمل می کند:
src – تصویر ورودی

top, bottom, left, right:  تعداد پیکسل ها در جهت های مربوطه

borderType: – پرچم  برای تعریف اینکه چه نوع حاشیه ای اضافه می شود. می تواند انواع زیر باشد:

cv2.BORDER_CONSTANT : حاشیه رنگ ثابت را اضافه می کند. ارزش باید به عنوان آرگومان بعدی داده شود.

cv2.BORDER_REFLECT : مرز بازتابی از عناصر مرزی است، مثل این: fedcba | abcdefgh | hgfedcb

cv2.BORDER_REFLECT_101 یا cv2.BORDER_DEFAULT – همانند بالا، اما با تغییر جزئی، مانند این است: gfedcb | abcdefgh | gfedcbacv2.BORDER_REPLICATE

cv2.BORDER_REPLICATE – آخرین عنصر در سراسر تکرار شده است، مانند این: aaaaaa | abcdefgh | hhhhhhh

cv2.BORDER_WRAP – نمی توان توضیح داد، به نظر می رسد: cdefgh | abcdefgh | abcdefg
value – رنگ مرزی اگر نوع مرزی cv2.BORDER_CONSTANT باشد
در زیر یک کد نمونه برای نشان دادن تمام این انواع مرز برای درک بهتر است:

قطعه کد زیر از  from matplotlib import pyplot as plt  برای نمایش استفاده کرده است.

 



import cv2
import numpy as np
from matplotlib import pyplot as plt
yellow = [255,255,0]
img1 = cv2.imread('openCV (1).png')
img2 = cv2.cvtColor(img1, cv2.COLOR_BGR2RGB)
replicate = cv2.copyMakeBorder(img2,10,10,10,10,cv2.BORDER_REPLICATE)
reflect = cv2.copyMakeBorder(img2,10,10,10,10,cv2.BORDER_REFLECT)
reflect101 = cv2.copyMakeBorder(img2,10,10,10,10,cv2.BORDER_REFLECT_101)
wrap = cv2.copyMakeBorder(img2,10,10,10,10,cv2.BORDER_WRAP)
constant= cv2.copyMakeBorder(img2,10,10,10,10,cv2.BORDER_CONSTANT,value=yellow)
plt.subplot(231),plt.imshow(img2,'gray'),plt.title('ORIGINAL')
plt.subplot(232),plt.imshow(replicate,'gray'),plt.title('REPLICATE')
plt.subplot(233),plt.imshow(reflect,'gray'),plt.title('REFLECT')
plt.subplot(234),plt.imshow(reflect101,'gray'),plt.title('REFLECT_101')
plt.subplot(235),plt.imshow(wrap,'gray'),plt.title('WRAP')
plt.subplot(236),plt.imshow(constant,'gray'),plt.title('CONSTANT')
plt.show()

copyMakeBorder

در قطعه کد زیر از opencv برای نمایش استفاده شده است:

 

import cv2
import numpy
image = cv2.imread("openCV.png")
BLUE = [255,0,0]
replicate = cv2.copyMakeBorder(image,10,10,10,10,cv2.BORDER_REPLICATE)
reflect = cv2.copyMakeBorder(image,10,10,10,10,cv2.BORDER_REFLECT)
reflect101 = cv2.copyMakeBorder(image,10,10,10,10,cv2.BORDER_REFLECT_101)
wrap = cv2.copyMakeBorder(image,10,10,10,10,cv2.BORDER_WRAP)
constant= cv2.copyMakeBorder(image,10,10,10,10,cv2.BORDER_CONSTANT,value=BLUE)
#cv2.imshow("image",replicate)
#cv2.imshow("image",reflect)
cv2.namedWindow('My Image', cv2.WINDOW_NORMAL)
cv2.imshow("My Image",reflect101)
#cv2.imshow("image",wrap)
#cv2.imshow("image",constant)
#cv2.imshow("image",image)
cv2.waitKey(0)

 

در قطعه کد زیر نوشتن یک متن، رسم چند ضلعی، دایره ، مستطیل و یک خط نمایش داده شده است:

import numpy as np
import cv2
img = cv2.imread('carr.jpg',cv2.IMREAD_COLOR)
print(img.shape)
cv2.line(img,(0,0),(100,100),(255,255,255),5)
cv2.rectangle(img,(0,100),(100,200),(0,0,0),5)
cv2.circle(img,(63,250), 63, (0,255,0), -1)
pts = np.array([[10,100],[40,50],[50,10],[30,10]], np.int32)
pts = pts.reshape((-1,1,2))
cv2.polylines(img, [pts], True, (255,100,0), 3)
font = cv2.FONT_HERSHEY_SIMPLEX
# def putText(img, text, org, fontFace, fontScale, color, thickness=None, lineType=None, bottomLeftOrigin=None):
cv2.putText(img,"I Iove Lamborghini!",(200,40), 0, 0.8, (255,100,0), 3, cv2.LINE_AA) cv2.imshow('image',img) cv2.waitKey(0) cv2.destroyAllWindows() car-red

 

در این قطعه کد: تعداد کانال نوع تصویر با استفاده از if( در تصاویر رنگی img.shape  دارای ۳ مقدار طول، عرض و تعداد کانال میباشد ولی در خاکستری دیگر تعداد کانال را مشخص نمیکند و ۲ مقدار دارد
)  تصویر خاکستری را از رنگی تشخیص میدهد. شما میتوانید با استفاده از تصویر خاکستری نتیجه دیگر بگیرید:

import numpy as np
import cv2
image = cv2.imread('carr.jpg',cv2.IMREAD_COLOR)
print(image.shape)
print(image.shape[2])
if image.shape[2] == 2:
print("Gray Image")
elif image.shape[2] == 3:
print("RGB Image")
print(image.size)
print(image.dtype)

۳
RGB Image
۶۵۸۳۵۹
uint8

 

 

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

 

تبدیلات (Transformations)

OpenCV دو تابع تبدیل، cv2.warpAffine و cv2.warpPerspective را فراهم می کند که  شما می توانید تمام انواع تبدیلات را داشته باشید. Cv2.warpAffine یک ماتریس تبدیل ۲×۳ را در حالی که cv2.warpPerspective یک ماتریس تبدیل ۳×۳ را به عنوان ورودی می گیرد.

Scaling

 

Scaling  فقط تغییر اندازه تصویر است ،OpenCV ، تابع ()cv2.resize  برای این منظور عرضه می کند.اندازه تصویر را می توان بصورت دستی مشخص کرد، یا می توانید فاکتور مقیاس را مشخص کنید.  روش های مختلفی استفاده می شود.

روش های مختلفی استفاده می شود. روش پیشنهادی cv2.INTER_AREA برای کاهش و (cv2.INTER_CUBIC (slow و cv2.INTER_LINEAR برای بزرگنمایی است. به طور پیش فرض، تابع cv2.INTER_LINEAR برای همه اهداف تغییر اندازه است.

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

 

import cv2
import numpy
import matplotlib.pyplot
image = cv2.imread("car.jpg")
print(image.shape)
# def resize(src, dsize, dst=None, fx=None, fy=None, interpolation=None): # real signature unknown; restored from __doc__
#res = cv2.resize(image,None,fx=2, fy=2, interpolation = cv2.INTER_CUBIC)
# or
height, width = image.shape[:2]
res = cv2.resize(image,(2*width,2*height), interpolation = cv2.INTER_CUBIC)
cv2.imshow("image",res)
cv2.waitKey(0)
cv2.destroyAllWindows()

 

Translation 

Translation جابجایی شی از یک مکان به مکان دیگر. اگر می دانید تغییر جهت (x، y)، با اجازه  آن را (tx، ty) قرار می هیم، شما می توانید ماتریس تبدیل M به شرح زیر ایجاد کنید:

 

M = \begin{bmatrix} 1 & 0 & t_x \\ 0 & 1 & t_y  \end{bmatrix}

می توانید آن را به یک آرایه Numpy از نوع np.float32  تبدیل و بعد آن را به تابع ()cv2.warpAffine  منتقل کنید. مثال زیر را برای شیفت به مکان (۱۰۰،۵۰) زیر را ببینید:

 

import cv2
import numpy
import matplotlib.pyplot
image = cv2.imread("car.jpg")
print(image.shape)
rows,cols = image.shape[:2]
M = numpy.float32([[1,0,100],[0,1,50]])
dst = cv2.warpAffine(image,M,(cols,rows))
cv2.namedWindow('image', cv2.WINDOW_NORMAL)
cv2.imshow("image",dst)
cv2.waitKey(0)
cv2.destroyAllWindows()

car2

 

هشدار

آرگومان سوم تابع ()cv2.warpAffin  اندازه تصویر خروجی است که باید در فرم (عرض، ارتفاع) باشد.
به یاد داشته باشید عرض = تعداد ستون ها، و ارتفاع = تعداد ردیف.

 width = number of columns, and height = number of rows.

Rotation

چرخش یک تصویر برای زاویه تتا به دست می آید توسط ماتریس M تبدیل فرم.

M = \begin{bmatrix} cos\theta & -sin\theta \\ sin\theta & cos\theta   \end{bmatrix}

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

\begin{bmatrix} \alpha &  \beta & (1- \alpha )  \cdot center.x -  \beta \cdot center.y \\ - \beta &  \alpha &  \beta \cdot center.x + (1- \alpha )  \cdot center.y \end{bmatrix}

 

\begin{array}{l} \alpha =  scale \cdot \cos \theta , \\ \beta =  scale \cdot \sin \theta \end{array}

 

برای پیدا کردن این ماتریس تبدیل، OpenCV تابع cv2.getRotationMatrix2Dرا فراهم می کند، .

 مثال زیر را بررسی کنید که تصویر را به اندازه  ۹۰ درجه میچرخاند:

 

import cv2
import numpy
import matplotlib.pyplot
image = cv2.imread("car.jpg")
print(image.shape)
rows,cols = image.shape[:2]
#or
# rows,cols,_ = image.shape
#or
#rows,cols,ch=image.shape
M = cv2.getRotationMatrix2D((cols/2,rows/2),90,1)
dst = cv2.warpAffine(image,M,(cols,rows))
cv2.namedWindow('image', cv2.WINDOW_NORMAL)
cv2.imshow("image",dst)
cv2.waitKey(0)
cv2.destroyAllWindows()



car3

 

Affine Transformation


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

برای پیدا کردن ماتریس تبدیل، ما نیاز به سه نقطه از تصویر ورودی و نقاط  متناظر خود را در تصویر خروجی داریم. سپس cv2.getAffineTransform یک ماتریس ۲×۳ ایجاد می شود که به cv2.warpAffine منتقل می شود.

 

import cv2
import numpy
import matplotlib.pyplot
image = cv2.imread("carr.jpg")
print(image.shape)
rows,cols = image.shape[:2]
pts1 = numpy.float32([[50,50],[200,50],[50,200]])
pts2 = numpy.float32([[10,100],[200,50],[100,250]])
M = cv2.getAffineTransform(pts1,pts2)
dst = cv2.warpAffine(image,M,(cols,rows))
cv2.namedWindow('image', cv2.WINDOW_NORMAL)
cv2.imshow("image",dst)
cv2.waitKey(0)
cv2.destroyAllWindows()


car5

Perspective Transformation

برای Perspective Transformation، شما نیاز به یک ماتریس تبدیل ۳×۳ دارید. خطوط راست هم حتی پس از تغییر نیز باقی خواهند ماند.برای پیدا کردن این ماتریس تبدیل، شما نیاز به ۴ نقطه در تصویر ورودی و نقاط متناظر در تصویر خروجی دارید. ماتریس تبدیل را می توان با عملکرد cv2.getPerspectiveTransform پیدا کرد. سپس cv2.warpPerspective را با این ماتریس تبدیل ۳×۳ اعمال کنید.

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


import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread("sudoku-original.jpg")
rows,cols,ch = img.shape
rows,cols,ch = img.shape
pts1 = np.float32([[56,65],[368,52],[28,387],[389,390]])
pts2 = np.float32([[0,0],[300,0],[0,300],[300,300]])
M = cv2.getPerspectiveTransform(pts1,pts2)
dst = cv2.warpPerspective(img,M,(300,300))
plt.subplot(121),plt.imshow(img),plt.title('Input')
plt.subplot(122),plt.imshow(dst),plt.title('Output')
plt.show()

Transformation