zbar cannot decode barcode - decode

I have two images of the same barcode. When I use zbar library (or qrtools wrapper) to decode images of QR Codes, ImageScanner.scanner returns 0 for some of them. As an example, I cannot figure out why this first qr code cannot be decoded:
while the 2nd one can be decoded:
Below is the code I use for decoding. Result value is 0, for the first image, and 1 for the second one.
import zbar
from PIL import Image
scanner = zbar.ImageScanner()
# configure the reader
scanner.parse_config('enable')
# obtain image data
pil = Image.open(filename).convert('L')
width, height = pil.size
raw = pil.tostring()
# wrap image data
image = zbar.Image(width, height, 'Y800', raw)
# scan the image for barcodes
result = scanner.scan(image) #Value is 0, -1, 1
Any feedback on how I can make the zbar decoder work for the 1st image?

The issue was around shadow removal. Once the image was binarized and shadow was removed, zbar was able to decode it

Related

Gdal substract 1 bit raster gives me hard time

I want to use gdal_calc to subtract one file from another. It works, but I get the wrong result all the time no matter what command line i try.
For your understanding I created 3 files.
Picture A:
Picture B:
Picture C:
As you can see I always get the overlap as result but I need the other part.
Desired Result:
gdal_calc.py -A pica.tif -B picb.tif --outfile=result.tif --calc="A-B"
Change the line to
gdal_calc.py -A pica.tif -B picb.tif --outfile=result.tif --calc="B-A"
or swap filenames doesn't work? I always get the same result.
I also delete the output file before trying new stuff so thats not the problem that I always look at the same file.
What are the values of your black and white pixels? Usually white would be 1 (or 255), and black 0, but that's just a guess. If that's the case, you probably want the inverse, so something like (1-A)-(1-B) (if your values are really 1bit).
For testing\debugging, it's a good idea to first convert both input images to an unsigned integer datatype. For example:
gdal_translate -ot Int32 pica.tif pica_int32.tif
That would allow negative values in the result, because gdal_calc does not convert the data to a new "working datatype" (as gdalwarp can do with -wtfor example). So that would mean you're doing the calculation in the input datatype (probably Byte?). See the "Note" box at:
https://gdal.org/programs/gdal_calc.html#cmdoption-type
And if you're subtracting, and the datatype is Byte, it probably causes results beyond the valid range of that datatype (like -1). Normal Numpy behavior is to simply "wrap around" (instead of clip etc), so that might cause some surprising results, for example:
import numpy as np
a = np.array([1, 0, 1, 1], dtype=np.uint8)
b = np.array([0, 1, 254, 255], dtype=np.uint8)
a - b
Results in:
array([ 1, 255, 3, 2], dtype=uint8)

Read a locally stored image as the background image for subtraction

I'm using Emgu.CV and planning to use background subtraction. I want to do something fairly simple and read two background images from my local disk, and use one of them as the background image and the other one as the overlay to compare with / the mask.
I haven't got far though, because the signature of the method is very different than just accepting a file. I'm guessing I'm missing some conversion from a File.Read to IInputArray
IBackgroundSubtractor backgroundSubtractor = new BackgroundSubtractorMOG2();
IInputArray inputImage; // how do I create an instance of an InputArray from a local file?
IOutputArray mask;
backgroundSubtractor.Apply(imputImage, mask);
How do I go from a file in C:\<somepath>\someimage1.png to formats IInputArray, IOutputArray below?
EmguCv offers different methods to load images from file (see V1 and V2 below). For the mask you just need to define a new Mat object and it will be allocated and filled automatically when you call backgroundSubtractor.Apply(input1, mask);
//V1 load image
var input1 = new Mat(#"C:\<somepath>\someimage1.png");
//V2 load image
Mat input2 = CvInvoke.Imread(#"C:\<somepath>\someimage1.png", ImreadModes.AnyColor);
var mask = new Mat();
IBackgroundSubtractor backgroundSubtractor = new BackgroundSubtractorMOG2();
backgroundSubtractor.Apply(input1, mask);
The Mat class implements IInputtArray as well as IOutputArray.

Load and Save opaque 8 bit PNG Files using ImageSharp

I am trying to Load -> Manipulate byte array directly -> Save an 8 bit png image.
I would like to use ImageSharp to compare its speeds to my current library, however in their code example they require the pixel type to be defined (they use Rgba32):
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Processing;
// Image.Load(string path) is a shortcut for our default type.
// Other pixel formats use Image.Load<TPixel>(string path))
using (Image<Rgba32> image = Image.Load("foo.jpg"))
{
image.Mutate(x => x
.Resize(image.Width / 2, image.Height / 2)
.Grayscale());
image.Save("bar.jpg"); // Automatic encoder selected based on extension.
}
I looked through the pixel types: https://github.com/SixLabors/ImageSharp/tree/master/src/ImageSharp/PixelFormats
But there is no grayscale 8 bit pixel type.
As of 1.0.0-beta0005 There's no Gray8 pixel format because we couldn't decide what color model to use when converting from Rgb (We need that internally). ITU-R Recommendation BT.709 seems like the sensible solution because that is what png supports and what we use when saving an image as an 8bit grayscale png so it's on my TODO list.
https://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale
So... currently you need to use either Rgb24 or Rgba32 when decoding the images.
Update.
As of 1.0.0-dev002094 this is now possible! We have two new pixel formats. Gray8 and Gray16 that carry only the luminance component of a pixel.
using (Image<Gray8> image = Image.Load<Gray8>("foo.png"))
{
image.Mutate(x => x
.Resize(image.Width / 2, image.Height / 2));
image.Save("bar.png");
}
Note. The png encoder by default will save the image in the input color type and bit depth. If you want to encode the image in a different color type you will need to new up an PngEncoder instance with the ColorType and BitDepth properties set.

Windows Small System Icon Height Incorrect

I'm running on Windows 10, but using Delphi 7 (yes, I know it's quite old).
I want to use the system icons in Windows and have gone about this by defining a TImageList called SystemIcons which I initialize as follows:
var
fileInfo: TSHFileInfo;
begin
SystemIcons.Handle := ShGetFileInfo('', 0, fileInfo, SizeOf(fileInfo),
SHGFI_ICON or SHGFI_SMALLICON or SHGFI_SYSICONINDEX);
...
I have SystemIcons properties set statically as a TImageList component with width and height set to 16.
Elsewhere, I wish to retrieve an icon from this image list given a valid shell object's image index. Because these are "small system icons", I expect them to be 16x16. The result of calling GetSystemMetrics(SM_CYSMICON) yields 16. Oddly, the dimensions depend upon whether I retrieve them as a bitmap or an icon.
...
var
icon: TIcon;
bm: TBitmap;
begin
...
icon := TIcon.Create;
SystemIcons.GetIcon(imgIndex, icon);
bm := TBitmap.Create;
SystemIcons.GetBitmap(imgIndex, bm);
The imgIndex is correct and the same in both cases. The image retrieved is the same in each case, as expected. The dimensions of the bitmap (bm.Width and bm.Height) are also as expected: 16x16. However, the dimensions of the icon (icon.Width and icon.Height) are not. They are 32x32.
When I paint the icon on a canvas it appears as 16x16. So it's only its Height and Width values that appear incorrect. Very odd.
Why are these different?
The images are likely actually 32x32 to begin with.
Internally, TImageList.GetIcon() simply retrieves an HICON for the chosen image directly from the underlying Win32 ImageList API, using ImageList_GetIcon(), and assigns that to the TIcon.Handle property.
TImageList.GetBitmap(), on the other hand, is a bit different. It sizes the TBitmap to the dimensions of the TImageList (16x16), and then stretch draws the chosen image onto the TBitmap.Canvas using TImageList.Draw(), which in turn uses ImageList_DrawEx().

How can I losslessly crop a jpeg in R

I am new to R. I have a folder full of images(RGB) which are not of the same dimensions. My requirement is to have them all in the same dimensions which would involve resizing a bunch of them. I wrote the following code to get this done
#EBImage
library(EBImage)
path = "G:/Images/"
file.names = dir(path,full.names = TRUE, pattern =".jpeg")
reqd_dim = c(3099,2329,3)
sprintf("Number of Image Files is: %d", length(file.names))
for(i in 1:length(file.names)){
correction_flag = FALSE
print("Loop Number:")
flush.console()
print(i)
flush.console()
img = readImage(file.names[i])
# Checking if the dimensions are the same
for (j in 1:length(reqd_dim)) {
if(dim(img)[j]!=reqd_dim[j]){
correction_flag = TRUE
break
}
}
if(correction_flag==TRUE){
print("Correcting dimensions of the image")
flush.console()
writeImage(img[1:3099, 1:2329, 1:3],file.names[i],quality = 100)
}
}
My problem is that while the images are originally between 500-600 kb in size, the ones that are resized end up being between 1.8 to 2 Mb. In my particular case the images are in either of the two sizes - 3100x2329 or 3099x2329. So my resizing involves removing the extra column of pixels to make all images 3099x2329. I am ok with the file size of the files going down a bit as I expect some information to be lost; but in my case the file size is increasing more than three-fold.
Alternatively I have thought of converting the images into matrices(which is supported by EBImage) and remove the extra row. But I have two issues here, one is that I don't know how to do it and two is even if I found a way to do it, I'm afraid I might loose some information if I ever needed to convert it back to an image.
I'm open to an improvement over this approach, or a totally different one as well. My only requirement is that I need to be able to do resize my images in R without adding or losing any information (apart from the information in the pixels to be removed)
To perform lossless JPEG cropping you can use jpegtran, an external command line tool distributed as part of the IJG library. For example, the following command removes the last column of pixels from a 768x512 image:
jpegtran -crop 767x512+0+0 -optimize image.jpg >image.jpg
The -crop switch specifies the rectangular subarea WxH+X+Y, and -optimize is an option for reducing file size without quality loss by optimizing the Huffman table. For a complete list of switches see jpegtran -help.
Once jpegtran is installed on your system, it can be invoked from R by system(). The following example first takes a sample image and saves it as JPEG. The image is then cropped, and the pixel values are compared to the values from the original image.
library("EBImage")
# resave a sample image as JPG
f = system.file("images", "sample.png", package="EBImage")
writeImage(readImage(f), "image.jpg", quality=90)
# do the cropping
system("jpegtran -crop 767x512+0+0 -optimize image.jpg >cropped.jpg")
# compare file size
file.size("image.jpg", "cropped.jpg")
## [1] 65880 65005
original = readImage("image.jpg")
dim(original)
## [1] 768 512
cropped = readImage("cropped.jpg")
dim(cropped)
## [1] 767 512
# check whether original values are retained
identical(original[1:767,], cropped)
## TRUE
Back to your specific use-case: your script could be further improved by examining image dimensions without actually loading the whole pixel array into R. For this you could, for example, use RBioFormats to only read image meatadata containing image dimensions into R. But you can also use another command line tool identify distributed as part of the ImageMagick suite to retrieve the image dimensions, as illustrated below.
path = "G:/Images/"
file.names = dir(path, full.names = TRUE, pattern =".jpeg")
reqd_dim = c(3099,2329,3)
cat(sprintf("Number of Image Files is: %d\n", length(file.names)))
for (i in seq_along(file.names)) {
file = file.names[i]
cat(sprintf("Checking dimensions of image number %d: ", i))
flush.console()
cmd = paste('identify -format "c(%w, %h)"', file)
res = eval(parse(text=system(cmd, intern=TRUE)))
# Checking if the dimensions are the same
if ( all(res==reqd_dim) ) {
cat("OK\n")
flush.console()
}
else {
cat("Correcting\n")
flush.console()
system(sprintf("jpegtran -crop %dx%d+0+0 -optimize %s >%s",
reqd_dim[1], reqd_dim[2], file, file))
}
}

Resources