故事背后: 我正在尝试构建一个适应环境变化(主要是光线)的简单手部检测,因此使用粗略估计的直方图(使用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)
大多数人应该已经猜到了,这与这段代码有关:
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]
那么,如何写出这样漂亮又优雅的东西?
答案 0 :(得分:2)
如果要获取亮度和饱和度(最后2个通道)的最大值和最小值,一种方法是在您的显示器上使用np.max()
和np.min()
方法图像数组直接。
要获得所需通道的此类值,可以从图像中对其进行切片,然后查询这些值:
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