使用OpenCV的Python图像中的颜色百分比
我正在创建一个可以检测图像中绿色百分比的代码 我对OpenCV有一点经验,但对图像处理还是相当陌生,希望在代码方面得到一些帮助。我应该如何更改此代码,使其能够计算绿色而不是棕色的百分比?如果不太麻烦的话,有人能解释一下这些更改是如何影响代码的吗?下面是我想使用的图像链接。 代码归@mmensing所有使用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
将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
数组硬编码此间隔值。这是您必须修改的位。此外,我正在将输入图像转换为