Sat, 10 Oct 2026

On Photography and AI

— SjG @ 12:42 pm

There was a recent brouhaha about a video competition withdrawing its award because of AI use. I talk about image manipulation apropos photography and “cheating” here occasionally (most recently on choosing angles and removing power lines).

To some extent, this is simply a problem where we’ve been trained to believe that photographs depict some objective reality. It’s never been true, but it’s strangely less true than ever before. Generative diffusion techniques unlock a whole new horizon of fakery, and it’s hard not to conclude that the people pushing it everywhere are interested in destroying baseline confidence in the ability to understand reality (or to destroy a concept of reality itself).

For what it’s worth, I do use tools to post-process images, and this is usually in order to change or enhance the narrative of the picture.

For example, here’s a picture of a hummingbird sitting on branch in front of the full moon I took in April.

Hummingbird and full moon

This image is different than the original capture. First off, the sensor in most digital cameras does not have true color perception, but only measures luminance. A pattern of colored filters are put over the sensor, and the camera uses interpolation to determine the color image.

Beyond that, I cropped the image, and adjusted the relative lighting. That hummingbird was not illuminated, so in contrast to the moon behind it, there was almost visible detail. In software, I brightened up the levels of the shadowed area, and I increased the saturation so you could see the faintest hint of color.

Wanna see the straight-out-of-the-camera version? Of course you do.

Un-edited photo

This original picture tells a different story. It tells me that I didn’t have the 600mm lens on the camera. It’s not a bad picture, but I like my edited version better: it’s more about the hummingbird.

A few other things are worth discussing. My camera isn’t taking “High Dynamic Range” (HDR) photographs. With HDR, it would have taken multiple exposures at different light levels and then combined them algorithmically. It could have got more color in the hummingbird. The camera is also not doing focus stacking. With focus stacking, it would have taken multiple exposure at different focal distances, then combined the sharp areas of each photo to form the final image. In this case, there are really only two focal areas, the bird and the moon. The physics of my lens allowed me to get one or the other in focus. With focus stacking, I could have combined multiple images and gotten both.

You could look at both of these multiple exposure techniques as cheating, or you could consider them ways of circumventing physics to make an image more like one we “see.” Our eyes play all sorts of tricks to circumvent physics, like constantly moving and changing focus, but the processing that takes place in our brains makes it seem like we’re seeing this heavily processed information gathered over time as a single instantaneous image.

The following version is from ChatGPT. It was asked to take the top image, and fed the prompt “Can you please enhance this image, bring out the colors in the hummingbird, and bring the full moon behind it into clearer focus? I’d like it to remain photorealistic and dramatic.” Below are the results. I’ll let you assess for yourself.

ChatGPT Processed Image

What’s did the AI processing do? Well, it cropped closer in, for one thing. It brought up the colors in the hummingbird. And it replaced the moon with a different picture of the moon.

My processing could never have made the image look like this. The information simply wasn’t in the data I got from the camera — the moon, for example, was too far out of focus and had none of the detail in it. It looked like the hummingbird was replaced too. Could I have got those colors if I’d tweaked the exposure enough? Well, to find out, I took the original unaltered image, and cranked up the exposure to see. And yes, you can see that it replaced the hummingbird altogether. Compare the chin coloration and the angle of the head — that ain’t the same bird!

Original image details

So what’s the point of this entire discussion? I guess I’m trying to draw lines between “legitimate” image manipulation to tell a story, and “faking it.” The line’s not a very clear one, but I do think there’s a distinction to be made.

Obviously, with better prompting, I may have gotten less obvious changes. If they had been subtle, would I have felt better about it? Not really. To me, the addition of statistically-generated data means it’s no longer “real.”

What are your thoughts?

Fri, 9 Oct 2026

Notes and Replacing Proprietary Services, Part II

— SjG @ 10:38 am

I’ve migrated my notes back to Obsidian, and have been using it pretty much exclusively for note-taking since I last posted in September.

There’s a core plugin for Obsidian called “Importer” that will import Apple Notes. However, there is a caveat: the notes have to be unlocked. So if you have a bunch of locked (encrypted) notes, you’ll need to unlock them before doing the import. Another caveat that I discovered today, a month after my switch, is the way the importer uses the first line of an Apple Note as a title. More on this below.

I wanted to be able to encrypt select notes, like I did with note locking in Apple Notes. There’s a community plugin for Obsidian called “MeldEncrypt” that lets me do that. The UI takes a little getting used to, but it seems to work pretty well.

Then there’s syncing. I want to access my notes on my phone, on my notebook, or wherever. I’d like to be able to add a new computer or device to this sharing at any time.

Initially, I set up the Obsidian vault (which is the directory structure on the filesystem where it saves the notes) in an iCloud directory. That way, on my iPhone or notebook computer, I was able to open the vault and let Apple handle the syncing. But this whole process is about moving away from proprietary systems. iCloud is a proprietary dependency and isn’t available on Linux. Obsidian has a subscription sync service that I could use, but again, I’d like to be independent of other providers and keep my stuff on “my” servers.

There’s a plugin called RemotelySave, which allows syncing notes to a wide variety of services. It’s currently free, and will be adding more sophisticated features for paid subscribers, but theoretically will continue to be free for basic sync to standard services. One of those standard services is WEBDAV.

Well, I have a VPS to host web stuff. I know how to set up Apache services. So I went in and configured a WEBDAV service on one of my web servers (not the one hosting this blog). I secured the HTTP connection using a LetsEncrypt certificate and Basic Authentication, and point it at a directory outside the web root (in this case /var/webdav). The Apache configuration looks like:

<IfModule mod_ssl.c>
<VirtualHost *:443>
    ServerName webdav.somedomain.com

    Alias /webdav /var/webdav

    <Directory /var/webdav>
        Options None
        AllowOverride None

        Dav On

        AuthType Basic
        AuthName "WebDAV"
        AuthUserFile /etc/httpd/webdav.passwd
        Require valid-user

        <LimitExcept GET HEAD OPTIONS>
            Require valid-user
        </LimitExcept>
    </Directory>

    ErrorLog /var/log/httpd/webdav_error.log
    CustomLog /var/log/httpd/webdav_access.log combined

SSLCertificateFile /etc/letsencrypt/live/webdav.somedomain.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/webdav.somedomain.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
</IfModule>

I had to create the directory /var/webdav, give the web account access to it, and use htpasswd to create a user/password file as /etc/httpd/webdav.passwd.

So then I set up RemotelySave, and watched the data show up on the server! Excellent! You can set RemotelySave to sync on various schedules, on or after Obsidian startup, and (experimentally) upon save. I opted to set it up to sync one second after startup and upon save.

Then I set up Obsidian on a Linux box that has no access to the iCloud directory. Would it sync? Boom! No, it would not. Going into the low-level logs, I could see the problem.

Remember above I said there were issues with the first line of notes and titles? That’s what tripped me up here. I had a big folder of notes that were quotations. Often, I’d paste those into Apple Notes and not do any further editing. The Obsidian Apple Notes importer sees the first line of each note as its title.

Also, the filename for each note created (or imported) by Obsidian is based on the title, and seems to be truncated at 60 characters. Mysteriously, though, some imported Notes had filenames that include the entire title. I can’t find the factor that determined which were truncated and which were not. Many of the un-truncated titles start with quotation marks, but also many notes that have titles starting with quotation marks truncated correctly. In any case, I had a number of files with names over 255 characters. Those crashed the plugin when I tried to sync to Linux.

Another thing I discovered at this point is that the importer truncates the first line of the note after 200 (or so) characters within the newly created note. Up ’til now, I hadn’t noticed that I’d lost significant content on some of these notes that were created when I pasted long quotations into Apple Notes.

Fortunately, even at this late time, I can remediate the problem by going into Apple Notes, changing the title of these notes to something shorter, and re-running the Obsidian Importer plugin for that folder. It cleverly uses the Apple Note opaque ID to decide whether to update or create a note. I then had to delete the long-named files manually on the WEBDAV server filesystem, and re-sync.

It worked! Now the files sync correctly to Linux as well.

Again, I’ll report back here if I have any new conclusions.

Thu, 17 Sep 2026

Notes, and Replacing Proprietary Services

— SjG @ 12:31 pm

I’ve gone through a lot of notes apps in my time. I’ve used SimpleNotes, Joplin, Obsidian, and Apple Notes. My requirements are relatively simple: notes must be fast and easy to enter, I need to be able to search through them expeditiously, I need to be able to organize them by nested folder structure (e.g., work > meetings > clientX), I need to be able to edit them offline, and I need them to sync between my desktop (MacOS) and my phone (iOS). I need them to be encrypted if the notes are sitting on someone else’s server.

There are a bunch of other features I’d really like to have too: ordinary text files, easily exportable to a portable format (pure text ideally, markdown acceptable, Word or PDF as a last resort), local encryption or password protection of notes, versioning. I’d like the program to be free or a one-time payment; I don’t want to be stuck with yet another subscription. Other ideal-but-not-absolutely-necessary features would be scriptability, support for “to-do” style lists, F/OSS.

For various reasons, every year or two, I get frustrated with the note program I’m using, and painfully switch. Most recently, I went from Obsidian to Apple Notes.

Apple, however, has been annoying me. They’re stuffing AI and “Apple Intelligence” into everything, and I’m old, and cranky, and believe in the benefits of human creation, and I just don’t want it. I want a platform that respects my wishes rather than tells me what’s best for me. I know, I know, Apple has always had their own opinion of what I wanted, but for many years it was close enough that I was willing to go with it. But the mandatory AI is crossing the Rubicon.

Despite the fact that Linux ecosystem source code is now widely being written using AI, I still have the ability to turn it off on the user side. But if I switch to a Linux desktop, I have a new requirement for my notes: they need to be cross platform. (Also, dunno what I can do about switching to a non-AI-ridden phone. Maybe it’s time for a dumb phone.)

Anyway, I’m moving back towards Obsidian.

I’ve always used a shared filesystem approach to syncing Obsidian: my “vault” was stored on in an iCloud directory. This isn’t perfect, but works so long as I’m careful not to edit on two devices at the same time or the same note when devices are offline. However, if I go cross-platform, iCloud will no longer be viable. I could probably move to Dropbox — there are clients available for Linux. The Obsidian app on the iPhone can access that through additional plugins, but then I’m beholden to yet another 3rd party service. Maybe it’s time to install my own file-share/sync.

I’m currently working on setting up a VPS with Seafile. If all goes well, I can try syncing Obsidian across platforms using this Seafile community server instance and the Seafile-sync plugin. I’ll report back here if I get anywhere.

Wed, 5 Aug 2026

Diagnosing Weird Thingino Errors

— SjG @ 1:58 pm

Well, just a few months into using a Thingino-flashed WyzeCam3, I noticed that one of the units had stopped responding.

I could see it connecting to the network (or at least taking a DHCP lease from the router), but all connection attempts failed. The LED was lit, but I couldn’t tell what it was doing. I shut it down, and checked the SD Card — the last motion it had captured was from fifteen hours ago, although there was plenty of room left on the card. Something was weird.

I powered it back up, confirmed that it was connecting to the network, and checked to see if it was actually offering any network services. This was where things got weirder:

#nmap -Pn 192.168.x.x
Starting Nmap 7.99 ( https://nmap.org ) at 2026-08-05 08:49
Nmap scan report for MuhCam.lan (192.168.x.x)
Host is up (0.051s latency).
Not shown: 999 filtered tcp ports (no-response)
PORT   STATE SERVICE
53/udp open  ssh

Nmap done: 1 IP address (1 host up) scanned in 11.03 seconds

Say what!? Running sshd with UDP listening on the DNS port!? I’ve seen strange configurations in my time, but I haven’t seen that. Also, trying to ssh to that port didn’t work.

The fact that it connected to WiFi told me that it was mostly booting, but this made me think there was some corruption in the config files. It made no sense.

I was getting ready to open it up and see if there was a way I could hook up to a serial console or some other desperate measure, when I saw it flash the IR LEDs briefly, but not very brightly. This roused suspicion. Out of curiosity, I swapped the USB cable that it uses for power. Slightly different results now:

-Pn 192.168.x.x
Starting Nmap 7.99 ( https://nmap.org ) at 2026-08-05 09:14
Nmap scan report for MuhCam.lan (192.168.x.x)
Host is up (0.029s latency).
Not shown: 999 filtered tcp ports (no-response)
PORT STATE SERVICE
123/udp open ssh

Nmap done: 1 IP address (1 host up) scanned in 10.19 seconds

OK, so now it says that sshd is listening on the NTP port? So whatever was corrupting the config files was not a one-time thing. Was it filesystem issues? Memory corruption? Failing hardware?

I thought Id’ try one more thing. I unplugged it, and plugged the original USB cable into a different A/C adapter.

What do you know? It came up cleanly, with the configuration intact! It was the power supply!

For the record, the normal nmap output looks more like:

#nmap -Pn 192.168.x.x            
Starting Nmap 7.99 ( https://nmap.org ) at 2026-08-05 09:27
Nmap scan report for MuhCam.lan (192.168.x.x)
Host is up (0.0053s latency).
Not shown: 994 closed tcp ports (conn-refused)
PORT     STATE SERVICE
22/tcp   open  ssh
53/tcp   open  domain
80/tcp   open  http
443/tcp  open  https
554/tcp  open  rtsp
8080/tcp open  http-proxy

Nmap done: 1 IP address (1 host up) scanned in 1.72 seconds

Fri, 26 Jun 2026

Setting up a WyzeCam3 as a Stand-alone Unit with Thingino

— SjG @ 10:45 am

The WyzeCam3 is a relatively cheap device that can capture video. It can be set up for motion capture or continuous recording. But even if you install a memory card in the device, it will want to use the company’s app and stream data via their cloud storage. I don’t know much about how much thought went into their codebase with regard to security, but this is the kind of device where the usual answer is “not much.”

Furthermore, the WyzeCam requires an app for installation and configuration, and the WyzeCam3 needs to connect to your 2.4GHz WiFi network. Oops. I have no 2.4GHz WiFi network. It’s all 5Ghz here. Now what?

Enter Thingino, an open-source replacement firmware. One nice feature is that it allows the camera hardware to enable an Wi-Fi access point (“AP mode”) — it creates its own 2.4GHz WiFi network, which my Mac will happily connect to! Once the camera is set up, I can further customize things, and have it write motion capture files to the SD memory card rather than someone’s cloud.

You’re being watched…

So, there’re a few gotchas that were not obvious to me:

  1. When you’ve downloaded the firmware, you need to use something to flash it as an image on your micro-SD (e.g., Balena Etcher, Rufus, or the like). I came across at least one guide that said “simply copy the files onto the SD card” which is incorrect!
  2. When the Thingino installation has completed, you connect to the WiFi network it creates. A captive portal form pops up for basic configuration. You’re asked to provide a device name, a root password, and a WiFi SSID and password. There’s also a checkbox to have the camera create its own WiFi hot-spot (the aforementioned AP mode). If you’re going to have it work in AP mode, the SSID and password you provided above are used for the network it creates. If you are not, it will use those to connect to an existing network. Don’t make the mistake of giving the SSID and credentials for your existing network and then checking that checkbox!
  3. Once you’ve installed Thingino via the SD card and you’ve connected to the network admin, you might want to set up motion capture to “Storage.” You’re gonna have to reformat that SD card first! The UI won’t complain, or tell you why it’s not working, but it just won’t let you submit the form. Thingino recommends formatting in exFAT.
  4. Even if you’ve configured the “Motion” panel, you have to click on the Storage link and tell it that you really mean the storage mounted at /mnt/mmcblk0p1 (or the mountpoint for your SD card ). You can have motion sensing and capture enabled, but it will fail if you haven’t taken that step.
  5. You may need to go into storage manager to tell it how to clear off space before you can enable motion capture. The control panel for motion capture does not seem consistent.
  6. Even after all that, the motion capture details may not save correctly. At least the firmware version I downloaded, it just wouldn’t save the settings consistently. There is a workaround! You have to ssh in to the camera, and set the values:
    Enable motion detection
    jct /etc/prudynt.json set motion.enabled true
    jct /etc/prudynt.json set motion.send2storage true
    Configure the storage destination
    jct /etc/send2.json set storage.mount /mnt/mmcblk0p1
    jct /etc/send2.json set storage.send_video true
    Set motion sensitivity, range is 1-8, default is 1. Higher = more sensitive
    jct /etc/prudynt.json set motion.sensitivity 5
    Configure clip length (in seconds)
    jct /etc/prudynt.json set motion.video_length 15
    Restart prudynt
    /etc/init.d/S31prudynt restart
  7. If you want to restore the original WyzeCam firmware, the instructions say to copy the original config files that get backed up by the Thingino install into the root directory of the SD card, name the file autoupgrade-full.bin, and then power it up. Oh, did you have that SD card formatted in exFAT? Ha ha, the firmware replacement process requires the SD card to be formatted FAT32 with Master Boot Record (MBR). The failure mode for this is somewhat opaque — it does seem to do something, and then in my case it announced it was ready for setup… in Italian. It was not ready for setup, though, as it hadn’t replaced the firmware.

Other Problems:

  1. There’s no way to have the device do its own time management without a network (NTP). You can set the clock (ssh in, use the “date” command in BusyBox) but it doesn’t survive power-cycles.
  2. I set up an isolated 2.4GHz guest network for the cameras that only allows DNS and NTP traffic to/from the internet. Then I went to reconfigure the cameras to use that network. From the admin panel, when I changed the network settings and turned off the “create AP,” it never seemed to connect. I had to reflash to the original firmware and then reinstall Thingino.

Other notes:

  1. If you set up the Thingino camera with an AP network, it defaults to the IP address 100.64.1.1