۱- دسترسی به مقادیر پیکسل و تغییر آنها
۱-۲- img.shape
۱-۳- img.size
۱-۴- img.dtype
۲- Image ROI
۲-۱- تقسیم و ادغام کانال های تصویری با opencv
۲-۲- ساخت مرز و حاشیه برای تصاویر
۳- تبدیل هندسی تصاویر
۳-۱- Translation
۳-۲- Rotation
۳-۳- Affine Transformation
تقریبا تمام عملیات در این بخش به طور عمده به Numpy بیشتر از OpenCV مربوط می شود. دانش خوبی از Numpy برای نوشتن کد بهینه سازی بهتر با OpenCV لازم است.
* (نمونه ها در ترمینال پایتون نشان داده می شوند، زیرا اکثر آنها فقط کدهای خطی هستند)
اجازه دهید یک تصویر رنگی را بار اول بگذاریم:
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]) [۰ ۰ ۰]هشدار
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
تعداد کل پیکسل ها توسط img.size قابل دسترسی است:
print (img.size) ۱۲۲۸۸۰۰img.dtype
نوع داده تصویر توسط img.dtype بدست می آید:
print (img.dtype) uint8نکته
توجه داشته باشید img.dtype بسیار مهم است در اشکال زدایی، زیرا تعداد زیادی از خطاها در کد های OpenCV-Python، ناشی از نوع داده معتبر است.
تقسیم و ادغام کانال های تصویری ,Image ROI
Region of Interest، همان طور که از نام آن مشخص است، یعنی منطقه ای از تصویر که توسط ما انتخاب می شود. دلیل این کار، این است که ما به جای انتخاب کل تصویر، فقط ناحیه ای که لازم است را مورد پردازش قرار می دهیم که باعث افزایش کارایی و سرعت در پرازش می شود. غیر مثال زیر نمونه بارز استفاده از این عملیات، تشخیص پلاک خودرو است.
گاهی اوقات، باید با یک منطقه خاص از تصاویر بازی کنید.
برای تشخیص چشم در تصاویر، اول تشخیص چهره در سراسر تصویر انجام می شود و هنگامی که چهره به دست آمد، ما تنها یک منطقه چهره را انتخاب می کنیم و به دنبال آن، چشم ها را در داخل آن تصویر، جستجو می کنیم. 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)تقسیم و ادغام کانال های تصویری با 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()یا بعضی وقتها، ممکن است نیاز به پیوستن این کانال های فردی و تبدیل آن به تصویر 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)هشدار
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()در قطعه کد زیر از 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):<br data-jekyll-commonmark-ghpages="" />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()در این قطعه کد: تعداد کانال نوع تصویر با استفاده از 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 به شرح زیر ایجاد کنید:
می توانید آن را به یک آرایه 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()هشدار
آرگومان سوم تابع ()cv2.warpAffin اندازه تصویر خروجی است که باید در فرم (عرض، ارتفاع) باشد.
به یاد داشته باشید عرض = تعداد ستون ها، و ارتفاع = تعداد ردیف.width = number of columns, and height = number of rows.
Rotation
چرخش یک تصویر برای زاویه تتا به دست می آید توسط ماتریس M تبدیل فرم.
اما OpenCV چرخش مقیاس پذیر با مرکز قابل تنظیم چرخش را فراهم می کند به طوری که شما می توانید در هر مکانی که ترجیح می دهید چرخش دهید.
ماتریس تبدیل اصلاح شده است:برای پیدا کردن این ماتریس تبدیل، 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()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()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()
۱-پردازش تصویر با پایتون-OpenCV
۲-آموزش نصب pip در پایتون
۳- کتابخانه های مورد نیاز پردازش تصویر
۴ – خواندن و نمایش فرمت تصویر در پایتون
۵- نمایش تصویرRGB با Matplotlib و تابع تبدیل ()cvtColor در OpenCv
۶-تغییر فضاهای رنگ- opencv
۷-تقسیم و ادغام کانال های تصویری با opencv
۸-بخشبندی تصویر (Image Segmentation)
۹-آستانه گذاری ساده