ImageMagick command to Image::Magick code - perl

I found the following ImageMagick command in some forum and works nicely for compare images.
convert image1 image2 -compose Difference -composite -format '%[fx:mean*100]' info:
The result is one floating point number and low values (like 0.5 and such) mean: the images are similar.
Using the attached images, it produces the number: 0.0419167. (the images are very similar)
I want to use Image::Magick (perlmagick). The problem is i don't know how to achieve the same result with perlmagick. The following works, and creates the composite, (black image using the attached images)
#!/usr/bin/env perl
use 5.014;
use strict;
use warnings;
use Data::Dumper;
use Image::Magick;
my $i1 = Image::Magick->new;
$i1->Read('s1.jpg');
my $i2 = Image::Magick->new;
$i2->Read('s2.jpg');
$i1->Composite(image => $i2, compose=>'Difference');
$i1->Display();
The question is, how to convert the result to an number, e.g. how to achieve the
... -format '%[fx:mean*100]' info:
part of the above command in PerlMagick for getting only the above "number"?
Is someone want test, attaching two images:

I am guessing you want to call
my $format = $iI->Fx( expression=>'mean*100' );
This should do the same thing as what you had on command line.
see here for more detailed documentation of fx in PerlMagick
( there is an example fx line on the page )
On the same page: search for #statistics.
Seems to me the mean is accessible via
my #stats = $i1->Statistics;
my $mean = $stats[3]; # hash would be nice, mean is 4th according to docs
print "$mean\n"; # outputs something like .0413 for me
Not sure if this is what you need, but that is how I found the 'mean',
whether this is precisely what fx mean does I am not certain and honestly not willing to understand the entire doc on the fx method ;)
BTW, the script I still had was based on Randall Schwartz's post

Just found the answer.
Image::Magick has the Statistics method, so calling:
my #stat = $i1->Statistics();
say Dumper \#stat
prints image stats for each channel, like:
$VAR1 = [
'8',
'0',
'0.168627450980392',
'0.0418661437908497', <--- mean RED
'0.0236850206077085',
'-0.250788990333716',
'0.312238727773058',
'8',
'0',
'0.133333333333333',
'0.0385273202614379', <- mean GREEN
'0.0193189321997568',
'-0.435325792918546',
'0.0686645009183608',
'8',
'0',
'0.23921568627451',
'0.0453563725490196', <- mean BLUE
'0.0301331898766906',
'0.309072091600589',
'0.66336367830764'
];
e.g. averaging the 3 numbers, got the wanted number: 0.0419166122004357
use List::Util qw(sum)
my $s = sum #stat[3,10,17];
say $s/3;
From the docs: misc methods
Statistics() returns the image statistics for each channel in the
image. The returned values are an array of depth, minima, maxima,
mean, standard deviation, kurtosis, skewness, and entropy values in
RGB, CMYK, RGBA, or CMYKA order (depending on the image type).

Related

Is there a symbolic implementation of the PDL API?

To test a matrix algorithm, I would like to be able to calculate with variables instead of numbers only but not change the algorithm itself.
The direction in which I assume there is a solution (but probably there are others equally welcome) would be to use polymorphism within PDL or replace the PDL library with a symbolic library with the same API as PDL has.
To illustrate my point, the following is a simple algorithm implemented using PDL:
use utf8;
use strict;
use warnings;
use PDL;
sub algorithm ($$) {
my $alpha = shift;
my $beta = shift;
my $A = pdl(
[ cos $alpha, -sin $alpha ],
[ sin $alpha, cos $alpha ],
);
my $B = pdl(
[ cos $beta, -sin $beta ],
[ sin $beta, cos $beta ],
);
print $A x $B;
}
Now to test the code, instead of many calls like
algorithm 0.1, 0.1;
algorithm 0.2, 0.1;
algorithm 0.1, 0.2;
…
use a single call similar to
algorithm 'α', 'β';
or – equally acceptable – similar to
algorithm pdl('α'), pdl('β');
which would eventually output a matrix of terms in the named variables α and β (of course, Latin variable names a and b should be equally possible).
Ideally, nothing in the algorithm would have to change for this; in the end, I want to test the algorithm as it is, not a different algorithm. Adding a use PDL::Symbolic qw( pdl ); or use SPDL qw( pdl ); statement in the header as extension or replacement of use PDL; to me seems an acceptably small exception to the rule of not changing anything.
The only solution which comes to my mind is basically to re-implement the PDL API, at least the functions used in my algorithm and probably with less consideration for efficiency, but using a symbolic object instead of each piddle cell, and probably expanded with an indexing-naming feature for the cells within larger piddles for improved usability.
Is there a better way than programming this library myself from scratch?
Very short answer: No.
Slightly more helpful answer: PDL's whole purpose is to operate on binary data (as C or Fortran would), in the computer's memory (using the "shared memory" model), at great speed. You are describing an entirely different piece of software.

How to recognize and print the segmented character

I'm applying some image processing techniques in MATLAB I was able to segment the license plate as show in the figure below:
Now if I apply the followig code in a for loop:
ocrResults = ocr(finalImage);
ocrResults.Text
I'm getting output like VV, u etc that means these characters are not recognized properly. So, how can I fix that? It's not mandatory to use the OCR class so any other solution will also work.
MATLAB's ocr function accepts additional inputs as Name/Value pairs. In your case, to limit the output to numeric values, simply add in the following parameters:
ocrResults = ocr( finalImage, 'CharacterSet', '0123456789' );
However, I'm not certain doing just this will get you the output you desire. It might be helpful to erode the image and add additional blackspace around each character. Take advantage of other possible input parameters which may be added, such as 'TextLayout'.

random binomial distributed dataset in perl

I try to do in perl what I succeedd in R but is difficult to combine with my downstream needs.
in R I did the following
library("MASS")
d <- rnegbin(100000, mu = 250, theta = 2)
hist(d, breaks=1000, xlim=c(0,1000))
producing the nice graph I need with a peak round 180-200 and a tail to the right.
Could someone help me code the perl equivalent using Math::Random
I tried this but do not get the right shape
use Math::Random qw(random_negative_binomial);
# random_negative_binomial($n, $ne, $p)
# When called in an array context, returns an array of $n outcomes
# generated from the negative binomial distribution with number of
# events $ne and probability of an event in each trial $p.
# When called in a scalar context, generates and returns only one
# such outcome as a scalar, regardless of the value of $n.
# Argument restrictions: $ne is rounded using int(), the result must be positive.
# $p must be between 0 and 1 exclusive.
# I tried different variable values but never got the right shape
my #dist = random_negative_binomial($n, $ne, $p);
what values do I need to mimic the R results?
I need the same range of values on X and the same general shape
Thanks for any help, I did not find illustrated examples of that package
Stephane
I don't know much about statistics, but since nobody else comes forward: I would use the Perl Data Language PDL (which I use for other things) and fetch the PDL::Stats::Distr module. You can find an example that looks somewhat similar to yours here http://pdl-stats.sourceforge.net/Distr.htm. The module includes pmf_binomial (mass function) and mme_binomial (distribution). You will also need the PGPLOT module.
You will need some random data:
$data = pdl 1..100000; ## generate linear 1 - 100000
$data = $data->random; ## make them random between 0..1

Detect a PNG image's length from a stream

Basically my question is like this one, but from PNG instead of JPEG.
More specifically, I have a bunch of PNG images concatenated together and I want to discover their lengths, so I can split the stream in pieces corresponding to individual images.
I do not need to decode or validate the images. I can assume that the input stream is composed of valid PNG images and do not want to verify that. Instead, it is useful for me to do this as quickly as possible, so the less amount of decoding operations are required, the better.
Here you have a perl script, based on this answer
#!/usr/bin/perl
undef $/;
$_ = <>;
$n = 0;
for $match (split(/(?=\x{89}PNG\x{0d}\x{0a}\x{1a}\x{0a})/)) {
open(O, sprintf('>temp%04d.png',++$n));
print O $match;
close(O);
}
Save this as, say splitpng.pl and run perl splitpng.pl < myfile
This is not 100% foolproof (the rigourous way would be to count chunks sizes, as per Jongware's comment), but the probabilty of having that signature inside a PNG should be small.

Issue on sprintf in Matlab

How to print in Matlab Like following....
0.01000E+02
I have tried
sprintf('%12.5e',[0.01000E+02])
it is giving me
1.00000e+000
You format is a bit specific. You should consider writing your own output function.
But a few pointers:
Make e large with upper
only 2 digits in exp number through a regexp. new_string = regexprep(old_string,'\d(\d{2})$','\1')
the thing with leading 0 in exp representation is not standard - so maybe multiply with 1e2, print the float and later attach the E+02.
Something like ['0.0' strrep(sprintf('%12.5E',v*100), '.', '')] (with v your value) should work if I understand correctly your format.