That’s great, thanks.
Thanks for connecting the dots. Typo?
|x|<3.5 * radius
If we are talking about percentages, would radius = 3.5 * max_dimension * std_deviation (expressed in %) / 100
?
Yes, |x| < 3.5*std_dev
.
Yes to this statement as well?
New question.
gmic sp tiger,dog,wall echo_test
# tiger
# dog
# wall
echo_test:
echo_stdout "\n"
repeat $! local[$>]
echo_stdout ""{b}""
endl done quit
What if I wanted to do this without local
? Something like b#$>
doesn’t work. I am asking because I cannot use local
in some cases; e.g., when iterating over pixels like for MSE but I still want to echo the input names with the respective MSE values.
echo_stdout {$>,b}
More generally, {ind,feature}
works for all kind of image features.
That’s right, I flipped the items by mistake to !{feature,ind}
What is the simplest way to store values and strings into a vector? Two ways demonstrated by @garagecoder post #9 and @David_Tschumperle post #12 of the other thread seem over complicated (or I am just not used to doing it that way). Here is an example. Goal: make each line a vector element in s
and echo the fifth element of s
somewhere down the pipeline.
This
is
the
number
0
okay?
For that, I usually use numbered variables as $lineN
(where N
is an integer) to simulate an array of variables. It’s quite easy to manage. For instance, the following code read each non-empty line of a text file:
read_lines:
verbose -
input raw:"$1",uchar # Get ascii values of the file as a new image of data in [0,255].
split -,{'\n'} # Decompose as lines (and discard '\n').
repeat $! line$>={$>,t} done # Assign line content to numbered variables
remove
verbose +
echo[] "Fifth non-empty line : "$line4
echo[] "First 5 non-empty-lines :"
repeat 5 echo[] " ["{1+$>}"] = "${line$>} done
Then, using it like this : $ gmic read_lines README
gives:
$ gmic read_lines README
[gmic]-0./ Start G'MIC interpreter.
Fifth non-empty line : | | __ |_| | / | | || |
First 5 non-empty-lines :
[1] = --------------------------------------------------------------------------------
[2] = --------------------------------------------------------------------------------
[3] = _____ _ __ __ _____ _____
[4] = / ____| | | | / |_ _/ ____|
[5] = | | __ |_| | / | | || |
[gmic]-0./ End G'MIC interpreter.
Thanks: read_lines
explains a lot. The part that I was missing was split -,{'\n'}
. I don’t quite know when to use echo[]
and echo_stdout
though. Besides error versus standard output, echo[]
appears to require less quoting "
, so maybe I will stick with that one. I guess my choice would affect the logs…? I also discovered the string
command, so I could do
echo_test:
string "hello world"
split -,{'\ '}
repeat $! word$>={$>,t} done
echo[] ""
echo[] $word1
echo[] ""
q
# world
Next question. I have been playing around with norm
s and deciding what I could use them for. I wanted to try calculating the Frobenius norm but I don’t know a simple way to add all the elements of a matrix. norm
is sqr compose_channels + sqrt
; I guess that is supposed to be done before compose_channels +
… Wait, are we already calculating the f-norm since an image is already a matrix?
I’m not sure how you define this for multi channel images because it’s equivalent to euclidean norm of an m x n matrix treated as a vector (i.e. output is a scalar). In other words sum the squares of the elements then take the square root of that. For single channel image it would just be:
sqr echo {sqrt(is)} # output to console
Yes, that occurred to me after writing the post . I think norm
takes the L2-norm of every I
vector.
by @afre, using Inkscape
If that is true, then a matrix would be a line of pixels… I think a more useful application might be to move a f-norm window over an image for each channel but I don’t know how to do that yet . Sure enough, Google Scholar does yield papers where people use norms as a filter.
…
Speaking of image filtering, one exercise would be to write a command that passes an arbitrary kernel (given by user) through an image like the Convolution matrix filter in GIMP, but it might not be able to do a f-norm, because I don’t know what the matrix is…?
Yes, it’s per pixel vector norm
One way is with a convolution kernel:
sp dog
sqr
(1) # a single pixel image with value 1
resize. 5,5
convolve.. . # convolve input by kernel
rm.
sqrt
For larger kernels you could do that with the boxfilter command (approximate but fast), there’s also the option of using the math parser. It’s very easy to specify a kernel by image values (here I use the backslash to escape newline for clarity):
(0,1,0;\
1,1,1;\
0,1,0)
I need some ideas to get started with finding edges. There are so many commands that I don’t know where to start. So far, I have only made threshold images based on Boolean expressions. Not necessarily but something like this would be nice:
Source: Images borrowed from this paper.
…
What I have so far. Not great but a start .
edge_test0:
l50_ 1 # L* channel from L*a*b* D50
laplacian - {im}
fill i<ia+sqrt(iv)&&i>ia-sqrt(iv)
negate 1
Edge detection is a large subject in itself, but the one I usually end up using is gradient_norm. Combined with an exponent or a threshold (of which there are many, perhaps give ‘otsu’ a try) it’s quite hard to beat in general situations, for such a simple operation.
Used gradient_norm
before and wanted to try laplacian
. Otsu
is cleaner overall but may ignore weaker edges. Turns out it is still the right one to use:
Speaking of convolution, I came across Sharpening Images with Edge Detection in the Imagemagick docs. I am having trouble understanding and reproducing the first command.
convert face.png -define convolve:scale='100,100%' \
-morphology Convolve 'Log:0x2' face_sharpen.png
Hint: jump here for details on -define
and here for -morphology
. Actually, 0x2
might have to do with -gaussian-blur
. I am not quite sure; I haven’t used IM in a while. (@snibgo, maybe you could help me with the explanation.)
This is what I have but it doesn’t match.
convolve_test0:
(-1,-1,-1;\
-1,+8,-1;\
-1,-1,-1)
/. 8
(0,0,0;\
0,1,0;\
0,0,0)
+[-2,-1]
b {2/3.5},1,1
convolve.. .
rm.
Hmm those docs have some suspect descriptions of so-called ‘LoG’. I assume the -define part is setting parameters for the convolution (I never use imagemagick). The idea of that kernel is to save doing two separate steps (blur then laplacian) by using laplacian of a gaussian as the kernel:
gmic image.png blur 2 laplacian
becomes:
gmic 11,11,1,1 gaussian 2,2 laplacian image.png convolve. ..
however for gmic I doubt this saves any time due to the fast blur command.
Edit: oops was in a hurry there, it should really be normalised and I guess you want to actually sharpen! In which case it’s:
gmic 11,11,1,1 gaussian 2,2 normalize_sum laplacian image.png +convolve. .. rm... +
I suppose some memory can be saved by adding 1 to the kernel centre instead of copy and add…
gmic 11,11,1,1 gaussian 2,2 normalize_sum laplacian +f 0 =. 1,50%,50% + sp dog convolve. ..
The trouble that I am having and your examples seem to do as well is that we end up with a softer image. At least they appear to have less of a punch.
sp tiger
'Log:0x2'
'Log:0x.5'
PS
I also came across fun effects.
And wrote a filter that highlights or darkens edges.
Hmm it could be due to inversion and clipping instead of normalise. Try this:
gmic sp tiger +b 2 laplacian. -*. 10 - c 0,255
Okay, upon reading more of the IM docs, I know what the difference is. 0x2
does refer to the blur, except IM’s blur has two components: one for the radius and the other for the sigma of the blur. When radius=0, radius is optimized for the specified sigma (and according to the precision).
If you look at the image below, which I set to be roughly the same perceptively (same psnr), the IM version retains more fine detail whereas G’MIC contains more contrast.
G’MIC → +b .92,1,1 laplacian. - c 0,255
Magick → -define convolve:scale="100,100%" -morphology Convolve "Log:0x.5"
That seems like a blur setting less than 1, perhaps 0.8. In any case it makes no more sense to match gmic exactly to IM than the reverse; so long as both are mathematically correct there’s no problem and it’s just user preference about the control of it. Interesting to investigate anyway