G'MIC exercises

Value of variable boundary will be used for all functions that have a boundary_conditions arguments that is not set. So if you always use the same boundary conditions in a math expression, it’s shorter to set the variable once and not pass the argument for each function call.

(Does const mean that it applies to all operations involving the boundaries and not just crop() ? Or are there other distinctions?)

Declaring it const has no particular meaning except that you tell the math expression compiler that this is a const variable, so its value will be set only once (just as if you’d put it in a begin(..) bloc.

  • What does a parameter without a variable mean? Why is it 0 instead of d ?

The four first variables of crop() corresponds to the location of the upper-left corner, so here, (x-2,y-2,0,c). The next four parameters set the crop size (and not the location of the lower-right corner), so in this case 5,5,1,1 for a 5x5 single channel crop.

It would be a crop starting from column 100 and having 100 columns width.

No particular reasons, it avoids dividing by zero and it creates cool rendering, but you can choose any value you want.

What is the difference between x-2,y-2,0,c,.. and x-2,y-2,d,c,..? If c means stepping through the channels, why can’t I use d for an image where there is only one slice? Edit: Oh, I think I used the wrong variable. z might be the correct term… Still, if I replace 0 with z, the resultant output is different.

What values do the omitted parameters take?

d is the depth, i.e. the number of slices, a constant equal to 1 in the case of 2D images. There is no slice #1 in such images (but only one slice #0). So, I’m not sure why you want to do this (cropping always outside the image domain).
You could eventually put z instead, which is always equal to 0 for 2D images, but then writting 0 is the same.

Actually, see crop() as a function that is overloaded with different signatures:

2 or 3 arguments : crop(x0,width,_boundary);
4 or 5 arguments : crop(x0,y0,width,height_boundary);
6 or 7 arguments : crop(x0,y0,z0,width,height,depth_boundary)
8 or 9 arguments : crop(x0,y0,z0,c0,width,height,depth,spectrum_boundary);

The number of parameters you give tells what version of crop() must be used.

Just tired and simply curious. :blush:

I tried again and found that 0, d and z yield the same output. However, d takes 20x the processing time (with the fans whirling). I wonder why that is… What is it processing for so long? Shouldn’t there be an error since slice 1 DNE?

I understand that part but what values do the omitted parameters take? E.g., if I do crop(100,100), does y0,z0,c0=0, height,depth,spectrum=h,z,c and _boundary=0?

It just double the processing time for me, and it’s not that surprising, as accessing values outside the image domain with boundary conditions is slightly slower (involves additional tests or calculations). And this happens for all pixels in your case.

Typically, crop(X0,W0) will be equivalent to crop(X0,y,z,c,W0,h,d,s,boundary)

1 Like

What is an efficient way to select the top $1% brightest pixels?

ATM, I made this. Hope it is doing what it is supposed to do; please check my work.

gmic sp tiger +brightest_pixels_afre 10
brightest_pixels_afre: skip ${1=10}
  n={wh*$1/100-1}
  +l
    norm 100%,100%,1,1,1 +extract_region.. .,0,1 rm.. 
    l. sort - z 0,0,0,$n m={im} rm endl
    >= $m
  endl *

Why not

$ gmic sp tiger +luminance ge. {100-30}% mul 

?

Why not indeed. Originally that was what I was doing but the paper that I have been following seems to want $1% of pixels that are the brightest (Which is the top percentile…? The phrasing is kind of ambiguous.), so the % corresponds to the number of pixels rather than a brightness threshold. Of course, this is not exact because you can have multiple pixels of the same value. Occasionally, the result is the same. Anyway, I want to try both interpretations on an image data set to see which is more robust.

I’m not sure there is any interest in getting the 10% brightest pixels if this represents the number of pixels. What would the algorithm do with a completely white image ? or a black and white image that has only 5% black in it ? Some pixels with the same value would be treated differently, that does not sound good :slight_smile:

I have been following http://kaiminghe.com/publications/pami10dehaze.pdf. Edit: I will try to closely match the paper before adding my personal touches.

For comparison, this is the RT implemention RawTherapee/ipdehaze.cc at dev · Beep6581/RawTherapee · GitHub but I can’t read C++. This is a MATLAB implementation of what I am asking about https://github.com/sjtrny/Dark-Channel-Haze-Removal/blob/master/get_atmosphere.m; I don’t understand it either.

I think Jérome Boulanger has already implemented this one in gmic-community
(command dehaze in jerome_boulanger.gmic), see gmic-community/jerome_boulanger.gmic at master · dtschump/gmic-community · GitHub

After experimenting with the two interpretations, I have decided that the threshold method is the better choice because 1) it is simpler and 2) was what I did originally. I also tested erosion vs opening (which Jerome did; I sometimes use it too) and found that a partial opening rendered the top pixel method obsolete since it yielded the exact same result as results that were subsets of the threshold one most of the time. Probably not worth the time but it was fun to explore.

So, can I feel the hype of the new dehaze?

Uncertain whether it deserves the hype you feel; however, the initial attempt 2 weeks ago did perform better than the one currently in gmic-community, which I became aware of 3 days ago.

It is an exercise meant to help me learn math and G’MIC scripting. Now that you have mentioned it, it could potentially be useful to everyone. Community: thanks for the encouragement!

2 Likes

I get distracted easily. There are many domains in which we could manipulate an image. So far I have delved into colour, frequency, wavelet and maybe a few others I can’t name. Now I have been reading some papers on Gradient-domain image processing - Wikipedia. I am aware of blend_seamless; never used it though. ATM, I just want to know how one would enter and exit this domain. Here is an example workflow:

image

1 Like

I am still working on the dehaze script, albeit slowly (due to real life challenges).

@David_Tschumperle I am revisiting post #53 on grey scale morphology. The trouble with erode is that it makes values negative and dilate makes them large. Is there a good way to limit this? In comparison, binary morphology keeps values sensible. Dehaze requires sensible values.

That’s why it haven’t been released. What does erode/dilate have to do with dehazing?

Erosion/dilation are just min()/max() of the pixel values in a local neighborhood, so in theory, it shouldn’t dramatically change the initial value range of the image. Do you observe negative values after applying an erosion on an image that has only positive values ?

It happens in your example code too. The degree to which the values deviate depends on the image. Sometimes it stays in a sensible range but more often than not it does not. If I normalize the kernel to [-128,0], it seems to work out; however, 1 I don’t know if it works in all cases (esp. when the range is different like [0,1] or something unusual) and 2 I don’t think I can explain why it works that way. I must be missing something…

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

yields

d-in : 3,248,98.015365333333335
d-out: 258,503,385.95019265367296

and

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

yields

e-in : 3,248,98.015365333333335
e-out: -252,-34.592300415039062,-186.30248914299182

In contrast, binary dilate and erode stay well within the range of the input image.

I made a new filter and placed it in user.gmic to test it. Unfortunately, it crashed the plugin in Partha’s GIMP. I updated it to a newer version.

image

Now, it doesn’t crash but outputs an error with no parameters available.

When I copy the Hessian Norm from gmic-community/include/afre.gmic to user.gmic, it outputs the same error.

Can anyone confirm this issue?