Pull to refresh

Датчик освещённости из веб-камеры вашего ноутбука

Reading time 3 min
Views 24K
image
Почти всегда на ночь (или утром, со словами «Что? Рассвет уже?») я включаю на ноутбуке фильм или сериал. Чтобы бубнило и успокаивало. Недавно заметил, что совсем не уменьшаю яркость при включении. Свет светит в глаза, мешает уснуть. Решается поворотом на другой бок или уменьшением яркости, конечно, но я слишком ленив, чтобы искать Fn+уменьшить яркость или установить и вывести апплет яркости. Уменьшение яркости при неактивности ставить не захотел, потому как это меня раздражает (пьешь себя кофе и смотришь код, тут резко до нуля так хрясь). Вспомнил про свою старую Nokia E70 (ох и шикарный телефон был), в котором был индикатор освещённости. Подумал, что такой датчик может заменить и обычная камера.

Ничего необычного. Фотографируем себя то, что видит камера, обесцвечиваем, определяем средний цвет и устанавливаем новую яркость.
#!/bin/bash
x=320 #ширина фото
y=240 #высота фото
n=1000 # порог проверки фото (от 0 до x*y) - каждый N пиксель будет взят для подсчета
max=40 #максимальный "цвет" (от 0 до 255)
sleep=60 #ожидание, перед повторением операции
maxbright=100 #максимальная яркость
minbright=20 #минимальная яркость
while [ 1 ]; do #бесконечный цикл
	ffmpeg -f video4linux2 -s ${x}x${y} -i /dev/video0 -f image2 /tmp/snapshot.jpg 2>/dev/null #делаем скрин
	convert /tmp/snapshot.jpg -colorspace gray /tmp/snapshot.jpg #обесцвечиваем его
	sum=0
	count=0
	let "s = x*y" #всего пикселей
        color=(`convert /tmp/snapshot.jpg[${x}x${y}+0+0] -depth 8 txt: | tail -n +2 | sed -n 's/^.*\(#[^ ]*\).*$/\1/p' | cut -c2-3`); #массив цветов пикселей, у которых взял только R из RGB, грубо говоря. Цвет то серый
		for i in `seq 0 $n $s`; #для каждого N-го
       						 do			
				#переводим цвет из 16-ричной в десятичную запись
				color1=`echo ${color[i]} | cut -c1-1` 
				color2=`echo ${color[i]} | cut -c2-2`
				case "$color1" in
					"A"  ) color1=10;;					
					"B"  ) color1=11;;
					"C"  ) color1=12;;
					"D"  ) color1=13;;
					"E"  ) color1=14;;
					"F"  ) color1=15;;
				esac
				case "$color2" in
					"A"  ) color2=10;;					
					"B"  ) color2=11;;
					"C"  ) color2=12;;
					"D"  ) color2=13;;
					"E"  ) color2=14;;
					"F"  ) color2=15;;
				esac
				let "rgbcolor = color1*16+color2"
				let "sum = sum+rgbcolor" #сумма "цветов". Потом поделим на количество и получим средний цвет
				let "count = count+1" #считаем количество
				
		done
        	
	let "avcolor = sum/count" #средний цвет
	#echo "Цвет: $avcolor" #раскомментировать для просмотра яркости при максимальном освещении (чтобы вписать в max)
	let "bright=avcolor*100/$max" #яркость
        #проверка на максимальную и минимальную яркость
        if [ $bright -gt $maxbright ]; then 
		bright=$maxbright 
	fi
	if [ $bright -lt $minbright ]; then 
		bright=$minbright 
	fi
	xbacklight -set $bright #устанавливаем яркость экрана
	echo "Установлена яркость: $bright"
	sleep $sleep #спим
done

Максимальную яркость смотреть, когда много света. Я поставил ниже, чем выводит, чтобы при небольших изменениях яркость не прыгала туда-сюда. Надеюсь, скрипт поможет глазам хоть как-нибудь. В темноте все же лучше сидеть с чуть притушенным монитором, чем с яркостью в 100%.
Всё написано для себя, в интернете по такому подходу ничего не видел, поэтому делюсь.
Что надо установить (для работоспособности скрипта): ffmpeg, ImageMagick и xbacklight.
Усовершенствования, ошибки и всё такое жду в комментариях. Знаю, что код не идеален.

PS: на картинке камера с ноутбука ASUS N53sv (у меня такой). Если закрыть шторку, яркость падает до минимума, что подтверждает работу скрипта. Параноики, завидуйте.

UPD: romik предлагает заменять математику на
avcolor=`convert snapshot.jpg -colorspace GRAY -resize 1x1 txt: | sed 's/[^(]*(\s*\([0-9]*\),.*/\1/p;d'`

А wrewolf менять яркость через acpi
echo -n $bright > /proc/acpi/video/VGA/LCD/brightness; 
Tags:
Hubs:
+82
Comments 31
Comments Comments 31

Articles