הדרכה זו היא היסוד של חזון ממוחשב המשוייכת ל"שיעור 2" בסדרה; יש עוד שיעורים שמתקרבים שידברו על הרחבת בניית פרויקטי חזון ממוחשב מבוססי שיטות למידה עמיקה משלך. תוכלו למצוא את הנושאים המלאים וכרטיסיית התוכן כאן.
הדברים העיקריים שכדאי לזכור מהמאמר הזה:
- טעינת תמונה מהדיסק.
- קבלת ה"גובה", "רוחב" ו"עומק" של התמונה.
- מציאת הרכיבים R, G ו-B של התמונה.
- ציור באמצעות OpenCV.
טעינת תמונה מהדיסק
לפני שאנו מבצעים כל פעולות או שינויים בתמונה, חשוב עבורנו לטעון תמונה מבחירתנו לדיסק. נבצע את הפעולה הזו באמצעות OpenCV. ישנן שתי דרכים שבהן נוכל לבצע את פעולת הטעינה. דרך אחת היא לטעון את התמונה על ידי העברת מסלול התמונה וקובץ התמונה לפונקציה "imread" של OpenCV. הדרך השנייה היא להעביר את התמונה דרך טקסט של טיעון שורת הפקודה באמצעות מודול ה-argparse של Python.
#טעינת תמונה מהדיסק
import cv2
image = cv2.imread(“C:/Sample_program/example.jpg”)
cv2.imshow(‘Image’, image)
cv2.waitKey(0)
נבנה קובץ בשם Loading_image_from_disk.py ב-Notepad++. קודם כל, אנו מייבאים את ספריית OpenCV שלנו, המכילה את פונקציות העיבוד התמונה שלנו. אנו מייבאים את הספריה באמצעות השורה הראשונה של הקוד כ-cv2. השורה השנייה של הקוד היא המקום בו אנו קוראים את התמונה שלנו באמצעות פונקציית cv2.imread ב-OpenCV, ואנו מעבירים את הנתיב של התמונה כפרמטר; הנתיב צריך גם לכלול את שם הקובץ עם רשימת הקישורים של התמונה .jpg, .jpeg, .png, או .tiff.
תחביר — // image=cv2.imread(“path/to/your/image.jpg”) //
צריך להיזהר באופן מוחלט במהלך הציון שמו של קישורים. סביר להניח שנקבל את השגיאה הבאה אם נספק את הסוג הלא נכון של קישורים.
ERROR :
c:\Sample_program>python Loading_image_from_disk.py
Traceback (most recent call last):
File “Loading_image_from_disk.py”, line 4, in <module>
cv2.imshow(‘Image’, image)
cv2.error: OpenCV(4.3.0) C:\projects\opencv-python\opencv\modules\highgui\src\window.cpp:376: error: (-215:Assertion failed) size.width>0 && size.height>0 in function ‘cv::imshow’
השורה השלישית של הקוד היא המקום בו אנו באמת מציגים את התמונה שהועלתה. הפרמטר הראשון הוא מחרוזת, או "שם" החלון שלנו. הפרמטר השני הוא האובייקט אליו הועלתה התמונה.
לבסוף, קריאה ל-cv2.waitKey עוצרת את ביצוע התסריט עד שאנו לוחצים על מקש במקלדת שלנו. השימוש בפרמטר של "0" מציין שכל לחיצה על מקש תבטל את העצירה של הביצוע. אנא תן לעצמך לרוץ על התכנית שלך ללא שורת הקוד האחרונה בתכנית שלך כדי לראות את ההבדל.
#קריאת תמונה מהדיסק באמצעות Argparse
import cv2
import argparse
apr = argparse.ArgumentParser()
apr.add_argument(“-i”, “ — image”, required=True, help=”Path to the image”)
args = vars(apr.parse_args())
image = cv2.imread(args[“image”])
cv2.imshow(‘Image’, image)
cv2.waitKey(0)
לדעת לקרוא תמונה או קובץ באמצעות טיעון שורת הפקודה (argparse) היא כישור ממש הכרחי.
שתי השורות הראשונות של הקוד הן לייבא את הספריות ה הכרחיות; כאן, אנו מייבאים את OpenCV ו-Argparse. אנו נחזור על זה לאורך כל הקורס.
השורות הבאות של קוד מטפלות בניתוח טיעוני שורת הפקודה. הטיעון היחיד שאנו זקוקים לו הוא — תמונה: הנתיב לתמונה שלנו במחשב. לבסוף, אנו מנתחים את הטיעונים ומאחסנים אותם במילון הנקרא args.
בואו ניקח שנייה ונדבר במהירות על מה בדיוק הוא מתג — תמונה. מתג — תמונה "מתג" ("מתג" הוא מילה נרדפת ל"טיעון שורת פקודה" ואפשר להשתמש במונחים בליוויויות) הוא מחרוזת שאנו קובעים בשורת הפקודה. מתג זה אומר לתכנית Loading_image_from_disk.py שלנו איפה התמונה שברצוננו לטעון חיים במחשב.
שלוש השורות האחרונות של הקוד נדונו קודם; פונקצית cv2.imread לוקחת args["image'] כפרמטר, שזה בכלל לא דבר אחר מאשר התמונה שאנו מספקים בשורת הפקודה. cv2.imshow מציג את התמונה, שכבר מאוחסנת באובייקט תמונה מהשורה הקודמת. השורה האחרונה עוצרת את ביצוע התכנית עד שאנו לוחצים על מקש במקלדת שלנו.
אחת היתרונות העיקריים של השימוש בargparse — טיעון שורת פקודה הוא שנוכל לטעון תמונות ממיקומים תיקיות שונים ללא צורך לשנות את מסלול התמונה בתכנית שלנו על ידי העברת מסלול התמונה באופן דינמי Ex — "C:\CV_Material\image\sample.jpg" בשורת הפקודה כטיעון כשאנו מבצעים את תכנית ה-Python שלנו.
c:\Sample_program>python Loading_image_from_disk.py — image C:\CV_Material\session1.JPG
כאן אנו מבצעים את Loading_image_from_disk.py קובץ Python ממיקום c:\sample_program על ידי העברת הפרמטר "-image" יחד עם מסלול התמונה C:\CV_Material\session1.JPG.
קבלת ה'גובה', 'רוחב' ו-'עומק' של תמונה
מאחר שתמונות מיוצגות כמערכים NumPy, אנו יכולים פשוט להשתמש בתכונה .shape כדי לבחון את הרוחב, הגובה ומספר הערוצים.
על ידי שימוש בתכונה .shape על אובייקט התמונה שטענו עכשיו. אנו יכולים למצוא את הגובה, הרוחב והעומק של התמונה. כפי שדנו בשיעור – 1 הקודם, הגובה והרוחב של התמונה יכולים להיות בדיקת אורך על ידי פתיחת התמונה ב-MS Paint. ראה את השיעור הקודם. נדון על העומק של התמונה בשיעורים הקרובים. העומק ידוע גם כערוץ של תמונה. תמונות צבע בדרך כלל מורכבות מ-3 ערוץ בגלל הרכב RGB בפיקסלים שלהם ותמונות מקושרות בדרך כלל מורכבות מ-1 ערוץ. זהו משהו שדיברנו עליו בשיעור-1 הקודם.
#קבלת גובה,רוחב ועומק של תמונה
import cv2
import argparse
apr = argparse.ArgumentParser()
apr.add_argument(“-i”, “ — image”, required=True, help=”Path to the image”)
args = vars(apr.parse_args())
# ההבדל היחיד לקודים הקודמים - תכונת התאמה שמופעלת על אובייקט התמונה
print(f’(Height,Width,Depth) of the image is: {image.shape}’)
image = cv2.imread(args[“image”])
cv2.imshow(‘Image’, image)
cv2.waitKey(0)
פלט:
הגובה, הרוחב והעומק של התמונה הם: (538, 723, 3)
ההבדל היחיד מהקודים הקודמים הוא הצהרת ההדפסה שמפעילה את תכונת הצורה על אובייקט התמונה הטעון. f’ היא מחרוזת F @ מחרוזת מודרכת המקבלת משתנים דינמיים ומדפיסה.
f’ write anything here that you want to see in the print statement: {variables, variables, object, object.attribute,}’
כאן, השתמשנו ב-`{object.attribute}` בתוך הסוגריים הפרושים למאכלס תכונה `.shape` כדי לחשב את הגובה, הרוחב והעומק של אובייקט התמונה.
#קבלת גובה,רוחב ועומק בנפרד
import cv2
import argparse
apr = argparse.ArgumentParser()
apr.add_argument(“-i”, “ — image”, required=True, help=”Path to the image”)
args = vars(apr.parse_args())
image = cv2.imread(args[“image”])
#חיתוך מערך NumPy לקבלת הגובה, הרוחב והעומק בנפרד
print(“height: %d pixels” % (image.shape[0]))
print(“width: %d pixels” % (image.shape[1]))
print(“depth: %d” % (image.shape[2]))
cv2.imshow(‘Image’, image)
cv2.waitKey(0)
פלט:
רוחב: 723 פיקסלים
גובה: 538 פיקסלים
עומק: 3
כאן, במקום לקבל את הגובה, הרוחב והעומק יחדיו כטופל. אנו מבצעים חיתוך מערך ומקבלים את הגובה, הרוחב והעומק של התמונה בנפרד. האינדקס הראשון במערך מכיל את הגובה של התמונה, האינדקס השני מכיל את רוחב התמונה, והאינדקס השלישי מכיל את עומק התמונה.
מציאת רכיבים R, G ו-B של התמונה
פלט:
ערך רכיב הכחול ירוק אדום של התמונה במיקום (321, 308) הוא: (238, 242, 253)
שימו לב כיצד הערך y מועבר לפני הערך x – התחביר הזה אולי ירגיש לא אינטואיטיבי בהתחלה, אך הוא עולה בקנה אחד עם הדרך בה אנו גולשים בערכים במטריצה: קודם כל אנו מציינים את מספר השורה, ואז את מספר העמודה. משם, מקבלים טופל המייצג את רכיבי הכחול, הירוק והאדום של התמונה.
אנו יכולים גם לשנות את צבע הפיקסל במיקום נתון על ידי הפיכת הפעולה.
#מציאת R,B,G של התמונה במיקום (x,y)
import cv2
import argparse
apr = argparse.ArgumentParser()
apr.add_argument(“-i”, “ — image”, required=True, help=”Path to the image”)
args = vars(apr.parse_args())
image = cv2.imread(args[“image”])
#קבל את ערכי הקואורדינטות הפיקסלים [y,x] מהמשתמש, עבורם יש לחשב את ערכי RGB
[y,x] = list(int(x.strip()) for x in input().split(‘,’))
#הוצאת ערכי ה-(כחול,ירוק,אדום) של הקואורדינטות הפיקסלים הנוכחיות
(b,g,r) = image[y,x]
print(f’The Blue Green Red component value of the image at position {(y,x)} is: {(b,g,r)}’)
cv2.imshow(‘Image’, image)
cv2.waitKey(0)
(b,g,r) = image[y,x] למעשה image[y,x] = (b,g,r)
כאן אנו מקצים את הצבע ב(BGR) לקואורדינטות הפיקסל בתמונה. בואו ננסה לקצוץ את הפיקסל במיקום (321,308) ולאמת את זה על ידי הדפסת הפיקסל BGR במיקום הנתון.
#הפיכת הפעולה להקצאת ערך RGB לפיקסל בחרנו
import cv2
import argparse
apr = argparse.ArgumentParser()
apr.add_argument(“-i”, “ — image”, required=True, help=”Path to the image”)
args = vars(apr.parse_args())
image = cv2.imread(args[“image”])
#קבלת ערכי קואורדינטות הפיקסל [y,x] מהמשתמש, עבורם יש לחשב את הערכים RGB
[y,x] = list(int(x.strip()) for x in input().split(‘,’))
#הוצאת הערכים (Blue,green,red) של הקואורדינטות הפיקסל שהתקבלו
image[y,x] = (0,0,255)
(b,g,r) = image[y,x]
print(f’The Blue Green Red component value of the image at position {(y,x)} is: {(b,g,r)}’)
cv2.imshow(‘Image’, image)
cv2.waitKey(0)
פלט:
הערכים של הרכיבים Blue, Green, ו-Red בתמונה במיקום (321, 308) הם (0, 0, 255)
בקוד שלעיל, אנו מקבלים את קואורדינטות הפיקסל דרך שפת הפקודה על ידי הזנת הערך כמופיע באיור 2.6 ומקצים לקואורדינטות הפיקסל את הצבע האדום על ידי הקצאה (0,0,255) כלומר, (Blue, Green, Red) ולאמת את זה על ידי הדפסת קואורדינטות הפיקסל המבוקש.
ציור באמצעות OpenCV
בואו נלמד כיצד לצייר צורות שונות כמו מלבנים, ריבועים ומעגלים באמצעות OpenCV על ידי ציור עיגולים כדי להסתיר את העיניים שלי, מלבנים כדי להסתיר את השפתיים שלי, ומלבנים כדי להסתיר את הדג מנטרה-ריי לידי.
הפלט צריך להיראות ככה:
תמונה זו מסומנת בצורות באמצעות MS Paint; ננסה לעשות את אותו הדבר באמצעות OpenCV על ידי ציור עיגולים סביב העיניים שלי ומלבנים כדי להסתיר את השפתיים שלי ואת הדג מנטרה-ריי לידי.
אנו משתמשים בשיטה cv2.rectangle כדי לצייר מלבן ובשיטה cv2.circle כדי לצייר עיגול ב-OpenCV.
cv2.rectangle(image, (x1, y1), (x2, y2), (Blue, Green, Red), Thickness)
השיטה cv2.rectangle מקבלת תמונה כארגומנט הראשון עליה אנו רוצים לצייר את המלבן שלנו. אנו רוצים לצייר על אובייקט התמונה הטעון, אז אנו מעבירים אותו לשיטה. הארגומנט השני הוא המיקום ההתחלתי (x1, y1) של המלבן שלנו – כאן, אנו מתחילים את המלבן שלנו בנקודות (156 ו-340). לאחר מכן, אנו מספקים נקודה סופית (x2, y2) עבור המלבן. אנו מחליטים לסיים את המלבן שלנו ב-(360, 450). הארגומנט הבא הוא צבע המלבן שאנו רוצים לצייר; כאן, במקרה זה, אנו מעבירים צבע שחור בפורמט BGR, כלומר (0,0,0). לבסוף, הארגומנט האחרון שאנו מעבירים הוא עובי הקו. אנו נותנים -1 לציור צורות מלאות, כפי שנראה ב-Fig 2.6.
באופן דומה, אנו משתמשים בשיטה cv2.circle לציור העיגול.
cv2.circle(image, (x, y), r, (Blue, Green, Red), Thickness)
השיטה cv2.circle מקבלת תמונה כארגומנט הראשון עליה אנו רוצים לצייר את המלבן שלנו. אנו רוצים לצייר על אובייקט התמונה שטענו, אז אנו מעבירים אותו לשיטה. הארגומנט השני הוא המיקום המרכזי (x, y) של העיגול שלנו – כאן, לקחנו את העיגול שלנו בנקודה (343, 243). הארגומנט הבא הוא הרדיוס של העיגול שאנו רוצים לצייר. הארגומנט הבא הוא צבע העיגול; כאן, במקרה זה, אנו מעבירים צבע אדום בפורמט BGR, כלומר (0,0,255). לבסוף, הארגומנט האחרון שאנו מעבירים הוא עובי הקו. אנו נותנים -1 לציור צורות מלאות, כפי שנראה ב-Fig 2.6.
אוקיי! כשאנו יודעים את כל זה, בואו ננסה להשיג את מה שהתחלנו. כדי לצייר את הצורות בתמונה, עלינו לזהות את הקואורדינטות ההתחלתיות והסופיות (x,y) של האזור המסתורי כדי להעביר אותם לשיטה המתאימה.
איך?
נשתמש בעזרת MS Paint פעם נוספת. על ידי הנחת הסמן על אחת מהקואורדינטות (שמאל עליון) או (ימין תחתון) של האזור להסתרה, הקואורדינטות מוצגות בחלק המודגש של MS Paint כפי שמוצג באיור 2.7.
בדומה לכך, ניקח את כל הקואורדינטות (x1,y1) (x2,y2) עבור כל האזורים המסתוריים כפי שמוצג באיור 2.8.
#ציור באמצעות OpenCV כדי להסתיר עיניים, פה ועצמים קרובים
import cv2
import argparse
apr = argparse.ArgumentParser()
apr.add_argument(“-i”, “ — image”, required=True, help=”Path to the image”)
args = vars(apr.parse_args())
image = cv2.imread(args[“image”])
cv2.rectangle(image, (415, 168), (471, 191), (0, 0, 255), -1)
cv2.circle(image, (425, 150), 15, (0, 0, 255), -1)
cv2.circle(image, (457, 154), 15, (0, 0, 255), -1)
cv2.rectangle(image, (156, 340), (360, 450), (0, 0, 0), -1)
#הצגת התמונה הסופית
cv2.imshow(“Output drawing “, image)
cv2.waitKey(0)
תוצאות:

Source:
https://dzone.com/articles/computer-vision-tutorial-2-image-basics