More on recognizing Magic cards

Computer vision is hard.

I have code written that detects edges in a video image, picks pairs of edges that are both within a certain ratio of lengths relative to each other and within a specific angle of each other. I’ll post the code up once I have pushing to my github account set up correctly. It’s actually pretty poor at locating cards in a video image, but it is a demo of how to use some of the UI and feature recognition stuff from OpenCV.

From here, I have a few ideas about how to proceed. The first is to have the program display a rectangle and ask the user to align the card to that rectangle. This means the program will not have to find the card in the image, and can focus on recognizing parts of the image. This will use template-based recognition to pick out mana symbols, and should be pretty simple. The classifier that tries to pick out colors will be even easier, as it will just select a sample region, blur it, and match it to precomputed colors. This can be calibrated for specific lighting conditions for each run.

An even less hands-on approach was suggested by my co-worker Eric. The cards could be displayed by a machine that essentially deals one card at a time. The machine would have a magazine of cards, and would photograph a card, deal it into a hopper, photograph the next card, and so forth, until it was empty. This would have the problem that it wouldn’t be something anyone could download and use, as it would require a special card-handling machine, but the software end would be compatible with the user-based registration approach described above, so someone with a lot of patience could use the manual method.

Another approach would be to throw all the cards on a flatbed scanner (possibly with a funny-colored (e.g. red) bed lid, do template matching to locate card borders, and then segment the images based on that. An ADF scanner with a business card attachment could probably also make short work of a modestly-sized set of cards.

Magic Card Recognizer

I used to play the collectible card game (CCG) Magic:The Gathering. Like most CCGs, Magic has a large set of different cards that players can use to build a set for playing games. This is both fun, as it means new cards will allow new play types and strategies, and annoying because of the artificial rarity of some of the cards. I don’t have a lot of people to play with, so I am planning to sell my cards.

I will probably make more money selling the cards as individual cards (“singles”) than I would get by selling the whole set. However, that means that I need to know how many of each card I have. Given that I probably have upwards of 8,000 cards, I don’t want to sit down and type in the name of each card. It would be better if I could have a computer program do it for me, so I’m working on writing one. The rest of this article uses jargon from Magic and computer vision, so it may be a little incomprehensible to people who are not Magic-playing computer vision nerds.

The program will take an image using a web cam and look for two straight edges, probably using some form of edge detection or a Hough transform. Once it has the edges, it will look for two edges whose ratio of lengths is the same as a Magic card. The edges must share an endpoint, so that the system can tell they are the edges of the same object. The area inside the rectangle that has those lines as its edges is the card.

Once the card is detected, the simplest thing to do is to match the card image against card images stored in a massive database of all card images. Unfortunately, there are over 11,000 unique cards (11,458 as of Feb 2009), which would make for a processor-intensive comparison process.

My plan to circumvent this is to have the program get the casting cost of the card by using processing techniques similar to face detection. The most useful technology to detect mana symbols is probably feature-based template matching. Feature-based template matching allows the computer to pick out a region of a picture that matches another, smaller image, even in the presence of some distortion. Mana symbols haven’t changed significantly since the development of the game, so they should be easy to pick out.

I can also get the color of the card by selecting a region of border, blurring it to remove any texture, and comparing the color to a set of swatches. I’ve done this sort of comparison before, by measuring distance in RGB color space, and it can be done quickly and effectively. The main possible pitfall is poor lighting shifting the color of the object, but I can at least arrive at a probabilistic result based on the RGB distance. Combining the estimated color of the card and the casting cost will allow me to significantly reduce the set of possible pictures that the card image needs to be matched against.

There is also the question of building the database of card images, but I believe I can do that by screen-scraping the web site of the company that makes Magic Cards. I won’t be able to distribute the database with my program, as it will contain copies of copyrighted data, but I can distribute the screen-scraping script.

I may also be able to recognize features like card text, but that will rely on very good lighting and very good cameras. I would prefer that this program work with a moderately high-quality webcam, so that it will be useful to people other than me.

The recognizer will try to build a list of cards that it thinks matches, ordered by the confidence of the match. If the user rejects the first card, it will present the next, until it runs out of guesses. If the use accepts the guess, the recognizer will add that card to a database of all the cards the user owns. In this manner, the user can build a database of cards by simply showing the cards to a computer.


There are a few DIY plasma cutter plans floating around the Internet. Most of them are napkin-sketches that someone scanned and put on a forum for experienced welders to blanch at.

A rough schematic of a plasma cutter
Don't try this at home

This has a few issues. The main one is that it’s not properly isolated from the AC mains. An isolation transformer can provide that isolation, and can be improvised from two identical transformers back-to-back, with their secondaries connected. That will act as a 1:1 transformer, but instead of having a conductive path from the input to the output, the power is passed by induction.

I am making a plasma cutter with a pair of isolation transformers made from microwave oven transformers. I chose microwave oven transformers because I can get them for cheap or free, and they can handle a lot of power.

After I wire up my variac, I’m going to test the power supply. Assuming all goes well with the test, I’ll look into getting a plasma torch head off Ebay or from Harbor Freight, and finish the assembly with a borrowed or improvised air compressor.

Cracking Captchas

Captchas are those distorted snippets of text that some web sites use to try to prevent spammers and bots from automatically registering accounts. The idea is that a human can read the words, but a computer cannot, and so only a human can fill out the text box correctly.

However, it’s probably possible to get humans to crack the captcha for fun. Imagine a “missile defense” typing tutor and game, where each incoming missile is a captcha text. If you type the text, it goes away. Since the game can’t tell what the texts are to begin, it would send the same word to multiple players and only block the “incoming missile” when multiple players typed in the same thing. From that, it could build a massive database of images and corresponding text, which could then be used to register accounts. Alternatively, someone who wants to crack a captcha could submit it to a server, which would then include that captcha in all the currently-running games and reply with the text when several people typed the same thing.

Fixing Firefox's colors

If you are running Ubuntu with a dark theme and Firefox, you may have noticed that some text entry areas are too light to read. This is because a web developer only set the background and not the foreground color of the text area. When this happens, Firefox picks up the webpage’s background (likely white or something light), and the window manager theme’s text color (likely also white or something light in a dark theme). This means you get stuck reading light grey on white text. The fix is to put:


in your userContent.css file. That file may not exist yet, but you can create it in:


And the next time Firefox starts up, it will use this code to color all inputs, textareas, and select boxes as white with black text.

I still don’t have a fix for all the buttons getting dark text on dark backgrounds.

Sprint cell phone codes

These are codes for doing a lot of random things to Sprint phones. I have an LG Lotus, and have been poking around in these service menus a bit. Unfortunately, I don’t have any way to get the MSL of a phone. I only have my MSL because I got my phone online, and they give you the MSL to register it.

I got the codes from this very useful thread.

##2342# (##CDG2#) CDG2 Menu (NAI setting here). Requires MSL.
##2539# (##AKEY#) AKey Menu. Requires MSL to Edit.
##2739# (##BREW#) BREW Software Menu. Requires MSL.
##2769737# (##BROWSER#) Browser Settings, also available under ##DATA#
##3282# (##DATA#) Power Vision Program. Requires MSL to Edit.
##33284# (##DEBUG#) Debugging Menu. Requires MSL.
##7738# (##PREV#) MOB_P_PREV (P_REV Prefs). Requires MSL.
##786# (##RTM#) Life Timers & Memory Reset. Requires MSL.
##8626337# (##VOCODER#) Vocoder Settings. Requires MSL to Edit.
##889# (##TTY#) TTY Menu (Same as Menu > Settings > More > Accessibility > TTY)
##XXXXXX# (MSL Code) Replace the 6 X with your MSL, offers SVC menu to change NAM and MSID

Turned off commenting

I’ve turned off commenting on this blog, because it only got spam. Drop me a line on twitter if you want to chat.

Gstreamer and the Logitech Pro 9000

This is a gstreamer pipeline that takes frames from a UVC camera on /dev/video0 and displays them on the screen, while simultaneously saving one frame per second to a file. In other words, it’s a single-command-line surveillance camera.

gst-launch v4l2src device=/dev/video0 ! ffmpegcolorspace ! video/x-raw-rgb,width=640,height=480 ! identity name=artoolkit ! tee name="logger" ! queue ! ximagesink sync=false logger. ! queue ! videorate ! video/x-raw-rgb,framerate=1/1 ! ffmpegcolorspace! pngenc snapshot=false ! multifilesink location="frame%05d.png"

Obviously, the camera can be set up to display in different resolutions, and save to differently named files. The next one expands the length of the section of the filename that changes to 8 digits, enough for one picture every second for 3.16 years. I also reorganized the order of the parameters so that ARToolkit can work with the data stream and do augmented reality stuff to it.

export ARTOOLKIT_CONFIG="v4l2src device=/dev/video0 ! tee name=logger ! queue ! ffmpegcolorspace ! video/x-raw-rgb,width=640,height=480 ! identity name=artoolkit ! fakesink sync=false logger. ! queue ! videorate ! video/x-raw-rgb,framerate=1/1 ! ffmpegcolorspace ! pngenc snapshot=false ! multifilesink location=frame%08d.png"

Cat Ear Code

This is the Arduino code for running the cat person ears. The circuit was simply three switches, one for each paw and one for the petting sensor, and a pair of servos. The code just checks each sensor and moves the corresponding ear.

#include <Servo.h>

//Servo pins
#define rightpaw 6
#define leftpaw 7
#define pet_sense 8

//Ear positions
#define r_up 95
#define r_down 160
#define l_up 180-r_up
#define l_down 180-r_down

Servo leftear;  // create servo object to control a servo
Servo rightear;

int pos = 0;    // variable to store the servo position

void setup()
  leftear.attach(9);  // attach the ear servos

  pinMode(7, INPUT);


void loop()
  if(digitalRead(rightpaw) == HIGH)

  if(digitalRead(leftpaw) == HIGH)

  if(digitalRead(pet_sense) == HIGH)

Flaws with the original cat ears

My first version of the cat ears for people had these problems:

  • The servos are not as powerful as I would like, so they don’t move the ears as far down as I wanted.
  • The petting sensor on the headband between the ears was an afterthought, so instead of one cable leading from the headband to the controls, there are two.
  • The paw cables snap to the gloves with normal clothing snaps. If you dance like a spaz, they will get unsnapped.
  • The palm material of the gloves is insufficiently stretchy. This puts a bunch of load on the seams and, given time or big beefy hands, might cause the seams to fail.
  • The cable between the controller board and the gloves and hands has a non-locking, non-polarized connector in the middle of it. It is possible for this to get unplugged and then put back together backwards.
  • The cables are all absurdly long. It would fit me better if I was nine feet tall.
  • I’m not terribly pleased with the construction of the ears, particularly where the ear lining meets the headband.

I’ll be posting a bunch of links to the techniques used in making the ears and the code soon. It won’t be a full write-up of the process, but it will be enough pointers for someone who wants their own set of ears to do it fairly quickly.

If you can’t sew, solder, and operate simple hand tools, you may want to get a friend to help, but then you can make two sets, and bat your ears at each other.