Ответ 1
Поскольку ваше исходное изображение довольно шумно, просто исправить это, чтобы удалить часть шума с помощью cv2.medianBlur()
Это позволит удалить небольшие области шума в исходном изображении и оставить только один контур. Первые несколько строк вашего кода выглядят следующим образом:
im = cv2.imread('shot.bmp')
im = cv2.medianBlur(im,5) # 5 is a fairly small kernel size
hsv_img = cv2.cvtColor(im, cv2.COLOR_BGR2HSV)
Однако этот метод не является наиболее надежным, потому что вы должны вручную указать размер ядра, а строка cnt=contours[0]
в вашем коде предполагает, что интересующий контур является первым в списке контуров, что справедливо только в том случае, если есть только один контур. Более надежный способ состоит в том, чтобы предположить, что вас интересует самый большой контур, который позволит вам компенсировать даже умеренный шум.
Для этого добавьте строки:
# Find the index of the largest contour
areas = [cv2.contourArea(c) for c in contours]
max_index = np.argmax(areas)
cnt=contours[max_index]
после строки:
contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
Результат в этом коде:
import numpy as np
import cv2
im = cv2.imread('shot.bmp')
hsv_img = cv2.cvtColor(im, cv2.COLOR_BGR2HSV)
COLOR_MIN = np.array([20, 80, 80],np.uint8)
COLOR_MAX = np.array([40, 255, 255],np.uint8)
frame_threshed = cv2.inRange(hsv_img, COLOR_MIN, COLOR_MAX)
imgray = frame_threshed
ret,thresh = cv2.threshold(frame_threshed,127,255,0)
contours, hierarchy = cv2.findContours(thresh,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(im,(x,y),(x+w,y+h),(0,255,0),2)
cv2.imshow("Show",im)
cv2.waitKey()
cv2.destroyAllWindows()
Оба эти метода дают результат с правильной ограничивающей рамкой:
N.B.
Начиная с OpenCV
3.x метод findContours()
возвращает 3 результата (как можно видеть здесь), поэтому дополнительное возвращаемое значение должно быть пойманным как:
_, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)