在特定颜色上查找并绘制 opencv 中的最大轮廓(Python)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/44588279/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 00:11:13  来源:igfitidea点击:

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

pythondrawcontour

提问by Zaptimist

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

希望有人可以提供帮助

回答by Jo?o Cartucho

You can start by defining a maskin the range of the redtones of the book you are looking for.

您可以首先在您要查找的书的红色调范围内定义一个蒙版

Then you can just find the contour with the biggest areaand 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.

如果您希望这本书旋转,您可以使用,rect = cv2.minAreaRect(cnt)因为您可以在此处找到它。

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.

您还应该考虑除 RGB 之外的其他颜色空间,如 HSV 或 HLS。通常,人们使用 HSV,因为 H 通道在阴影或过度亮度方面保持相当一致。换句话说,如果您使用 HSV 颜色空间,您应该获得更好的结果。

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 Hand 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.

具体来说,在 OpenCV 中,色调范围是[0,179]. 在下图中(由@Knight 制作),您可以在 中找到该圆柱体的 2D 切片V = 255,其中水平轴是H,垂直轴是S。从该图中可以看出,要捕捉红色,您需要同时包含色调值的较低(例如,H=0 到 H=10)和较高的区域(例如,H=170 到 H=179)。

enter image description here

在此处输入图片说明