Адаптивная подсветка с датчиком из веб-камеры

Софт под Linux, разные программы, но только связанные с Linux

Модератор: /dev/random

Аватара пользователя
olecya
Сообщения: 901
ОС: debian, fedora (i3-wm)

Re: Адаптивная подсветка с датчиком из веб-камеры

Сообщение olecya »

А у меня ко всему получился генератор. Можно дирижировать руками перед камерой, а как надоест то закомментировать print:
cat dimmer.sh:

Код: Выделить всё

#!/bin/bash
shopt -s lastpipe

while true; do
  fswebcam --greyscale --no-banner -qr 160x120 - | 
    convert - -colorspace GRAY -resize 1x1 txt: |
      grep -oP 'gray\(\K\d+'
done |
  awk '
  !/^[0-9]+$/  {next}
               {$1=$1*4>100?100:$1*4}
  !f           {f = $1-1}
  $1 == f      {next}
               {d = f>$1?-1:1
                while(f != $1) {
                   f+=d
                   print f
                   system("light -S "f"; sleep 0.1")}
                f=$1
  }'
А если сюда еще добавить утилиту: pip install pipeplot для визуализации,
то получится графический терменвокс. Добавим через конвеер полсе awk:

Код: Выделить всё

}' | pipeplot --direction left --min 20 --max 100
termenvoks.png
termenvoks.png (19.05 КБ) 1236 просмотров
Вот как плавненько меняется освещение
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 20791
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: Адаптивная подсветка с датчиком из веб-камеры

Сообщение Bizdelnick »

olecya писала:
06.12.2020 13:24
Вот как плавненько меняется освещение
Где ж плавненько, когда такие пики острые, и внезапные скачки в обратную сторону?
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
Аватара пользователя
olecya
Сообщения: 901
ОС: debian, fedora (i3-wm)

Re: Адаптивная подсветка с датчиком из веб-камеры

Сообщение olecya »

Bizdelnick писал:
06.12.2020 14:34
Где ж плавненько, когда такие пики острые, и внезапные скачки в обратную сторону?
Так это я светом игралась а само изменение идет плавно по 1 проценту за 0.1 секунду в любую сторону, лесенка видна. А самый большой всплеск это я лист белой бумаги показала камере :( что говорит о том что камеру лучше встраивать в ноутбук в противоположную сторону :)
Спасибо сказали:
nick87720z
Сообщения: 178
ОС: Gentoo / Calculate

Re: Адаптивная подсветка с датчиком из веб-камеры

Сообщение nick87720z »

olecya писала:
06.12.2020 17:10
Так это я светом игралась а само изменение идет плавно по 1 проценту за 0.1 секунду в любую сторону, лесенка видна. А самый большой всплеск это я лист белой бумаги показала камере :( что говорит о том что камеру лучше встраивать в ноутбук в противоположную сторону :)
Получается некий фейс-контроль. Сидеть за ноутом только во всем белом :D .
и с накрахмаленной физиономией :crazy:

Кстати, удалось соединить fswebcam и ffmpeg, чтобы был был постоянный конвейер (ffmpeg же не умеет хватать камеру на каждый кадр).
Правда, при этом сам ffmpeg создает задержку в 1 кадр, что при частотах <1 fps не комфортно.

Код: Выделить всё

#!/bin/bash
  
shopt -s lastpipe

stdbuf -o0 fswebcam --greyscale --no-banner -qr 1x1 --scale 1x1 --jpeg -1 --loop 1 - \
| stdbuf -o0 ffmpeg -v quiet -f mjpeg -i - -f rawvideo -pix_fmt gray - \
| stdbuf -oL od -An -w1 -tu1 \
| awk '
  /^*/         {next}
               {$1 = $1 > 100 ? 100 : $1}
  !f           {f = $1 - 1}
               {d = f > $1 ? -1:1
                while(f != $1) {
                   f+=d
                   printf "%u ", f
                   print ("light -S "f"; sleep 0.01") | "sh"
                }
                f=$1
  }'

printf "\n"
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 20791
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: Адаптивная подсветка с датчиком из веб-камеры

Сообщение Bizdelnick »

olecya писала:
06.12.2020 17:10
Так это я светом игралась а само изменение идет плавно по 1 проценту за 0.1 секунду в любую сторону, лесенка видна.
А зубцы вверх-вниз — это нормально, что ли? Изменение идёт плавно, но пока оно идёт, оказывается, что нужно уже в другую сторону менять. Ещё и задержка в считывании показаний из-за этого. Десять секунд машем рукой перед камерой, потом минуту наслаждаемся "плавными" плясками яркости. Пока не выкинете слипы — о плавности говорить нельзя.
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
nick87720z
Сообщения: 178
ОС: Gentoo / Calculate

Re: Адаптивная подсветка с датчиком из веб-камеры

Сообщение nick87720z »

olecya писала:
06.12.2020 17:10
Так это я светом игралась а само изменение идет плавно по 1 проценту за 0.1 секунду в любую сторону, лесенка видна. А самый большой всплеск это я лист белой бумаги показала камере :( что говорит о том что камеру лучше встраивать в ноутбук в противоположную сторону :)
Тогда в цикле с fswebcam тоже надо sleep на 10 секунд.

Если переход непрерываемый, то можно его дополнительно сгладить:

Код: Выделить всё

                s = f
                print "from", s, "to", $1
                while (f != $1) {
                   f+=d
                   v = (s + sin((f-s)/($1-s) * pi_2)^2 * ($1-s))
                   printf "%u:%0.1f ", f, v
                   print ("light -S "v"; sleep 0.02") | "sh"
                }
                print ""
Или вот квадратичный вариант, но его я только в gnuplot смотрел:

Код: Выделить всё

v = x / M
v = 100*(1 + (v > 0.5 ? 1 - (2*v-2)**2 : (2*v)**2-1)) / 2
Кстати, недавно узнал про переменную RETRY в awk. Думаю, с ней можно сделать цикл на собственной частоте, использующий неблокирующее чтение из потока. Правда, сглаживание тогда будет похитрее.
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 20791
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: Адаптивная подсветка с датчиком из веб-камеры

Сообщение Bizdelnick »

nick87720z писал(а):
06.12.2020 22:57
Тогда в цикле с fswebcam тоже надо sleep на 10 секунд.
Это, конечно, решает часть проблем, но чем вам обоим так не нравится вариант с ФНЧ? Он ведь ещё и кратковременные флуктуации отсеет.
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
Аватара пользователя
olecya
Сообщения: 901
ОС: debian, fedora (i3-wm)

Re: Адаптивная подсветка с датчиком из веб-камеры

Сообщение olecya »

Bizdelnick писал:
06.12.2020 19:29
Десять секунд машем рукой перед камерой, потом минуту наслаждаемся "плавными" плясками яркости.
Можно уменьшить в awk время sleep до .05. В цикле fswebcam отрабатывает по факту за 0.8, значит размер очереди не должен становится сильно инертным. Ну и это конечно без работы pipeplot, потому что его скорость обработки одного значения более 0.1 секунды
Bizdelnick писал:
06.12.2020 23:39
чем вам обоим так не нравится вариант с ФНЧ?
Мне нравится, но пока этот был надкушенный и горячий...
Последний раз редактировалось olecya 07.12.2020 00:59, всего редактировалось 1 раз.
Спасибо сказали:
nick87720z
Сообщения: 178
ОС: Gentoo / Calculate

Re: Адаптивная подсветка с датчиком из веб-камеры

Сообщение nick87720z »

Bizdelnick писал:
06.12.2020 23:39
nick87720z писал(а):
06.12.2020 22:57
Тогда в цикле с fswebcam тоже надо sleep на 10 секунд.
Это, конечно, решает часть проблем, но чем вам обоим так не нравится вариант с ФНЧ? Он ведь ещё и кратковременные флуктуации отсеет.
Да оно тут похоже и не обсуждается. Сначала я хотел вариант с фильтром tmix окруженным двумя geq (первый переводит в логарифмическое пространство, второй обратно). Но появились проблемы из за отрицательных чисел из за нехвата точности вычислений (которые в uint сами знаете во что переводятся). Вот и решил пока остаться на ручной адаптации с постоянной скоростью (типа фнч, только с треугольной фолной вместо синуса).

Update:
Я как-то не догадался, что необязательно двигать все содержимое буфера фильтра, лучше циклически двигать индекс.
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 20791
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: Адаптивная подсветка с датчиком из веб-камеры

Сообщение Bizdelnick »

nick87720z писал(а):
07.12.2020 00:36
Я как-то не догадался, что необязательно двигать все содержимое буфера фильтра, лучше циклически двигать индекс.
Ему и не нужен буфер. См. приведённый мной пример.
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
nick87720z
Сообщения: 178
ОС: Gentoo / Calculate

Re: Адаптивная подсветка с датчиком из веб-камеры

Сообщение nick87720z »

Bizdelnick писал:
07.12.2020 01:13
Ему и не нужен буфер. См. приведённый мной пример.
Только что пропарсил (тогда я был как чукча-писатель). У вашего варианта только финиш плавный, старт резкий. Я все пытался балансировать между замедлением и ускорением (до полной скорости), но дисбаланс был неисправим. В итоге забросил, пока tmix не открыл. Что до буфера - то, что у меня в голове было, я нашел под названием скользящее среднее. Но это получается прямоугольный фильтр. Если хоть пик попадет, то на все время буфера будет маленькое но постоянное изменение. 2 фильтра - линейный вариант, как у меня. Думал было попробовать 3, как в kawase blur, но... сейчас дошло, что хватит и одного, если поставить поверх линейной адаптации. По крайней мере, проще чем балансировать между ускорением и замедлением.
Спасибо сказали:
Аватара пользователя
olecya
Сообщения: 901
ОС: debian, fedora (i3-wm)

Re: Адаптивная подсветка с датчиком из веб-камеры

Сообщение olecya »

nick87720z писал(а):
06.12.2020 18:12
print ("light -S "f"; sleep 0.01") | "sh"
Вот здесь ошибка. Без system() мы получается просто спим на работе,
Без цикла while следует отказаться от включения lastpipe. Вобще здорово получилось без цикла.

Код: Выделить всё

#!/bin/bash

stdbuf -o0 fswebcam --greyscale --no-banner -qr 1x1 --scale 1x1 --jpeg -1 -l 1 - | 
  stdbuf -o0 ffmpeg -v quiet -f mjpeg -i - -f rawvideo -pix_fmt gray - | 
    stdbuf -o0 hexdump -e '1/1 "%u" "\n"' |
      awk '
/^*/     {next}
!f       {f = $1 - 1}
         {d = f > $1 ? -1:1
              while(f != $1) {
                 f+=d
                 printf "%u ", f
                 system("light -S "f"; sleep .05")
              }
          f=$1
}'
Осталось подумать над фильтрами.
Обрезала хвосты c головами и ввела прогрессию:
Spoiler

Код: Выделить всё

    stdbuf -o0 hexdump -ve '1/1 "%u" "\n"' |
      awk '
BEGIN   {"light -G" | getline; f = int($1)}
        {$1=int($1*0.5)*3; k=1}
$1>100  {$1 = 100}
#!f      {f = $1 - 1}
f==$1   {next}
int(($1-f)/10) {k=2}
        {d = f>$1?-1:1
        while(f != $1) {
          f+=d
          if(!(f%k)) {printf "%u ", f
            system("light -S "f"; sleep 0.05")
          }
        }
        f=$1
}'
Последний раз редактировалось olecya 08.12.2020 20:47, всего редактировалось 5 раз.
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 20791
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: Адаптивная подсветка с датчиком из веб-камеры

Сообщение Bizdelnick »

nick87720z писал(а):
07.12.2020 06:20
У вашего варианта только финиш плавный, старт резкий.
Есть такое дело, да. Если уменьшить k, станет плавнее, но и то, и другое. Можно и более хитрое что-нибудь придумать.
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
nick87720z
Сообщения: 178
ОС: Gentoo / Calculate

Re: Адаптивная подсветка с датчиком из веб-камеры

Сообщение nick87720z »

Проверяя ФНЧ, решил тоже поиграться с графиками:

Код: Выделить всё

                l = (x - $bl_min + 1) / ($bl_max - $bl_min + 1)
                llen = 250
                "'printf ("%"int( llen * l )"s%"(250 - int(llen * l >= 1 ? llen * l : 1))"s\n", "#", "|") > stderr'"
Сам фильтр:

Код: Выделить всё

        "BEGIN {
                stderr = \"/dev/stderr\"
                
                r = $bl_max / $bl_min
                d = $bl_max - $bl_min
                log_rd = d / log(r)

                # init LPF
                stage_frames = int( $fade_frames / 2 )
                bl_step = stage_frames > 0 ? ($bl_max / $bl_min )^( 1 / stage_frames) : 0
                for (fi = 0; fi < stage_frames; fi += 1)
                        fbuf[fi] = bl_cur
                fi = 0
                fsum = bl_cur * stage_frames
        }
        bl > bl_cur ? (bl_cur *= bl_step) > bl : (bl_cur /= bl_step) < bl \
                { bl_cur = bl }
        {
                # to log space
                p = $bl_min + log(bl_cur / $bl_min) * log_rd
        
                fsum = fsum + p - fbuf[fi]
                fbuf[fi] = p
                fi = (fi + 1) % stage_frames
                p = fsum / stage_frames

                l = (p - $bl_min + 1) / (d+1)
                llen = 250
                "'printf ("%"int( llen * l )"s%"int( llen * (1 - l) )"s\n", "#", "|") > stderr'"

                # from log space
                p = int($bl_min * r^((p - $bl_min) / d))
        }
        bl == p { next }
        { printf (\"%u\n\", p) }"
Спасибо сказали:
nick87720z
Сообщения: 178
ОС: Gentoo / Calculate

Re: Адаптивная подсветка с датчиком из веб-камеры

Сообщение nick87720z »

Недавно локализовал баг. При определенных методах записи в $acpi_dir/brightness слишком частые записи приводят к ошибке "invalid argument". Это происходит если запись идет через "cat > $acpi_dir/brightness", замена "cat" на чепуху типа tr ' ' ' ' или "tee > ..." бесполезна. А вот bc этому не подвержен, и так как на входе цифры, то он отлично справляется с ролью cat. Но это скорее заглушка.

Можно пережить sigpipe если не игнорировать результат записи. Минимальный пример:

Shell

n=1
while :; do
echo $n
n=$(( (n + 10) % 2000 ))
sleep 0.001
done | stdbuf -oL awk 'BEGIN {
cmd = "exec cat > /sys/class/backlight/intel_backlight/brightness"
PROCINFO[cmd, "NONFATAL"]=1
}{
ERRNO=0
print ($1+2000) | cmd
if (ERRNO) {
print (ERRNO, $1 + 2000) > "/dev/stderr"
close (cmd)
}
}'
Если же запись идет прямо в файл, а не через посредника типа cat, то можно вообще избежать sigpipe, если делать fflush().

Код: Выделить всё

	ERRNO=0
	print ($1+2000) > acpi_file
	if (ERRNO) {
		print (ERRNO, $1 + 2000) > "/dev/stderr"
		close (acpi_file) 
	} else {
		fflush (acpi_file);
	}
А вот пример с awk, работающим на своей частоте (более высокой). Правда все, что в @load 'time' считается устаревшим, взамен рекомендуют самим ставить timex из своей коллекции (интересно, если в дистрах пакеты типа awk-plugin-* или awk-plugins[куча юзов]).

Shell

n=1
while :; do
echo $n
n=$(( (n + 1) % 10 ))
sleep 1
done | awk '
@load "time"
BEGIN {
PROCINFO["/dev/stdin", "READ_TIMEOUT"] = 1000/30
PROCINFO["/dev/stdin", "RETRY"] = 1
while (1) {
t = gettimeofday()
switch (getline < "/dev/stdin") {
case 1: print $1;
case 0: break;
default: printf "."
}
sleep(1/30)
}
}'
Спасибо сказали:
Ответить