简体   繁体   中英

Draw contours around images of the same color with openCV python

I have this image with 3 channels RGB (a result of a VARI Index computation) and I would like to draw bounding boxes (rectangles) around the plants, represented in green here. What is the best and easiest way to do it with OpenCV / python?

I guess it's an easy problem for OpenCV experts, but I could not find good tutorials online to do this for multiple objects.

The closest tutorial I found was: determining-object-color-with-opencv

The assumptions for the bounding boxes should/could be:

  • green is the dominant color.
  • it should be more than X pixels.

Thanks in advance!

VARI指数

You need to do HSV filtering

  1. Change image colors from BGR to HSV (Hue Saturation Value).
  2. Filter a certain range of saturation and hue that matches green by thresholding.

Refer to this page for code to do the first 2

https://pythonprogramming.net/color-filter-python-opencv-tutorial/

  1. Do some morphological operations like Erosion, Dilation, Opening, Closing to remove the small bits of green that don't represent trees and to connect the trees that look broken together.

Refer to https://docs.opencv.org/master/d9/d61/tutorial_py_morphological_ops.html

  1. Detect the contours then draw the rectangles
import cv2
import numpy as np

img = cv2.imread('8FGo1.jpg',1)

hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
lower_red = np.array([45,100,50])
upper_red = np.array([75,255,255])
    
mask = cv2.inRange(hsv, lower_red, upper_red)

kernel = np.ones((5,5),np.uint8)
mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)
mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)


contours, hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)


for contour in contours:
    x,y,w,h = cv2.boundingRect(contour)
    img = cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)
    cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)


cv2.imshow('img',img)
#cv2.imshow('mask',mask)

Output

在此处输入图片说明

Just answering my own question after stumbling upon this resource: https://docs.opencv.org/3.4/da/d0c/tutorial_bounding_rects_circles.html

May not be the best answer but it somehow solves my problem!

import cv2
import numpy as np

image = cv2.imread('vari3.png')

# https://www.pyimagesearch.com/2016/02/15/determining-object-color-with-opencv/
# https://docs.opencv.org/3.4/da/d0c/tutorial_bounding_rects_circles.html

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
lab = cv2.cvtColor(image, cv2.COLOR_BGR2LAB)

# mask: green is dominant.
thresh = np.array((image.argmax(axis=-1) == 1) * 255, dtype=np.uint8)

cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[0]

contours_poly = [None] * len(cnts)
boundRect = [None] * len(cnts)
for i, c in enumerate(cnts):
    contours_poly[i] = cv2.approxPolyDP(c, 3, True)
    boundRect[i] = cv2.boundingRect(contours_poly[i])

for i in range(len(cnts)):
    # cv2.drawContours(image, contours_poly, i, (0, 255, 0), thickness=2)
    pt1 = (int(boundRect[i][0]), int(boundRect[i][1]))
    pt2 = (int(boundRect[i][0] + boundRect[i][2]), int(boundRect[i][1] + boundRect[i][3]))
    if np.sqrt((pt2[1] - pt1[1]) * (pt2[0] - pt1[0])) < 30:
        continue
    cv2.rectangle(image, pt1, pt2, (0, 0, 0), 2)

cv2.imwrite('result.png', image)
cv2.imshow("Image", image)
cv2.waitKey(0)

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM