اذهب إلى المحتوى
  • 0

اكتشاف الأشكال الهندسية البسيطة باستخدام OpenCV في بايثون

Ali Ismael

السؤال

Recommended Posts

  • 0

يمكنك أن تستخدم cv2.findContours و cv2.drawContours لرسم الحواف على الصور.  لكن أولاً ما هو Contours أو الإطار؟ هي عبارة عن منحنيات تضم كل النقاط المتصلة مع بعضها (على طول الحدود) والتي تملك نفس اللون أو الشدة، وهذه الإطارات هي أدوات مفيدة لتحليل الشكل، واكتشاف الأجسام والتعرف عليها.

cv2.findContours(src, contour_retrieval, contours_approximation)

الوسيط الأول يمثل الصورة (ثنائية)، والثاني يمثل نمط استرداد الإطار ويمكن أن يكون cv.RETR_EXTERNAL الذي يسترد الخطوط الخارجية الشاذة فقط أو cv.RETR_LIST الذي يسترجع كل المعالم دون إنشاء أي علاقات هرمية أو cv.RETR_TREE الذي يسترجع كل المعالم ويعيد بناء تسلسل هرمي كامل لخطوط الكنتورات المتداخلة. الوسيط الثالث هو تقريب الإطار ويمكن أن يكون cv.CHAIN_APPROX_NONE لتخزين جميع نقاط الحدود أو cv.CHAIN_APPROX_SIMPLE لتخزين نقاط النهاية (مثلاً في المربع يخزن 4 نقط). و الخرج لهذا التابع هو ال Contours وتسلسل الإطارات الهرمي hierarchy. وتكون الإطارات المكتشفة على شكل قائمة، وكل إطار هو عبارة عن مصفوفة نمباي لإحداثيات نقاط حدود الجسم. 

cv.DrawContours(src, contour, contourIndex, colour, thickness)

الوسيط الأول يمثل الصورة، والثاني هو الإطارات المطلوب رسمها، والثالث هو فهرس الإطارات ونعطيه القيمة -1 لرسم كل الإطارات أو رقم إطار محدد لرسمه فقط، ثم اللون ثم السماكة.
الخطوات التي يجب اتباعها هي: 1. قراءة الصورة. 2. تحويلها إلى رمادية. 3. تعتيبها بحيث نجعلها صورة ثنائية لأن ذلك يعطينا أفضل النتائج. 
سنطبق الآن مثال على صورتك:

import cv2
import numpy as np
from google.colab.patches import cv2_imshow
from matplotlib import pyplot as plt
# قراءة الصورة
img = cv2.imread('/content/shapes.png',0) # قراءتها بصيغة رمادية
# تعتيب الصورة
_, threshold = cv2.threshold(img, 200, 255, cv2.THRESH_BINARY)
# استخدام التابع الأول
contours, _ = cv2.findContours(threshold, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
i = 0
for c in contours: #   قائمة لتخزين أسماء الأشكال 
	if i == 0:
		i = 1
		continue
	# cv2.approxPloyDP() دالة لتقريب الشكل
	approx = cv2.approxPolyDP(
		c, 0.01 * cv2.arcLength(c, True), True)	
	# استخدام تابع الرسم
	cv2.drawContours(img, [c], 0, (0, 0, 255), 5)
	# إيجاد نقطة مركز الشكل 
	M = cv2.moments(c)
	if M['m00'] != 0.0:
		x = int(M['m10']/M['m00'])
		y = int(M['m01']/M['m00'])
	# وضع اسم الشكل في وسط كل شكل 
	if len(approx) == 3:
		cv2.putText(img, 'Triangle', (x, y),
					cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 255, 255), 2)
	elif len(approx) == 4:
		cv2.putText(img, 'Quadrilateral', (x, y),
					cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 255, 255), 2)
	elif len(approx) == 5:
		cv2.putText(img, 'Pentagon', (x, y),
					cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 255, 255), 2)
	elif len(approx) == 6:
		cv2.putText(img, 'Hexagon', (x, y),
					cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 255, 255), 2)
	else:
		cv2.putText(img, 'circle', (x, y),
					cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 255, 255), 2)
# عرض
cv2_imshow(img)

والنتيجة:
2.thumb.png.37aa7bcb53de55b80db70101648cf1e5.png

رابط هذا التعليق
شارك على الشبكات الإجتماعية

  • 0

اذا كان الغرض من السؤال تحديد اسم الشكل فيمكنك استخدام الاجابة السابقة، اما اذا كنت تريد تحديد حدود الشكل، فبالاضافة للطريقة السابقة، يمكنك استخدام الدالة cv2.Hough والتي تمكنك من تحديد الخطوط المتصلة سويا باستخدام cv2.HoughLines والتي باستخدامها يمكننا تحديد الأشكال الهندسية ، وهناك دالة أخرى لتحديد الدوائر باستخدام cv2 HoughCircles (هناك دالة خاصة للدوائر لانها تعد خطوطا مغلقة).

وتعمل عن طريق تتبع الخطوط المتصلة سويا وتقوم باظهارها بلون مختلف لتوضيحها، الكود التالي يوضح كيفية استخدامها:

#استدعاء المكتبات
import numpy as np
import matplotlib.pyplot as plt
import cv2

cap = cv2.VideoCapture(0)

while True:
    _, image = cap.read()
    # التحويل للرمادي
    grayscale = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    # تحديد حدود الاجسام
    edges = cv2.Canny(grayscale, 30, 100)
    # تحديد الخطوط
    lines = cv2.HoughLinesP(edges, 1, np.pi/180, 60, np.array([]), 50, 5)
    # توضيح الخطوط بلون مختلف
    for line in lines:
        for x1, y1, x2, y2 in line:
            cv2.line(image, (x1, y1), (x2, y2), (255, 0, 0), 3)
            cv2.line(edges, (x1, y1), (x2, y2), (255, 0, 0), 3)
    # عرض الصورة
    cv2.imshow("image", image)
    cv2.imshow("edges", edges)
    if cv2.waitKey(1) == ord("q"):
        break
cap.release()
cv2.destroyAllWindows()

 

رابط هذا التعليق
شارك على الشبكات الإجتماعية

انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أجب على هذا السؤال...

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.

  • إعلانات

  • تابعنا على



×
×
  • أضف...