I have a datafile with some points that looks like this (notice that some values are missing):
x A 1-A
0 1 0
0.25 0 1
0.5
0.75 0 1
1 1 0
1.25 0 1
1.5
1.75 0 1
2 1 0
2.25 0 1
2.5
2.75 0 1
3 1 0
3.25 0 1
3.5
3.75 0 1
4 1 0
4.25 0 1
5
I would like to plot this data into a graph that looks like this (notice that the pink line is the max of the other two lines at all times):
In order to do so, I have the following gnuplot code, which works well for all but the pink line:
gnuplot> max(x,y) = (x>y) ? x : y
gnuplot> plot "dataset1" using 1:2 title "A" with lines lc rgbcolor "black" lw 4, \
>"dataset1" using 1:3 title "1-A" with lines lc rgbcolor "blue" lw 4, \
>"dataset1" using 1:(max($2,$3)) title "Fuzzy(A)" with lines lc rgbcolor "purple" lw 4
However, this produces the following graph (notice that the purple line does not do what the pink line in the previous image does):
How could I go about producing a graph that looks like the first image, as opposed to what I have?
The are two reasons for this:
As long as you don't do calculations inside the using statement, the empty 'fields' are treated as missing data. If you have two points with a 'missing' point between them, they are still connected with a line. If the point between is undefined (as it becomes when you calculate), the other two points aren't connected. The simplest case showing this is:
set yrange[-0.1:1.1]
set multiplot layout 2,1
plot 'dataset1' using 1:2 with lines
plot 'dataset1' using 1:($2) with lines
unset multiplot
So you must filter you data with an external tool in order to plot it correctly (see also In gnuplot, with “set datafile missing”, how to ignore both “nan” and “-nan”?):
You need to calculate the intersections between the two curves in order to get your 'purple' line.
Here is a variant using awk which does both the filtering (uses only the rows which have three fields (if (NF == 3) and skips the first line which the description), and calculates the intersections and add them to the output:
max(x,y) = (x>y) ? x : y
plot "dataset1" using 1:2 title "A" with lines lc rgbcolor "black" lt -1 lw 4, \
"dataset1" using 1:3 title "1-A" with lines lc rgbcolor "blue" lt -1 lw 4, \
"< awk 'BEGIN { prevX = prevA = prevN = currX = currA = currN = -1 } \
{ if (NF == 3 && NR > 1) { \
if (currA != -1) { prevA = currA; prevN = currN; prevX = currX } \
currX = $1; currA = $2; currN = $3; \
if ((prevA != -1) && (prevA != currA)) { \
print 0.5*(currX + prevX), 0.5*(currA+prevA), 0.5*(currN+prevN); \
}\
print \
}\
}' dataset1" \
using 1:(max($2,$3)) title "Fuzzy(A)" with lines lc rgbcolor "purple" lt 2 lw 4
With some other little settings
set termoption dashed
set key above right
set autoscale fix
set offset 0,0,0.1,0
and 4.6.4 I get the following result:
Related
I have a matrix. e.g. 5 x 5 matrix
$ cat input.txt
1 5.6 3.4 2.2 -9.99E+10
2 3 2 2 -9.99E+10
2.3 3 7 4.4 5.1
4 5 6 7 8
5 -9.99E+10 9 11 13
Here I would like to ignore -9.99E+10 values.
I am looking for average of all entries after dividing diagonally. Here are four possibilities (using 999 in place of -9.99E+10 to save space in the graphic):
I would like to average over all the values under different shaded triangles.
So the desire output is:
$cat outfile.txt
P1U 3.39 (Average of all values of Lower side of Possible 1 without considering -9.99E+10)
P1L 6.88 (Average of all values of Upper side of Possible 1 without considering -9.99E+10)
P2U 4.90
P2L 5.59
P3U 3.31
P3L 6.41
P4U 6.16
P4L 4.16
It is being difficult to develop a proper algorithm to write it in fortran or in shell script.
I am thinking of the following algorithm, but can't able to think what is next.
step 1: #Assign -9.99E+10 to the Lower diagonal values of a[ij]
for i in {1..5};do
for j in {1..5};do
a[i,j+1]=-9.99E+10
done
done
step 2: #take the average
sum=0
for i in {1..5};do
for j in {1..5};do
sum=sum+a[i,j]
done
done
printf "%s %5.2f",P1U, sum
step 3: #Assign -9.99E+10 to the upper diagonal values of a[ij]
for i in {1..5};do
for j in {1..5};do
a[i-1,j]=-9.99E+10
done
done
step 4: #take the average
sum=0
for i in {1..5};do
for j in {1..5};do
sum=sum+a[i,j]
done
done
printf "%s %5.2f",P1L,sum
Just save all the values in an aray indexied by row and column number and then in the END section repeat this process of setting the beginning and end row and column loop delimiters as needed when defining the loops for each section:
$ cat tst.awk
{
for (colNr=1; colNr<=NF; colNr++) {
vals[colNr,NR] = $colNr
}
}
END {
sect = "P1U"
begColNr = 1; endColNr = NF; begRowNr = 1; endRowNr = NR
sum = cnt = 0
for (rowNr=begRowNr; rowNr<=endRowNr; rowNr++) {
for (colNr=begRowNr; colNr<=endColNr-rowNr+1; colNr++) {
val = vals[colNr,rowNr]
if ( val != "-9.99E+10" ) {
sum += val
cnt++
}
}
}
printf "%s %.2f\n", sect, (cnt ? sum/cnt : 0)
sect = "P1L"
begColNr = 1; endColNr = NF; begRowNr = 1; endRowNr = NR
sum = cnt = 0
for (rowNr=begRowNr; rowNr<=endRowNr; rowNr++) {
for (colNr=endColNr-rowNr+1; colNr<=endColNr; colNr++) {
val = vals[colNr,rowNr]
if ( val != "-9.99E+10" ) {
sum += val
cnt++
}
}
}
printf "%s %.2f\n", sect, (cnt ? sum/cnt : 0)
}
.
$ awk -f tst.awk file
P1U 3.39
P1L 6.88
I assume given the above for handling the first quadrant diagonal halves you'll be able to figure out the other quadrant diagonal halves and the horizontal/vertical quadrant halves are trivial (just set begRowNr to int(NR/2)+1 or endRowNr to int(NR/2) or begColNr to int(NF/2)+1 or endColNr to int(NF/2) then loop through the resultant full range of values of each).
you can compute all in one iteration
$ awk -v NA='-9.99E+10' '{for(i=1;i<=NF;i++) a[NR,i]=$i}
END {for(i=1;i<=NR;i++)
for(j=1;j<=NF;j++)
{v=a[i,j];
if(v!=NA)
{if(i+j<=6) {p["1U"]+=v; c["1U"]++}
if(i+j>=6) {p["1L"]+=v; c["1L"]++}
if(j>=i) {p["2U"]+=v; c["2U"]++}
if(i<=3) {p["3U"]+=v; c["3U"]++}
if(i>=3) {p["3D"]+=v; c["3D"]++}
if(j<=3) {p["4U"]+=v; c["4U"]++}
if(j>=3) {p["4D"]+=v; c["4D"]++}}}
for(k in p) printf "P%s %.2f\n", k,p[k]/c[k]}' file | sort
P1L 6.88
P1U 3.39
P2U 4.90
P3D 6.41
P3U 3.31
P4D 6.16
P4U 4.16
I forgot to add P2D, but from the pattern it should be clear what needs to be done.
To generalize further as suggested. Assert NF==NR, otherwise diagonals not well defined. Let n=NF (and n=NR) You can replace 6 with n+1 and 3 with ceil(n/2). Which can be implemented as function ceil(x) {return x==int(x)?x:x+1}
Here's my input file :
1.37987
1.21448
0.624999
1.28966
1.77084
1.088
1.41667
I would like to create bins of a size of my choice to get histogram-like output, e.g. something like this for 0.1 bins, starting from 0 :
0 0.1 0
...
0.5 0.6 0
0.6 0.7 1
...
1.0 1.1 1
1.1 1.2 0
1.2 1.3 2
1.3 1.4 1
...
My file is too big for R, so I'm looking for an awk solution (also open to anything else that I can understand, as I'm still a Linux beginner).
This was sort of already answered in this post : awk histogram in buckets but the solution is not working for me.
This should be very close if not exactly right. Consider it a starting point at least and verify/figure out the math yourself (in particular decide/verify which bucket(s) an exact boundary match like 0.2 should go into - 0.1 to 0.2 and/or 0.2 to 0.3?):
$ cat tst.awk
BEGIN { delta = (delta == "" ? 0.1 : delta) }
{
bucketNr = int(($0+delta) / delta)
cnt[bucketNr]++
numBuckets = (numBuckets > bucketNr ? numBuckets : bucketNr)
}
END {
for (bucketNr=1; bucketNr<=numBuckets; bucketNr++) {
end = beg + delta
printf "%0.1f %0.1f %d\n", beg, end, cnt[bucketNr]
beg = end
}
}
$ awk -f tst.awk file
0.0 0.1 0
0.1 0.2 0
0.2 0.3 0
0.3 0.4 0
0.4 0.5 0
0.5 0.6 0
0.6 0.7 1
0.7 0.8 0
0.8 0.9 0
0.9 1.0 0
1.0 1.1 1
1.1 1.2 0
1.2 1.3 2
1.3 1.4 1
1.4 1.5 1
1.5 1.6 0
1.6 1.7 0
1.7 1.8 1
Note that you can assign the bucket delta size on the command line, 0.1 is just the default value:
$ awk -v delta='0.3' -f tst.awk file
0.0 0.3 0
0.3 0.6 0
0.6 0.9 1
0.9 1.2 1
1.2 1.5 4
1.5 1.8 1
$ awk -v delta='0.5' -f tst.awk file
0.0 0.5 0
0.5 1.0 1
1.0 1.5 5
1.5 2.0 1
This is also possible :
awk -v size=0.1
'{ b=int($1/size); a[b]++; bmax=b>bmax?b:bmax; bmin=b<bmin?b:bmin }
END { for(i=bmin;i<=bmax;++i) print i*size,(i+1)*size,a[i] }' <file>
It essentially does the same as the solution of EdMorton, but starts printing buckets from the minimum value which is default 0. It essentially takes negative numbers into account.
Here is my stab at solving this with Awk.
To run: awk -f belowscript.awk inputfile
BEGIN {
PROCINFO["sorted_in"]="#ind_num_asc";
delta = (delta == "") ? 0.1 : delta;
};
/^-?([0-9][0-9]*|[0-9]*(\.[0-9][0-9]*))/ {
# Special case the [-delta - 0] case so it doesn't bin in the [0-delta] bin
fractBin=$1/delta
if (fractBin < 0 && int(fractBin) == fractBin)
fractBin = fractBin+1
prefix = (fractBin <= 0 && int(fractBin) == 0) ? "-" : ""
bins[prefix int(fractBin)]++
}
END {
for (var in bins)
{
srange = sprintf("%0.2f",delta * ((var >= 0) ? var : var-1))
erange = sprintf("%0.2f",delta * ((var >= 0) ? var+1 : var))
print srange " " erange " " bins[var]
}
}
Some notes:
I added support for providing the bin size on the command line like Ed Morton did.
It only prints the bins that contain something
Which bin an exact match goes in - the smaller or the larger bin naturally with this approach negated when going negative, and required tweaking to make it consistent.
the 0 boundary needed special casing for those numbers in the first negative bin, since there is no such number as -0. Awk's associative arrays use strings for keys, so "-0" was possible, and with #ind_num_asc sort order for the for loop, seems to sort the -0 properly - though this may not be portable.
Another solution with Python
# draw histogram in command line with Python
#
# usage: $ cat datafile.txt | python this_script.py [nbins] [nscale]
# The input should be one column of numbers to be piped in.
#
# forked from https://gist.github.com/bgbg
from __future__ import print_function
import sys
import numpy as np
def asciihist(it, bins=10, minmax=None, str_tag='',
scale_output=30, generate_only=False, print_function=print):
"""Create an ASCII histogram from an interable of numbers.
Author: Boris Gorelik boris#gorelik.net. based on http://econpy.googlecode.com/svn/trunk/pytrix/pytrix.py
License: MIT
"""
ret = []
itarray = np.asanyarray(it)
if minmax == 'auto':
minmax = np.percentile(it, [5, 95])
if minmax[0] == minmax[1]:
# for very ugly distributions
minmax = None
if minmax is not None:
# discard values that are outside minmax range
mn = minmax[0]
mx = minmax[1]
itarray = itarray[itarray >= mn]
itarray = itarray[itarray <= mx]
if itarray.size:
total = len(itarray)
counts, cutoffs = np.histogram(itarray, bins=bins)
cutoffs = cutoffs[1:]
if str_tag:
str_tag = '%s ' % str_tag
else:
str_tag = ''
if scale_output is not None:
scaled_counts = counts.astype(float) / counts.sum() * scale_output
else:
scaled_counts = counts
if minmax is not None:
ret.append('Trimmed to range (%s - %s)' % (str(minmax[0]), str(minmax[1])))
for cutoff, original_count, scaled_count in zip(cutoffs, counts, scaled_counts):
ret.append("{:s}{:>8.2f} |{:<7,d} | {:s}".format(
str_tag,
cutoff,
original_count,
"*" * int(scaled_count))
)
ret.append(
"{:s}{:s} |{:s} | {:s}".format(
str_tag,
'-' * 8,
'-' * 7,
'-' * 7
)
)
ret.append(
"{:s}{:>8s} |{:<7,d}".format(
str_tag,
'N=',
total
)
)
else:
ret = []
if not generate_only:
for line in ret:
print_function(line)
ret = '\n'.join(ret)
return ret
if __name__ == '__main__':
nbins=30
if len(sys.argv) >= 2:
nbins = int(sys.argv[1])
nscale=400
if len(sys.argv) == 3:
nscale = int(sys.argv[2])
dataIn =[]
for line in sys.stdin:
if line.strip() != '':
dataIn.append( float(line))
asciihist(dataIn, bins=nbins, scale_output=nscale, minmax=None, str_tag='BIN');
I wrote a program in SciLab that solves sudoku's.
But it can only solve sudoku's that always have a square with 1 possible value.
Like very easy and easy sudoku's on brainbashers.com .
Medium sudoku's always reach a point that they do not have a square with 1 possible value.
How can I modify my code to solve these, more difficult sudoku's?
///////////////////////////////////////////////////////////////////////////
////////////////////////// Check Sudoku ///////////////////////////////
///////////////////////////////////////////////////////////////////////////
function r=OneToNine(V) // function checks if the given vector V contains 1 to 9
r = %T // this works
u = %F
index = 1
while r == %T & index < 10
for i=1 : length(V)
if V(i)==index then
u = %T
end
end
index=index+1
if u == %F then r = %F
else u = %F
end
end
if length(V) > 9 then r = %F
end
endfunction
function y=check(M) // Checks if the given matrix M is a solved sudoku
y = %T // this works too
if size(M,1)<>9 | size(M,2)<>9 then // if it has more or less than 9 rows and columns
y = %F // we return false
end
for i=1 : size(M,1) // if not all rows have 1-9 we return false
if OneToNine(M(i,:)) == %F then
y = %F
end
end
endfunction
function P=PossibilitiesPosition(board, x, y)
// this one works
// we fill the vector possibilites with 9 zeros
// 0 means empty, 1 means it already has a value, so we don't need to change it
possibilities = [] // a vector that stores the possible values for position(x,y)
for t=1 : 9 // sudoku has 9 values
possibilities(t)=0
end
// Check row f the value (x,y) for possibilities
// we fill the possibilities further by puttin '1' where the value is not possible
for i=1 : 9 // sudoku has 9 values
if board(x,i) > 0 then
possibilities(board(x,i))=1
end
end
// Check column of the value (x,y) for possibilities
// we fill the possibilities further by puttin '1' where the value is not possible
for j=1 : 9 // sudoku has 9 values
if board(j, y) > 0 then
possibilities(board(j, y))=1
end
end
// Check the 3x3 matrix of the value (x,y) for possibilities
// first we see which 3x3 matrix we need
k=0
m=0
if x >= 1 & x <=3 then
k=1
else if x >= 4 & x <= 6 then
k = 4
else k = 7
end
end
if y >= 1 & y <=3 then
m=1
else if y >= 4 & y <= 6 then
m = 4
else m = 7
end
end
// then we fill the possibilities further by puttin '1' where the value is not possible
for i=k : k+2
for j=m : m+2
if board(i,j) > 0 then
possibilities(board(i,j))=1
end
end
end
P = possibilities
// we want to see the real values of the possibilities. not just 1 and 0
for i=1 : 9 // sudoku has 9 values
if P(i)==0 then
P(i) = i
else P(i) = 0
end
end
endfunction
function [x,y]=firstEmptyValue(board) // Checks the first empty square of the sudoku
R=%T // and returns the position (x,y)
for i=1 : 9
for j=1 : 9
if board(i,j) == 0 & R = %T then
x=i
y=j
R=%F
end
end
end
endfunction
function A=numberOfPossibilities(V) // this checks the number of possible values for a position
A=0 // so basically it returns the number of elements different from 0 in the vector V
for i=1 : 9
if V(i)>0 then
A=A+1
end
end
endfunction
function u=getUniquePossibility(M,x,y) // this returns the first possible value for that square
pos = [] // in function fillInValue we only use it
pos = PossibilitiesPosition(M,x,y) // when we know that this square (x,y) has only one possible value
for n=1 : 9
if pos(n)>0 then
u=pos(n)
end
end
endfunction
///////////////////////////////////////////////////////////////////////////
////////////////////////// Solve Sudoku ///////////////////////////////
///////////////////////////////////////////////////////////////////////////
function G=fillInValue(M) // fills in a square that has only 1 possibile value
x=0
y=0
pos = []
for i=1 : 9
for j=1 : 9
if M(i,j)==0 then
if numberOfPossibilities(PossibilitiesPosition(M,i,j)) == 1 then
x=i
y=j
break
end
end
end
if x>0 then
break
end
end
M(x,y)=getUniquePossibility(M,x,y)
G=M
endfunction
function H=solve(M) // repeats the fillInValue until it is a fully solved sudoku
P=[]
P=M
if check(M)=%F then
P=fillInValue(M)
H=solve(P)
else
H=M
end
endfunction
//////////////////////////////////////////////////////////////////////////////
So it solves this first one
// Very easy and easy sudokus from brainbashers.com get solved completely
// Very Easy sudoku from brainbashers.com
M = [0 2 0 0 0 0 0 4 0
7 0 4 0 0 0 8 0 2
0 5 8 4 0 7 1 3 0
0 0 1 2 8 4 9 0 0
0 0 0 7 0 5 0 0 0
0 0 7 9 3 6 5 0 0
0 8 9 5 0 2 4 6 0
4 0 2 0 0 0 3 0 9
0 1 0 0 0 0 0 8 0]
But it doens't solve this medium:
M2= [0 0 6 8 7 1 2 0 0
0 0 0 0 0 0 0 0 0
5 0 1 3 0 9 7 0 8
1 0 7 0 0 0 6 0 9
2 0 0 0 0 0 0 0 7
9 0 3 0 0 0 8 0 1
3 0 5 9 0 7 4 0 2
0 0 0 0 0 0 0 0 0
0 0 2 4 3 5 1 0 0]
Error code when trying to solve medium sudoku:
-->solve(M2)
!--error 21
Invalid index.
at line 14 of function PossibilitiesPosition called by :
at line 3 of function getUniquePossibility called by :
at line 20 of function fillInValue called by :
at line 182 of function solve called by :
at line 183 of function solve called by :
at line 183 of function solve called by :
at line 183 of function solve called by :
at line 183 of function solve called by :
solve(M2)
at line 208 of exec file called by :
_SCILAB-6548660277741359031.sce', 1
while executing a callback
Well, one of the easiest way to program a Sudoku solver (not the most efficient) could be to solve each cell with all the possible options recursively (which could be similar to the "Backtracking" algorithm) until a full answer is found.
Another options (I would say it's better) is to iterate trough all the squares solving all the "simple" squares and storing the possible answers in the others squares, then repeat (now you have some more solved), repeat the process until the Sudoku is solved or no more squares can be solved directly. Then you could try the rest with brute-force or Backtracking (maybe half or more of the Sudoku is already solved, so it may be relatively efficient)
Anyway,with a quick search I found this Wikipedia page where some Sudoku solving algorithms are explained with pseudo-code examples, hopefully these will be useful to you
I have a matrix that's m x 2:
.2 .8
.3 .7
.7 .3
...
and I would like to map the '>' operation to each row, resulting in the column like so:
0
0
1
...
However, I can't seem to find a good way to do this without removing columns and applying a custom function to the matrix in something like
res = arrayfun(#mapfunction, matrix(:,1))
function cl = mapfunction(v)
cl = v > .5
Is there a simpler way?
You can simply calculate a Boolean / logical column that checks to see whether the first column is greater than the second column for every row in your matrix:
res = matrix(:,1) > matrix(:,2);
Given your example matrix:
matrix = [.2 .8; .3 .7; .7 .3];
This is what I get:
>> res = matrix(:,1) > matrix(:,2)
res =
0
0
1
I recently had to merge images like these:
These images represents different sorts of events happening at different locations. The idea is to merge these images in a way to keep the "hot" zones of each images (red-yellow-green) to get a global picture of what happens globally.
In my current approach, I take take the second image and extracts the red/green channel, in order to form a mask of the relevant parts, like this:
Then I merge it with the first image by using this mask so only the relevant parts gets copied over.
Here is the script used for this:
#!/bin/bash
# Extract RGB
convert b.png -colorspace RGB -separate b-sep-%d.png
# Keep red & green only
convert b-sep-2.png b-sep-0.png -compose minus -composite b-tmp-br.png
convert b-sep-2.png b-sep-1.png -compose minus -composite b-tmp-bg.png
convert b-tmp-br.png b-tmp-bg.png -compose plus -composite -level 10%,100% b-mask.png
# Composite!
composite b.png a.png b-mask.png final.png
Here is my current result so far:
As you can see, it works well for the red-yellow-green part, but the blue part is missing. The problem is that if I enlarge the mask to include the blue part, then it'll overwrite red-yellow-green parts from the first image with blue parts from the second one! This is already visible in the final result, the top left first image red part is overwritten by the green part of the second image.
Getting the blue part correctly is trickier, but I think the following algorithm should work (pseudo code):
function merge_pixel(pixel a, pixel b)
{
points = { :red => 4, :yellow => 3, :green => 2, :blue => 1, :default => 0 }
a_points = points[a.color()]
b_points = points[b.color()]
return a_points > b_points ? a : b
}
That is, when merging images, copy the pixel from image a or b depending on which color is the most important for the final image. Maybe this algorithm isn't sound (e.g how to handle the gradient part, maybe with a threshold), feel free to debunk it.
REAL QUESTION:
using imagemagick, how to:
get the desired result using any technique/whatever?
implement the algorithm from above?
You don't need to answer both questions, just finding an imagemagick way of getting the desired result is fine.
[EDIT]
Hint: I just had an idea, I think you can generate the masks (including blue parts) for both images and do some "set intersection/union/difference/whatever" of the masks to generate the appropriate "final" mask so only the real relevant parts of image b is copied over.
Ok, I did the "merge_pixel" strategy and it worked!
require 'RMagick'
include Magick
def pixel_score(p)
r, g, b = [p.red, p.green, p.blue].map{ |i| i / 256 }
is_flat = (r-g).abs < 20 && (r-b).abs < 20 && (g-b).abs < 20
is_grey = is_flat && r < 200
is_red = r >= 240 && g <= 100 # && b < 10
is_yellow = r >= 150 && g >= 100 && b <= 10
is_green = r <= 200 && g >= 200 && b <= 100
is_cyan = r <= 10 && g >= 100 && b >= 30
is_blue = r <= 10 && g <= 100 && b >= 200
if is_red
(999**8) + (r - g)
elsif is_yellow
(999**7) + (r + g)
elsif is_green
(999**6) + (g - b)
elsif is_cyan
(999**5) + (g + b)
elsif is_blue
(999**4) + (b - g)
else
(999**1) + r ** 3 + g ** 2 + b
end
end
def rmagick_merge(file_a, file_b, file_merged)
img_a = ImageList.new(file_a)
img_b = ImageList.new(file_b)
result = Image.new(img_a.columns, img_a.rows)
img_a.columns.times do |col|
img_a.rows.times do |row|
pixel_a = img_a.pixel_color(col, row)
pixel_b = img_b.pixel_color(col, row)
pixel = [pixel_a, pixel_b].sort_by{ |p| pixel_score(p) }.last
#pixel = [pixel_a, pixel_b].sort_by{ |p| [p.red - p.green, p.green, p.blue] }.first
#pixel = [pixel_a, pixel_b].sort_by{ |p| [p.red - p.green - p.blue * 100, p.green, p.blue] }.last
result.pixel_color(col, row, pixel)
end
end
result.format = "PNG"
result.write(file_merged)
end
if __FILE__ == $0
if ARGV.size < 3
puts "usage #{__FILE__} a.png b.png merged.png"
exit 1
end
rmagick_merge(ARGV[0], ARGV[1], ARGV[3])
end
Here is the result (not perfect but fine tuned for my needs on the real pictures):