G'MIC exercises

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 :slight_smile:

I updated my last post to match the PSNRs. As said in the edit, the IM version retains more fine detail whereas G’MIC contains more contrast. When the image is viewed in a small scale, G’MIC’s result looks better. When you examine it more closely, you would see some rounding of the shadows at the bottom of the long grass.

The advantage IM has over G’MIC is that the radius doesn’t have to grow proportionately with the standard deviation but has its own parameter. In my examples, I let IM choose its radius. That is why 0x2 has off putting thick lines compared with 0x.5.

PS Now, this might not seem like a problem, just a difference in approach, but in terms of post-processing, I have trouble keeping up the others in terms of sharpness in the PlayRaws. I.e., every time I use a smoothing or guided filter, I end up over-softening the image even though I am using a tiny radius. However, I still have much to learn about G’MIC, so maybe I need more experience.

Remember there’s also scaling to consider (the multiplier after laplacian in my last example). It would take a very determined person to find the exact matching parameters, not least because IM hides some details! Perhaps using IM options to dump the resulting kernel… but that’s far further than I’d have patience for. It’s beyond me I’m afraid :face_with_raised_eyebrow:

In code shown above, G’MIC caps the diameter (D) of the Gaussian filter. IM can cap the radius (R) (EDIT: I mean R in parentheses, not registered trademark. I hate computers that think they are smarter than me.), where D = 2*R+1.

The following is Windows BAT syntax, but copy-paste removes the new lines, so you’ll have to imagine them.

First, with G’MIC:

%GMIC% 11,11,1,1 gaussian 2,2 normalize_sum print

[gmic]-0./ Start G'MIC interpreter. [gmic]-0./ Input black image at position 0 (1 image 11x11x1x1). [gmic]-1./ Draw centered gaussian on image [0] with standard deviations (2,2) an d angle 0 deg. [gmic]-1./ Normalize image [0] with a unitary sum. [gmic]-1./ Print image [0] = '[unnamed]'. [0] = '[unnamed]': size = (11,11,1,1) [484 b of floats]. data = (7.76554e-005,0.000239195,0.0005738,0.001072,0.00155975,0.00176743,0.00155975,0.001072,0.0005738,0.000239195,7.76554e-005;0.000239195,(...),0.000239195;7.76554e-005,0.000239195,0.0005738,0.001072,0.00155975,0.00176743,0.00155975,0.001072,0.0005738,0.000239195,7.76554e-005). min = 7.76554e-005, max = 0.0402265, mean = 0.00826446, std = 0.0100279, coords_min = (0,0,0,0), coords_max = (5,5,0,0). [gmic]-1./ End G'MIC interpreter.

Now, with IM:

%IM%convert ^ xc: ^ -define showkernel=1 ^ -morphology Convolve:0 Gaussian:5x2 ^ null:

Kernel "Gaussian" of size 11x11+5+5 with values from 0 to 0.0402265 Forming a output range from 0 to 1 (Normalized) 0: 7.76554e-005 0.000239195 0.0005738 0.001072 0.00155975 0.00176743 0.0015597 5 0.001072 0.0005738 0.000239195 7.76554e-005 1: 0.000239195 0.000736774 0.00176743 0.00330199 0.00480437 0.00544406 0.00480437 0.00330199 0.00176743 0.000736774 0.000239195 2: 0.0005738 0.00176743 0.00423984 0.00792106 0.0115251 0.0130596 0.0115251 0.00792106 0.00423984 0.00176743 0.0005738 3: 0.001072 0.00330199 0.00792106 0.0147985 0.0215317 0.0243986 0.0215317 0.0147985 0.00792106 0.00330199 0.001072 4: 0.00155975 0.00480437 0.0115251 0.0215317 0.0313284 0.0354997 0.0313284 0.0215317 0.0115251 0.00480437 0.00155975 5: 0.00176743 0.00544406 0.0130596 0.0243986 0.0354997 0.0402265 0.0354997 0.0243986 0.0130596 0.00544406 0.00176743 6: 0.00155975 0.00480437 0.0115251 0.0215317 0.0313284 0.0354997 0.0313284 0.0215317 0.0115251 0.00480437 0.00155975 7: 0.001072 0.00330199 0.00792106 0.0147985 0.0215317 0.0243986 0.0215317 0.0147985 0.00792106 0.00330199 0.001072 8: 0.0005738 0.00176743 0.00423984 0.00792106 0.0115251 0.0130596 0.0115251 0.00792106 0.00423984 0.00176743 0.0005738 9: 0.000239195 0.000736774 0.00176743 0.00330199 0.00480437 0.00544406 0.00480437 0.00330199 0.00176743 0.000736774 0.000239195 10: 7.76554e-005 0.000239195 0.0005738 0.001072 0.00155975 0.00176743 0.00155975 0.001072 0.0005738 0.000239195 7.76554e-005

Compare the values from G’MIC and IM: they are the same (phew!).

By asking for a radius of zero, IM will automatically calculate the minimum radius that doesn’t lose precision:

%IM%convert ^ xc: ^ -define showkernel=1 ^ -morphology Convolve:0 Gaussian:0x2 ^ null: 2>&1 | findstr Kernel

Kernel "Gaussian" of size 15x15+7+7 with values from 0 to 0.0398008

So, if we use 15,15,1,1 in GMIC, we will get the same values as IM’s “Gaussian:0x2” or “Gaussian:7x2”. I won’t bore you with it, but I have checked, and they are the same.

I don’t know if G’MIC can automatically calculate the radius. But we can make the kernel over-large and then “autocrop” (EDIT: which is like IM’s “-trim”):

%GMIC% 20,20,1,1 gaussian 2,2 normalize_sum autocrop print

2 Likes

Thanks @garagecoder and @snibgo for your insights. I think I figured it out. Merging both worlds can be confusing for all of us but I learned a lot :smile:.

PS @snibgo Unfortunately, null: doesn’t output anything for me. I am currently using ImageMagick 7.0.7-21 Q16 x64 2018-01-06. I tried txt:

convert xc: -define showkernel=1 -morphology Convolve:0 Gaussian:0x2 txt:

and that output

# ImageMagick pixel enumeration: 1,1,65535,srgb
0,0: (65535,65535,65535)  #FFFFFFFFFFFF  white

Also, autocrop doesn’t crop to 15,15,1,1. Without parameters, I believe it discards 0s; therefore, it crops to 56,56,1,1. I guess I could mathematically determine the value. Or someone better at math could tell me how :wink:.

I’m not sure what you mean. “null:” is part of the command that starts with “%IM%convert”. Forget the IM part. Each ^ shows where I had a line-break, but those get stripped out by some software. I’ll try again:

convert xc: -define morphology:showkernel=1 ^
  -morphology Convolve:0 Gaussian:0x2 null: 2>&1 | findstr Kernel

That’s a single command line.

“findstr” is a Windows command, like grep on unix. We don’t care about the image, just the text output from “showkernel”.

I misread the G’MIC output: the command with autocrop I showed doesn’t crop at all. If I start with 300x300 pixels, it crops to 56x56, and most of the values are very small (less than 1e-16). Oops, sorry.

To use autocrop, you could first adjust so values that are near zero become exactly zero. I don’t know the best way to do this in G’MIC. But one method that seems to work is:

%GMIC% 300,300,1,1 gaussian 2,2 normalize_sum ^
  +select_color 1e-8,0 oneminus. mul autocrop 0 print output x.tiff

Explanation: make a 300x300 image, gaussian with SD=2, normalized. Make a copy that has values near zero to white, and make the others black. Flip black and white. Multiply this by the gaussian image, so now we have a gaussian that has all values near zero, actually zero. Autocrop to trim off columns and rows with just zeros. Print info, and save to x.tiff.

I think that’s what it does, but I’m probably wrong. Adjust the limit (1e-8) to whatever you want.

EDIT: IM v7 needs “-define morphology:showkernel=1”, with that “morphology:” prefix. V6 doesn’t need that prefix, and works fine with or without it.

What I meant was that the command up to null: doesn’t output anything so there is nothing to redirect. Must be something wrong with my IM version or setup…

PS I just posted about this in the IM forums under Bugs: http://www.imagemagick.org/discourse-server/viewtopic.php?f=3&t=33645.

PPS They got back to me. It isn’t a bug but a change in syntax. In IM7, we prefix showkernel with morphology:.  convert xc: -define morphology:showkernel=1 -morphology Convolve:0 Gaussian:0x2 null: 2>&1 | findstr Kernel

I have 2 problems that I am trying to figure out.

A. Dilate and erode aren’t very smooth. We end up with distinct shapes (square being the default).


If is better if I do a partial open



B. Related to #1 is that I would like to blur inward and outward.

My attempts here aren’t great. When inward, some outward pixels appear to have been affected and vice versa. Also the differences between the edges and the first blur values are too large to be natural. Maybe combine blurring with morphology?

This problem might be similar to the one that raw processors address where highlight and detail reconstruction are concerned.

Default morphological operations dilate and erode are indeed working in binary mode (Dilation (morphology) - Wikipedia), this is the most usual way dilation/erosion with a structuring element are defined.
But there exists also a real mode which makes them work with float-valued kernels (Dilation (morphology) - Wikipedia). This mode can be activated by setting the argument is_real to 1 when calling those operators.
E.g.:

gmic sp tiger 32,32 gaussian. 20% n. 100,255 dilate.. .,1,1

Same for erode:

About blurring a mask inward/outward, one suggestion:

It’s not really a blur, but using the distance function is great to get shaded mask around the contours:

$ gmic sp tiger norm ge 30% distance. 0 c 0,10 n 0,1

That’s a linear decay, but you can still make it more gaussian if needed afterwards.

1 Like

Nice example for functional morphology.
Still I would recommend odd kernel sizes to avoid shifts!

@samj’s thread Place some points on outlines with G'MIC got me thinking about making a starry sky out of an image. Here is what I have come up with so far:

I am naive about what stars are supposed to look like because I haven’t really examined a night sky. In my mind, stars should be round points of various sizes, colors and intensities, with a small Gaussian blur and perhaps a twinkle caused by our atmosphere and other forms of scattering (e.g., as a result of the camera hardware). Right now the image has lines, though I have finely chopped them up.

I will address color first. I would have to know how to color each line-object with a random but plausible color. I blotted out the greens and purples to the rainbow_lut but don’t know how to remove the black bars. I would also have to randomize the intensities within a reasonable range.

star_lut

Bonjour,

@afre

-to_rgba[-1]
-replace_color[-1] 100%,0,0,0,0,255,255,255,255,255

:o)

@samj The intent is to generate a rainbow clut without greens and purples. A lazy way is to use the rainbow_lut and remove the offending I elements. I don’t know how to do that. ATM I can only make them black. Then the plan is to apply this to the white specks of the tiger.

@afre

Can you illustrate your request because the French translation is not understandable.

:o)

This would be the French. Google Translate was helpful but I had to revise it.

Je voudrais représenter les couleurs de l’arc-en-ciel sans les verts et les pourpres dans un clut. Une manière paresseuse est d’utiliser rainbow_lut et d’enlever les couleurs que je ne veux pas. Au lieu de remplacer la couleur avec du blanc ou du noir, je voudrais enlever l’élément RGB (I) de clut lui-même.

@samj, sometimes DeepL:

gives more understandable translations: ???

L’intention est de générer un clut arc-en-ciel sans greens et violets. Une façon paresseuse est d’utiliser le rainbow_lut et d’enlever les éléments I offensants. Je ne sais pas comment faire ça. ATM Je ne peux que les rendre noirs. Ensuite, il est prévu de l’appliquer aux taches blanches du tigre.

@afre, to remove a particular vector value in an image:

foo :
  # Generate rainow lut with random holes (filled with -1).
  rainbow_lut f ">set()=(f=x+u(w/10);d=u(w/20));init(set());x<f?I:x<f+d?vector3(-1):(set();I)"

  # Discard colors having values -1.
  +discard. -1 r. {h/3},1,1,3,-1