Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find and draw the largest contour in opencv on a specific color (Python)

Im trying to get the largest contour of a red book. I've got a little problem with the code because its getting the contours of the smallest objects (blobs) instead of the largest one and I can't seem to figure out why this is happening

The code I use:

camera = cv2.VideoCapture(0) kernel = np.ones((2,2),np.uint8)  while True:     #Loading Camera     ret, frame = camera.read()      blurred = cv2.pyrMeanShiftFiltering(frame, 3, 3)     hsv = cv2.cvtColor(blurred, cv2.COLOR_BGR2HSV)      lower_range = np.array([150, 10, 10])     upper_range = np.array([180, 255, 255])     mask = cv2.inRange(hsv, lower_range, upper_range)      dilation = cv2.dilate(mask,kernel,iterations = 1)      closing = cv2.morphologyEx(dilation, cv2.MORPH_GRADIENT, kernel)     closing = cv2.morphologyEx(dilation, cv2.MORPH_CLOSE, kernel)      #Getting the edge of morphology     edge = cv2.Canny(closing, 175, 175)     _, contours,hierarchy = cv2.findContours(edge, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)      # Find the index of the largest contour     areas = [cv2.contourArea(c) for c in contours]     max_index = np.argmax(areas)     cnt=contours[max_index]      x,y,w,h = cv2.boundingRect(cnt)     cv2.rectangle(frame,(x,y),(x+w,y+h),(0,255,0),2)       cv2.imshow('threshold', frame)     cv2.imshow('edge', edge)      if cv2.waitKey(1) == 27:         break   camera.release() cv2.destroyAllWindows() 

As you can see on this picture

Hopefully there is someone who can help

like image 346
Zaptimist Avatar asked Jun 16 '17 11:06

Zaptimist


People also ask

How do you choose the biggest contour in OpenCV?

You can start by defining a mask in the range of the red tones of the book you are looking for. Then you can just find the contour with the biggest area and draw the rectangular shape of the book. If you want the book to rotate you can use rect = cv2. minAreaRect(cnt) as you can find it here.

How does OpenCV determine contours?

Use the findContours() function to detect the contours in the image. Draw Contours on the Original RGB Image.


1 Answers

You can start by defining a mask in the range of the red tones of the book you are looking for.

Then you can just find the contour with the biggest area and draw the rectangular shape of the book.

import numpy as np import cv2  # load the image image = cv2.imread("path_to_your_image.png", 1)  # red color boundaries [B, G, R] lower = [1, 0, 20] upper = [60, 40, 220]  # create NumPy arrays from the boundaries lower = np.array(lower, dtype="uint8") upper = np.array(upper, dtype="uint8")  # find the colors within the specified boundaries and apply # the mask mask = cv2.inRange(image, lower, upper) output = cv2.bitwise_and(image, image, mask=mask)  ret,thresh = cv2.threshold(mask, 40, 255, 0) if (cv2.__version__[0] > 3):     contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) else:     im2, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)  if len(contours) != 0:     # draw in blue the contours that were founded     cv2.drawContours(output, contours, -1, 255, 3)      # find the biggest countour (c) by the area     c = max(contours, key = cv2.contourArea)     x,y,w,h = cv2.boundingRect(c)      # draw the biggest contour (c) in green     cv2.rectangle(output,(x,y),(x+w,y+h),(0,255,0),2)  # show the images cv2.imshow("Result", np.hstack([image, output]))  cv2.waitKey(0) 

Using your image:

enter image description here

If you want the book to rotate you can use rect = cv2.minAreaRect(cnt) as you can find it here.

Edit:

You should also consider other colour spaces beside the RGB, as the HSV or HLS. Usually, people use the HSV since the H channel stays fairly consistent in shadow or excessive brightness. In other words, you should get better results if you use the HSV colourspace.

enter image description here

In specific, in OpenCV the Hue range is [0,179]. In the following figure (made by @Knight), you can find a 2D slice of that cylinder, in V = 255, where the horizontal axis is the H and the vertical axis the S. As you can see from that figure to capture the red you need both to include the lower (e.g., H=0 to H=10) and upper region (e.g., H=170 to H=179) of the Hue values.

enter image description here

like image 109
João Cartucho Avatar answered Sep 20 '22 05:09

João Cartucho