Your frame may already do this
picframe3 does this by itself, so on a Raspberry Pi 4 or 5 you no longer need anything below. The article stays here for frames still running the older software.
If you run picframe3, this is already done for you. The frame announces itself to Home Assistant over MQTT auto-discovery and brings two counters with it: Pictures indexed, which is the whole library, and Selected pictures, which is how many are in the running under whatever folder, tag, place and date filter is currently set. No script, no systemd unit, no YAML. The rest of this article is the hand-rolled version for the old pi3d PictureFrame.
I am always amazed by what Home Assistant, the home automation software, is capable of.
One piece of information I always wanted to see is how many images I have loaded onto the frame over time. With Home Assistant and MQTT this is easy to achieve, and I will show how to do it.
The following instructions assume that you are running Home Assistant and that you have installed an MQTT broker like Mosquitto on your Raspberry Pi.
If you are not familiar with this technology, please read my article “Control your digital picture frame with Home Assistant’s wifi presence detection and MQTT” first.
More than you can count
Python has this pretty cool os.walk command which can be used for many applications.
os.walk() generates the file names in a directory tree by “walking” the tree either top-down or bottom-up. It is recursive and also looks at all the subdirectories. You can then use the result and count the number of files in a given directory.
When I first tried the os.walk command, it didn’t add up. I looked at the number of objects of the shared Pictures folder (about 1,300), but I knew that this also included the folders. I estimated the number of subfolders to be around 150, but the number counted using os.walk was about over 2,500.
I quickly had a suspicion about the culprit.
As much as I love Apple computers, they have the nasty habit that they leave something behind when they access shared network folders. And for some reason, os.walk() counts these files that you cannot see in the network folder as they are hidden.
The files in question have an “.AppleDouble” name part, which makes them easy to identify. After doing some further research, I also needed to exclude “.” hidden files and “.sync” files.
So in the end, my function had a condition that only counted “real” jpg files.
if ext in ('.jpg') and not '.AppleDouble' in root and not name.startswith('.') and not '.sync' in root:
I ran a few tests and low and behold, this time the number was accurate.
The Python script to count the images
So, the first step is to add the following Python script to the home directory of your Raspberry Pi digital picture frame.
This script is automatically triggered by a change in your Pictures directory when you add or remove images.
In requires a package called “Watchdog” that you install with
source venv_picframe/bin/activate
pip install watchdog
Open your file editor. Copy & paste the content below it and save it as count_images_mqtt.py.
Enter the IP address of your Mosquitto broker and adjust the “searchdir” to your images folder.
#!/usr/bin/python3
#requires installation of watchdog
import time
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
import paho.mqtt.client as mqtt
import os
#MQTT
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION1)
# client.username_pw_set("your_username", "your_password")
client.connect("your-ip-address-of-mqtt-broker", 1883, 60)
client.publish("frame/images/available", "online", qos=0, retain=True)
client.loop_start()
searchdir = r"/home/pi/Pictures" #image count search directory
def count_images():
image_count = 0
for root, dirs, files in os.walk(searchdir):
for name in files:
ext = os.path.splitext(name)[1].lower()
if ext in ('.jpg') and not '.AppleDouble' in root and not name.startswith('.') and not '.sync' in root:
image_count += 1
image_count = "{:,}".format(image_count)
print(image_count)
client.publish("frame/images", image_count, qos=0, retain=True)
#Initial count of images
count_images()
class OnMyWatch:
# Set the directory on watch
watchDirectory = searchdir
def __init__(self):
self.observer = Observer()
def run(self):
event_handler = Handler()
self.observer.schedule(event_handler, self.watchDirectory, recursive = True)
self.observer.start()
try:
while True:
time.sleep(50)
except:
self.observer.stop()
print("Observer Stopped")
self.observer.join()
class Handler(FileSystemEventHandler):
@staticmethod
def on_any_event(event):
if event.is_directory: #look only for directory changes
count_images()
return None
if __name__ == '__main__':
watch = OnMyWatch()
watch.run()
The number of images is being published via MQTT in the topic “frame/images”.
Note: This script only counts JPG files. Other image formats are currently not supported. That was a fair assumption in 2019; it is not any more. If your library has HEIC photos from an iPhone, PNGs, or videos, this count will be too low — add the extensions you care about to the if ext in ('.jpg') line.
A note on mqtt.Client(): I have changed that line to mqtt.Client(mqtt.CallbackAPIVersion.VERSION1) above. paho-mqtt 2.x, which is what you get on Bookworm and Trixie, refuses the bare constructor and the script dies on the first line that matters. If you are still on paho-mqtt 1.x the new form works there too.
One more thing worth knowing: the script formats the number with a thousands separator ("{:,}".format), so it publishes 1,300 rather than 1300. Home Assistant expects a numeric state on a sensor that has a unit_of_measurement, and will complain in the log about a non-numeric value. If you see that, drop the image_count = "{:,}".format(image_count) line.
Launching the script at boot
To activate this script at boot, we’ll use systemd.
Enter
sudo nano /etc/systemd/system/count_images.service
Paste the following text into the editor window
[Unit]
Description=Count images in Pictures
After=multi-user.target
Requires=network.target
[Service]
Type=idle
User=pi
ExecStart=/home/pi/venv_picframe/bin/python /home/pi/count_images_mqtt.py
Restart=always
[Install]
WantedBy=multi-user.target
Two paths in there to check against your own machine. Raspberry Pi OS has had no default pi user for a few years now, so User= and both /home/pi/ paths need to be your own user name. And venv_picframe is the pi3d PictureFrame virtual environment — if you do not have one, point ExecStart at whatever Python you installed watchdog and paho-mqtt into.
Save and close.
Now change the file permissions with
sudo chmod 644 /etc/systemd/system/count_images.service
and update the services with
sudo systemctl daemon-reload
sudo systemctl enable count_images.service
Reboot.
Now we have to tell Home Assistant to pick up this sensor and display it on the frontend.
Setting up the image count sensor in Home Assistant
Add this paragraph in configuration.yaml:
#MQTT Sensor
mqtt:
sensor:
- name: "image_count_frame"
unique_id: image_count_frame
state_topic: "frame/images"
unit_of_measurement: "Photos"
That block used to read sensor: / - platform: mqtt. Home Assistant removed the MQTT platform from under sensor: in 2022 — MQTT entities live under the top-level mqtt: key now, and the old form stops Home Assistant from starting at all. If you already have an mqtt: section in your configuration.yaml, put the sensor: list inside the one you have rather than adding a second mqtt: key.
Restart Home Assistant and check the device states.
In the front end of Home Assistant, define the entity like in this example:
entities:
- entity: sensor.image_count_frame
icon: 'mdi:camera'
name: Number of images
show_header_toggle: false
title: Digital Picture Frame
type: entities
Restart Home Assistant. The number of photos should now be shown. Test it by adding a few images and deleting them again.

Congratulations. You’re done!
Conclusion
This is another example of how you can connect your digital picture frame and your Home Automation system with simple MQTT messages.
Let me know what you think!
Was this article helpful?
Thank you for your support and motivation.