I am trying to use OpenCV with Python in order to detect squares in a live video feed from a Raspberry Pi camera. However, the cv2.GaussianBlur
and cv2.Canny
functions in the code below are causing the following error: "TypeError: numpy.ndarray' object is not callable".
I cannot seem to resolve the error. Any help is appreciated.
Code taken from https://www.pyimagesearch.com/2015/05/04/target-acquired-finding-targets-in-drone-and-quadcopter-video-streams-using-python-and-opencv/#comment-446639
import cv2
# load the video
camera = cv2.VideoCapture(0)
# keep looping
while True:
# grab the current frame and initialize the status text
(grabbed, frame) = camera.read()
status = "No Targets"
# check to see if we have reached the end of the
# video
if not grabbed:
break
# convert the frame to grayscale, blur it, and detect edges
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (7, 7), 0)
edged = cv2.Canny(blurred, 50, 150)
# find contours in the edge map
(cnts, _) = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
# loop over the contours
for c in cnts:
# approximate the contour
peri = cv2.arcLength(c, True)
approx = cv2.approxPolyDP(c, 0.01 * peri, True)
# ensure that the approximated contour is "roughly" rectangular
if len(approx) >= 4 and len(approx) <= 6:
# compute the bounding box of the approximated contour and
# use the bounding box to compute the aspect ratio
(x, y, w, h) = cv2.boundingRect(approx)
aspectRatio = w / float(h)
# compute the solidity of the original contour
area = cv2.contourArea(c)
hullArea = cv2.contourArea(cv2.convexHull(c))
solidity = area / float(hullArea)
# compute whether or not the width and height, solidity, and
# aspect ratio of the contour falls within appropriate bounds
keepDims = w > 25 and h > 25
keepSolidity = solidity > 0.9
keepAspectRatio = aspectRatio >= 0.8 and aspectRatio <= 1.2
# ensure that the contour passes all our tests
if keepDims and keepSolidity and keepAspectRatio:
# draw an outline around the target and update the status
# text
cv2.drawContours(frame, [approx], -1, (0, 0, 255), 4)
status = "Target(s) Acquired"
# draw the status text on the frame
cv2.putText(frame, status, (20, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.5,
(0, 0, 255), 2)
# show the frame and record if a key is pressed
cv2.imshow("Frame", frame)
key = cv2.waitKey(1) & 0xFF
# if the 'q' key is pressed, stop the loop
if key == ord("q"):
break
# cleanup the camera and close any open windows
camera.release()
cv2.destroyAllWindows()
Output: We see that there are three essential arguments in cv2. findContours() function. First one is source image, second is contour retrieval mode, third is contour approximation method and it outputs the image, contours, and hierarchy. 'contours' is a Python list of all the contours in the image.
To put in simple words findContours detects change in the image color and marks it as contour. As an example, the image of number written on paper the number would be detected as contour. The part that you want to detect should be white like above numbers in 1st image.
You've seen that the findContours() function returns two outputs: The contours list, and the hierarchy.
cv2 (old interface in old OpenCV versions was named as cv ) is the name that OpenCV developers chose when they created the binding generators. This is kept as the import name to be consistent with different kind of tutorials around the internet.
An alternative to work with 2.x 、3.x、4.x is:
cnts, hiers = cv2.findContours(...)[-2:]
Notice:
cv2.findContours
has changed since OpenCV 3.x
, but in OpenCV 4.0
it changes back!!!
In OpenCV 3.4:
findContours(image, mode, method[, contours[, hierarchy[, offset]]]) -> image, contours, hierarchy
In OpenCV 4.0:
findContours(image, mode, method[, contours[, hierarchy[, offset]]]) -> contours, hierarchy
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With