Just sharing a quick project I completed last weekend. I recently purchased a new webcam and I found that I often need to tweak the white balance and brightness depending on the weather and time of day. For example, I tend to appear red when I turn my office lights on in the evening and I ‘white out’ when my office is in full sun.
As a simple approach I grabbed a photoresister and a spare arduino nano and wrote a quick sketch so that I could detect the brightness at the window (How to Use Photoresistors to Detect Light on an Arduino - Circuit Basics). I then wrote a shell script to read the brightness value from the serial port and update the camera settings. So far this works well
This seems like an awesome project! Are you able to share the shell script and Arduino code? I’m sure there are plenty of WFH makers that would love to give it a go
Assume the photodiode circuit is connected to A0. It takes a number of readings and averages them to minimise the noise.
int photoPin = A0;
void setup() {
Serial.begin(9600);
}
unsigned int readSensor(){
unsigned int sval = 0;
for (int i = 0; i < 50; i++){
sval += analogRead(photoPin);
delay (10);
}
return sval / 50;
}
void loop() {
Serial.println(readSensor());
delay(250);
}
Here is the shell script. It is still rather rough and ready, but it has been working well. It uses a python camera control script to update the camera settings.
#!/bin/bash
lightLevel=254
zoom=35
stty -F /dev/ttyUSB0 raw 9600
updateCamera () {
/home/john/usr/cameractrls/cameractrls.py \
-d /dev/v4l/by-id/usb-Microsoft_Microsoft_Modern_Webcam_0C33JBG222301N0-video-index0 \
-c brightness=$1,contrast=$2,saturation=24,white_balance_temperature_auto=0,white_balance_temperature=$3,zoom_absolute=$4,pixelformat=MJPG,resolution=1920x1080,fps=30 \
>>/dev/null 2>&1
}
while true
do
oldLightLevel=$lightLevel
read -r lightLevel < /dev/ttyUSB0
lightLevel=${lightLevel//$'\r'} # strip carriage return
echo $lightLevel
# Has the light level changed and also check the zoom level in case the camera has been reset since (it appears that the settings are reset after each use of the camera)
if [ "$oldLightLevel" != "$lightLevel" ] || [ $(v4l2-ctl -d /dev/video2 -C zoom_absolute |cut -d' ' -f2) != $zoom ]; then
if ((0 <= lightLevel && lightLevel < 1 )); then
echo Night
updateCamera 130 160 3500 $zoom
elif ((1 <= lightLevel && lightLevel < 4 )); then
echo Evening
updateCamera 125 160 4600 $zoom
elif ((4 <= lightLevel && lightLevel < 10)); then
echo Cloudy dusk
updateCamera 110 160 4800 $zoom
elif ((10 <= lightLevel && lightLevel < 30)); then
echo Bright cloudy
updateCamera 110 160 4800 $zoom
elif ((lightLevel >= 30)); then
echo Very sunny
updateCamera 100 160 4800 $zoom
fi
fi
sleep 5
done
I do wonder if I can come up with a better software only solution to:
grab a frame from the camera every few seconds
use OpenCV to find the face
find the average skin colour over the face
adjust the camera settings to keep the skin colour within to a known preferred range