JoakimSoderberg / catcierge

Image recognition (to keep cat prey out) and RFID chip reader system for automated DIY cat door.
GNU General Public License v2.0
62 stars 13 forks source link

Daemon mode / logging #12

Open Schaussi opened 7 years ago

Schaussi commented 7 years ago

I have now configured catcierge with haar matching and would like to collect some more real images of my cat, and test it with your cascade file - so I want to run catcierge in the background. Do you have any preferred way to to this, e.g. special parameters etc., or can I run it in background simply via "&"? Is there a logging option at the moment? I saw some information in your description, but cannot see a catcierge_grabber parameter regarding logging. "log=1" or "log_path=/var/log/catcierge.log" etc. do not work in cfg file. Thank you

JoakimSoderberg commented 7 years ago

I have created a systemd service file if you run raspbian (which uses systemd). So I would recommend you install catcierge on your system. To do that you first need to create a debian package:

cd build/
cmake ..
make
cpack  # Builds the debian package.
ls *.deb  # Or check output from above command what it is named.
sudo dpkg -i catcierge-0.6.3-armhf.deb  # If you built the latest version it should be named this...

So that installs catcierge as a daemon on the system:

(Reading database ... 42601 files and directories currently installed.)
Preparing to unpack catcierge-0.6.3-armhf.deb ...
Unpacking catcierge (0.6.3) over (0.6.3) ...
Setting up catcierge (0.6.3) ...
#########################################
Creating user catcierge
#########################################
The system user `catcierge' already exists. Exiting.
Getting started
---------------

1. Create a system-wide catcierge config file to get started:

  sudo cp /etc/catcierge/catcierge-example.cfg /etc/catcierge/catcierge.cfg

2. To see available options run:

  catcierge_grabber --help

3. And to finally start the service:

  sudo systemctl start catcierge

So yea, if you are not familiar with systemd read up some on how you stop start services using systemctl.

To follow the log live you can run the following command:

sudo journalctl -f -u catcierge

Or if you want to check the entire log since yesterday:

sudo journalctl --since yesterday -u catcierge

Here is the contents of the systemd service file:

cat /lib/systemd/system/catcierge.service
[Unit]
Description=Catcierge automatic cat door awesomeness
After=catcierge_rpi_gpio.service

[Service]
ExecStart=/usr/local/bin/catcierge_grabber
RemainAfterExit=yes
StandardOutput=journal+console
StandardError=journal+console
User=catcierge
Group=users

[Install]
WantedBy=multi-user.target

As you see it also installs services that sets the proper GPIO settings.... Which pins are used and so on are defined at compile time using CMake (see cmake -LH .. for CATCIERGE_LOCKOUT_GPIO and CATCIERGE_BACKLIGHT_GPIO to change which pins to use by default).

They can also be set at runtime via the command line/config file:

catcierge_grabber --help|grep gpio
JoakimSoderberg commented 7 years ago

This are the sources for the service files that are generated: https://github.com/JoakimSoderberg/catcierge/blob/master/cmake/catcierge_rpi_gpio.service.in

[Unit]
Description=Set cat door to open on boot

[Service]
Type=oneshot
ExecStart=@CMAKE_INSTALL_PREFIX@/share/catcierge_rpi_gpio.sh

[Install]
WantedBy=multi-user.target

The script referenced: https://github.com/JoakimSoderberg/catcierge/blob/master/cmake/catcierge_rpi_gpio.service.in


#!/bin/sh

# Cat door
echo "Catcierge lockout pin GPIO@CATCIERGE_LOCKOUT_GPIO@"
echo @CATCIERGE_LOCKOUT_GPIO@ > /sys/class/gpio/export
echo out > /sys/class/gpio/gpio@CATCIERGE_LOCKOUT_GPIO@/direction
echo 0 > /sys/class/gpio/gpio@CATCIERGE_LOCKOUT_GPIO@/value

# Backlight pin
echo "Catcierge backlight pin GPIO@CATCIERGE_BACKLIGHT_GPIO@"
echo @CATCIERGE_BACKLIGHT_GPIO@ > /sys/class/gpio/export
echo out > /sys/class/gpio/gpio@CATCIERGE_BACKLIGHT_GPIO@/direction
echo 0 > /sys/class/gpio/gpio@CATCIERGE_BACKLIGHT_GPIO@/value

echo "Catcierge GPIO ports setup"

And the catcierge service file: https://github.com/JoakimSoderberg/catcierge/blob/master/cmake/catcierge.service.in

[Unit]
Description=Catcierge automatic cat door awesomeness
@CATCIERGE_SERVICE_AFTER@

[Service]
ExecStart=@CMAKE_INSTALL_PREFIX@/bin/catcierge_grabber
RemainAfterExit=yes
StandardOutput=journal+console
StandardError=journal+console
User=catcierge
Group=users

[Install]
WantedBy=multi-user.target
JoakimSoderberg commented 7 years ago

Is there a logging option at the moment? I saw some information in your description, but cannot see a catcierge_grabber parameter regarding logging. "log=1" or "log_path=/var/log/catcierge.log" etc. do not work in cfg file.

Yes this is kind of deprecated, I have not even tested it for a long time... So I was planning to remove this eventually... This was some very basic logging I added early on. Now I'd rather rely on the console output which is logged by systemd... And then for special events one can use the "template output" stuff I mentioned in the other issue.

JoakimSoderberg commented 7 years ago

Note that the first thing you should be tweaking is the "background image" in front of your cat door. You haven't described your setup at all, but I'm assuming you've seen the pictures of my setup with a backlight and so on?

TL;DR

Use the catcierge_grabber --save_auto_roi to get a debug image to tweak the region of interest for your background image.

$ sudo systemctl stop catcierge
$ catcierge_grabber --auto_roi_thr 180 --save_auto_roi

OMG SO LONG

If you don't have this working good so it is a uniform and stable background, you will get a lot of false positive matches getting triggered.

I have added some code that makes all of this easy. However there is no easy "test program" for this. But rather you will need to use the catcierge_grabber program to do this.

The detection for when to start matching works in the way that the camera is filming a white background. The image is made "binary" that is, a pixel is either BLACK or WHITE depending on a certain threshold for the grey value for a pixel. When something enters that white image, a certain percentage of black pixels end up in the camera picture, which triggers the logic to start the match sequence.

Here is the logic for this, sum all black pixels. If there are more than 200 then something is obstructing the frame. https://github.com/JoakimSoderberg/catcierge/blob/master/src/catcierge_matcher.c#L249

All settings related to the Region Of Interest (ROI):

$ catcierge_grabber --help|grep -C5 roi
...
    --startup_delay STARTUP_DELAY            Number of seconds to wait after starting before starting to
                                             capture anything. This is so that if you have a back light
                                             that is turned on at startup, it has time to turn on,
                                             otherwise the program will think something is obstructing the
                                             image and start trying to match.
    --roi X Y WIDTH HEIGHT                   Crop all input image to this region of interest. Cannot be used
                                             together with --auto_roi.
    --auto_roi                               Automatically crop to the area covered by the backlight. This
                                             will be done after --startup_delay has ended. Cannot be used
                                             together with --roi.
    --auto_roi_thr THRESHOLD                 Set the threshold values used to find the backlight, using a
                                             binary threshold algorithm. Separate each pixel into either
                                             black or white. White if the greyscale value of the pixel is
                                             above the threshold, and black otherwise.
                                             Default value 90
    --min_backlight MIN_BACKLIGHT            If --auto_roi is on, this sets the minimum allowed area the
                                             backlight is allowed to be before it is considered broken. If
                                             it is smaller than this, the program will exit. Default 10000.
    --save_auto_roi                          Save the image roi found by --auto_roi. Can be useful for
                                             debugging when tweaking the threshold. Result placed in
                                             --output_path.

The ideal picture would be like this: match__2014-06-08_15_10_03__0

thr sq

That is, the white background is perfectly framed. But that becomes quite a hazzle to achieve with the correct camera distance and whatever.

So to make that simpler I added the auto_roi feature... ROI as in Region Of Interest. So we can feed it a background like this (from my current cat door):

goodbg04

From my config file I use these settings for the auto_roi stuff:

auto_roi=1
auto_roi_thr=180

To verify you have a good background for your setup you can use the --save_auto_roi command line option, which makes it save images of the background and region of interest at startup:

$ sudo systemctl stop catcierge  # Make sure catcierge_grabber service is stopped
$ catcierge_grabber --auto_roi_thr 180 --save_auto_roi # This will save a debug image for the ROI, see path below.
...
[2016-08-13 14:59:40.649604]  Automatically setting the frame obstruction Region Of Interest (ROI) to the back light area.
[2016-08-13 14:59:40.653278]  Back light found with area 15528 (which is greater than the minimum allowed 10000)
[2016-08-13 14:59:40.664023]  Saved auto roi image to: /home/pi/dev/catcierge/build/auto_roi.png
[2016-08-13 14:59:40.674148]  Saved auto roi image to (highlighted): /home/pi/dev/catcierge/build/auto_roi_highlight.png
[2016-08-13 14:59:40.674536]  Obstruction Region Of Interest (ROI): x: 89 y: 59 w: 128 h: 131

auto_roi auto_roi_highlight

Or using another threshold (default is 90):

$ catcierge_grabber --auto_roi_thr 90 --save_auto_roi
...
[2016-08-13 15:08:45.635883]  Startup delay of 0.00 seconds has ended!
[2016-08-13 15:08:45.636330]  Automatically setting the frame obstruction Region Of Interest (ROI) to the back light area.
[2016-08-13 15:08:45.640741]  Back light found with area 48090 (which is greater than the minimum allowed 10000)
[2016-08-13 15:08:45.652071]  Saved auto roi image to: /home/pi/dev/catcierge/build/auto_roi.png
[2016-08-13 15:08:45.664543]  Saved auto roi image to (highlighted): /home/pi/dev/catcierge/build/auto_roi_highlight.png
[2016-08-13 15:08:45.665326]  Obstruction Region Of Interest (ROI): x: 1 y: 1 w: 318 h: 238
[2016-08-13 15:08:45.969035]  Something in frame! Start matching...
[2016-08-13 15:08:45.988765]
[2016-08-13 15:08:45.989088]  === Match group id: b3815f627de480a6195c6d44633467a88ca17244 ===
[2016-08-13 15:08:45.989356]
[2016-08-13 15:08:45.989972]  [Waiting] -> [Matching]
[2016-08-13 15:08:46.034472]  Match in - No cat head detected (5e005292298c4d2fbe288a73297777b5cdd441c3)
[2016-08-13 15:08:46.067820]  Match in - No cat head detected (d5132f19d10faaa04cf19f35802a7fe1e6d428c3)
[2016-08-13 15:08:46.100927]  Match in - No cat head detected (a93c45586f979a52b0e3e37a30fc1b3294fe17d)
[2016-08-13 15:08:46.135553]  Match in - No cat head detected (b64cd4b1d1298cea24c1812a45075202ee4ac9b9)
[2016-08-13 15:08:46.136593]  !!! Match group vetoed match success: No head found in any image !!!
[2016-08-13 15:08:46.139099]  Lockout! 0 out of 4 matches failed (for 30 seconds).
[2016-08-13 15:08:46.139424]  Waiting for lockout timer only (Lockout method 1)
[2016-08-13 15:08:46.139659]  [Matching] -> [Lockout]

As you see in the text output above, this was not a good threshold, since it incorrectly thought the image was obstructed... Which is clear from the images below. The white outline is the thresholded area. If one encloses this in a rectangle you have the region of interest. But since the outline is so big it becaomse the entire picture (which includes a lot of black pixels):

auto_roi_highlight

Same for 120: auto_roi_highlight

160 works, but is not good because it will throw off the algorithm because it is including the reflection at the bottom: auto_roi_highlight

Offline?

Currently I have no native code helper program to do this "offline" just giving it an image like with the other test programs. Instead of having to run it through the camera like this.

But I have a small prototype script written in python:

If you have docker installed you can run it (or if you have a python + opencv environment set up on your machine, but docker makes this simple). Note that I have my code checked out in ~/dev/catcierge/ in the below example (I am mounting the example images inside of the docker so the script can find them).

goodbg04

However, since this is not the exact same code as in the cat door code, with Python in between "translating" some OpenCV stuff. So if we run it on the same image as before where 180 was a good threshold, it now does not work:

180:

$ docker run -v $PWD:/app -v ~/dev/catcierge/examples:/examples ibotdotout/python-opencv python find_backlight.py --threshold 180 /examples/real/goodbg02.png

thr sq

But raising it works...

220:

$ docker run -v $PWD:/app -v ~/dev/catcierge/examples:/examples ibotdotout/python-opencv python find_backlight.py --threshold 220 /examples/real/goodbg02.png

thr sq

So this script is more good to play with to understand how it works, rather than use it to find the best setting.

JoakimSoderberg commented 7 years ago

Btw, here is the difference between how it looked when I had newly built my latest version of the cat door (I use plexiglas as a divider in front of the camera)

Before: goodbg05

But after a while there will be dirt and scratches:

After: goodbg04

So something good to think about. My setting with 180 as the threshold works fine for both those scenarios. But be aware things can shift as time goes on :)

JoakimSoderberg commented 7 years ago

Oh and an example of a bad background would be this:

badbg01

Here my old backlight that was made out of normal led strips kind of stopped working because of the cold or just shitty quality... so the light because non-uniform... So it gives a ROI like this, which is bad:

thr sq

With some tweaking one can get the area slightly bigger, but the goal is to get a square, not some blob like this:

thr sq

JoakimSoderberg commented 7 years ago

It's cold and rainy today, hence my crazy spamming :)

I wrote a small helper program to tweak the above Auto ROI threshold: https://github.com/JoakimSoderberg/catcierge/blob/master/src/catcierge_bg_tester.c

Make sure you remember to update the submodules if you want to get the changes:

git checkout master
git pull --rebase upstream master   # upstream or whatever your remote is named (git remote -v)
git submodule update # Must be in project root when running this.
git fetch --all  # Get tags to get proper version.

This program can be run in both command line or GUI mode:

Background tester settings:
  Use these settings to pass a set of images you want to test when tweaking the
  settings relating to finding the backlight in the background using --auto_roi
  and other command line options.
     IMAGE                                   Input image containig the
                                             background image used to tweak
                                             settings with.

    --interactive                            GUI required, allows changing the
                                             auto roi threshold interactively.

So to run it in GUI mode:

bin/catcierge_bg_tester --interactive --haar --cascade ../extra/catcierge.xml ../examples/real/goodbg04.png

2016-08-13 18_38_18-mingw64__c_users_js_dev_catcierge_build2

Or to save images as I previously showed (but only with catcierge_grabber running live) just using the command line:

bin/catcierge_bg_tester --haar --cascade ../extra/catcierge.xml ../examples/real/goodbg04.png --auto_roi_thr 130 --save_auto_roi

I've tested this on both Windows and OSX, should work fine on Linux as well. However on OSX the trackbar does not show its value, so one has to look in the console window.

Schaussi commented 7 years ago

Thank you for your answers.

I think the background should be "white enough", and the default ROI threshold also seems to work fine. During the day, I might get problems regarding sun shadow, but I will try to solve this later (also night recording; it is the Rpi cam without the IR filter).

I can now basically start the daemon via "systemctl start catcierge.service", but it does not start on boot, though the service is enabled. It seems to only work when the service is stopped and then started again (otherwise no catcierge_grabber appears in process list). Also there appears an error "Failed to open PID file /var/run/catcierge.pid".

Journal logging also works, but does not show all information you see when you manually start catcierge_grabber.

What I would like to achieve: The Rpi should run now for some days and collect cat picture data. Then I would like to see how the images were processed, what were the results and what I have to optimize. E.g. it would be great if I could easily see a detailed log text for every directory under /home/catcierge/images/[date]/. It would be even better if I could see the recognized regions (cat head, snout) painted into the processed images in the subfolders (but I think --highlight does not work). Would this be possible?

At the moment, I have not modified the default haar cascade file in any way. Which way do you recommend to "teach" the application some good and bad head/snout pictures? (I would not like to damage or confuse the default haar file)

Thank you

JoakimSoderberg commented 7 years ago

Hello again,

I think the background should be "white enough", and the default ROI threshold also seems to work fine. During the day, I might get problems regarding sun shadow, but I will try to solve this later (also night recording; it is the Rpi cam without the IR filter).

Hmm well it would be nice if you could maybe provide an image of how your background looks by using --save_auto_roi?... You can include the image here by simply dropping it in the text field.

I am stressing this, because it is absolutely essential to get this working properly.

I am NOT using the IR camera either for this. But the point is that the background should be a light source. Or you are guaranteed to have issue with different lightning condition during the day/night. You will get spammed with invalid events.

I can now basically start the daemon via "systemctl start catcierge.service", but it does not start on boot, though the service is enabled.

Ah yes, to enable it starting on boot you use this command (or is that what you meant with "enabled"?):

sudo systemctl enable catcierge.service

Ah yes now that I come to think of it. I have it setup so that the GPIO "oneshot" service that will run at boot to enable the proper GPIO pins. Then the catcierge.service will run After that:

$ cat /lib/systemd/system/catcierge.service
[Unit]
Description=Catcierge automatic cat door awesomeness
After=catcierge_rpi_gpio.service
...

so you need to run:

sudo systemctl enable catgpio.service

To see which services that are run at boot:

ls -al /etc/systemd/system/*.service

Also there appears an error "Failed to open PID file /var/run/catcierge.pid".

This can be ignored, it is not used by systemd

Journal logging also works, but does not show all information you see when you manually start catcierge_grabber.

Yes I remember having this issue, but it should work with the latest version. Note that when you follow the log it will only show the "tail" of the log... You can extend so it shows more lines (200 in this example):

$ sudo journalctl -f -n 200 -u catcierge

Note however that journalctl does not seem to properly show the order of stderr/stdout... so for example stderr comes after the stdout output which is why you might think it does not show the full log.

What I would like to achieve: The Rpi should run now for some days and collect cat picture data. Then I would like to see how the images were processed, what were the results and what I have to optimize. E.g. it would be great if I could easily see a detailed log text for every directory under /home/catcierge/images/[date]/. It would be even better if I could see the recognized regions (cat head, snout) painted into the processed images in the subfolders (but I think --highlight does not work). Would this be possible?

Again I stress the importance of the backlight... It must be a light!

But yes this is a good idea to do... Could you please provide me the contents of your config?

Here is mine for example:

matchtime=20

# Haar matcher
haar=1
cascade=/usr/local/share/catcierge/catcierge.xml
in_direction=right
min_size=80x80

# Save images
save=1
save_obstruct=1
save_steps=1

output_path=/home/catcierge/images/%match_group_start_time:&Y-&m-&d%
match_output_path=%output_path%/%match_group_id%
steps_output_path=%match_output_path%/%matchcur_idx%

auto_roi=1
auto_roi_thr=180

noanim=1

#lockout_dummy=1

zmq=1

# OLD
#input=/usr/local/share/catcierge/templates/match_group_done_full.json

input=/usr/local/share/catcierge/templates/event.json

You should not use highlight I should probably remove that setting. As you see above I use the --save_steps setting to get full debug output. (I showed example of the images you get for each match with this in https://github.com/JoakimSoderberg/catcierge/issues/11)

With this config, each match will generate a JSON with a unique ID. In the same directory as that JSON file there is a directory with the same ID containing all the images for that match.

At the moment, I have not modified the default haar cascade file in any way. Which way do you recommend to "teach" the application some good and bad head/snout pictures? (I would not like to damage or confuse the default haar file)

You should NOT edit this by hand, it will fail. This file was generated from thousands of training samples. The process for doing this (quite tedious) can be found in this repository: https://github.com/JoakimSoderberg/catcierge-samples

But you should not have to modify this at all most likely. Unless you have some very weird looking cat that is (long haired that makes its profile look completely different from my training data or something) :)

The most important thing as I keep repeating is to have a good consistent environment for the camera + background image. You describe the night/sun disturbing the picture. This is bound to be the problem, rather than the Haar cascade itself, you won't be able to tweak that to fix those issues even if you create your own training data. The important thing is the consistency of the input images.

It would be great if you could provide some images of your cat door setup, pictures of how you have placed your camera, the background taken by the Raspberry Pi camera, pictures of your cat etc... It would make it a lot easier for me to help you. If you don't want to post those here you can email them to me: joakim.soderberg@gmail.com

JoakimSoderberg commented 7 years ago

Btw I added "live camera" support to the catcierge_bg_tester last night, so you should update your repo:

git checkout master
git pull --rebase origin master
git fetch --all  # To get my tags
JoakimSoderberg commented 7 years ago

Also note that the directory structure created for the output images is just the format I prefer, based on these settings:

output_path=/home/catcierge/images/%match_group_start_time:&Y-&m-&d%
match_output_path=%output_path%/%match_group_id%
steps_output_path=%match_output_path%/%matchcur_idx%

If you just want all images as a flat structure you can simply do:

output_path=/home/catcierge/images/%match_group_start_time:&Y-&m-&d%

Or one directory for each event 2016-08-15/1726/:

output_path=/home/catcierge/images/%match_group_start_time:&Y-&m-&d%
match_output_path=%output_path%/%match_group_start_time:&H&M&S%
steps_output_path=%match_output_path%/steps/

You get the point, it's configurable as you like...

The time formatting is based on http://man7.org/linux/man-pages/man3/strftime.3.html ... But instead of % you use & since catcierge uses % for the variables as well...

Schaussi commented 7 years ago

Sorry for replying late. I did some further tests but had do realize the cat door is at the worst place for such a project: Built into a door panel, sun problems (shadows from time to time, too hot in summer for Rpi), WLAN issues, .... So the next step will probably to create a new cat door in a place with a more neutral environment, which will take a few weeks. I will send you pics then if you would like to. Thank you for your help yet.

JoakimSoderberg commented 7 years ago

No worries, I thought I simply scared you away with my somewhat obsessive manners :)

Feel free to ask for pointers on building the hardware, I have built two