使用OpenCV的Python图像中的颜色百分比

使用OpenCV的Python图像中的颜色百分比,python,opencv,image-processing,Python,Opencv,Image Processing,我正在创建一个可以检测图像中绿色百分比的代码 我对OpenCV有一点经验,但对图像处理还是相当陌生,希望在代码方面得到一些帮助。我应该如何更改此代码,使其能够计算绿色而不是棕色的百分比?如果不太麻烦的话,有人能解释一下这些更改是如何影响代码的吗?下面是我想使用的图像链接。 代码归@mmensing所有 将numpy导入为np 进口cv2 img=cv2.imread('potato.jpg') 布朗=[145,80,40]#RGB 差值=20 边界=[([brown[2]-diff,brown

我正在创建一个可以检测图像中绿色百分比的代码

我对OpenCV有一点经验,但对图像处理还是相当陌生,希望在代码方面得到一些帮助。我应该如何更改此代码,使其能够计算绿色而不是棕色的百分比?如果不太麻烦的话,有人能解释一下这些更改是如何影响代码的吗?下面是我想使用的图像链接。 代码归@mmensing所有

将numpy导入为np
进口cv2
img=cv2.imread('potato.jpg')
布朗=[145,80,40]#RGB
差值=20
边界=[([brown[2]-diff,brown[1]-diff,brown[0]-diff],
[棕色[2]+diff,棕色[1]+diff,棕色[0]+diff])]
对于边界中的(下部、上部):
lower=np.array(lower,dtype=np.uint8)
upper=np.array(upper,dtype=np.uint8)
遮罩=cv2.inRange(img,下部,上部)
输出=cv2。按位_和(img,img,mask=mask)
比率=cv2.countNonZero(掩码)/(img.size/3)
打印('brown pixel percentage:',np.round(比率\u brown*100,2))
cv2.imshow(“图像”,np.hstack([img,输出])
cv2.等待键(0)

我修改了您的脚本,以便您可以在测试图像中找到绿色的(近似)百分比。我添加了一些注释来解释代码:

# Imports
import cv2
import numpy as np

# Read image
imagePath = "D://opencvImages//"
img = cv2.imread(imagePath+"leaves.jpg")

# Here, you define your target color as
# a tuple of three values: RGB
green = [130, 158, 0]

# You define an interval that covers the values
# in the tuple and are below and above them by 20
diff = 20

# Be aware that opencv loads image in BGR format,
# that's why the color values have been adjusted here:
boundaries = [([green[2], green[1]-diff, green[0]-diff],
           [green[2]+diff, green[1]+diff, green[0]+diff])]

# Scale your BIG image into a small one:
scalePercent = 0.3

# Calculate the new dimensions
width = int(img.shape[1] * scalePercent)
height = int(img.shape[0] * scalePercent)
newSize = (width, height)

# Resize the image:
img = cv2.resize(img, newSize, None, None, None, cv2.INTER_AREA)

# check out the image resized:
cv2.imshow("img resized", img)
cv2.waitKey(0)


# for each range in your boundary list:
for (lower, upper) in boundaries:

    # You get the lower and upper part of the interval:
    lower = np.array(lower, dtype=np.uint8)
    upper = np.array(upper, dtype=np.uint8)

    # cv2.inRange is used to binarize (i.e., render in white/black) an image
    # All the pixels that fall inside your interval [lower, uipper] will be white
    # All the pixels that do not fall inside this interval will
    # be rendered in black, for all three channels:
    mask = cv2.inRange(img, lower, upper)

    # Check out the binary mask:
    cv2.imshow("binary mask", mask)
    cv2.waitKey(0)

    # Now, you AND the mask and the input image
    # All the pixels that are white in the mask will
    # survive the AND operation, all the black pixels
    # will remain black
    output = cv2.bitwise_and(img, img, mask=mask)

    # Check out the ANDed mask:
    cv2.imshow("ANDed mask", output)
    cv2.waitKey(0)

    # You can use the mask to count the number of white pixels.
    # Remember that the white pixels in the mask are those that
    # fall in your defined range, that is, every white pixel corresponds
    # to a green pixel. Divide by the image size and you got the
    # percentage of green pixels in the original image:
    ratio_green = cv2.countNonZero(mask)/(img.size/3)

    # This is the color percent calculation, considering the resize I did earlier.
    colorPercent = (ratio_green * 100) / scalePercent

    # Print the color percent, use 2 figures past the decimal point
    print('green pixel percentage:', np.round(colorPercent, 2))

    # numpy's hstack is used to stack two images horizontally,
    # so you see the various images generated in one figure:
    cv2.imshow("images", np.hstack([img, output]))
    cv2.waitKey(0)
输出:

green pixel percentage: 89.89
我制作了一些图像,这是绿色的二值遮罩:

这是从掩模和输入图像中导出的

关于此代码段的其他一些备注:

  • 在加载图像时,必须小心使用
    OpenCV
    BGR
    格式,而不是通常的
    RGB
    。在这里,代码片段有如下内容 通过反转边界列表中的元素来覆盖,但保持 注意这个常见的陷阱

  • 您的输入图像太大,甚至无法使用
    cv2.imshow
    。我调整了它的大小并处理了它。最后, 你看,我在最后的百分比中考虑了这个调整大小的比例 计算

  • 取决于您定义的目标颜色和所需的差异 使用时,可能会产生负值。在这种情况下 例如,对于
    R=0
    值,减去
    diff
    后 获取
    -20
    。这在编码颜色时没有意义 无符号8位的强度。这些值必须在
    [0255]
    范围内。 使用此方法时,请注意负值

  • 现在,您可能会看到该方法不是很健壮。根据您正在做的事情,您可以切换到以获得更好、更精确的二进制掩码

    您可以使用以下方法尝试基于HSV的

    # The HSV mask values, defined for the green color:
    lowerValues = np.array([29, 89, 70])
    upperValues = np.array([179, 255, 255])
    
    # Convert the image to HSV:
    hsvImage = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    
    # Create the HSV mask
    hsvMask = cv2.inRange(hsvImage, lowerValues, upperValues)
    
    # AND mask & input image:
    hsvOutput = cv2.bitwise_and(img, img, mask=hsvMask)
    
    这将为您提供一个漂亮的蒙面图像:


    我已经修改了你的脚本,所以你可以在测试图像中找到绿色的(近似)百分比。我添加了一些注释来解释代码:

    # Imports
    import cv2
    import numpy as np
    
    # Read image
    imagePath = "D://opencvImages//"
    img = cv2.imread(imagePath+"leaves.jpg")
    
    # Here, you define your target color as
    # a tuple of three values: RGB
    green = [130, 158, 0]
    
    # You define an interval that covers the values
    # in the tuple and are below and above them by 20
    diff = 20
    
    # Be aware that opencv loads image in BGR format,
    # that's why the color values have been adjusted here:
    boundaries = [([green[2], green[1]-diff, green[0]-diff],
               [green[2]+diff, green[1]+diff, green[0]+diff])]
    
    # Scale your BIG image into a small one:
    scalePercent = 0.3
    
    # Calculate the new dimensions
    width = int(img.shape[1] * scalePercent)
    height = int(img.shape[0] * scalePercent)
    newSize = (width, height)
    
    # Resize the image:
    img = cv2.resize(img, newSize, None, None, None, cv2.INTER_AREA)
    
    # check out the image resized:
    cv2.imshow("img resized", img)
    cv2.waitKey(0)
    
    
    # for each range in your boundary list:
    for (lower, upper) in boundaries:
    
        # You get the lower and upper part of the interval:
        lower = np.array(lower, dtype=np.uint8)
        upper = np.array(upper, dtype=np.uint8)
    
        # cv2.inRange is used to binarize (i.e., render in white/black) an image
        # All the pixels that fall inside your interval [lower, uipper] will be white
        # All the pixels that do not fall inside this interval will
        # be rendered in black, for all three channels:
        mask = cv2.inRange(img, lower, upper)
    
        # Check out the binary mask:
        cv2.imshow("binary mask", mask)
        cv2.waitKey(0)
    
        # Now, you AND the mask and the input image
        # All the pixels that are white in the mask will
        # survive the AND operation, all the black pixels
        # will remain black
        output = cv2.bitwise_and(img, img, mask=mask)
    
        # Check out the ANDed mask:
        cv2.imshow("ANDed mask", output)
        cv2.waitKey(0)
    
        # You can use the mask to count the number of white pixels.
        # Remember that the white pixels in the mask are those that
        # fall in your defined range, that is, every white pixel corresponds
        # to a green pixel. Divide by the image size and you got the
        # percentage of green pixels in the original image:
        ratio_green = cv2.countNonZero(mask)/(img.size/3)
    
        # This is the color percent calculation, considering the resize I did earlier.
        colorPercent = (ratio_green * 100) / scalePercent
    
        # Print the color percent, use 2 figures past the decimal point
        print('green pixel percentage:', np.round(colorPercent, 2))
    
        # numpy's hstack is used to stack two images horizontally,
        # so you see the various images generated in one figure:
        cv2.imshow("images", np.hstack([img, output]))
        cv2.waitKey(0)
    
    输出:

    green pixel percentage: 89.89
    
    我制作了一些图像,这是绿色的二值遮罩:

    这是从掩模和输入图像中导出的

    关于此代码段的其他一些备注:

  • 在加载图像时,必须小心使用
    OpenCV
    BGR
    格式,而不是通常的
    RGB
    。在这里,代码片段有如下内容 通过反转边界列表中的元素来覆盖,但保持 注意这个常见的陷阱

  • 您的输入图像太大,甚至无法使用
    cv2.imshow
    。我调整了它的大小并处理了它。最后, 你看,我在最后的百分比中考虑了这个调整大小的比例 计算

  • 取决于您定义的目标颜色和所需的差异 使用时,可能会产生负值。在这种情况下 例如,对于
    R=0
    值,减去
    diff
    后 获取
    -20
    。这在编码颜色时没有意义 无符号8位的强度。这些值必须在
    [0255]
    范围内。 使用此方法时,请注意负值

  • 现在,您可能会看到该方法不是很健壮。根据您正在做的事情,您可以切换到以获得更好、更精确的二进制掩码

    您可以使用以下方法尝试基于HSV的

    # The HSV mask values, defined for the green color:
    lowerValues = np.array([29, 89, 70])
    upperValues = np.array([179, 255, 255])
    
    # Convert the image to HSV:
    hsvImage = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    
    # Create the HSV mask
    hsvMask = cv2.inRange(hsvImage, lowerValues, upperValues)
    
    # AND mask & input image:
    hsvOutput = cv2.bitwise_and(img, img, mask=hsvMask)
    
    这将为您提供一个漂亮的蒙面图像:


    非常感谢你!这真的帮助了我,我真的很感激。解释也很清楚!我只想问一下如何测试基于HSV的面罩。我应该将其替换/添加到代码的哪个部分?@LimWZ在您的代码中定义了颜色范围的下限和上限,如下所示:
    bounders=[([green[2],green[1]…
    作为
    绿色
    的函数。HSV版本通过
    低值
    高值
    数组硬编码此间隔值。这是您必须修改的位。此外,我正在使用
    cv2.cvlor
    将输入图像转换为
    HSV
    。该位不会出现在代码中,因为您是已经在处理
    RGB
    颜色空间。您可以在HSV版本中获得如下
    ratio_green
    ratio_green=cv2.countNonZero(hsvMask)
    。非常感谢!这真的帮助了我,我非常感谢。解释也很清楚!我只是想问一下如何测试基于HSV的掩码。我应该替换/添加到代码的哪个部分?@LimWZ在您的代码中定义了颜色范围的下限和上限,如下所示:
    边界=[([green[2],green[1]…
    作为
    green
    的函数。HSV版本通过
    lowerValues
    upperValues
    数组硬编码此间隔值。这是您必须修改的位。此外,我正在将输入图像转换为