Hayden Walker (www.haywalk.ca), 2022-04-17. CC-BY-3.0
I had an idea in the car yesterday: What would happen if you treated colours as three-dimensional vectors, with red, green, and blue values as entries? Then, what would happen if you took an image, got the colour vectors for each pixel, applied some linear transformation to them, and then used the resulting vectors as the colours for pixels in a new image?
I thought this was an interesting idea, so I wrote some software in Java that takes in an image file and a matrix and does exactly that. I don't know if there are any practical applications for this, but I thought it was neat, and the results are some cool-looking images.
If you're interested in trying this out, the code for my little program is available on my GitHub.
This is the original image, on which all the transformations were performed. I got it from Wikimedia Commons and it is licenced under the CC0 license (it is in the public domain).
Multiplying an n-dimensional vector by the n*n Identity Matrix gives the same vector back. The Identity Matrix is:
1 | 0 | 0 |
0 | 1 | 0 |
0 | 0 | 1 |
And as expected, the resulting image is the same as the original:
Multiplying an n-dimensional vector by the n*n Zero Matrix gives back the n-dimensional Zero Vector. The Zero Matrix is:
0 | 0 | 0 |
0 | 0 | 0 |
0 | 0 | 0 |
As you might expect, it makes the whole image black:
Each column in the matrix represents one of red, green, or blue. If we want to isolate one colour, for example, red, we can multiply the image by a matrix like this:
1 | 0 | 0 |
0 | 0 | 0 |
0 | 0 | 0 |
By doing this, we remove all non-red pixels:
We can also isolate green with the matrix:
0 | 0 | 0 |
0 | 1 | 0 |
0 | 0 | 0 |
Which results in:
Similarly for blue:
0 | 0 | 0 |
0 | 0 | 0 |
0 | 0 | 1 |
Giving:
We can also multiply images by colours and get something like a filter, using the below matrix for a colour (R, G, B):
R/255 | 0 | 0 |
0 | G/255 | 0 |
0 | 0 | B/255 |
To apply a yellow filter, which is (255, 255, 0), we can multiply by:
1 | 0 | 0 |
0 | 1 | 0 |
0 | 0 | 0 |
And get:
Or for pink, which is (255, 192, 203):
1 | 0 | 0 |
0 | 0.7529 | 0 |
0 | 0 | 0.7961 |
To get:
The standard matrix for a projection onto the line in the direction of unit vector u is u*u^{T}. So to project vectors onto the line in the direction of (R, G, B), we multiply by the matrix:
1/(r^{2} + g^{2} + g^{2}) * | r^{2} | rg | rb | |
rg | g^{2} | gb | ||
rb | gb | b^{2} |
Where r = R/255, g = G/255, and b = B/255.
If we take the colour aquamarine's RGB vector (127, 255, 212), normalize it, and multiply it by its transpose as in the above formula, the resulting matrix is:
0.1279 | 0.2568 | 0.2135 |
0.2568 | 0.5157 | 0.4288 |
0.2135 | 0.4288 | 0.3564 |
And the result of that matrix being applied to the original image is:
It may be interesting to use a colour from the filter section to see the difference between multiplying the image by a colour and projecting it onto the line in the direction of a colour. Let's use yellow, which is (255, 255, 0). Using the projection formula, the matrix is:
0.5 | 0.5 | 0 |
0.5 | 0.5 | 0 |
0 | 0 | 0 |
And the resulting image is:
If you compare this image to the image in the previous section that was the result of multiplying the original image by yellow, you'll notice that this one is monochromatic and the previous one is not. The projection makes it so that every pixel is a shade of the colour the image was projected onto, instead of simply layering the new colour over the previous colours.
We can use projections from the above section to make images black and white, simply by projecting them onto the line in the direction of the colour white, which is (255, 255, 255).
Plugging (255, 255, 255) into the formula from the last section, the standard matrix is:
0.3333 | 0.3333 | 0.3333 |
0.3333 | 0.3333 | 0.3333 |
0.3333 | 0.3333 | 0.3333 |
And naturally, the result is:
The standard matrix for a rotation about the x-axis (really being the 'red' axis) by angle θ is:
1 | 0 | 0 |
0 | cos θ | –sin θ |
0 | sin θ | cos θ |
So if we rotate each colour vector by π/2 radians about the x-axis, we multiply it by:
1 | 0 | 0 |
0 | 0 | -1 |
0 | 1 | 0 |
And the result is:
Please see the notes section for details about how negative numbers are handled.
The standard matrix for a rotation about the y-axis (the 'green' axis) by angle θ is:
cos θ | 0 | sin θ |
0 | 1 | 0 |
–sin θ | 0 | cos θ |
So to rotate π/2 radians about the green axis, we use:
0 | 0 | 1 |
0 | 1 | 0 |
-1 | 0 | 0 |
And get:
The standard matrix for a rotation about the z-axis (the 'blue' axis) by angle θ is:
cos θ | –sin θ | 0 |
sin θ | cos θ | 0 |
0 | 0 | 1 |
So to rotate π/2 radians about the blue axis, we multiply by:
0 | -1 | 0 |
1 | 0 | 0 |
0 | 0 | 1 |
And the result is:
The 3x3 Pascal matrix is:
1 | 0 | 0 |
1 | 1 | 0 |
1 | 2 | 1 |
When applied to the original image, the result is:
The Matrix of Ones is the matrix with all entries equal to one. The 3x3 Matrix of Ones is:
1 | 1 | 1 |
1 | 1 | 1 |
1 | 1 | 1 |
When applied to the image, the result is:
These are some things my software could do better:
Using this software and the idea of colours as vectors, I've been able to use matrices to apply filters, effects, and distortions to an image. This has been an interesting weekend project and I hope others might also find it interesting, and maybe even useful.
]]>2022-04-08
Just under a week ago, this website at this domain name turned two years old. I've had a website in some form since early 2017, which means I've had a website for over five years, but I've only been self-hosting for the past two. www.haywalk.ca went live on 2020-04-03.
I've overhauled it several times, changing its appearance and structure, adding and removing pages, switching from raw, static HTML to PHP and back, then switching from handwritten HTML to a static site generator and back again. As I write this on 2022-04-08, the entire site is in static, handwritten HTML and each page is a little different.
Despite all the changes, some pages have stayed basically the same in their content. Some of the oldest pages on my site are the page about the computers/software I use, the page about cool lights, and the page about my watch collection. One of the first pages I made was dedicated to my calculator collection, which now has its own dedicated site on a subdomain.
This site has become very important to me. No project or hobby of mine has taught me as much as hosting my own website. When I was younger and browsing the old internet where everyone had their own site, I always wanted one too. Now I have one, and I'm committed to keeping it online, and keeping it simple and document-driven, uncorrupted by the bloat and spyware of other sites online today.
I wish to thank everyone who has visited my site over the past two years, and everyone who has sent me e-mail. I look forward to keeping this site online for years to come.
]]>Mid-2020, I became interested in boardgames, specifically (but not limited to) Euro-style strategy games. Since then I've been picking up interesting games online and from charity shops. Even though my collection is still quite small, I thought I'd catalogue it here since I don't have a spare shelf to display them properly in real life.
This page is specifically dedicated to boardgames, and not other tabletop games like Dungeons & Dragons or trading card games like Magic: The Gathering. I have played both, and if eventually I am sufficiently interested in them, I'll make pages dedicated to each.
I'm Hayden Walker, and I'm the author, webmaster, maintainer, and server administrator for this site. It's a one-man show. If you're interested in a more detailed 'origin story' of sorts, click here. This page is more of a factsheet.
Some things I like include, but are not limited to:
This site is my outlet to publish whatever I want to publish. I use it to talk about things that interest me. But beyond the content I publish here, this site has a certain goal. I wrote this site to be what, in my opinion, is an ideal website. In this document I will talk about why and how I did this.
I think the modern Internet has strayed from its purpose. What was a Wild West of different people's websites hosted on their own servers, each slightly different from the last, is now a walled garden of curated 'content' posted by users to a small number sites all owned by a handful of megacorporations. This site is different, and this document will explain why.
When you visit a website, your computer is connecting to a remote server which then delivers the site back to your local machine. Often, this server is in a warehouse somewhere. But not here – when you visit this site, you're connecting to a credit-card sized Raspberry Pi 4 model B in the basement of my house.
Furthermore, I don't use a CMS (content management system), a static site generator, or any kind of scripting to run this site. When I want to make a change to the site, I edit the raw HTML and CSS on my local machine, and then I connect to the server via SFTP and upload it to my web directory. I don't log into Wordpress, or run a script on a Markdown file to generate HTML – this is a 100% homemade website.
I think web apps definitely have their place, but that place is not on a personal webpage like mine. I don't serve up megabytes of JavaScript or crunch lines and lines of PHP server-side before serving a page – everything on this site is in raw HTML and CSS. I don't even use a common stylesheet.
The most important part of any website is the text content. Thus, most of this site is text. Because that's what matters, not fancy menus and images. I use images when they're relevant to the content, and sometimes for backgrounds, usually semi-ironically, for fun.
]]>
I've decided to redo my website. Previously my site relied on PHP and a bunch of serverside scripts to run. This made it very efficient, but I thought it went against the spirit of running a server out of my basement. I don't want a polished site where every page looks the same – I want something with soul.
So the past couple days, I've been rewriting the whole site in raw HTML and making each page a little different. I've also been making sure to include GIFs and other things that make the Internet fun. This site should be able to be run out of a directory with no scripts, dependencies, or weird server configuration. And it shouldn't be boring.
]]>