Imaging: Programatically Recognizing Art

Sorting images has been a problem on my mind for years, but I never had a really good reason to sink time into it. Just recently, I finally found a reason. It occurred to me that it would be useful to have my webcam recognize magic cards by their art, and add them to a database for collection tracking. I've since learned that this wasn't as new an idea as I'd thought, and several complete software packages for this specific application have become available in the last 6 months. Nevertheless, it was an interesting excursion into image processing, admittedly not my home turf. It worked much better than planned too.

To my mind, the problem had three main tasks that I'd not undertaken before, in order of drastically increasing difficulty:

  1. Grabbing camera input from Python
  2. Isolating the card from the background
  3. Usefully comparing images

The first part was mostly just an exercise in googling it and adapting the code to my webcam. Short version, use OpenCV2's VideoCapture method, and be sure to chuck out a few frames while the camera is auto-focusing and tuning the white balance. The second bit proved to be slightly more interesting. Given a photo of a card on a plain white background, canny edge detection can reliably pull out the edge (though I haven't tried this with white-boarded cards yet). The card-background contour is easily picked it; it has the largest area. Once we've cropped the image down to that, we can isolate the art by knowing the ratios used to layout the cards. This process is shown below.

Original image

Original image



Isolated card

Isolated card

Isolated art

Isolated art

The third and most difficult step, effectively comparing the images, will have to wait until I've got more time to write. Soon!

Music Video Exchange

The CD-exchange group I've been meeting with for several weeks now decided to have a session entirely dedicated to sharing music videos. Given the ease of distribution, we settled on videos available freely online. I've compile the lists into one long YouTube playlist, which only misses out on a single track (Royksopp's "Remind Me", which is on Vimeo). Clocking in at just about two hours, the entire list makes for an interesting and discussion-sparking evening. While Beach House's "Wishes" was the stand-out video, I thoroughly enjoyed all the selections. Feel free to share your thoughts in the comments, or link to your favorite music videos.


Most Likely to Rock - A Metal Overview

Some context is necessary here. Several of my friends have formed a sort of bi-weekly disc exchange program in the spirit of old painfully 90s mix-tapes. Each week we're either exchanging CDs or meeting to discuss the selections we've listened to. It's been fun so far, providing an excuse to discover new music. In addition it's required us to engage in focused listening and critically evaluate what we're hearing before the discussion. Typically they're curated around a broad theme like "travel", but this previous round turned into a genre-focused overview, with each member tackling a genre that they had more familiarity with. I'd gotten it into my head that I knew a decent amount about metal music, so I went with that idea. Various factors collided to delay the next meeting, meaning I had something like six weeks rather than two to compose my disc. This is good, because I discovered that I actually knew very little about metal going into this.

I ended up spending an solid chunk of time just determining when and how various sub-genres of metal evolved, as well as what distinguished them from their siblings. Sites like Map of Metal and Every Noise at Once provided an amazing starting point as well as a shot of motivation for the task. While this did result in a playlist, the more interesting (read: time intensive) products were the liner notes. For each track I wrote up a short paragraph or two about the genre, threw in the album cover, lyrics, and a list of other artists that fall into the same camp. It's worth noting that chronology was used as the organizing principle behind the playlist, so don't expect smooth transitions nor consistent tempos. The tracks were selected with three goals: provide exemplary tracks for the genres, be accessible for an audience who had never been interested in metal before, and above all fit within the 80 minute limit of a CD-R. I dropped a lot of amazing tracks to stay under the limit, and they were painful omissions, but the various metalheads I consulted with eventually agreed that it was a reasonable introduction.

Enough words, here's the goods.

Album Cover

Playlist (Google Docs)
Liner Notes (PDF)

Metal working: Quick thoughts

A few successful furnace cycles have been run, and a handful of lessons have resulted. I was given a whole bunch of machine shop turnings to melt down (13.6 lbs of them) and learned that it takes a little more care than melting cans. Turnings (also called chip) have very large surface area compared to their volume, and their surfaces are saturated with crystal structure defects due to the machining. Taken together this means that they very readily react and oxidize at elevated temperatures. Not thinking about any of that, I went ahead and tossed a bunch of chip into a fresh steel can and fired up the furnace.

Failed Crucible

Steel crucible failed catastrophically

As evidenced in the above photo, this didn't work out great. A second attempt was made later with three thoughts in mind. 1) Allowing the crucible to reach temperature would thicken the protective oxides on the steel that prevent reaction with aluminum, 2) an existing bath of liquid aluminum would prevent rapid oxidation of the aluminum turnings if they could be effectively submerged, and 3) the residual machining oil on the chip might be a contributor to the reaction. After allowing a new crucible to reach temperature, and observing that a foil-and-salt flux packet readily melted into a bead, cans were fed in until a good layer of liquid aluminum was apparent. At that point I was able to feed in foil-wrapped packets of turnings which seemed to melt readily without adverse reaction. I haven't come up with an easy way to remove all the machining oil, but in the short term it doesn't seem to be an issue. It will take me quite a while to melt down all the turnings, as it doesn't look like I can just feed them in non-stop, but there is no shortage of cans.

Metal working: First firings

Before I dive into my weekend's efforts, a quick note on nomenclature (so exciting, I know). I've been misappropriating a few terms as I've gone along, and should clarify. Smelting is extracting metal from ore, and inasmuch as soda cans aren't really "aluminum ore", I'm really just melting things. Also, I may have mistakenly conflated furnace (for melting) with forge (for heating to working temperature).

The first time we fired it up, starting the coals in a borrowed coal starter, the crucible seemed like it just couldn't reach a high enough temperature. After cooling and cleaning I noticed that the foil we'd thrown in as a test had melted, but only partially. Given the amount of time (and fuel) we gave it, this seemed strange. The body and lid of the furnace visibly darkened in color during use, leading me to believe that a good deal of the heat went into driving off residual water in the plaster. The body did have a week to set, but it was very thick and the lid had only set for a few days. A second reason that the aluminum did not melt may have been due to the crucible. As it is made of a silica-based ceramic, it doesn't conduct heat well and is likely better suited to a less directional electrical-element based furnace. Hoping that the initial firing had burned off any residual water, I decided to work on finding a steel crucible as well.

A second (better documented) attempt was made the following day. I thought for a while about where to find a serviceable steel crucible at short notice, and eventually decided to buy a large-mouth can of soup. The soup was tasty, and the can was steel. I've been calling them "tin cans" my entire life, but the magnet doesn't lie. While it looked bad enough after one use for me to throw it out, at a dollar or so a firing it's a reasonable approach in the short term.

Steel "Crucible"

Steel "Crucible"

I gathered together all of the supplies and got a friend over just in case of emergency then started in.

Casting Supplies

Casting Supplies. Left to right: Bag of scrap aluminum, face shield and gloves, crucibles, long steel spoon, tongs, furnace and blower, steel muffin pan, coal starter, fireplace matches, and emergency water.

After dumping the started charcoal into the furnace, placing the crucible and replacing the lid, we turned the blower on and added the flux. For flux I obtained some Morton's Lite Salt, which is half KCl and half NaCl, which lines up well with the recommended flux for aluminum. Rather than pouring it in (the airflow kept tossing it back out), a teaspoon of the salts was folded into a pouch of aluminum foil and dropped in as a packet. After just a few minutes a metallic bead of aluminum was apparent at the bottom of the crucible, so we commenced loading in the scrap aluminum. A few charcoal briquettes were added when the melting slowed down, but far less than were burnt through the first time.

The air exits the furance vent fast enough to juggle bits of aluminum!

Using discarded cans as the sole source of aluminum did generate a lot of dross, as seen piled on the brick in the photo below, though a bit of additional flux tossed in at the end did seem to free it from the liquid. The two lumps of reclaimed aluminum are visible in the muffin tin. They were allowed to cool for about 20 minutes while my friend ran to the grocery for hot dogs and marshmallows, as the coals still had a good deal of heat left in them.

Dross and Ingots

Dross and Ingots

I'm planning on collecting all the supplies and their costs into a table for reference, just in case anyone else is thinking about taking a stab at this but is being held back by cost concerns. The next steps will be to build a mold flask for green sand casting, mixing up some green sand, and picking a few good objects to cast. I've got some ideas already!

Metal working: Background bits

I've got a lot of materials science study behind me, but never really embraced the core activities of metallurgy, namely smelting and casting. It's been on my mind for a while now, but I kept waving it off by reasoning that it would be far too expensive and dangerous to attempt on a residential scale. Recently I've come across a good number of videos and write-ups by people who've undertaken so-called backyard blacksmithing (by no means limited to iron) and the costs of their furnaces have been comparatively cheap. Some are definitely more professional looking than others, to be sure, but they're all a factor of 2-5 cheaper than the comparable commercial models. As for safety, I guess I qualify as "adult supervision", so as long as I keep all precautions in mind, everything will be fine.

So, with a couple aluminum projects in mind, I went about the task of comparing designs based on price, capability, aesthetic (it's silly, but everyone loves a sharp dressed forge), and ease of construction. There were some fun looking designs for electric arc and gas-powered furnaces, but I decided to limit my first foray to a forced-air and wood/charcoal affair. Capability was also an interesting beast, because I hadn't thought about the relative melting temperatures of various metals (excepting outliers like lead, mercury, and tungsten) in many years. I've thrown together a table for quick comparison below.

Metal Symbol(s) Melt (C) Melt (F)
Tin Sn 232 450
Lead Pb 327 621
Zinc Zn 419 786
Aluminum Al 659 1218
Magnesium Mg 670 1240
Brass (85 Cu 15 Zn) Cu+Zn 920 1688
Bronze (90 Cu 10 Sn) Cu+Sn 925 1197
Silver Ag 961 1762
Gold Au 1063 1946
Copper Cu 1083 1981
Cast Iron C+Si+Mn+Fe 1260 2300
Manganese Mn 1260 2300
Steel-High Carbon Cr+Ni+Mn+C 1353 2500
Stainless Steel Cr+Ni+Mn+C 1363 2550
Inconel Ni+Cr+Fe 1393 2540
Silicon Si 1420 2588
Medium Carbon Cr+Ni+Mn+C 1427 2600
Nickel Ni 1452 2646
Low Carbon Cr+Ni+Mn+C 1464 2700
Iron Fe 1530 2786
Chromium Cr 1615 3034
Titanium Ti 1795 3263
Tungsten W 3000 5432

Based on the numbers that others have posted, it looks like the design I selected (unless upgraded to gas or electric elements) will probably reach past 700-900 C depending on air flow and insulation. That being said, if everything works out with the first iteration, with an upgrade I should be able to work with metals up through copper without issue. I do plan on obtaining a thermocouple thermometer and logging the ramp rate and peak temperatures for a few configurations of fuel and air flow, just to see how far it can be pushed.

The general idea that I went with was a plaster and sand refractory cast inside of a steel bucket, with an air intake drilled in from the side. The initial build went quite quickly, allowing a full day for all the setting of the plaster parts. Over all, the materials for the furnace cost $51 at Home Depot, and left me with extra sand, plaster, and buckets. That doesn't include the hair dryer I already had on-hand that will become the blower on the air intake, but those can be found cheap.

Furnace Supplies

Furnace Supplies

The body and lid are already made, safety supplies and a good crucible are headed my way from Amazon! I'll post another update with the details of the build and, barring any unforeseen snags, photos from the first melt.

2015 so far

The year is still relatively new, with barely a sixth of it behind us. The first two months have shown good progress, and I'm starting to have more to show for it. For instance, the patent application we put in back in 2012 finally issued! This is well-timed, as our publication on that work is finally trucking along towards a final manuscript. In other career-stress news, I also finally revamped my CV for the first time in years. It took almost two days to parse through all the feedback I got in order to get it into a form that everyone had a positive view of. You can't make everyone happy, but settling for a few HR people during the interview process might be a good idea. I'll be giving a talk during industrial affiliates in two weeks about the hybrid solar collector that we've been designing, and the unique challenges with optimizing that kind of system. With the big pushes on self-promotion I've been given lately, I should also take time to polish up my LinkedIn page, despite the fact that I really don't like LinkedIn.

The reading list I posted earlier has more-or-less held up, some books have been dropped and others have been added. I've had mostly good experiences with the books I chose, but am finding a few less engaging than I'd hoped. I'll reserve judgement until I've finished them though. While I haven't had as much time to dedicate to side project as I'd hoped, I'll definitely post updates when I do.

2015 Reading List!

I've had a perpetual problem with owning books that I never get around to reading, even going so far as to relegate the unread books to their own shelf. I'm constantly finding new books I want to read, despite having a sizable backlog, and decided that this year I should try to clear the pipes. I decided to set aside 30 minutes before bed each evening for reading, and going at a little over a page a minute, with an average book being about 400 pages (a little bit of a high estimate, but there are a few long ones on the shelf), that brings it to about 27 books per year. I've got 32 on the "unread" shelf, but thankfully airports provide an excellent environment for distraction free reading; in the first three weeks I've already gone through three books, putting me at about twice the baseline pace. If everything stays on track, this should be my most literary year in a long time.

My partial list for this year is below, the finished ones are crossed out. Once I've got my bookshelf in front of me I'll add the rest I've already got lined up, but I'm definitely open to suggestions if something integral is missing! I've only got 7 non-fiction books on the list at present, so if you have a favorite, let me know!

  • Proof: The Science of Booze by Adam Rogers
  • Stuff Matters by Mark Miodownik
  • Cibola Burn (Expanse, #4) by James S.A. Corey
  • How Not to Be Wrong by Jordan Ellenberg
  • The Color of Magic by Terry Pratchett
  • That is All by John Hodgman
  • Care of Wooden Floors Will Wiles
  • Cold Hand in Mine: Strange Stories by Robert Aickman
  • The Wine-Dark Sea by Robert Aickman
  • The Science of Good Cooking by Guy Crosby
  • Wool by Hugh Howey
  • Speaker for the Dead by Orson Scott Card
  • Xenocide by Orson Scott Card
  • Children of the Mind by Orson Scott Card
  • Meat Eater by Stevem Rinella
  • The Windup Girl by Paolo Bacigalupi
  • Infinite Jest by David Foster Wallace
  • Endymion by Dan Simmons
  • Salt: a World History by Mark Kurlansky
  • Understanding Physics by Isaac Asimov
  • Siddhartha by Hermann Hesse
  • Dawrin's Radio by Greg Bear
  • Faust (German-English edition!) by Goethe (Peter Salm translation)
  • Cathedral by Raymond Carver
  • The Grand Design by Stephen Hawking

Note: I've also got a handful of Asimov's Foundation books on-hand, but not the original. I've been told to read them in order while ignoring the prequels (e.g. foundation, empire, second, edge, earth), so I'll probably put them off until I find a used copy of the first one.

Python: Filtering lists for value

I've worked with Python for years now, but had never really pursued the idea of running it server-side to generate dynamic content. I came across a problem that was suited for it recently. I had a box of ~5000 Magic: The Gathering commons and uncommons from older sets, and I didn't have a good idea of which were worth something compared to the rest of the chaff. I found the Deckbrew API, and was able to make calls to that by grabbing a well-shaped URL. It was a short path to putting together a simple HTML form for specifying the filter and threshold values as well as displaying the results.

The resulting tool can be found here!

There are certainly bugs, primarily that I've already encountered cards that are listed, but have no listed price for the printing of interest. I'm thinking to work around this by picking the value of an alternate printing, but haven't bothered to work that out yet.