Add Blog entry
BIN
blog/Idea.png
Normal file
After Width: | Height: | Size: 50 KiB |
BIN
blog/Matrix.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
blog/Weights.png
Normal file
After Width: | Height: | Size: 32 KiB |
79
blog/blog.md
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
# Acknowledgements
|
||||||
|
|
||||||
|
I blame [cqql](https://tech.lgbt/@cqql) for this existing.
|
||||||
|
|
||||||
|
# Disclaimer
|
||||||
|
|
||||||
|
I largely know nothing about this topic and everything you see here is knowledge I gathered myself over the course of an afternoon.
|
||||||
|
|
||||||
|
# The Idea
|
||||||
|
|
||||||
|
|
||||||
|
![hi! :neocat_floof:\nI'm looking for help with programmatic shape retrieval. I need to rank a couple million shapes by how similar each is to a shape given as input. \ndo you know anything about this or anyone that could help me? I'd really appreciate boosts! :blobcatheartR:](Idea.png)
|
||||||
|
This is the post that threw me down this rabbit hole and started it all.
|
||||||
|
|
||||||
|
After doing a bit of searching around, for ways to maybe solve this problem I stumbled on opencv, which also happens to have a python port. Perfect for quickly hacking something together.
|
||||||
|
|
||||||
|
|
||||||
|
# The Process
|
||||||
|
|
||||||
|
First I imported the image as grayscale and let OpenCV find the contours for me. The contours themselves are represented as the points at the edges as seen here:
|
||||||
|
![Edges](edges.png)
|
||||||
|
Which we can trace to form the complete outline as seen here:
|
||||||
|
![Contours](contours.png)
|
||||||
|
|
||||||
|
Next, I had OpenCV compare the different outlines with each other, which I used to build a NxN Matrix of weights.
|
||||||
|
(I love when libraries already do everything for me, especially all the math I wouldn't even know where to start with learning it).
|
||||||
|
Then I just had to pretty print the matrix and that could be considered Task Complete:
|
||||||
|
![Table of Weights](Weights.png)
|
||||||
|
|
||||||
|
|
||||||
|
# There's more
|
||||||
|
|
||||||
|
Now that I've already come this far, why not present the information in a format, that's easy to visually parse?
|
||||||
|
So that's exactly what I did. I stitched together all the source images to form two axis and used the weights I previously got to color in all the squares.
|
||||||
|
(This might sound simple, but this is actually the part, that I needed to write the most code for, turns out transforming weights into a nice looking color matrix isn't as easy as it sounds.)
|
||||||
|
But the result was well worth the effort:
|
||||||
|
![Graphical Matrix](Matrix.png)
|
||||||
|
|
||||||
|
|
||||||
|
# Rotation
|
||||||
|
|
||||||
|
How does it handle rotated shapes? Was the next question thrown my way.
|
||||||
|
Turns out, better and worse than expected at the same time.
|
||||||
|
|
||||||
|
I expected rotation to not perform too well, as you can't perfectly rotate pixellated images. But it also turns out, OpenCV can handle them quite well and the biggest error actually comes from the way rotation is performed.
|
||||||
|
|
||||||
|
To Demonstrate, here we have 45° Rotations of the same object, performed with different Interpolation algorithms with their associated weights.
|
||||||
|
|
||||||
|
### Algorithm #1:
|
||||||
|
|
||||||
|
![Rotation similarities displayed Graphically](rot1.png)
|
||||||
|
![Rotation similarities displayed using weights](rot1w.png)
|
||||||
|
|
||||||
|
### Algorithm #2:
|
||||||
|
|
||||||
|
![Rotation similarities displayed Graphically](rot2.png)
|
||||||
|
![Rotation similarities displayed using weights](rot2w.png)
|
||||||
|
|
||||||
|
The second algorithm seemed to perform more consistantly when using 45° rotations. Sadly, it completely failed with 22.5° rotations (which may be something I could fix, but I've already spent enough time on a "let's just do 10-15 minutes of research" project.)
|
||||||
|
|
||||||
|
|
||||||
|
# Why write this post in the first place?
|
||||||
|
|
||||||
|
There's more pictures here than text, which means fedi isn't the best place to post this with the way it handles pictures. And I really wanted to share the pictures I generated.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Where to find this stuff?
|
||||||
|
|
||||||
|
### Frost Pattern Generator
|
||||||
|
|
||||||
|
I used the Frost Pattern Generator written by cqql for my sample images, as they provide the perfect base for this. Yep, the same person who got me started on this. It can be found here:
|
||||||
|
[https://moonlit.technology/cqql/frost_patterns](https://moonlit.technology/cqql/frost_patterns)
|
||||||
|
|
||||||
|
### My own code for this
|
||||||
|
|
||||||
|
Now, keep in mind, this was quickly hacked together while I was learning how to even do this thing. With this disclaimer, the code can be found here:
|
||||||
|
[https://moonlit.technology/NixLynx/shape_matching](https://moonlit.technology/NixLynx/shape_matching)
|
||||||
|
(Make sure to follow the license)
|
BIN
blog/contours.png
Normal file
After Width: | Height: | Size: 6.3 KiB |
BIN
blog/edges.png
Normal file
After Width: | Height: | Size: 7.9 KiB |
BIN
blog/rot1.png
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
blog/rot1w.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
blog/rot2.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
blog/rot2w.png
Normal file
After Width: | Height: | Size: 15 KiB |