Dear Colleagues.
Could you help me please with next question.
I want to resize huge amount of images and substitute original images with resized for saving disk space. But before substitution I want to be sure, that resized image is the same original image but with different dimensions (not white list, not Malevich's square and so on).
Is there a way to check such similarity to be sure that resizing was successful?
Thanks.
One idea might be to downscale your image into a tentative down-resed version, then scale it back up to the original size and compare that with the original. If they seem pretty similar, overwrite the original with the tentative conversion, if not, report error.
Here's how you might do that in bash with comments. It can be rehashed into other languages of course, or you can use a system() to shell out and use this command line version from another language.
#!/bin/bash
# Downscale an image and check if correct
# Supply image name as parameter
original="$1"
tentative="t-$$-$original"
echo DEBUG: tentative filename=$tentative
# Get size of original so we can resize back up to that size
origsize=$(identify -format "%G" "$original")
echo DEBUG: origsize=$origsize
# Do downsizing of image, saving result tentatively
convert image.jpg -resize 800x800 "$tentative"
# Test quality/success of conversion by looking at PSNR
PSNR=$(convert "$tentative" -resize $origsize\! "$original" -metric PSNR -format "%[distortion]" -compare info:)
echo DEBUG: PSNR=$PSNR
# PSNR above 20 is pretty indicative of good similarity - use "bc" as shell doesn't do floats
if [ $(echo "$PSNR>20" | bc) -eq 1 ]; then
echo $original looks good
else
echo $original something wrong
fi
One thing to beware of is transparency - don't convert from a GIF or PNG (both of which support transparency) to a JPEG (which doesn't) and then resize and compare - you are asking for trouble. You will see in my script above that I retain the image extension and pre-pend bits to the front rather than the end of the filename.
well as far as the size is concerned you can simply check the dimensions
in matlab
[x,y]=size(im);
this will let you know that the if the image has been resized
To check if the image is the same you can use feature extraction such as SURF features.
Extract the surf features, match them if you get 100% ~ 90% match you have the same image!!
Related
I'm trying to batch convert PDF's to PNG's. Previously, this was always done manually through GIMP by importing a PDF, then converting it to PNG.
With the script that I wrote, this should all be done automatically. But for some reason, the image quality I get from using
convert \
-density 300 \
-adaptive-resize 2048 \
-define png:compression-level=9 \
"File1"
"File2"
Doesn't have the same "quality" compared to doing it via GIMP. See the image below for the difference in image quality.
In GIMP, I don't change much to the image. When I import the PDF, I change the resolution to 2048 pixels. When I convert and export it to PNG, I use all the default values GIMP offers, nothing fancy.
Changing the density to a higher or lower value doesn't do anything to the image. Also changing adaptive-resizing to normal resizing doesn't do much.
In the example image, both pictures are 2048 pixels wide. As you can see the lower image has a lot thicker/blurrier lines.
Example image comparison:
So, I have found a way around my problem.
Increasing the PPI kind of helped but still not as much as I would have liked it to.
Eventually I added this:
-channel A -fx "p*(p>0.2?22:0)"
Just some simple piece of code I found somewhere around here. It checks for the Alpha levels in the picture and if it's below a certain threshold it will just remove or "make the pixel" transparent. If it's over the threshold it will just boost the pixel to maximum visibility. Combined with the high PPI I dont get any "half pixels" anymore.
I have a PDF file that I render using Adobe PDF engine as well as another PDF rip. I want to try to identify places where they render differently. The problem is that they both render with slightly different anti-alias, color, and very minimal positional differences. I am more concerned with larger difference. I'd like to compare the attached files match1.png and match2.png. These two should match. The files diff1.png and diff2.png should NOT match. They should fail as the one has a missing letter. I've worked with ImageMagick's compare, but haven't got good enough results to ignore the slight rendering differences and only focus on the major ones. I think the below algorithm could work, but I wasn't sure how to read PNG files and compare them pixel by pixel.
sample image files
compare each pixel in ImageA to the same pixel in ImageB. Also compare to each neighboring pixel in ImageB
Find the nearest matching pixel from all the tested pixels in ImageB.
Store the color difference of this closest matching pixel as difference index for that pixel in ImageA.
Repeat this calculation for each pixel in ImageA.
Normalize the difference values to make the smallest difference a zero. Un-normalized values might be (3,8,5,18) and normalized may be (0,5,2,15) or some other type of normalizing function.
Then count up how many pixels are over a threshold value, say, 5 or whatever. Then this count of 'bad' pixels could be used to calculate the probability that there is a rendering error in one of the images.
This is just a sample algorithm. I wasn't sure how to process PNG files pixel by pixel. I'd be open to a PHP solution or a solution using command line tools such as imagemagick, etc.
If you flicker the two match image (alternately display one then the other and back and forth) you will see that both orange colors are different. It is not just difference due to anti-aliasing at the edges.
So using Imagemagick 6, compare will show quite a lot of change (as red). If using Imagemagick 7, use magick compare. See http://www.imagemagick.org/Usage/compare/#compare.
compare -metric rmse match1.png match2.png match_diff.png
2304.18 (0.0351595)
Here the difference is one 3.5%, but the difference image show a lot of red since every pixel has a different value.
Another way to see the difference is with -compose difference. The whiter the result the more difference.
convert match1.png match2.png -compose difference -composite match_diff2.png
This does not show much different, so all values are only slightly different. But by stretching the dynamic range, you can see where it is most different.
One way to check neighboring pixels is to repeat the compare shifting one image 1 pixel in each direction (using -roll +X+Y) and perhaps trimming off 1 pixel all around each image using -shave XxY. You can do that in a loop and save each result. Then use -evaluate-sequence min to find the minimum (closest pixel values) for each image at the same pixel location. That would be equivalent to search the 3x3 neighborhood of compares. The problem is you won't know which image gave the max result.
P.S. You can also use compare -metric AE -fuzz 5% . The fuzz value will allow the compare to ignore values that within that percent. This does not seem to be working in Imagemagick 6.9.9.10 but is working in Imagemagick 7.0.6.10.
im7 magick compare -metric AE -fuzz 5% match1.png match2.png match_diff3.png
219487
This says that there are 219487 mismatched pixels of any amount. Here are where they differ.
I would blur the images slightly to remove any fine detail, then look for the maximum difference. A simple difference metric is dE76. Spatial CIELAB does something very similar (if a little fancier).
Here's an implementation using php-vips:
#!/usr/bin/env php
<?php
require __DIR__ . '/vendor/autoload.php';
use Jcupitt\Vips;
$a = Vips\Image::newFromFile($argv[1]);
$b = Vips\Image::newFromFile($argv[2]);
$a = $a->gaussblur(2);
$b = $b->gaussblur(2);
$diff = $a->dE76($b);
# output a 500 pixel across difference map
$scale = 500.0 / $diff->width;
$diff->multiply(5)->resize($scale)->writeToFile("map.png");
echo("maximum image difference is " . $diff->max() . " dE76\n");
For your images, I see:
$ ./measure_diff.php match1.png match2.png
maximum image difference is 13.739426612854 dE76
$ ./measure_diff.php diff1.png diff2.png
maximum image difference is 55.040554046631 dE76
The 13 in the first pair is just differences in colour rendering, the 55 in the second is the extra comma. It's very visible on the map image:
I searched everywhere but couldn't find an answer to this.
I would like to output all images of a folder in 50Kb exactly and maintain the original aspect ratio.
I tried ImageMagick and resizing to 250x250 e.g but it is not working for me, what it does is change the first dimension and adapt the other, so output images have not the same size.
for image in `ls $#*.jpg`; do
mogrify "${image}" -resize 250x250 "${image}"
done
How do it? Thanks
Updated Answer
If you want the file size of the images to be limited to 50kB, use:
convert input.jpg -define jpeg:extent=50KB output.jpg
Original Answer
Use mogrify, but be careful it will overwrite all your images:
mogrify -resize 250x250! *.jpg
In general, when using mogrify I like to use the -path option to specify an output directory for results, like this to avoid originals getting overwritten:
mkdir results
mogrify -path results ...
Your script will work if you add the ! after the resize which forces the resize even if it distorts the shape of the picture.
If you want a way to do something similar with Python, I wrote an answer that works pretty well here. It does a binary search for a JPEG quality that satisfies a maximum size requirement.
When working with JPEG image properties (resolution, sampling, etc.) and you export the final product are you ALWAYS double dipping into 'jpegification'?
From my understanding when you load a JPEG image into an image manipulation tool (GIMP, Photoshop, ImageMagick, etc.) it goes like so:
Import JPEG
Decode JPEG into easier workable format (Bitmap)
Manipulate the pixels
Export back into JPEG (REDOING JPEG QUANTIZATION AGAIN, even if you copy the original JPEG parameters it's a double dip)
Am I correct in this?
Thanks!
Any areas of the image that have changed would have to be quantized again anyway.
In theory, an application could keep the quantized values lying around then use them again. However,
That would require 3 times as much memory. The quantized values require 16 bits to store (+8 bits for the pixel value).
If you changed the sampling or quantization tables, the quantized values would have to be recalculated.
There would be very few cases where it would make sense to hang on to the quantized DCT values.
I think it depends on what you do after reading the image... but I think you can check for yourself for any particular operation and whether it has re-quantised by using this function in ImageMagick
identify -format "%#\n" image.jpg
bb1f099c2e597fdd2e7ab3d273e52ffde7229b9061154c970d23b171df3aca89
which calculates the checksum (or signature as IM calls it) of the pixels - disregarding the header information.
So, if I create a file of random noise, like this
convert -size 1000x1000 xc:gray +noise gaussian image.jpg
and get the checksum of the data, like this
identify -format "%#\n" image.jpg
84474ba583dbc224d9c1f3e9d27517e11448fcdc167d8d6a1a9340472d40a714
I can then use jhead to change the comment in the header, like this
jhead -cl "Comment" image.jpg
Modified: image.jpg
and yet the checksum remains unchanged so I would say jhead has NOT re-quantised the data.
I guess my point is that your statement that images are ALWAYS re-quantised is not 100% accurate and it depends on what you actually do to the image, and further, that I am showing a way you can readily check for yourself whether any processing has actually caused requantisation. HTH !!!
Problem description:
In imagemagick, it is very easy to diff two images using compare, which produces an image with the same size as the two images being diff'd, with the diff data. I would like to use the diff data and crop that part from the original image, while maintaining the image size by filling the rest of the space with alpha.
The approach I am taking:
I am now trying to figure the bounding box of the diff, without luck. For example, below is the script I am using to produce the diff image, see below. Now, I need to find the bounding box of the red color part of the image. The bounding box is demonstrated below, too. Note that the numbers in the image are arbitrary and not the actual values I am seeking.
compare -density 300 -metric AE -fuzz 10% ${image} ${otherImage} -compose src ${OUTPUT_DIR}/diff${i}-${j}.png
You asked quite a while ago - I found the question just today. Since I think the answer might still be of interest, I propose the following.
The trim option of convert removes any edges that are the same color as the corner pixels. The page or virtual canvas information of the image is preserved. Therefore, if you run
convert -trim edPdf.png - | identify -
it gives you:
PNG 157x146 512x406+144+32 8-bit PseudoClass 2c 1.08KB 0.000u 0:00.000
and the values you are looking for are (144,228), where the latter is 406-146-32 because you looked for the lower left corner whereas (+144+32) gives the upper left corner.