Periodically I find a word that I find interesting. I’d call it “Word of the Day” except that I find new words much less frequently than that. I put the most recent one on the main page. Here is the archive of all words that intrigued me so far:
Last time we took an image that displayed a message which would disappear when the image was rendered in grayscale. A much more interesting problem is the opposite one — can we embed a message an in image so that it appears when the image is rendered in grayscale?
It’s not as easy as the first problem — there we had information theory on our side (the conversion to grayscale destroys information as three components — red, green and blue — get converted to just one — intensity). Now we have to get a little more creative (again, you should be able to improve on my proposed algorithm).
Instead of using information theory, we’re going to use psychology: we’re going to trick the brain.
The idea is pretty simple, but it requires us to think in the HSL space: instead of thinking of color as a composite of three primary colors, think of a color as a composite of three properties: its hue (“where on the rainbow the color is”), its saturation (“how vivid the color is”) and its lightness (“how close is the color to white”). Lightness is not quite the same as intensity (because hue and saturation are nonlinear in the red, green and blue components). It turns out that our brain decomposes the colors into their HSL components better than their RGB components (which one of the two colors has a higher R component, this one or this one?). The idea is to encode the message with a color of a lower intensity that compensates for it by having an unusually high lightness.
First, we’ll define a scratchpad — a two-dimensional set of all possible colors of a given intensity I (I used I=0.3 experimentally). The color space is three-dimensional, but if we add one constraint (intensity has to be equal to I) we can map the resulting colors onto a two-dimensional space. We will use the x-coordinate to determine the intensity of the green component and the y-coordinate — of the red component. We would like the pixel color to be uniquely identified by these two values. This is often possible, but if the green and red intensities are outside of certain bounds such a color won’t be possible (for example, consider a pixel whose green and red components are both 0.5 — if you want the pixel to have an intensity of 0.3, the blue component would have to be equal to -1.25).
Hence, we’ll transform the x and y coordinates so that the resulting image is rectangular — that is, for each row, x=0 will map to the smallest value of the green component that makes a color possible, and x=max will map to the largest value of the green components that makes a color possible.
If we didn’t transform the coordinates, the resulting scratchpad would look like this — note the areas that make it impossible to construct a color:
All possible colors of intensity 0.3
Now transform the coordinates (this gets rid of the empty space and expands the rest). Click on the image to cycle through the scratchpad, its lightness map, and its intensity map (the latter should be all homogenous color, equal to I)
An expanded version of the above set of colors
We’ll take advantage of two properties of such a scratchpad: every pixel has the same intensity; and pixels that are close are of similar colors (since the mapping is continuous in the red — as we move up and down the scratchpad — green — as we move left to right — and blue space — because blue is derived from the intensity formula, which is linear).
Now go through the scratchpad and find pixels that have unusually high lightness values and make them darker. By changing the lightness we’ll be changing the intensity of the pixel but because these pixels have high lightness our brain won’t be able to determine the difference in intensities. I use a scaling function with a gamma correction:
if(lightness>I)
lightness = ( ( (lightness-I)/0.35 )^0.8 )*0.2 + I
end
Click on the image to cycle through the scratchpad, its lightness map and its intensity map (this time the latter should have a darker area):
We've altered some pixels to lower their lightness
Now, if you look at the resulting image, you will see that a number of pixels have an intensity different from I but they still look pretty bright (because their lightness is high). We’ll pick either the dark or the bright pixels based on whether we’re encoding the message or the background. We limit the colors we pick to a subset of the scratchpad that features pixel ranges with the highest changes in intensities (that way we can “smuggle” a low-intensity pixel in around similar pixels of a higher intensity).
Secret message embedded using pixels of lower intensity but unusually high lightness
We can stop here — transform the input image the same way we did it last time, by decreasing the variance between white and black and pick a color from the scratchpad that matches the intensity. But this is not good enough (our brain is, after all, smart). Let’s introduce a distraction message that appears faintly in the color version of the image but disappears in the grayscale version (we already know how to do that!). Based on the intensity of the respective pixel in the distraction image we’ll alter the color we picked from the scratchpad without altering its intensity (so as to cause no difference in the grayscale image).
Added a distraction image
We’re done — we’ve successfully tricked our brain (provided that we pick a smart distraction message).
Note that on your computer, you will still be able to see the message in the image above, for two reasons.
Depending on which browser (!) you’re running, your browser may embed color profiles in images to compensate for differences that various computer screens render colors. This, of course, screws our mathematics up somewhat.
If you’re viewing this on an LCD screen (and, let’s face it, you are), you will be able to change the angle from which you look at the screen to reveal the hidden message.
If we print the image out, however, we’ll see the full effect. To fix it so that the message disappears on a computer screen as well, we can simply apply the inverse color profile transformation, or define the region of the scratchpad that we pick pixels from differently.
Enter some short text here:
Enter the distraction text here (ideally same length as the message above):
As I drove home last night I wondered whether the green light I was seeing was really green. It seemed much closer to turquoise than green. I took a picture but the iPhone messed up the colors even more.
I mean, come on. It’s so childish. It doesn’t achieve anything, only added embarrassment for whoever happened to break the glass (which in an overwhelming majority of the cases was an accident anyway).
I already rambled about it, but the fact that our brains react to the most significant figure is just sad. I’ve heard two people conversing the other day, looking at the $19.99 item.
“It’s nineteen dollars, we shouldn’t get it”
“But it’s half the price of the other one ($29.99)”
“I don’t know…”
“What else are you going to spend ten bucks on?”
This is really annoying… when high-defintion versions of TV stations display footage captured in fullscreen (4:3 ratio), they resort to ever more creative (and terrible) ideas, like this effect I recently saw on ESPN — displaying fullscreen in the middle of the widescreen view, and “filling in” the bands on the sides with replicated fragments of the image, like this:
Converting 4:3 to 16:9 with pain
There are so many better ways to solve this problem:
Do nothing. Seriously, there is no reason it’s bad to have bands on either side of the screen. Most people sit so close to the TV screen that the bands are in their peripheral vision anyway
Shoot in HD. That makes the problem go away altogether!
Resize (proportionally) and crop. It gets rid of 25 of the screen, but very likely the very top/bottom part is not that important anyway
Never, ever resize without maintaining aspect. It’s misleading, makes everything look really tall or fat. Especially this kind of conversion that “gradually” expands the screen as you move off of the center. It’s really annoying and results in funky accelerations if any kind of continuous motion is shown on the screen (which is 95% of the time). Like the ticker that slows down as it approaches the edge of the screen (black hole?)
Talking about late adopters… all the TV stations (sports stations in particular) have embraced twitter and integrated it into their newscasts. Often the inclusion of twitter seems forced, as if the station desperately tried to appear “hip” and up-to-date with what’s happening in the world, which often results in misuses of twitter (twitter as a polling mechanism? Really?)
I think it’s much easier to think about the framework you should apply when thinking about your goals and purpose than to actually come up with the purpose. I’ll attempt to provide the framework I came up with. A nice thing about the framework is that it should be independent of one’s values, goals, and purpose — there may still be multiple different frameworks but they should be equivalent; modulo perhaps some things they are trying to optimize for (some framework may try to help you come up with a design more efficiently than some other, for example).
At the most fundamental level, this framework will help us answer a very simple question: “What should I be doing right now?”. We all ask ourselves this question many times (or wish to, but don’t): “Should I be working at my current job or not?”, “Should I buy a house?”, “Perhaps I should be helping poor children in third-world countries…”. We make some decisions but often we’re not sure whether our reasoning for our choices is correct. Ultimately, then, this will be the framework to guide us in making decisions in life.
Let’s start with goals because I think a lot of people viscerally understand what goals are. Goals are not the most concrete item but also not the most abstract (i.e. they influence other things in our life (for example, our actions), but are also shaped by other things), so we’ll have to explore goals in two directions — down (to the more concrete) and up (to the more abstract).
You may have been taught that goals should be SMART — specific, measurable, attainable, realistic, and timely. I’d actually simplify this mnemonic a little and say that a goal needs just one thing: to be measurable (i.e. you have to know when you’ve achieved it). For now I’ll assume that you already have a goal in mind that is measurable. Most likely it doesn’t have a timeline attached to it, and you’re not even sure if you can achieve it (other than a visceral feeling you have). This is fine, we’ll handle all these problems shortly.
The next step is to come up with a way to achieve that goal, a design. This is where art comes in. There is no formula for coming up with great designs. There are some properties that great designs have, however, and your design should also exhibit these properties:
A good design is not sensitive to small changes in the inputs: if you miss some deadline, or if you catch a cold, a good design should be able to withstand it
A good design anticipates any problems you may run into when trying to satisfy your goal
A good design can be iterated upon so that it can be fine-tuned and altered
A good design is modular — it consists of a list of subgoals that connect logically
You should be able to prove that your design satisfies your goal. This is usually hard, which is why having a modular design is a good idea — you should be able to prove at a high level why achieving subgoals X, Y and Z will achieve your goal G. We’ve just replaced our goal with three subgoals and a thin layer of “proof” connecting them all. Each subgoal needs a design, so yes, it may seem like there is much more work to be done, but these subgoals X, Y and Z are now most likely easier to measure (perhaps instead of a binary — “Have I achieved this goal?” — you can come up with a continuous — “How much of this goal have I achieved?” — measure). They may also be more timely (it’s good to get early feedback and if all you have is a binary goal and five years to achieve it, you are risking a big waste of time!) and specific, and, most importantly, they feel much more attainable (because they require less work to fulfill). And so as you come up with your tree of goals, the lower you get, the more SMART each goal gets. Ultimately, then, to fulfill your goal you just need to fulfill each of the “leaf” subgoals (and make sure that your logic for connecting subgoals is correct at each level). If at any point you are unable to come up with a design, you have an unrealistic or unattainable goal and you should alter your design.
Now that you have a design you can start executing on it. But you won’t get perfectly lucky — problems will arise that appear as outcomes in conflict with the outcomes you expected. A very smart man Ray (usually I fake out the initials but I hope he won’t mind me unanonymizing him) taught me a way to use these outcomes to refine the design (in fact, I owe my inspiration for coming up with my framework to him). The idea is simple: observe the outcomes, compare them to the outcomes you expect based on your design, and if the outcomes are in conflict, you have a problem. You can work around the problem, or solve it superficially, but the most effective thing to do is to alter your design based on fundamental, root causes of the problem. For example, if you’re a poor driver and keep smashing into walls, the solution is not to buy you a stronger car; it’s to improve your driving skills. If you alter your design according to the superficial causes, you are likely to encounter more problems that are due to the same fundamental cause.
In fact, in a robust design, you can anticipate all problems, diagnose them and change your design even before you started executing on it!
As you achieve your subgoals, you should make sure that your higher-level design is still correct by re-evaluating whether achieving your subgoals leads to a fulfillment of the overarching goal. It’s possible that your “proof” was weak and you didn’t take into account some inputs that have changed since you originally came up with your design. Or it was insufficient and you actually need to fulfill more than the subgoals you originally came up with.
Hence, assuming you know your goals already, you should be able to successfully execute upon them with a help of a simple design.
Now, to the much more interesting question: how do you come up with your goals?
I’m fascinated by color. When I was younger I dreamt of discovering a color that nobody has ever seen before. And since most computer languages give you easy ways to manipulate graphics, I played with color on a computer.
One day I saw an interesting effect on some certificate I got. When you photocopied it in black and white, a word appeared in the photocopy that wasn’t visible in the original that said “COPY”. In fact, this effect took advantage of the photocopier’s inability to faithfully replicate the document (in this case the word COPY was visible in the original but it was difficult to see because it consisted of a bunch of tiny dots), but I wondered whether it would be possible to hide messages in documents even if the copier were to produce faithful facsimiles.
Specifically, I asked myself, can I come up with a message that is visible on a color version of an image but that disappears on the grayscale version? It turns out that it’s possible, and not that difficult. I’ll explain how, while trying to limit distracting you with color theory to the minimum.
On a computer screen, each color is a mixture of three primary colors, red, green and blue (printers use a slightly different scheme but for all intents and purposes we can limit ourselves to talking about the RGB space). It turns out that pure red does not appear as “bright” to the eye as pure green. In fact, the intensity of a color (how “bright” it appears to the eye regardless of its hue) has been found to be a weighed average of the three primary components:
intensity = 0.299*red + 0.587*green + 0.114*blue
This intensity is precisely what you see when you convert an image to grayscale (note that you may find different formulas depending on what devices you’re dealing with — different devices have different sensitivity to various primary colors). For example, consider the following image and its grayscale version:
Not all colors were created equally bright
(Of course your favorite graphics editing software simply applies the above transformation; to find the precise relation from first principles you can take a picture of the image below with an old-fashioned analog camera on a black-and-white film and find rectangles that match in intensity).
Use this to derive the intensity formula
A simple idea for hiding messages is therefore to produce an image of pixels whose intensity is all the same, but whose hue is different (so that we can see the message in color). For example, we can give every pixel of the message the color of (1, 0.3, 0.4) and every pixel of the background the color of (0.3, 0.7, 0.176). The intensity of the former is 0.52, as is the intensity of the latter. Since the intensities are close to each other, when we desaturate the image, the message will blend with the background.
This works well if we know the relationship for a given device exactly. Some printers (if we wish to print the image out) use a slightly different relationship (or perhaps they round the weights). In such a case the two intensities will not be exactly the same and the eye is surprisingly good at telling the difference between two close colors if they cover large areas! We can improve this algorithm by adding some randomness (this is just a suggestion that works pretty well, you can find much better algorithms!):
Consider an input image that contains the message (white text on black background). Each pixel has an intensity of 0 (if the pixel belongs to the background) or 1 (if the pixel belongs to the text), and probably somewhere in between if the text is antialiased.
The secret message we'll try to hide
First, transform the image by adding some random noise and reducing the variance between white and black:
Once we have the target intensity, we’ll randomly adjust the intensity formula and find an output color such that the intensity formula cancels targetIntensity out:
ratio = (alpha-gamma)/beta
r = 0.44 + targetIntensity/3.0
g = 0.62 - targetIntensity*ratio/3.0
b = 0.9 - targetIntensity/3.0
Convince yourself that the intensity is a constant, independent of targetIntensity. But since targetIntensity varies, the color version of the image will consist of distinctly different pixels.
As a nice touch we can alternate between two different formulas for added noise:
The resulting message that disappears when rendered in grayscale!
Print the above image out in black and white and see the message disappear!
Of course, it would be great if we could write a program that takes a message and displays an image like the one above. Ruby with RMagick makes it very easy: