Compare two images and get the percent difference - opencv

I known some ways to compare 2 images with ImageMagick or OpenCV
Using Objective-C, is there any way to compare two images and get a % difference value returned?
http://www.imagemagick.org/Usage/compare/#methods
How can I quantify difference between two images?
Image comparison - fast algorithm.
But for my case, I also have the same character with different position.
Image1:
Image2:
or
or
So, what should I do now to find the % difference value between Image1 and Image2?

This actually answers your question - which doesn't in fact ask anything about images 3 and 4 - but I fear it will not help you much.
As #GPPK suggests, you need to trim the extraneous material off around your kanji characters, which you can do with the -trim command in ImageMagick. I have added a thin red border so you can see where the edges are:
convert kanji2.png -trim kanji2-t.png
If you want do that to images 1 and 2, and then compare them, you can do that all in one go like this:
convert -metric ae kanji1.png kanji2.png -trim -compare -format "%[distortion]" info:
0
which shows there are zero pixels different in the resulting images if you trim kanji1 and kanji2.
If you compare the trimmed kanji1 and kanji3 like this, you get:
convert -metric AE kanji1.png kanji3.png -trim -compare -format "%[distortion]" info:
893184
which indicates 900,000 pixels of 5,000,000 are different.
Likewise, if you compare kanji1 and kanji4:
convert -metric AE kanji1.png kanji4.png -trim -compare -format "%[distortion]" info:
1.14526e+06
or 1.1 million of 5 million.
But this doesn't help when your images are a different size (scale), or rotated.
You could scale your images to a normalised size before comparing, and I guess that might help you become a bit more "scale invariant":
convert -metric AE kanji1.png kanji4.png -trim -scale 1000x1000! -compare -format "%[distortion]" info:
You could also rotate your images using a little iterative procedure that rotates the images through say +/- 20 degrees and chooses the one with the smallest trimmed bounding box to become a little more "orientation invariant". But then you will still have a problem if the characters are sheared, or fatter, or thinner, or brighter, or darker, or contrastier... I think you need to look into "Template Matching".

Related

ImageMagick: Divide AE distortion by total pixels in fx output info format

I am trying to use ImageMagick 7 to detect if a specific channel in an image is largely pure black and pure white (plus a little antialiasing, and there's a chance the image could be pure black). This is to distinguish from another kind of image that shares a naming convention but has photographic-like image data in the r/g/b channels.
(Basically both image types are specular maps from different engines. The one I'm trying to differentiate here is more modern and has the metallic map in the blue channel; the other is much older and just has the specular colour in the RGB channels and the gloss map in the alpha.)
Currently I'm comparing the channel to a clone of itself that has had a 50% threshold applied, using the AE metric to see if it's largely the same apart from a small amount of antialiasing, and a fuzz of 1% to account for occasional aberration from pure black/white. This command works, but of course at the moment it only returns the number of distorted pixels:
magick ( "file.png" -channel b -separate ) ^
( +clone -channel b -separate -threshold 50% ) ^
-fuzz 1% -metric AE -compare ^
-format "%[distortion]" info:
Because the input image sizes will vary, I want to divide the distortion by the total number of pixels in the image to get the relative amount of the image that's not pure black/white -- under 10% has seemed good so far in my manual testing -- but I can't get the format syntax right. Everything I've tried -- for example "%[fx:%[distortion]/w*h]" -- has given the magick: undefined variable `[distortion]' # error/fx.c/FxGetSymbol/1169 error.
What syntax should I use? (And if there's a better way to do what I'm doing, I always appreciate it!)
I believe the following is what you want in Imagemagick. Basically you save the distortion in -set option: argument and then use it in -fx later.
However, +clone gives you just the b channel, so there should be no need for -channel b -separate in your second line.
magick ( "file.png" -channel b -separate ) ^
( +clone -threshold 50% ) ^
-fuzz 1% -metric AE -compare ^
-set option:distort "%[distortion]" ^
-format "%[fx:distort/(w*h)]" info:
Fred (#fmw42) has already provided an excellent method. There is another method for differentiating pure black and white images from greyscale images with a fuller tonal scale which may interest you. Credit to Anthony Thyssen for the technique described here.
If you use -solarize 50% in ImageMagick it inverts all the highlights, so it effectively folds your histogram in half and all the whites become pure black and all the near-whites become near blacks. The command looks like this:
magick INPUT -solarize 50% OUTPUT
So, if I apply that to a couple of input images - the first one pure black and near white, the second a greyscale - and show the corresponding output image on the right you'll see the effect:
If you now inspect the mean and standard deviation of the two solarised images:
magick {a,b}-sol.jpg -format "%f, mean: %[mean], stdev: %[standard-deviation]\n" info:
a-sol.jpg, mean: 2328.91, stdev: 3175.67
b-sol.jpg, mean: 16319.5, stdev: 9496.04
you can see that the mean and standard deviation of the first (pure black and white) image is low because all the bright whites have folded to near blacks, whereas the mean and standard deviation of the greyscale image are both higher because the tones are more spread out.

What is distortion of a channel in an image?

I am relatively new to image processing, and I have a basic question: what is a distortion of red/green/blue channel, and the distortion of the entire image ?
taken from the imagemagick home site, in the compare command section:
In addition to the visual interpretation of the difference in an image and its reconstruction, we report a mathematical measure of the difference:
magick compare -verbose -metric mae rose.jpg reconstruct.jpg
difference.png Image: rose.jpg Channel distortion: MAE red: 2282.91
(0.034835) green: 1853.99 (0.0282901) blue: 2008.67 (0.0306503)
all: 1536.39 (0.0234439)
I dont understand the concept, can someone explain it to me ?
It's nothing to do with shape transformation or -distort if that is what is confusing you. All that "distortion" means, in this context, is "the specific error metric you requested". When comparing images there are various "metrics" you can select to measure:
AE
MAE
DSSIM
RMSE
etc.
and so on. The "distortion" is just a generic term meaning "whichever one of those you selected".
Here is a little example, a 100x10 red rectangle on a large black background.
convert -size 100x10 xc:red -bordercolor black -border 100 a.png
Now roll that 1-pixel to the right and re-save as b.png:
convert a.png -roll +1+0 b.png
Now compare absolute error:
compare -metric ae [ab].png null:
20
and you can see that the 10 pixels on the left and 10 pixels on the right of the red bar are "distorted".
Now roll down one pixel instead of across and compare again:
convert a.png -roll +0+1 b.png
compare -metric ae [ab].png null:
200
and the "distortion" is 100 pixels along the top pf the red bar that have become black and 100 pixels below the bottom of the red bar that have become red.
It may make more sense if you use the convert based method of comparing rather than the compare method. Here, you use the more common convert command with 2 images and then use -compare as the operator but you now will see the variable called distortion being used and that it just refers to whatever -metric you selected:
convert a.png b.png -metric AE -compare -format "%[distortion]" info:
200

Generating Low Resolution Black and White Text with Image Magick

I need to generate low resolution black and white images of texts in ImageMagick. These images will be plotted in a small LED matrix. The text need to have 7 pixels of height.
For now, I'm using:
convert -negate -threshold 15% -font Courier -size 80x11 caption:'hello' out.bmp
Output image:
Even with the height being more than I need, due to low resolution and anti-aliasing correction, the letters are not pretty and symmetric. Has anyone did this and can help me out?
Version: ImageMagick 6.8.9-9 Q16 x86_64
The solution I found was to use an TrueType font. Just got a free font from the internet and used it in the size it was built for.
P.S.: Switched for OpenCV as well. My Python app generates images dynamically. The cost for invoking ImageMagick several times(could get close to hundred) per minute is too high.
Posting a snippet, hope it helps.
import cv2 as cv
from PIL import ImageFont, ImageDraw, Image
# Creates a black image with 80x10 size
img = Image.new('RGBA', (80, 10), (0,0,0,0))
draw = ImageDraw.Draw(img)
# Load TrueType font of height size 8
font = ImageFont.truetype("font.ttf", 8)
# Draw text using the loaded font
draw.text((0, 0), "Hello World!", font=font)
img.save("out.bmp")
Output Image:
I would be inclined to output the letters larger than required, then to trim any extraneous spare space so as to make the most of the available resolution, then resize down to your specific needs:
convert -size 320x32 -font Courier label:'hello' -trim +repage -resize 80x8 +write out.gif
Mark, I think he wants a binary result. But you have an excellent idea.
Let's take Mark's result, threshold and then scaling down to 8 pixels tall. This ImageMagick command seems to work better than my earlier post.
Mark's Output:
convert wcwuj.gif -threshold 60% +write thresh.gif -scale x8 result.gif
Threshold Result:
Scaled Result:
Perhaps making Mark's image much larger and choosing a better threshold will produce a better result.
You have not told us what version of ImageMagick nor platform and you do not show your result for us to see what might be wrong. Also your ImageMagick syntax is not proper, though ImageMagick 6 is rather forgiving.
This is what I get using ImageMagick 6.9.10.8 Q16 Mac OSX Sierra. The first output is 8 pixels tall and the second output is scaled by 1000% (10x).
This forum does not seem to convert bmp to a usable format for display, so I am using GIF in place of BMP. But my results look the same whether BMP or GIF
convert -size x8 -font Courier label:'hello' -negate -threshold 20% +write out.gif -scale 1000% out2.gif
I have tried changing threshold, but much larger or smaller values make it worse. A range from about 10-30% produces the same results.
I have also tried using -monochrome in place of -threshold and get the following:
convert -size x8 -font Courier label:'hello' -negate -monochrome +write out3.gif -scale 1000% out4.gif
You might try a dot-matrix type font. See https://www.1001fonts.com/digital+dot-matrix-fonts.html?page=1&items=10. I have not tried any of them.
You could try some of the old X11 fonts. These were hand-drawn rather than being rendered from a set of curves, so they look good at very small sizes.
For example, if I run xfontsel I get things like this (enlarged for clarity):
Take a look in /usr/share/fonts/X11/misc.

Compare pixels moved but similar images using ImageMagick

When comparing two images, both of the images are the same, except that in one of the images the text is moved by a couple of pixels. Please take a look at the below URL. It is a GIF that shows the difference of both the similar images.
https://giphy.com/gifs/9x50JjoLSPZ7lKRebk
My team initially used compare command which doesn't address this issue. Need suggestions please?
You can remove all the text in Imagemagick and just compare the bars by thresholding the Saturation/Chroma channel and then doing the compare. The text is gray, so it has little if any saturation. The bars are cyan, so they are colored and have a medium to high saturation.
convert giphy.gif -colorspace HCL -channel g -separate +channel -threshold 5% +write tmp.gif miff:- | compare -metric rmse - null:
3164.96 (0.0482942)
So this is 4.8% different.
I save tmp.gif, which you do not need, only to show the result of the processing before the compare.
If your version of Imagemagick is too old and you do not have -colorspace HCL, then try HSL or HSB. C and S are similar and measure saturation/chroma.

How to treshold image from greyscale screen by webcome

I have image like this from my windstation
I have tried get thoose lines recognized, but lost becuase all filters not recognize lines.
Any ideas what i have use to get it black&white with at least some needed lines?
Typical detection result is something like this:
I need detect edges of digit, which seams not recognized with almost any settings.
This doesn't provide you with a complete guide as to how to solve your image processing question with opencv but it contains some hints and observations that may help you get there. My weapon of choice is ImageMagick, which is installed on most Linux distros and is available for OS X and Windows.
Firstly, I note you have date and time across the top and you haven't cropped correctly at the lower right hand side - these extraneous pixels will affect contrast stretches, so I crop them off.
Secondly, I separate your image in 3 channels - R, G and B and look at them all. The R and B channels are very noisy, so I would probably go with the Green channel. Alternatively, the Lightness channel is pretty reasonable if you go to HSL mode and discard the Hue and Saturation.
convert display.jpg -separate channel.jpg
Red
Green
Blue
Now make a histogram to look at the tonal distribution:
convert display.jpg -crop 500x300+0+80 -colorspace hsl -separate -delete 0,1 -format %c histogram:png:ahistogram.png
Now I can see all your data are down the dark, left-hand end of the histogram, so I do a contrast stretch and a median filter to remove the noise
convert display.jpg -crop 500x300+0+80 -colorspace hsl -separate -delete 0,1 -median 9x9 -normalize -level 0%,40% z.jpg
And a final threshold to get black and white...
convert display.jpg -crop 500x300+0+80 -colorspace hsl -separate -delete 0,1 -median 9x9 -normalize -level 0%,40% -threshold 60% z.jpg
Of course, you can diddle around with the numbers and levels, but there may be a couple of ideas in there that you can develop... in OpenCV or ImageMagick.

Resources