Follow up from my own research: ends up there's no simple solution, should have figured. My options are either to go through the full learned state idea where a library is taught what to look for with examples, or you program it to compare against the sizes of a few basic shapes and nothing more.
This article was the most helpful, and it looks like there's no easy or intuitive solution to this. The closest is...
1. Get convex hull for current shape (like putting a rubber band around it)
2. Compare convex hull to smallest of X shape that would fit around it (circle, then square, then triangle, etc)
3. If areas are almost one to one, they are probably the same shape.
It's pretty good for what it sets out to achieve, but it can't handle interesting shapes that are different, but have similar convex shapes (so ellipses and diamonds are tricky for it).
If I find any better options, I'll report back here, but for now it looks like this isn't a good enough approach, so a library is probably necessary.