-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathlux-from-webcam.bash
executable file
·111 lines (101 loc) · 4.11 KB
/
lux-from-webcam.bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#!/bin/bash
#
# lux-from-webcam.bash - guess lux value based on a webcam image
# ==================================================================
# Copyright (C) 2023 Michael Hamilton
#
# This script will read lux/brightness values from ~/.config/lux-from-webcam.data
# Add as many discrete values as you require: name lux value. The name is
# simple a comment and should have no spaces.
#
# A default config file is created when the script is first run, please alter
# it to match your own ambient lighting conditions.
#
# The script will optionally include ~/.config/lux-from-webcam.config
# and can be used to override any of the follow constants:
#
# DATA_FILE=~/.config/lux-from-webcam.data
# CAMERA_DEVICE=/dev/video0
# MANUAL_EXPOSURE_OPTION=1
# MANUAL_EXPOSURE_TIME=64
# IMAGE_LOCATION=$HOME/tmp/out.jpg
#
# Exposure time is 1/s seconds, so 64 is 1/64 of a second.
# The appropriate manual exposure option (if there is one) can be
# discovered by running
#
# v4l2-ctl -d /dev/video0 --list-ctrls-menus
#
# GNU License
# ===========
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation, version 3.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along
# with this program. If not, see https://www.gnu.org/licenses/.
#
CONFIG_FILE=~/.config/lux-from-webcam.config
DATA_FILE=~/.config/lux-from-webcam.data
CAMERA_DEVICE=/dev/video0
MANUAL_EXPOSURE_OPTION=1
MANUAL_EXPOSURE_TIME=64
IMAGE_LOCATION=/tmp/lux-from-webcam.jpg
if [ -f $CONFIG_FILE ]
then
echo "INFO: including config file: $CONFIG_FILE" >&2
. $CONFIG_FILE
fi
if [ \! -f $DATA_FILE ]
then
echo "INFO: creating $DATA_FILE based on the Logitech Webcam C270, please customise to your local conditions." >&2
cat > $DATA_FILE <<EOF
SUNLIGHT 100000 250
DAYLIGHT 10000 160
OVERCAST 1000 110
SUNRISE_SUNSET 400 50
DARK_OVERCAST 100 20
LIVING_ROOM 50 5
NIGHT 5 0
EOF
fi
existing_settings=$(v4l2-ctl --device $CAMERA_DEVICE --get-ctrl auto_exposure,exposure_time_absolute | awk '
{setting[++i]=$2} END {printf "auto_exposure=%s,exposure_time_absolute=%s", setting[1], setting[2]}')
trap "v4l2-ctl --device $CAMERA_DEVICE --set-ctrl $existing_settings" EXIT
# Decide on exposure settings based on the output of v4l2-ctl --device /dev/video0 --list-ctrls-menus
# and trial images samples.
current_exposure_mode=$(v4l2-ctl --device $CAMERA_DEVICE --get-ctrl auto_exposure | awk '{print $2}')
v4l2-ctl --device $CAMERA_DEVICE \
--set-ctrl auto_exposure=$MANUAL_EXPOSURE_OPTION,exposure_time_absolute=$MANUAL_EXPOSURE_TIME \
--set-fmt-video=width=1280,height=720,pixelformat=MJPG \
--stream-mmap --stream-to=$IMAGE_LOCATION --stream-count=1 2>&1 | grep -v '<'
# Fix issues in MJPG that bother ImageMagick
convert $IMAGE_LOCATION $IMAGE_LOCATION-fixed 1>/dev/null 2>&1
# Compute average brightness 0..255.
brightness=$(convert $IMAGE_LOCATION-fixed -colorspace gray -resize 1x1 -format "%[fx:255*mean]" info:)
brightness=$(echo $brightness | sed 's/[.].*//')
[[ -n "$VERBOSE" ]] && echo "INFO: camera-brightness: $brightness/255" >&2
while read name lux value
do
if [ $brightness -ge $value ]
then
if [ "$previous_value" != '' ]
then
# Interpolate on a log10 scale - at least that's what I think this is (idea from chatgpt)
[[ -n "$VERBOSE" ]] && echo "INFO: log10 interpolating $brightness over $value..$previous_value to lux $lux..$previous_lux" >&2
lux=$(awk -v b=$brightness -v v=$value -v pv=$previous_value -v lx=$lux -v plx=$previous_lux '
BEGIN { print(lx + 10 ** ((b - v) / (pv - v) * log(plx - lx)/log(10))); exit 0; }' < /dev/null)
fi
echo "INFO: brightness=$brightness, value=$value, lux=$lux, name=$name" >&2
echo $lux
break
fi
previous_value=$value
previous_lux=$lux
done < $DATA_FILE