python - 迭代图像并在给定的色调范围内选择亮度/饱和度值,而不是使用嵌套的 for 循环

标签 python list opencv

背后的故事: 我正在尝试构建一个简单的手部检测,它可以适应环境变化(主要是光),因此每隔几分钟使用手部粗略估计的直方图(使用 YOLO-Darknet)重新校准一次。 想法是最后得到手指的位置。

目前我正在获取手的色调值并且亮度和饱和度是固定的。 我为亮度和饱和度搜索编写了一个简短的嵌套 for 循环,它遍历色调范围内的所有元素并找到其最大值和最小值以将其写入数组。

现在我的问题是: 我知道 python 具有编写此类嵌套循环和列表修改/操作的功能,简短而优雅,我该怎么做?

下面我有一个 MWE 和一个示例图像。

import numpy as np
import cv2

hue = 0
light = 1
satur = 2

img = cv2.imread('Untitled.png')
hls = cv2.cvtColor(img, cv2.COLOR_BGR2HLS)


# structure of histograms:
# 0, 2, 6 = histogram values for H, L and S
# 1, 3, 5 = bin values for H, L and S
histograms = [0] * 6

# Only 5 bins for a rough estimate of the skin color (so not too much is lost)
histograms[0], histograms[1] = np.histogram(hls[:, :, 0], 5)
histograms[2], histograms[3] = np.histogram(hls[:, :, 1], 5)
histograms[4], histograms[5] = np.histogram(hls[:, :, 2], 5)

# structure of HLS_bins:
# [Hue, Lightness, Saturation]         [min, min, min]
# [Hue, Lightness, Saturation]         [max, max, max]
HLS_bins = [[0, 200, 30], [0, 255, 255]]

# TODO alternative approach to the one below:
# todo...find the bin for the highest occuring color and select the Lightness
# todo...and Saturation according to the corresponding values

#  write in loop (elegant/generalized way) ?
# select the highest occurence of the hue
max_value_hue = max(histograms[0])
max_index_hue = list(histograms[0]).index(max_value_hue)
HLS_bins[0][0] = histograms[1][max_index_hue]
HLS_bins[1][0] = histograms[1][max_index_hue + 1]

min_value_light = 255
max_value_light = 0
min_value_saturation = 255
max_value_saturation = 0

for row in range(np.shape(hls)[0]):
    for col in range(np.shape(hls)[1]):
        if hls[row][col][hue] > HLS_bins[0][0] and hls[row][col][hue] < HLS_bins[1][0]:
            if hls[row][col][light] > max_value_light:
                max_value_light = hls[row][col][light]
            if hls[row][col][light] < min_value_light:
                min_value_light = hls[row][col][light]
            if hls[row][col][satur] > max_value_saturation:
                max_value_saturation = hls[row][col][satur]
            if hls[row][col][satur] < min_value_saturation:
                min_value_saturation = hls[row][col][satur]

HLS_bins[0][1] = min_value_light
HLS_bins[1][1] = max_value_light
HLS_bins[0][2] = min_value_saturation
HLS_bins[1][2] = max_value_saturation

HLS_bins = np.array(HLS_bins, dtype="uint8")
print(HLS_bins)

Test Image

大家应该已经猜到了,就是这部分代码:

for row in range(np.shape(hls)[0]):
        for col in range(np.shape(hls)[1]):
            if hls[row][col][hue] > HLS_bins[0][0] and hls[row][col][hue] < HLS_bins[1][0]:
                if hls[row][col][light] > max_value_light:
                    max_value_light = hls[row][col][light]
                if hls[row][col][light] < min_value_light:
                    min_value_light = hls[row][col][light]
                if hls[row][col][satur] > max_value_saturation:
                    max_value_saturation = hls[row][col][satur]
                if hls[row][col][satur] < min_value_saturation:
                    min_value_saturation = hls[row][col][satur]

那么,怎么写才好看呢?

最佳答案

如果您想要获得亮度和饱和度(最后 2 个 channel )的最大值和最小值,一种方法是使用 np.max()np.min()直接在图像阵列上的方法。

要获得所需 channel 的此类值,您可以将它们从图像中切片,然后查询这些值:

import cv2
img = cv2.imread('Untitled.png')
hls = cv2.cvtColor(img, cv2.COLOR_BGR2HLS)

#reading Lightness channel: No. 1
#this slice basically means: "give me all rows and all cols from channel 1"
max_value_light = hls[:,:,1].max()
min_value_light = hls[:,:,1].min()

#reading Saturation channel: No. 2
# and this slice means: "give me all rows and all cols from channel 2"
max_value_saturation = hls[:,:,2].max()
min_value_saturation = hls[:,:,2].min()

编辑: 根据您的说明,如果您想要查询此类最大/最小值,但仅查询那些落在特定区间内的值 [hue_min, hue_max]你可以使用 np.where()连同最大值:

#obtain the min hue that falls within the interval
#hue is channel 0, so we slice for all x,y pixels and for that channel
theMin = hls[np.where((hls[:,:,0]>hue_min) & (hls[:,:,0]<hue_max))][:,0].min()
#same story with the rest, compare to your _min and _max and use it's index

关于python - 迭代图像并在给定的色调范围内选择亮度/饱和度值,而不是使用嵌套的 for 循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51653625/

相关文章:

r - 计算矩阵列表 R 的按元素分位数

Python 3.6 - 将不同类型的列表作为输入

opencv - 大小和响应在 SURF 关键点中究竟代表什么?

c++ - 错误信息 : no match for call to ‘(cv::Rect) (cv::Mat&, cv::Point_<int>, cv::Point, cv::Scalar, int)’

python - 在 python 脚本中运行 sqoop

Python 自省(introspection) : access function name and docstring inside function definition

python - 编辑 pyparsing 解析结果

javascript - Django 模板将字符串解析为整数

python - 在 python 中就地反转列表和使用切片反转有什么区别?

c++ - 当 ogl::Arrays 的默认构造函数运行时,Opencv2 崩溃