Выполните итерации по изображению и выберите значения яркости / насыщенности в заданном диапазоне оттенков, не используя вложенные циклы for

1

Рассказ позади: я пытаюсь создать простое обнаружение рук, которое адаптируется к изменениям окружающей среды (главным образом свет) и поэтому повторно калибрует каждые несколько минут, используя гистограмму приблизительной оценки, где находится рука (с использованием YOLO-Darknet). Идея заключается в том, чтобы получить положение пальца в конце.

В настоящее время я получаю значение оттенка руки, а также легкость и насыщенность. Я написал короткий вложенный цикл для поиска легкости и насыщенности, где он проходит через все элементы в диапазоне оттенков и находит его максимальное и минимальное значение для записи в массиве.

Теперь мой вопрос: я знаю, что у 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)

Изображение 174551

Большинство должно было догадаться об этом уже сейчас, это об этой части кода:

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]

Итак, как написать это красиво и элегантно?

Теги:
opencv
list

1 ответ

2
Лучший ответ

Если вы хотите получить максимальные и минимальные значения вашей Lightness и Saturation (последние 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()

Изменить. Исходя из вашего пояснения, если вы хотите запросить такие значения max/min, но только те, которые попадают в определенный интервал [hue_min, hue_max] вы можете использовать np.where() вместе с max:

#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 index
  • 0
    Это на самом деле не то, что я имел в виду. Я хочу получить минимальное / максимальное значение, где оттенок находится между диапазоном HUE_MIN и HUE_MAX. Можете ли вы предоставить способ для этого тоже?
  • 0
    @ Дух так, скажем, ваш минимум 10, а ваш максимум 50 ... Вы хотите максимальное значение (например, 49), которое подходит между этими двумя, правильно?
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню