|
I've just tested your app, and that's very cool, Berend! Very well deserved prize!
Got my 5!
|
|
|
|
|
Could you give me the app to make the program run on Windows Mobile?(my email is 237650651@qq.com)
thank you
|
|
|
|
|
This is excellent work. I plan on trying this in a production project. The company processes periodicals in large amounts. They perfor to scan all the covers and then extract the barcode from it. Can you recommend an image scanner?
|
|
|
|
|
Basically for this software to work succesfully, any scanner that can scan at medium resolution (300 - 600 dpi) would be OK. Because the software needs the barcodes to be horizontally or vertically aligned, I would recommend some kind of automated paper transport for large volumes. However, most scanners with sheet feeders won't be able to handle a magazine unless you first separate it out in pages or sheets (by cutting it up or removing the staples). Is that what you plan to do? If not, perhaps a multifunctional copier that allows you to put the magazine cover on a glass plate might be more suitable.
For medium volume, we usually recommend the Canon DR series with sheet feeder, because they have an image reader element that can scan both sides at once, that simplifies paper handling for double sided scanning. Canon scanners are mostly sold for office environments, volume typically up to 3000 pages per day. For really high volume scanners, you might look at the high-end offerings of Fujitsu Siemens, Kodak or Agfa (note however that high volume scanners come at a hefty price). For multifunctionals, Ricoh is a popular choice among our customers.
|
|
|
|
|
I think what you have done is great, and I will give a 4 for doing so, but you are miles behind when it comes to barcode recognition software.
I have no affiliation to this product other than I found it to be the best barcode reader I could find for the money we had available.
http://www.dtksoft.com/barreader.php
There is a free trial and if you or someone else could surpass its functionality please let me know and I will happily switch to that solution.
TonyMac
|
|
|
|
|
I looked at the link you provided and it looked interesting. However the point of CodeProject (to me) is to learn how to code some things that I have never done before. Since I have never written any software to scan images for Bar Codes, but may have to at some point, I was very excited to see this article. It gives me a base to build on and enhance with my own development experience for a price that fits within my budget (free ). I really don't expect to find the equivalent of specialized commercial software on CodeProject. With 22 years of development experience - I can use this as a "fast-start" to shorten the learning curve and then do the rest myself. Kudos to the author for putting an interesting and helpful topic out there.
|
|
|
|
|
Agreed and sorry. I am in a commercial environment and need a solution yesterday so I look for code snippets that I can adapt into my programs. Hope the author keeps up his good work and also accepts my apologies
TonyMac
|
|
|
|
|
No hard feelings . Before, I decided to ignore your rant because it seemed like an blatant advertisement for a commercial product. When you post criticism, you could think a bit more about balancing and qualifying your statements. You say my code is "miles behind", that is a subjective opinion, without giving any indication where you find it lacking. In a good quality post, you would have pointed out clear deficiencies and provided evidence material to demonstrate them. Others have done just that, and it did help me to find bugs and improve the code.
What I wanted to say, even if my product is "miles behind", in my (not-so-humble ) opinion it is still the best you can get for free in this field. The reason I wrote this, is because all other open source image barcode readers I found were not good enough for my company's purpose. We now use it commercially to replace a closed source commercial product that was not 64 bit Windows compatible, and it works well enough for our purpose. I do eat my own dog food!
Finally, please note that I am a professional programmer with well over 20 years experience in coding and I donated several mandays of my time for free to the Code Project community in this and similar open source projects. That is not something to be dismissed so casually.
|
|
|
|
|
ok - you dont need to labour the point. I have already apologised, I was a dick sorry again.
Just wish I had several mandays I could easily contribute to this forum.
TonyMac
|
|
|
|
|
Dear Berend,
i am a newbie regarding the "barcode world".
I have read you code and i think that is is a great job: ASAP i start to rewrite it in C#.
I have a question: what kind of barcode reader I can buy to test the software and understand something more?
Could you recommend to me any barcode reader to use with your application?
I hope that you can help me
Begs
|
|
|
|
|
Dear Begs,
Please note that the barcode detection library is written in c#, so you shouldn't need much time to translate it to c#
The purpose of my code project is to read a barcode that is part of an image, there is no barcode reader required. The idea is that you have a printed page that has a barcode and some text on it, and that is input to the software using an image scanner (e.g., a flatbed scanner or a multifunctional scanner/copier). Document Management software (like the software that my employer sells) often uses barcodes to automatically route scanned documents.
POS Barcode Reader SoftwareFor handheld barcode readers, you would need a different kind of software. I have done a quick search of CodeProject and found these projects:
VBScan barcode software[^]
Controlling a Barcode Reader with POS for .NET[^]
Both of these projects use input from handheld barcode readers, also known as POS (Point Of Sales) barcode readers. This type of reader is usually connected to a serial port of your PC.
Barcode readers with keyboard emulationWhat you could also do is buy a barcode reader that emulates an USB keyboard. Then your software could be very simple: just write a program that has a single input text box, position the cursor in the input box and use the barcode reader. The output of the reader will appear in the textbox, just like normal keyboard output.
In my company, we use the Symbol LS 2208 barcode scanner for this kind of application. It is robust has good detection and reasonably cheap. Also, it is fully programmable. We programmed it to output ESC before the barcode digits and CR LF (Enter key) afterward, so that we can distinguish the barcode input from normal keyboard input and capture it without relying on a text box. For the .Net version of this "keyboard hook" interface, we based on this code project by George Mamaladze:
Processing Global Mouse and Keyboard Hooks in C#[^]
|
|
|
|
|
If barcodes will be surrounded by quiet zones, such that one can identify the beginning and end of any suspected barcode before one has to worry about trying to decode it, one can easily narrow down the possibilities for barcode type and compute bar/space widths without fancy histogram techniques.
For example, if there are 5n+4 bars between quiet zones (for some value n), the code might be an I2of5 barcode containing 2n+1 wide bars and 3n+3 narrow ones, along with 2n wide spaces and 3n+3 narrow ones. If one expects a 2:1 wide/narrow ratio, one can figure that the narrow bar width should be the total width of the black areas, divided by (7n+5). Likewise the narrow space width should be the total space of the white areas (not counting quiet zones) divided by (7n+3). If the number of bars isn't 5n+4, the code isn't I2of5, so there's no need to parse any further.
For Code39, the number of bars must be a multiple of five, and the bars should be processed in groups of five. There are two types of Code39 barcode (two wide and three narrow bars, plus one wide and three narrow spaces, or else five narrow bars, and three wide and one narrow spaces). If less than half the area within a symbol is white, it's the former style; if more than half, the latter. Once the style is determined, the wide/narrow widths for bars and spaces may be ascertained.
This approach is nicely amenable to things like Code128 which have multiple bar/space widths. Because the 'ink density' of Code 128 isn't constant, it's necessary to compute the module width based upon total symbol width, without using total white width and total black width separately. This makes it harder to factor out the effects of printers that cause black areas to come out wider or narrower than they should, but is much easier than using histograms.
|
|
|
|
|
Dear supercat9,
For any computing problem there are any number of solutions and you are of course welcome to publish your own. If you can improve on mine, you are welcome too - that is what I did with qlipoth's work and he with Liedblad's original version before me.
However, I have the feeling that you are trying to solve a problem that is already sufficiently solved (the published code already detects Code39, Code128 and EAN, also in bad quality scans), while not progressing in the problem that is still open: my code is not able to detect rotated barcodes very well, if at all. I tried a basic Hough transform and it works well only if the rectangle where the barcode is located is already known, so that the transform can be applied on an area without other image elements. My application however needs to detect multiple barcodes on pages that also have text and other graphics. Just applying a Hough transform over the full page often badly malfunctions.
If you look at this image, you may also notice a problem with the bar counting that you propose: actually in a rotated barcode, the scan line will not cover the full barcode and thus not return a complete bar count. What I plan to do is find partial barcodes (with the same approach that I use now) and if I find one, use that information to identify the rotated rectangle containing the barcode fragment that was found.
One more problem that you should be aware of: you cannot expect a 2:1 wide/narrow bar ratio. I have seen both 1.7 : 1 and 4:1 in Code 39. Also, in a bad scan the white bars are drawn too wide and the black bars too narrow (or the other way around), because the lighting is off. This causes a wide white bar to have a very different size from a wide black bar. This is the reason why the current version of the code does measurements for white and black bars separately. I had to later relax the constraints that I set on the ratio between white and black, to be able to pass more of our test material.
Finally, the reason why the code averages several rows of scan lines vertically is to compensate for noise. The image usually has white pixels in the middle of a black bar and black pixels in the background, and that will screw bar width calculations and bar counts if you consider just one scan line at the time. Unfortunately, the averaging technique is also a prime reason why the code is so sensitive for rotation: if you average two rotated bars vertically, the gap between them will be grayed out in the average scan line. I have tried to disable the averaging in good quality skewed scans and in that case detection actually improves. However, our customers manage to produce much more bad than good quality imaging, so the overall detection rate over our test set went down
Here is a sample of what I am up against: fail1a.tif. The current version of the code can just detect this barcode (with a bit of luck). Please zoom in on the image and notice in how bad shape the bars are ...
Best regards,
Berend
|
|
|
|
|
Hello,
it's possible to integrate an scew angle?
This is possible to calculate scew angle on scanned bape by some simple alg's or this cab be calculated within scanning software. Mostly uses some sort of transformation like Hough Transformation. With .NET it's easy but very slow to deSkew the image by this know angle and it's takes a lot of ressources.
Is it possible to incorporate an scewing angle as parameter in calculation routines? Maybe this angle manipulates internally calculated values in some easy/linear way or a procedures cas use their value for calculating internal values?
Thanks.
|
|
|
|
|
Dear Alexander,
That is a possibility yes. If the scanning software can give the skewing angle, it would certainly help to pass that. I agree about transformation algorithms, they are not only fairly complex, but also likely to be agonizingly slow if implemented in c#.
However, this will also have to wait until I have time. Currently in my company, the barcode reader has passed all our tests with actual customer scans (I have seen their test set and I am amazed at the ability of our customers to get truly lousy low quality scans out of expensive high end scanners ), but they found a bug in FreeImage (that we use to pre- and post-process multi-page tiffs). To fix that bug or find a workaround is now my first priority and unfortunately that may mean to dig in some fairly messy, hard-to-read c++ code
One thing that you need to consider also is that the rotation test that you did might give worse results than an actual scanner. Usually artificial barcode generators produce bitmaps where the most narrow bar is exactly 1 pixel, which quickly leads to aliasing defects of more than the bar width if you rotate - that is almost impossible to compensate for. An actual scanner will usually scan a barcode with the most narrow bar and gap being at least 4 - 6 pixels wide, and that is much easier to recognize than the artificial sample.
Best regards,
Berend
|
|
|
|
|
Hello Berend,
actually it's possible to calculate skew angle by software really fast.
Problem with barcodes is, that they developed to work under other conditions as digital document management - they must be printed at really high resolution printing engine and readed by barcode readers. This conditions are not given if the rendered pixelwiese and printed and scanned by paper scanners.
What could be interesting, is to calculate scew angle and if this one is to big (>5°) use it by software, otherwiese not.
Btw: actually .NET Framework can process multipage tiff also - it's possible to get single frame and store multiply frames within one tiff file. Here is the example: Save images into a multi-page TIFF file or add images to an existing TIFF file[^]
Thanks.
|
|
|
|
|
Dear Alexander,
I have fixed my problem with saving multipage tiffs by re-implementing the part that saves multi-page TIFFs in .NET/GDI+. I based my code on this sample by Bob Powell:
Adding frames to a Multi-Frame TIFF[^]
I am happy with the solution, because it not only solved my problem, but also saving is now faster and the output files are more compact when GDI+ is used.
Skew angle calculations
You say "actually it's possible to calculate skew angle by software really fast". Probably true, but I did not find any open source examples of doing that, so I will have to "invent" my own solution. Anything I found was either not freely available or patented, so I can't use it.
Please consider this image, that I use in the explanation of my proposed approach.
The current algorithm is visualized in the yellow "scan bands" and the blue "barcode zone" boundaries. The software scans strokes of the image top-to-bottom (and left-to-right, not shown). For each stroke it looks for large blank spaces and subdivides the scan bands in "barcode zones" by cutting it up through the middle of each large blank space.
A. If we encounter a rotated and/or skewed barcode, there are two angles to consider:
- solid edge angle: this is shown in the leading edge of sample 1. When we travel down the scan band, the start of the black pixels for each scan line will gradually shift in one direction. From that we can fairly easily calculate a skew angle and deskew.
- In a rotated barcode, there will also be a discontinuous edge. When we travel down the scan line, the furthest black pixel will regularly "jump back", where the band cuts through a gap in the barcode. We can still approximate an angle, by determining the average direction and minimum and maximum black pixel coordinate in the scan band.
B. From the solid edge angle, the band can be deskewed by shifting the pixel start point before averaging vertically. This would be enough if skew was the only defect (e.g., second barcode in the image). For a rotated barcode, this will give us a partial barcode.
Deskew can be applied locally, this has the advantage that local defects can be compensated and we do not need a slow image rotation.
C. If one or more partial barcodes is found, rotate the image by the average discontinuous edge angle found, then try again. As this step is inherently slow, it should be optional. Also, note that I propose to use the average angle, meaning that we can only compensate for a global rotation of the full image when using this method.
D. Perhaps step C can be optimized by looking for consecutive scan lines having barcode zones with a similar average angle and finding the bounding rectangle of those. Clone the bounding rectangle to a partial bitmap and only rotate that. Although this method will be more complex than a full image rotation, the advantage would be that less image data is copied and transformed, so the method could be faster than C (provided it is not called for noise data too often).
To configure step B, I would introduce a boolean property UseDeskew .
To configure step C/D, I would introduce a property DetectRotatedBarcodes of type BarcodeType . This can then be used to determine for which barcode type this algorithm must be attempted. Rotation should only be attempted if at least a partial barcode is detected, else the discontinous angle determination will be very unreliable and the software would be come far too slow.
Regards,
Berend
modified on Sunday, October 25, 2009 4:56 AM
|
|
|
|
|
Thank you for your code
it's useful
|
|
|
|
|
Hallo Berend,
is it planned to support barcodes on "bad" scanned images, like rotated or scewed images?
I've expiremented with originally generated Code128 (200x100 pixels) barcodes - if they rotated by more then 5-7 degrees, they would not be recognized anymore.
More other examples can be found here: lemQi Blog[^]
Thanks.
|
|
|
|
|
Dear Alexander,
Unfortunately, I don't think that I can spend time on that now. I was aware of IemQi project Bamby before I started this development, but I lack the time and the mathematical knowledge to write something similar. I have considered using their stuff, but as far as I am aware it is unfortunately still fully unpublished. I have also looked at the zxing google code project, but had to reject that because the code appeared to be slower and less capable than the code project that I based my stuff on. Also the c# implementation of ZXing is fairly buggy and we did need a solution in Microsoft.Net.
As to the technical possibility of improving my code in future: I believe that it is feasible to improve the code to support detection in rotated and linearly skewed barcodes. Detecting barcodes in an image of a curved surface as shown on the IemQi Blog page is too far beyond the capabilities of my code and will not be possible any time soon.
Best regards,
Berend
|
|
|
|
|
Hey Berend,
Awesome project. I was just wondering if you have any plans to add support for additional image formats.
Thanks,
Ndi
|
|
|
|
|
Dear Ndi,
Reading in the image is out of scope of the project. The barcode detection component receives a System.Drawing.Bitmap object as parameter to its public functions, that can be the in-memory representation of a wide range of image types, including multi-page tiff.
Image formats supported in sample codeIn the sample application BarcodeTestApp you'll find an example of using basic GDI+ to read in the image. That application reads in gif, jpeg, bmp, png, black and white tiff and some types of color tiffs (for instance, the color tiff that infal posted yesterday can be read in). In the COM sample COMTestApp we only included very basic image support, that sample only has the purpose of demonstrating the alternate (old-style) interface to the vb.net component. Internally, the COM interface functions allow passing COM IPictureDisp and IPicture references as well as .Net Bitmap objects. Finally, in the Microsoft Word VBA sample COMTest.doc, we demonstrate our GetImageFromClipboard utility function, that works around a limitation in VBA image handling.
Color TIFFsA problem with the Microsoft.Net imaging library is the lack of support for reading in JPEG-compressed color tiff images, that many modern scanners produce. In my company we always used a third-party component to alleviate this. In the Open Source era we switched to FreeImage[^]. FreeImage is a wrapper around libtiff and various other standard imaging libraries, that can easily be used from Microsoft.Net 2.0 and higher, and even has good Visual Basic 6 support. It works fine on both 32 bits and 64 bits Windows environments and can read in many more image formats than the standard Microsoft stuff.
[Edit October 24, 2009]
Unfortunately, we found serious bugs in the part of FreeImage that writes multi-page tiffs. Symptoms are that tiffs appear fine in some viewers, but often white-on-black instead of black-on-white in others. My solution is to use FreeImage only for opening tiffs (this is the area where Micorsoft GDI+ often fails), and GDI+ for saving them again.
For saving multi-page tiffs, we based on this excellent sample code by Bob Powell:
Adding frames to a Multi-Frame TIFF[^]
An added bonus is that GDI+ writes more compactt files than FreeImage
modified on Saturday, October 24, 2009 12:40 PM
|
|
|
|
|
Hi,
great work, but not allways does a job.
I've created 3 Code128a barcodes with the same barcode-creation engine in the same size.
The barcode creator is from here: Barcode Image Generation Library[^]
2 of barcodes will be recognized, but 1 will be not recognized.
To proove I've dome the test with DTK Barcode Reader SDK demo - this recognize all 3 barcodes.
The other commercial recognition library is from here: DTK Software[^]
Other lised here: Barcode recognitions download[^]
Now, I assume, that maybe check sum calculation is only broken.
Unfortunatelly I don't know how to attach example file here, but I can mail it to you.
Otherwise you can try create following Code 128a barcodes by suggested engine (Size was setupet to 200 x 100) from Code Project
1. Barcode: "0123 - 4567890" (recognized)
2. Barcode: "TEST - BARCODE" (recognized)
3. Barcode: "BETA - SYSTEMS" (not recognized)
I've also tried to create and recognize 300x150 barcode for the 3.rd case, but also without success.
Thanks,
Alexander
|
|
|
|
|
If you mail me an actual Code128 bitmap that does not work, I'll look in to it. Please also indicate what the barcode result is supposed to be, if it is not shown as readable text below the barcode.
Best regards,
Berend
|
|
|
|
|
Images are sent to your mail box.
Thanks!
modified on Thursday, October 22, 2009 3:27 PM
|
|
|
|
|