Pets, Plants, and Computer Vision
Header

Simple Steganography

February 16th, 2013 | Posted by admin in code | computer vision | demo | Fun! | pics or it didn't happen | steganography - (Comments Off on Simple Steganography)

I had a moment to play with steganography while I was watching tv tonight. Steganography is a way of encoding text messages inside image files in such a way that they don’t alter the original image content. I came across this nice little tutorial using the stepic python library. I was able to get Stepic working with and hooked into SimpleCV with only a little bit of massaging (needed to turn SimpleCV Image to a PIL Image and back again). Here is the actual commit.

The Source Image

The Source Image

 

 

The encoded Image.

This dinosaur has an encoded message, can you find it?.

I wrote a little bit of code to test my work and to see if I could tease out the algorithm. Basically all I did was encode a message, in this case the wikipedia entry on stegosaurs, into an image and then subtracted that image from the original imaage to create a diff. To the naked eye both the source image and the encoded image look the same. The diff also looks as it should, that is to say all black. To dig a bit deeper I applied a histogram equalization function to stretch out the images’s dynamic range. Bingo, the encoding scheme is clearly visible.

from SimpleCV import *
img = Image('stega.jpg')
msg = "Stegosaurus is a genus of armored stegosaurid dinosaur. They lived during the Late Jurassic period (Kimmeridgian to early Tithonian), some 155 to 150 million years ago in what is now western North America. In 2006, a specimen of Stegosaurus was announced from Portugal, showing that they were present in Europe as well.[2] Due to its distinctive tail spikes and plates, Stegosaurus is one of the most recognizable dinosaurs. At least three species have been identified in the upper Morrison Formation and are known from the remains of about 80 individuals.[3]A large, heavily built, herbivorous quadruped, Stegosaurus had a distinctive and unusual posture, with a heavily rounded back, short forelimbs, head held low to the ground and a stiffened tail held high in the air. Its array of plates and spikes has been the subject of much speculation. The spikes were most likely used for defense, while the plates have also been proposed as a defensive mechanism, as well as having display and thermoregulatory functions. Stegosaurus had a relatively low brain-to-body mass ratio. It had a short neck and small head, meaning it most likely ate low-lying bushes and shrubs. It was the largest of all the stegosaurians (bigger than genera such as Kentrosaurus and Huayangosaurus) and, although roughly bus-sized, it nonetheless shared many anatomical features (including the tail spines and plates) with the other stegosaurian genera.The quadrupedal Stegosaurus is one of the most easily identifiable dinosaur genera, due to the distinctive double row of kite-shaped plates rising vertically along the rounded back and the two pairs of long spikes extending horizontally near the end of the tail. Although large animals at up to 9 metres (30 ft) in length,[4] the various species of Stegosaurus were dwarfed by their contemporaries, the giant sauropods. Some form of armor appears to have been necessary, as Stegosaurus species coexisted with large predatory theropod dinosaurs, such as Allosaurus and Ceratosaurus.The hind feet each had three short toes, while each forefoot had five toes; only the inner two toes had a blunt hoof. All four limbs were supported by pads behind the toes.[5] The forelimbs were much shorter than the stocky hindlimbs, which resulted in an unusual posture. The tail appears to have been held well clear of the ground, while the head of Stegosaurus was positioned relatively low down, probably no higher than 1 meter (3.3 ft) above the ground.[6] The long and narrow skull was small in proportion to the body. It had a small antorbital fenestra, the hole between the nose and eye common to most archosaurs, including modern birds, though lost in extant crocodylians. The skull's low position suggests that Stegosaurus may have been a browser of low-growing vegetation. This interpretation is supported by the absence of front teeth and their replacement by a horny beak or rhamphotheca. Stegosaurian teeth were small, triangular and flat; wear facets show that they did grind their food. The inset placement in the jaws suggests that Stegosaurus had cheeks to keep food in their mouths while they chewed.[7] Despite the animal's overall size, the braincase of Stegosaurus was small, being no larger than that of a dog. A well-preserved Stegosaurus braincase allowed Othniel Charles Marsh to obtain in the 1880s a cast of the brain cavity or endocast of the animal, which gave an indication of the brain size. The endocast showed that the brain was indeed very small, maybe the smallest among the dinosaurs. The fact that an animal weighing over 4.5 metric tons (5 short tons) could have a brain of no more than 80 grams (2.8 oz) contributed to the popular old idea that dinosaurs were unintelligent, an idea now largely rejected.[8]Most of the information known about Stegosaurus comes from the remains of mature animals; however more recently juvenile remains of Stegosaurus have been found. One sub-adult specimen, discovered in 1994 in Wyoming, is 4.6 meters (15 ft) long and 2 meters (7 ft) high, and is estimated to have weighed 2.3 metric tons (2.6 short tons) while alive. It is on display in the University of Wyoming Geological Museum.[9] Even smaller skeletons, 210 centimeters (6.9 ft) long and 80 centimeters (2.6 ft) tall at the back, are on display at the Denver Museum of Nature & Science."
img2 = img.stegaEncode(msg)
img2.save("test.png")
img3 = Image('test.png')
img3.show()
temp = img2.stegaDecode()
print temp
diff = img-img3
diff.save("diff.png")
diff.equalize().save('morediff.png')

The pixelwise difference between the source and encoded image.

The pixelwise difference between the source and encoded image.

The difference between the source and encode information using an equalize operation.

The difference between the source and encode information using an equalize operation.

The next step is to look at the individual color channels to see if they are holding on to any information. I could look at the actual algorithm in the source, but that would be no fun. It would be interesting to see if I could build a heuristic for determining which images have encoded data. I would also be useful to add AES encryption to the encode/decode calls in SimpleCV.

As a side note I tried to decode my image using this on-line utility but I had no luck. My guess is there are incompatibilities between the stable 0.3 release of the stepic library and the development 0.4 release that might be on the utility.

Crawl, Walk, Drive

February 14th, 2013 | Posted by admin in Ann Arbor | automation | Automation Alley | C++ | code | demo | FIRST | Maker Works | pics or it didn't happen | robots - (Comments Off on Crawl, Walk, Drive)

We finally got the FIRST Team 830 drive train up an running. We still have a lot of hardware to attach, but this is a good start. currently the control system and battery are just loosely attached with cable ties. This will change once we get the final build-out of the pickup and firing mechanism. We have yet to test the pneumatic gear shifters or a PID controller so in these videos the robot is in low gear and capped at seventy percent power.

This is the first run of the robot.

Once we got used to the control I slipped my cell-phone in a spare cRIO slot and got some video.

I have a few screen captures of our current design that gives the programming team a better idea of what other subsystems we need to code and design controls for. Unfortunately I don’t have a nice overview image of the final cad design.

Slight Overview

Disc Shooter

Pickup

Drive Train

Elevator

I have a few screen captures of our current design that gives the programming team a better idea of what other subsystems we need to code and design controls for. Unfortunately I don’t have a nice overview image of the final cad design.

We are down to the final week before bag and tag. Hopefully I will have more cool videos soon.

FRC 830 Drive Train First Run

February 10th, 2013 | Posted by admin in Ann Arbor | automation | Automation Alley | code | demo | FIRST | Maker Works | Michigan | pics or it didn't happen | robots - (Comments Off on FRC 830 Drive Train First Run)

It took a lot of work, but we finally have a working drive train and shooter. Now we just need to put the two together, add the pickup mechanism, and we are ready for competition.

Perler Bead Project

July 2nd, 2012 | Posted by admin in code | computer vision | domestic life | Fun! | Uncategorized - (Comments Off on Perler Bead Project)

So I had to run to Jo-Ann fabric for a few odds and ends. My Mom gave me a couple of 50% off coupons and on a whim I purchased some perler beads and a tray for about $10. Perler beads are this kids craft where you patiently place little plastic beads on tray and then fuse them using an iron to create various toys. I am pretty sure that the beads themselves are just a ruse by the vacuum cleaner companies to sell more powerful vacuums.

Perler Beads

Perler Bead Set

I wanted to see if I could use SimpleCV to map images to  pearler bead colors to create little coasters from my photos. I took the beads and created a square calibration grid so I could pull out the colors. I then quantized the image to a palette and saved the results.

This is what the calibration grid looks like when I quantize it to have 16 colors (note that this result is not repeatable because of the k-means calculation’s initial conditions).

To test my approach I used an input image (in this case Lena), pixelized the image to match the perler bead grid, and then re-applied the quantization to the pixelized image. The results are not that great.

Image pipeline, input, pixelized image (17×17 block size), and quantized result.

There are about five colors in the output image and it seems to lose a lot of its information. I did some digging and found that two things seem to be going on. First, the quantization step seems to have some bad initial conditions. This is to say that I take the image and try to cluster the colors in it into 16 groups using k-means. If the algorithm starts with a bad initial condition a lot of the clusters “run into one another” and I end up with less than 16 color groups. The other problem is subtler and has to do with image dithering. I anticipated that this might be a problem because gif images also use a quantized color palette (for gifs it is 256 colors) to compress the image size. Back in the old days of the web you would use a technique called dithering as part of your gif compression algorithms to make photographs look more realistic. Generally dithering is used to lessen the effect of quantization error around gradients. To illustrate this I found an image on wikipedia with a lot of colors and color gradients, here is what would come out of the naive SimpleCV quantization (top is input, bottom is output using img.palettize(bins=256)):

Quantization makes things look weird. The top is the input image and the bottom is the image quantized to only have 256 colors (just like a normal GIF image).

Now here is the same result using ImageMagick with GIF dithering turned on (specifically the command: convert test.jpg -dither Riemersma -colors 256 test.gif).

Still 256 colors, but the dithering makes the gradients around the lights less apparent.

As you can see the dithered images look way better. The effect seems to hold even when I shrink the number of colors down to 16 but still use dithering. In the two images below the top is the output from SimpleCV quantizing to 16 colors, while the bottom is ImageMagick result with added dithering (note that there may be some re-compression artifacts from when I saved the image).

Top is SimpleCV’s output when I quantize the image to have 16 colors, while the bottom image is ImageMagicks results with 16 colors and dithering.

Hopefully in the next week or two I can read up on dithering algorithms and see if I can’t add a few to SimpleCV.