ImageMagick: Looking for a fast way to blur an image - perl

I am searching for a faster way to blur an image than to use the GaussianBlur.
The solution I am looking for can be a command line solution, but I prefer code in perl notation.
Actually, we use the Perl image magick API to blur images:
# $image is our Perl object holding a imagemagick perl image
# level is a natural number between 1 and 10
$image->GaussianBlur('x' . $level);
This works fine, but with the level height the amount of time it consumes seems to grow exponentially.
Question: How can I improve the time used for the bluring operation?
Is there another faster approach to blur images?

I found that the suggested method of resizing image for blur imitation makes output look very pixelated for very large values of sigma like 25 or more. So I finally came to an idea of downscale-blur-enlarge, which makes very nice result (almost indistinguishable from simple blur with large sigma):
# plain slow blur
convert -blur 0x25 sample.jpg blurred_slow.jpg
# much faster
convert -scale 10% -blur 0x2.5 -resize 1000% sample.jpg blurred_fast.jpg
On my i5 2.7Ghz it shows up to 10x speed up.

The documentation speaks of the difference between Blur and GaussianBlur.
There has been some confusion as to which operator, "-blur" or the
"-gaussian-blur" is better for blurring images. First of all "-blur"
is faster, but it does this using two stage technique. First in one
axis, then in the other. The "-gaussian-blur" operator on the other
hand is more mathematically correct as it blurs in all directions
simultaneously. The speed cost between the two can be enormous, by a
factor of 10 or more, depending on the amount of bluring involved.
[...]
In summary, the two operators are slightly different, but only
minimally. As "-blur" is much faster, use it. I do in just about all
the examples involving blurring. Large
That would simply be:
$image->Blur( 'x' . $level );
But the Perl ImageMagick documentation has the same text on both Blur and GaussianBlur (emphasis mine). I can't try now, you would have to benchmark it yourself.
Blur: reduce image noise and reduce detail levels with a Gaussian operator of the given radius and standard deviation (sigma).
GaussianBlur: reduce image noise and reduce detail levels with a Gaussian operator of the given radius and standard deviation (sigma).
An alternative that the documentation also lists is resizing the image to be very tiny, and then enlarging again.
Using large sigma values for image bluring is very slow. But onw
technique can be used to speed up this process. This however is only a
rough method and could use some mathematicaly rigor to improve
results. Essentually the reason large blurs are slow is because you
need a large window or 'kernel' to merge lots of pixels together, for
each and every pixel in the image. However resize (making image
smaller) does the same thing but generates fewer pixels in the
process. The technique is basically shrink the image, then enlarge it
again to generate the heavilly blured result. The Gaussian Filter is
especially useful for this as you can directly specify a Gaussian
Sigma define.
The example command line code is this:
convert rose: -blur 0x5 rose_blur_5.png
convert rose: -filter Gaussian -resize 50% \
-define filter:sigma=2.5 -resize 200% rose_resize_5.png

Not sure if I could still help OP with this, but I recently tried the same for a blurred screenlock picture.
I found that omitting the -blur part saves even more calculation time and is still delivering great results for a 4K picture:
convert in.png -scale 2.5% -resize 4000% out.png
# real: 0.174s user: 0.144s size: 1.2MiB
convert in.png -scale 10% -blur 0x2.5 -resize 1000% out.png
# real: 0.136s user: 2.117s size: 1.2MiB
convert in.png -blur 0x25 out.png
# real: 2.425s user: 21.408s size: 1KiB
However, you couldn't go lower than 2.5% with 3840x2160. It will resize the image. I guess the eps value differs for pictures of other sizes.
It should be noted, that the resulting image sizes differ noticably!

Related

Lossless compression of a sequence of similar grayscale images

I would like to have the best compression ratio of a sequence of similar grayscale images. I note that I need an absolute lossless solution (meaning I should be able to check it with an hash algorithm).
What I tried
I had the idea to convert my images into a video because there is a chronology between images. The encoding algorithm would compress using the fact that not all the scene change between 2 pictures. So I tried using ffmpeg but I had several problems due to sRGB -> YUV colorspace compression. I didn't understand all the thing but it's seems like a nightmare.
Example of code used :
ffmpeg -i %04d.png -c:v libx265 -crf 0 video.mp4 #To convert into video
ffmpeg -i video.mp4 %04d.png #To recover images
My second idea was to do it by hand with imagemagik. So I took the first image as reference and create a new image that is the difference between image1 and image2. Then I tried to add the difference image with the image 1 (trying to recover image 2) but it didn't work. Noticing the size of the recreated picture, it's clear that the image is not the same. I think there was an unwanted compression during the process.
Example of code used :
composite -compose difference 0001.png 0002.png diff.png #To create the diff image
composite -compose difference 0001.png diff.png recover.png #To recover image 2
Do you have any idea about my problem ?
And why I don't manage to do the perfect recover with iamgemagik ?
Thanks ;)
Here are 20 samples images : https://cloud.damien.gdn/d/f1a7954a557441989432/
I tried a few ideas with your dataset and summarise what I found below. My calculations and percentages assume that 578kB is a representative image size.
Method 1 - crush - 69%
I just ran pngcrush on one of your images like this:
pngcrush -bruteforce input.png crushed.png
The output size was 400kB, so your image is now only taking 69% of the original space on disk.
Method 2 - rotate and crush - 34%
I rotated your images through 90 degrees and crushed the result:
magick input.png -rotate 90 result.png
pngcrush -bruteforce result.png crushed.png
The rotated crushed image takes 34% of the original space on disk.
Method 3 - rotate and difference - 24%
I rotated your images with ImageMagick, then differenced two adjacent images in the series and saved the result. I then "pngcrushed" that which resulted in 142kB, or 24% of the original space.
Method 4 - combined to RGB - 28%
I combined three of your single channel images into a 3-channel RGB image and pngcrushed the result:
magick 000[123].png -combine result.png
pngcrush -bruteforce result.png crushed.png
That resulted in a 490kB file containing 3 images, i.e. 163kB per image or 28% of the original size.
I suspect video with "motion" estimation/detection would yield the best results if you are able to do it losslessly.
You might get some gain out of MNG, which is intended for lossless animation compression. You can use libmng to try it out.

Connect pixels in matlab

Please suggest how to connect the dotted pixels in an image like below:
Original Image
I want to apply OCR on this image. I have tried some morphological operations such as thickening and bridging but not obtaining the correct output as expected (NH5343320).
The original image is also uploaded. On applying horizontal edge detection on the original image, I got the dotted image as above. Is there any another methods available for applying OCR in these kind of images.
I would crop out and fill in a template for each of the available letters. Presumably, that would be the letters [A-Z] and the digits [0-9] like this.
0.png
3.png
Now I would do a sub-image search for each of them in your original image. I am doing this at the command-line with ImageMagick but you could use Matlab, OpenCV, or CImg or the Python, Perl, PHP, C, C++ bindings of ImageMagick.
So, I look for the 3 first:
compare -metric rmse -dissimilarity-threshold 1 -subimage-search plate.png 3.png result.png
25607.9 (0.390752) # 498,46
So, the 3 is found at coordinates 498,46. There will be 2 output files, output-0.png which looks like this:
and output-1.png in which you can see the brightest areas showing where the match is best:
Likewise with the 0:
compare -metric rmse -dissimilarity-threshold 1 -subimage-search plate.png 0.png result.png
31452.6 (0.479936) # 664,44

Why smaller PNG image takes up more space than the original after getting resized by GraphicsMagic

The original PNG image is 800x1200 and takes up about 34K. After the images is resized by GraphicsMagick to 320x480 size, the resulting images takes up approximately 37K. (For comparison, if the image is resized with Paint on Windows 7 then the resulting image is 40K.) What gives? The whole point of resizing an image was to save space. How should GraphicsMagick be used to shrink the image size?
PNG is a lossless format and compresses the image data by first performing a step called prediction and then applying the same algorithm used in zlib. The prediction step is a crucial one in order to effectively compress the file, and it is based on the values of earlier neighbors pixels.
So, suppose you have a large PNG in black & white (by that I really mean only black and white, some people confuse that by grayscale sometimes). Also suppose it is not a tiny checkerboard pattern. In many regions of this image, you will have a relatively large white region, and then a relatively large black region, and so on. When the predictor is inside one of these large regions, it has no trouble to correctly predict that the current pixel intensity is exactly equal to the last one. This makes it easier to better compress the data describing your image.
Now, let us downscale this black & white image using some resampling filter different than nearest neighbor (let's say Lanczos). This has a great chance to turn your black & white image into a grayscale one, which has a much greater intensity range. This potentially makes the job of the predictor much harder, and thus the final file size might be larger.
For instance here is a black & white 256x256 PNG image which takes 5440 bytes, a resizing of it (using 3-lobed Lanczos) to 120x120 which now takes 7658 bytes, and another resizing (using nearest neighbor) to 120x120 which occupies 2467 bytes.
PNG is a compressed format. Sometimes trying to compress a maximally compressed item actually results in a larger item. So if the 800x1200 is resized to a smaller size, but the result retains everything that was in the original, because the original is already as minimal as possible, you could see this happen. To demonstrate this, try using 7zip to compress some data with ultra compression. Then try compressing the compressed file. Often the second compressed file will be larger than the first.

Tesseract Trained data

Am trying to extract data from reciepts and bills using Tessaract , am using tesseract 3.02 version .
am using only english data , Still the output accuracy is about 60%.
Is there any trained data available which i just replace in tessdata folder
This is the image nicky provided as a "typical example file":
Looking at it I'd clearly say: "Forget it, nicky! You cannot train Tesseract to recognize 100% of text from this type of image!"
However, you could train yourself to make better photos with your iPhone 3GS (that's the device which was used for the example pictures) from such type of receipts. Here are a few tips:
Don't use a dark background. Use white instead.
Don't let the receipt paper crumble. Straighten it out.
Don't place the receipt loosely on an uneven underground. Fix it to a flat surface:
Either place it on a white sheet of paper and put a glas platen over it.
Or use some glue and glue it flat on a white sheet of paper without any bend-up edges or corners.
Don't use a low resolution like just 640x480 pixels (as the example picture has). Use a higher one, such as 1280x960 pixels instead.
Don't use standard exposure. Set the camera to use extremely high contrast. You want the letters to be black and the white background to be really white (you don't need the grays in the picture...)
Try to make it so that any character of a 10-12 pt font uses about 24-30 pixels in height (that is, make the image to be about 300 dpi for 100% zoom).
That said, something like the following ImageMagick command will probably increase Tesseract's recognition rate by some degree:
convert \
http://i.stack.imgur.com/q3Ad4.jpg \
-colorspace gray \
-rotate 90 \
-crop 260x540+110+75 +repage \
-scale 166% \
-normalize \
-colors 32 \
out1.png
It produces the following output:
You could even add something like -threshold 30% as the last commandline option to above command to get this:
(You should play a bit with some variations to the 30% value to tweak the result... I don't have the time for this.)
Taking accurate info from a receipt is not impossible with tesseract. You will need to add image filters and some other tools such as OpenCV, NumPy ImageMagick alongside Tesseract. There was a presentation at PyCon 2013 by Franck Chastagnol where he describes how his company did it.
Here is the link:
http://pyvideo.org/video/1702/building-an-image-processing-pipeline-with-python
You can get a much cleaner post-processed image before using Tesseract to OCR the text. Try using the Background Surface Thresholding (BST) technique rather than other simple thresholding methods. You can find a white paper on the subject here.
There is an implementation of BST for OpenCV that works pretty well https://stackoverflow.com/a/22127181/3475075
i needed exactly the same thing and i tried some image optimisations to improve the output
you can find my experiment with tessaract here
https://github.com/aryansbtloe/ExperimentWithTesseract

Getting rid of interpolation/aliasing in EPS export of matlab?

I have a 2D color-map plot created with imagesc and want to export it as a .eps file using
print -depsc.
The problem is that the "original" image data is from a rather small matrix (131 x 131). When I view the image in the matlab figure window, I can see all the individual pixels if I zoom a bit closer.
When I export to eps, however, there seems to be some interpolation or anti-aliasing going on, in that neighboring pixels get blurred/blended into each other. I don't get the problem if I export a high-resolution tiff, but that format is not an option (as demanded by a publisher).
How can I obtain an eps that preserves the pixely structure of my image without applying interpolation or anti-aliasing?
The blurring actually depends on the rendering software your viewer application or printer uses. To get good results all the time, make each pixel in your image an 8x8 block of pixels of the same color. The blurring then only affects the pixels at the edge of each block. 8x8 blocks are best as they compress without nasty artifacts using DCT compression (sometimes used in eps files).
Old question, but highly ranked in Google, so here is my answer:
Open the .eps-file with a text editor, search for "Interpolate" and change the following "true" to "false". Repeat that step for all Interpolate-statements.
It might also depend on the viewer you're using, but probably just because some viewers ignore the "Interpolate"s...
Had the same problem using plot2svg in Matlab and exporting from Inkscape to eps.