Machine Vision

cancel
Showing results for 
Search instead for 
Did you mean: 

Intelligent Mail Barcode (IMB)

Has anyone developed a way to decode this type of linear barcode.  It is on all USPS mail near the bottom of the envelope.

0 Kudos
Message 1 of 4
(5,135 Views)

IMB barcode reading is a 2-step process: First, the image with the bars is read, and converted into a 65-character string representing the tracking code, and then a decoder is used to convert that into 20-digit tracking (Barcode ID, Service IT, Mailer ID, Sequence Number) and up to 11 ID Routing Info.

 

The first step is done with image processing, the second with a JavaScript decoder provided by http://bobcodes.weebly.com/imb.html .I'm gonna walk you through the solution .. but will warn you that how I wrap that decoder is a bit ugly.. It's a working proof of concept.. 🙂

 

OK, let’s look at a barcode.  

barcode.png

 

This barcode describes 4 kinds of charactersA = Ascending bar, D = Descending bar, F = Full bar, T or S = Track (short) bar

I lifted the following graphic from Wikipedia (its public domain), it explains what it is...

barsexplanation.png

 

That means, the code above encodes those 65 characters:

FTAAFDTDFTAFDFFFTADAFTTDFTFDFAFDTDTTDFFADFTADTADAFADFTFFFAAATDTDF

 

This reading is easy, and there is a number of ways to get to Rome.. 
Intuitively I’d do some edge detection horizontally across barcode (1 edge polarity), get the edge coordinates of the trackers and then either use edge detection again on top and bottom of this.. or some sort of simple gauging..

 

But right now I’m assuming you can get a clear, clean image, thresholded, and at an upright angle (if you need help with that, you are gonna have to provide source images).

What we have then, is 65 particles that we can classify.

 

I’m using IMAQ Particle Analysis to look at their area and at their bounding boxes.
First step: Sort them by the x-coordinates. So you get letter by letter in the right direction. The combination of Index&Bundle Cluster Array + Sort 1D array is good for that. The typecast is only there for better readability of the code.
I also use the particle with the smallest area as an example for a (T) character, and the particle with the biggest area as an example for a (F) character.

 

code1.PNG

Then I loop through the particles.
If they are within a certain range of the smallest area, great – we have a (T) character.
If they are within a certain range of the largest area – great – we have a (F) character.
Else, if they are closer to the top boundary than the middle boundary, we have a (A) character, and else a D.
There are nicer ways to do this classification than a nested if (mainly: custom classification with a SVM or something like that), and there are more ways to cross-check the data.. the bottom boundaries have to be right for example.. or the areas should be 1*, 2* or 3* the smallest area.. and we definitely need to check that the particle number is 65.. but OK.
That’s exercise for the student .. and depends on the quality and variety of your sample data. In a real life application, you'd probably have to work harder than with nice and clean sample pics.

 

code2.PNG

OK, resulting is a string.

FTAAFDTDFTAFDFFFTADAFTTDFTFDFAFDTDTTDFFADFTADTADAFADFTFFFAAATDTDF

 

You can already see that I feed into a decoder.

I just downloaded this HTML and javascript file from a website. http://bobcodes.weebly.com/imb.html (this one)

 

Now.. I could write a nice interface for the JavaScript code, but let’s be honest, I am not particularly interested in IMB decoders and not too fluent in JavaScript. So what I’m doing is to modify the HTML to suit my needs… Plan is to use the HTML as a wrapper for the js-library (it calls it nicely), feed the barcode from LabVIEW via the URL to the HTML and let it print the result.

That means, I use a caller ?barcode=FTAA…., and feed that data into the form.
The webpage gets a little extra JavaScript for that…

var arr = document.URL.match(/barcode=([FTAD]+)/)
var code = arr[0].match(/([FTAD]+)/) [0];
document.getElementsByName("barcode")[0].value=code;

I’m sure there are more elegant ways to do that, but it works.
And then I further modify the html page to automatically call the decoder function and print the results in a way that is easy to parse for LabVIEW

do_decode();
document.write("For parsing and LabVIEW: <br>");
document.write(document.getElementsByName("zip")[0].value+";");
document.write(document.getElementsByName("plus4")[0].value+";");
document.write(document.getElementsByName("delivery_pt")[0].value+";");
document.write(document.getElementsByName("barcode_id")[0].value+";");
document.write(document.getElementsByName("service_type")[0].value+";");
document.write(document.getElementsByName("mailer_id")[0].value+";");
document.write(document.getElementsByName("serial_num")[0].value+";");

Don’t worry, I attached the HTML file for you anyway.

OK. So all I need to do now is copy-paste the HTML-file and the js-file into a folder and call it. If I used standard LabVIEW webfunctions, it wouldnt execute the js (yes, I could build a nice webservice around it .. or better, a REST API, but let’s face it, this is proof of concept, not production code)… so I use the internet explorer active x.

 

If you opened Internet Explore and typed in file:///C:/Users/birgit.ploetzeneder/OneDrive/_currentwork/IMB/usps-imb.html?barcode=FTAAFDTDFTAFDFFFTADAFTTDFTFDFAFDTDTTDFFADFTADTADAFADFTFFFAAATDTDF (your folder) in the internet explorer, it would exectute js and then give you the data. (Maybe you have to allow scripts or something permanently. IE is funny like that)…
This data needs to be parsed, and that requires some ActiveX-Ninjaing.. which is fortunately in my code-snippets folders. You can check out the example, or just trust me on that.. http://www.ni.com/example/27743/en/

And then parse and get an array.. and that way I get my values.

code3.PNG

code4.PNG

 

Quick and quite dirty. I’d probably check for falsely-read codes (the js-code can detect that), but thats it. Easy 🙂

 

 

 

Download All
Message 2 of 4
(5,093 Views)

Excellent explanation!  Perhaps I can use your code as a starting point.  The real challenge for me is that my images will be of a whole envelope so I will need to search for the barcode.  Given the constraints on this project it is looking more likely that I will have to purchase a third party toolkit.  I found one that works very well and is fairly fast (~50ms) even when reading first from a file.  The downside is that it costs $500/computer but that is less than my time to develop a robust vi. 

0 Kudos
Message 3 of 4
(5,071 Views)

Detecting barcodes is pretty easy, usually.
If the barcodes are roughly the same size, look at the gradient of the image with an appropriate sized kernel. Or correlate with a full-(T)-barcode.

0 Kudos
Message 4 of 4
(5,061 Views)