Hello I have a code which draws me the outlines of shapes/objects which have 3 or 4 vertices. So far everything works. But now I want that only shapes/objects are recognized, which are in a square. I wanted to solve it in such a way that I create a square or a picture, in which a square is represented, with cv2.imread read and then with cv2.matchShapes check, how much the recognized contour agrees with the contour of the square. And if this match is good enough, corresponding objects/shapes within this square should be recognized.
Following is the code I have written so far:
import math
import cv2
import numpy as np
from graphics import *
cam = cv2.VideoCapture(0)
cam.set(cv2.CAP_PROP_FRAME_WIDTH, 1920)
cam.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080)
rect = cv2.imread("Rectangle.png")
gray = cv2.cvtColor(rect, cv2.COLOR_BGR2GRAY)
rectcontour, _ = cv2.findContours(gray, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
while True:
_ , img = cam.read()
img = cv2.resize(img, None, fx = 0.5, fy = 0.5, interpolation=cv2.INTER_AREA)
gray1 = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#edges = cv2.Canny(gray1, 250, 300)
_ , binary1 = cv2.threshold(gray1, 130, 255, cv2.THRESH_BINARY)
inverted_binary1 = ~binary1
contours1, _ = cv2.findContours(inverted_binary1, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
a = 0
for a in contours1:
x = cv2.matchShapes(contours1[a], rectcontour[0], cv2.CONTOURS_MATCH_I1, 0.0)
print(x)
a = a + 1
for contour in contours1:
area = cv2.contourArea(contour)
if area > 100 and area < 20000:
approx = cv2.approxPolyDP(contour, 0.06 * cv2.arcLength(contour, True), True)
print(len(approx))
if 2 < len(approx) < 5:
moment = cv2.moments(contour)
cx = int(moment['m10'] / moment['m00'])
cy = int(moment['m01'] / moment['m00'])
#print(x, y)
print(cx, cy)
cv2.drawContours(img, [contour], -1, (0, 0, 255), 3)
n = approx.ravel()
print(n)
i = 0
for j in n:
if (i % 2 == 0):
x = n[i]
y = n[i + 1]
# String containing the co-ordinates.
string = str(x) + " " + str(y)
if (i == 0):
# text on topmost co-ordinate.
cv2.putText(img, string, (x, y),cv2.FONT_HERSHEY_COMPLEX_SMALL, 1, (255, 0, 0))
else:
# text on remaining co-ordinates.
cv2.putText(img, string, (x, y),cv2.FONT_HERSHEY_COMPLEX_SMALL, 1, (0, 255, 0))
i = i + 1
cv2.imshow("schwarz, weiß", inverted_binary1)
cv2.imshow('my webcam', img)
if cv2.waitKey(1) & 0xFF == ord("q"):
break
At the moment I get following error:
Traceback (most recent call last):
File "C:\Users\Paul\PycharmProjects\Opencv\test3.py", line 27, in <module>
x = cv2.matchShapes(contours1[a], rectcontour[0], cv2.CONTOURS_MATCH_I1, 0.0)
TypeError: only integer scalar arrays can be converted to a scalar index
[ WARN:0] global D:\a\opencv-python\opencv-python\opencv\modules\videoio\src\cap_msmf.cpp (438) `anonymous-namespace'::SourceReaderCB::~SourceReaderCB terminating async callback
And I dont exactly know how I can fix that.
The square image I am using:

And another Picture of the shape I actually want to detect:
