如何在 OpenCV Python 中获得预期区域 More/Less 的轮廓

How To Get A Contour Of More/Less Of The Expected Area In OpenCV Python

我在图像上进行一些轮廓检测,我想根据要修复的区域找到轮廓,在这种情况下,我希望轮廓标记为红色。
所以我想要一个围绕红色轮廓的边界框

以下是相关代码:

import cv2
import numpy as np

def nothing(x):
    pass

cv2.namedWindow("Tracking")
cv2.createTrackbar("LH", "Tracking", 0, 255, nothing)
cv2.createTrackbar("LS", "Tracking", 0, 255, nothing)
cv2.createTrackbar("LV", "Tracking", 0, 255, nothing)
cv2.createTrackbar("UH", "Tracking", 255, 255, nothing)
cv2.createTrackbar("US", "Tracking", 255, 255, nothing)
cv2.createTrackbar("UV", "Tracking", 255, 255, nothing)

while True:
    frame = cv2.imread('resultImages/imgCropped.png')
    img = frame.copy()

    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

    l_h = cv2.getTrackbarPos("LH", "Tracking")
    l_s = cv2.getTrackbarPos("LS", "Tracking")
    l_v = cv2.getTrackbarPos("LV", "Tracking")

    u_h = cv2.getTrackbarPos("UH", "Tracking")
    u_s = cv2.getTrackbarPos("US", "Tracking")
    u_v = cv2.getTrackbarPos("UV", "Tracking")

    l_b = np.array([65, 0, 28])
    u_b = np.array([120, 120, 130])

    mask = cv2.inRange(hsv, l_b, u_b)

    res = cv2.bitwise_and(frame, frame, mask=mask)
    res1 = res.copy()

    res = cv2.cvtColor(res,cv2.COLOR_BGR2GRAY)

    cont,_ = cv2.findContours(res,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)

    closed_contours = []
    open_contours = []
    for i in cont:
       if cv2.contourArea(i) > cv2.arcLength(i, True):
          closed_contours.append(i)
       else:
          open_contours.append(i)

    print(len(closed_contours))

    cont_img = cv2.drawContours(img, closed_contours, -1, 255, 3)
    c = max(closed_contours, key=cv2.contourArea)
    x, y, w, h = cv2.boundingRect(c)
    cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)

    cv2.imshow("frame", frame)
    cv2.imshow("mask", mask)
    cv2.imshow("res", res1)
    cv2.imshow("img",cont_img)

    key = cv2.waitKey(1)
    if key == 27:
        break

cv2.destroyAllWindows()

这会检测轮廓并显示大量有用的信息我已经设置了一些跟踪器值所以不需要修改跟踪器来获得它

我该怎么做?

import cv2
import numpy as np
#EDIT: imutils to grab contours
import imutils

def nothing(x):
    pass
'''
cv2.namedWindow("Tracking")
cv2.createTrackbar("LH", "Tracking", 0, 255, nothing)
cv2.createTrackbar("LS", "Tracking", 0, 255, nothing)
cv2.createTrackbar("LV", "Tracking", 0, 255, nothing)
cv2.createTrackbar("UH", "Tracking", 255, 255, nothing)
cv2.createTrackbar("US", "Tracking", 255, 255, nothing)
cv2.createTrackbar("UV", "Tracking", 255, 255, nothing)
'''

frame = cv2.imread('so.jpg')
img = frame.copy()

hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

l_h = cv2.getTrackbarPos("LH", "Tracking")
l_s = cv2.getTrackbarPos("LS", "Tracking")
l_v = cv2.getTrackbarPos("LV", "Tracking")

u_h = cv2.getTrackbarPos("UH", "Tracking")
u_s = cv2.getTrackbarPos("US", "Tracking")
u_v = cv2.getTrackbarPos("UV", "Tracking")

l_b = np.array([65, 0, 28])
u_b = np.array([120, 120, 130])

mask = cv2.inRange(hsv, l_b, u_b)

res = cv2.bitwise_and(frame, frame, mask=mask)
res1 = res.copy()

res = cv2.cvtColor(res,cv2.COLOR_BGR2GRAY)

cont = cv2.findContours(res,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)
#EDIT: I CAN'T REALLY REMEMBER WHAT IT DOES, BUT IT IS WORKING..
cont = imutils.grab_contours(cont)

closed_contours = []
open_contours = []

for count,i in enumerate(cont):
    #EDIT:produce boxes out of contours found before computing countourArea
    rect = cv2.minAreaRect(i)
    box = cv2.boxPoints(rect)
    i = np.int0(box)
    
    #HINT:IMPROVE THIS CONDITIONS. IT IS BASED ON FILTERING THE OTHER BOXES APPEARED..
    if (cv2.contourArea(i) < 2000 and cv2.contourArea(i)>100):#cv2.arcLength(i, True):
        print(cv2.contourArea(i))
        closed_contours.append(i)

#EDIT:(0,0,255) made box appeared in red color
cont_img = cv2.drawContours(img, closed_contours, -1, (0,0,255), 3)
c = max(closed_contours, key=cv2.contourArea)
x, y, w, h = cv2.boundingRect(c)

#EDIT: REMOVED CODE OUT OF WHILE- IT S NOT A VIDEO TO GRAB CONCURRENT FRAMES
while True:
    #cv2.imshow("frame", frame)
    #cv2.imshow("mask", mask)
    #cv2.imshow("res", res1)
    cv2.imshow("img",cont_img)

    key = cv2.waitKey(1)
    if key == 27:
        break

cv2.destroyAllWindows()

我稍微修改了你的代码。结果如下: