Smooth Feathering from black to white over ~6 pixel distance

Questions and postings pertaining to the usage of ImageMagick regardless of the interface. This includes the command-line utilities, as well as the C and C++ APIs. Usage questions are like "How do I use ImageMagick to create drop shadows?".
Post Reply
BrianP007
Posts: 49
Joined: 2013-12-13T09:54:14-07:00
Authentication code: 6789

Smooth Feathering from black to white over ~6 pixel distance

Post by BrianP007 »

Hi,
How does one take a Black & White, grayscale/16bit, Threshold mask and gradually "dissolve" a ~6 pixel border at the edge of the black where it touches the white without graying the interior blacks far away from any white?

I have a grayscale, 16bit Threshold mask containing only black and white. I expanded the black with:

Code: Select all

=$mim->Morphology(method=>"Erode", kernel=>"Disk:3.5", iterations=>2);
So far, it's just like in Photoshop: Select->Expand: ~6

I would like to put a smooth, FEATHERED gradient starting at pure black at the original mask edge, fading gradually to white at the new, Morph boundary. Parallel to Photoshop: select->modify->FEATHER ~6

Code: Select all

$dim->Morphology(method=>"Distance", kernel=>"Euclidean:4", iterations=>2);
creates the beautifully smooth transitions from black to white. But it does the entire picture, not just the 7 pixel black-white boundary.

FUZZ does not work. It selects colors close to some other color.
TRANSPARENT does not work. It SNAPS transparency on or off. Need smooth, gradual gradient.
Gaussian blur makes gray all of the solid black interiors (away from the white boundaries). I need the effect to only happen to the black areas within 5,6, 7 (a handful of) pixels of a WHITE EDGE.
Dilate undoes the ERODE, but it is binary, turning black to white, not making a smooth transition gradient.

Fred has a FEATHER script. It uses:

Code: Select all

convert $tmpA -blur ${dist}x${qmax} -level 50%,100% $outfile
It seems to remove all black, even from interior areas, far away from any white.

Images including the black.white.threshold mask, the mask expanded with morph: erode disk, the goal, the original threshold map expanded and feathered in Photoshop. https://picasaweb.google.com/1059471996 ... directlink
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Smooth Feathering from black to white over ~6 pixel distance

Post by fmw42 »

Fred has a FEATHER script. It uses:
CODE: SELECT ALL
convert $tmpA -blur ${dist}x${qmax} -level 50%,100% $outfile

It depends upon where you want the ramp. For a 20 pixel ramp, for example, try one of these (change to 6 pixels for your case). You need to use radius=X and sigma=65000 so you get a linear ramp. If you use radius=0 and sigma=X, then you have a Gaussian proflle and the exact values for -level to get the ramp to go Y distance would need to be computed from the Gaussian shape.

Test image

Code: Select all

convert -size 100x100 xc:white -background black -gravity center -extent 200x200 test.png
Image

Inside Ramping

Code: Select all

convert test.png -blur 20x65000 -level 50x100% test1.png
Image

Outside Ramping

Code: Select all

convert test.png -blur 20x65000 -level 0x50% test2.png
Image

Half inside and half outside

Code: Select all

convert test.png -blur 20x65000 -level 25x75% test3.png
Image


Another and perhaps better method, which works on the outside only (unless you shave off 10 or 20 pixels on all sides). It does not round the corners. You can use any value for the 4 so long as it is big enough. Replace the 20 with your 6.

Code: Select all

convert test.png -negate +level 0,100 -white-threshold 99 -morphology Distance Euclidean:4,20! -negate test4.png
Image

It is the one snibgo mentions below and is from Anthony's page at http://www.imagemagick.org/Usage/morpho ... ce_feather

You need the negates to have the correct polarity for morphology. But if you leave them off, it will feather inside. However, you get some corner (spike-like) artifacts.

Code: Select all

convert test.png +level 0,100 -white-threshold 99 -morphology Distance Euclidean:4,20! test5.png
Image
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Smooth Feathering from black to white over ~6 pixel distance

Post by snibgo »

black.white.mask.tif isn't only black and white, so I'm not sure what you are asking. We can threshold it at 50%, then get a gradient (Windows cmd syntax):

Code: Select all

convert black.white.mask.tif -threshold 50% -morphology Distance "Euclidean:7,6^!" f.tiff
Adjust "6" as desired. Leave "7" alone.
snibgo's IM pages: im.snibgo.com
BrianP007
Posts: 49
Joined: 2013-12-13T09:54:14-07:00
Authentication code: 6789

Re: Smooth Feathering from black to white over ~6 pixel distance

Post by BrianP007 »

FMW42,
This one looks like just what I need.
convert test.png -negate +level 0,100 -white-threshold 99 -morphology Distance Euclidean:4,20! -negate test4.png

When I did a Euclidean:4 kernel and a distance method, it did the entire picture, not just the areas around the black/white interfaces.
$err=$dim->Morphology(method=>"Distance", kernel=>"Euclidean:4", iterations=>2);
This method, unfortunately, does not support simultaneous negate, level and threshold activities.

In the convert command, it appears that you are actually calling the NEGATE(), Level(), WhiteThreshold(), Morphology() [with the undocumented METHOD parameter method not found on the perl-magick.php page], and yet another NEGATE() method.

Are the 5 methods being executed sequentially, in chunks or all at once?

Is there a 1:1 translation between IM with Convert and PERLMagick? I have been trying to translate these mile long shell commands into baby steps in PerlMagick and getting weird results. Are they working off of the same code base?
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Smooth Feathering from black to white over ~6 pixel distance

Post by fmw42 »

I am sure there should be command in Perlmagick that are equivalent to the command line. But they will not be options for one command. They will be separate commands. The command line processes the image in sequence with these commands above. I do not know Perlmagick and do not know if it supports the Euclidean:4,20! options.

see http://www.imagemagick.org/script/perl- ... manipulate

It lists:

Level (but I do not know if it supports the +level option rather than the usual -level)
Morphology
Negate
WhiteThreshold

see also
http://www.imagemagick.org/Usage/morphology/#distance for command line usage


In further review of my test cases. It appears that the +level 0,100 does not seem to produce any different result from -level 0,100 or leaving the level out altogether in my example. I am not sure why Anthony needed it for his example. It may be needed for other images. But you can try without it if that is not enabled in Perlmagick.

Code: Select all

convert test.png -negate -white-threshold 99 -morphology Distance Euclidean:4,20! -negate test4.png

But the negates are needed if your mask is white on a black background. Also you need the ! for autoscaling.
BrianP007
Posts: 49
Joined: 2013-12-13T09:54:14-07:00
Authentication code: 6789

Re: Smooth Feathering from black to white over ~6 pixel distance

Post by BrianP007 »

snibgo wrote:black.white.mask.tif isn't only black and white, so I'm not sure what you are asking. We can threshold it at 50%, then get a gradient (Windows cmd syntax):

Code: Select all

convert black.white.mask.tif -threshold 50% -morphology Distance "Euclidean:7,6^!" f.tiff
Adjust "6" as desired. Leave "7" alone.
I adjusted the "6" from 5-12 and 12 looked the best. And, the "black.white.mask.tif" shows only 0 K and 65535 K in photoshop. I suspect google is saving some disk space by compressing.

I wrote a program (function) to take a pristine tif, (never touched in Photoshop, either from ACR or Photomatix) and a burnt version and do all of he conversion to grayscale, threshold, composite, mask, etc. It works.

Google, on the other hand, refuses to host them. It uploads them and 15 minutes later decides they are too big.

So use IM to convert them to JPG.
`udjpg *.tif <enter>` Viila!! But wait! Picasa shows the thumbnail but throws up a black Invalid Image box when I try to look at them. Photoshop CS6/64 says Could not complete your request because a SOFn, DQT, or DHT JPEG marker is missing before the JPGE SOS marker.

Identify likes them:
> identify tl-2014.0416-215799.p1.pc.landscape.preset.jpg
tl-2014.0416-215799.p1.pc.landscape.preset.jpg JPEG 9950x6633 9950x6633+0+0 8-bit sRGB 71.53MB 0.000u 0:00.009

A highly interesting log file shows the quantize took 23 seconds, composite (compost?) 3.3, Threshold 1.03 and, the Big One, the Feathering took a whopping 112 seconds!
convert mask_lvl_3.tif -threshold 50% -morphology Distance "Euclidean:7,12!" feather.mask_lvl_3.tif'
Elapsed time=1.8624 Minutes => 81.753% for event "Feather"
Elapsed time=0.3908 Minutes => 17.153% for event "Quantize"
Elapsed time=0.0086 Minutes => 0.379% for event "Read New and Burnt"
Elapsed time=0.0163 Minutes => 0.715% for event "Threshold"
SET: Total time = 2.278 Minutes

I could do this faster in Photoshop manually. But then I would have to be here button pushing rather than out shooting!

The raw, 3% threshold mask, the feathered mask and the photoshop black+expand=7+feather=6 mask are all on Picasa. And, the results of the ~fully automated rescued versions are there too. Unfortunately, the original 16 bit, uncompessed TIFs were too big for google.
https://picasaweb.google.com/1059471996 ... directlink

I use IM to convert the TIF to JPG. There is some flack:
WARNING "Exception 350: Incompatible type for "RichTIFFIPTC"; tag ignored. `TIFFFetchNormalTag' @ warning/tiff.c/TIFFWarnings/850" Reading Image "tl-2014.0416-215799.p1.pc.landscape.preset.tif". Ignoring
Img ColorSpace sRGB, Magick TIFF, QuantumDepth 16, Mem 527.987 MB

P:\br2\tl-2014.0416\p1\c7>identify -version
Version: ImageMagick 6.8.9-2 Q16 x64 2014-05-27 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2014 ImageMagick Studio LLC
Features: DPC Modules OpenMP
Delegates: bzlib cairo freetype jbig jng jp2 jpeg lcms lqr pangocairo png ps rsvg tiff webp xml zlib

Looks like it is time to upgrade. I Hope PerlMagick is not a casualty. It has to be compatible with Strawberry Perl which also has my GCC compiler.
IM version ImageMagick-6.9.0-3-Q16-x64 wants ActiveState v5.8. I have Strawberry 5.18. Crap. Oh well.


And now, the code which will save me days of Photoshop drudgery!

Code: Select all

# =============================================================================
sub try_masks()  {
	$debug = 1;
	$MAX_DARK_PERCENT = 3;  # 2% or darkest 1/50th of pixels
	$dir = "P:/br2/tl-2014.0416/p1/c7";
	$ofn = "$dir/tl-2014.0416-215799.p1.pristine.tif";      # Original file. 
	$bfn = "$dir/tl-2014.0416-215799.p1.pc.landscape.preset.tif";  # Burnt file
	%evt2stime = (_LAST_EVENT => 'INIT', _LAST_TIME => [gettimeofday]);
	$dtime = &sum_event_time("T1", \%evt2stime, $debug=1);
	($bext = $bfn) =~ s/^.*\.([a-z]{3,4})$/$1/i;  # Last 3 or 4 letters are EXT.
	$mfn = "mask_lvl_$MAX_DARK_PERCENT.$bext";  # Mask FileName.

	$oim = new Image::Magick;  # Original, pre-burnt image
	$bim = new Image::Magick;  # Burnt Image
	$mim = new Image::Magick;  # Mask of burnt areas in Burnt Image
	$fim = new Image::Magick;  # Fixed image
	$dtime = &sum_event_time("Read New and Burnt", \%evt2stime, $debug=1);
	$oim = &img_fqp_imo($ofn, $debug);  # Read Img, check errs, rtn IM object
	$bim = &img_fqp_imo($bfn, $debug);  # Read Img, check errs, rtn IM object
	$qrange = $bim->QuantumRange; # Quantum Range on burnt, 65535
	$max_dark = &float_round($qrange * $MAX_DARK_PERCENT / 100.0);
	print("Max_dark=$max_dark, MASK fname=$mfn\n");

	# Clone the MASK object from the Burnt image. Quantize it to grayscale,
	# threshold it at MAX_DARK to make all darks BLACK and the rest WHITE.
	# Turn Alpha on to make GA (Gray, Alpha) channels. Write to Mask File name.
	$dtime = &sum_event_time("Quantize", \%evt2stime, $debug=1);
	$mim = $bim->Clone();  # Copies Burnt image
	$mim->Quantize(colorspace=>'gray');  
	$mim->Write("burnt.to.gray.tif");  # Rough mask.
	$dtime = &sum_event_time("Threshold", \%evt2stime, $debug=1);
	$mim->Threshold(threshold=>$max_dark);  
	$mim->Set(alpha=>'ON', compression=>'None');  
	$mim->Write("$mfn");  # Min mask, darkest N%, no expansion or feathering.

	# Feather the mask with the new secret formula!
	# convert black.white.mask.tif -threshold 50% -morphology Distance \
	#   "Euclidean:7,12!" feathered.tif   # For feathering
	$ffn = "feather.$mfn";  # Feather Filename
	unless(-f "$ffn")  {
		$dtime = &sum_event_time("Feather", \%evt2stime, $debug=1);
		# Feathering.  Perf meter shows > 1 GM of memory used!
		$cmd = "convert $mfn -threshold 50% -morphology Distance \"Euclidean:7,12!\" $ffn";  
		print("Feather cmd = '$cmd' ->");
		$rtn = `$cmd`;
		print("$rtn");
	}

	$dtime = &sum_event_time("Dir_to_file", \%evt2stime, $debug=1);
	@m = &dir_to_file_ara($dir, 1, 'DeBuG');  # Don't search subdir
	@m = grep(/mask.*.tif$/, @m);
	@m = grep(!/fix\./, @m);
	printf("Found %d tif mask files in dir $dir\n", scalar @m);
	$ii = -1;
	foreach $mask (@m)  {
		$ii++;
		@$mim = ();  # Clear MASK array
		$dtime = &sum_event_time("Read Mask $ii", \%evt2stime, $debug=1);
		$mim = &img_fqp_imo($mask, $debug);  # Read Img, check errs, rtn IM obj
		$fim = $oim->Clone();  # Copies ORIGINAL image
		$dtime = &sum_event_time("Compost", \%evt2stime, $debug=1);
		$err=$fim->Composite(compose=>'Over', image=>$bim, mask=>$mim);  # 
		warn "$err" if "$err";
		($path, $base, $ext) = @{&pathbaseext($mask)};
		$fn = "fix.$base.$ext";  # Fix filename. 
		$dtime = &sum_event_time("Write fix $fn", \%evt2stime, $debug=1);
		$fim->Write("$fn");  # Expect holes in burnt img
		print("$ii) Fixed file = $fn\n");
		#last;
	}
	undef $oim;  undef $bim;  undef $mim;  undef $fim;
	$dtime = &sum_event_time("Ending", \%evt2stime, $debug=1);
	&show_event_time(\%evt2stime, 1);  # Show sum of time spent on each event. 
}

BrianP007
Posts: 49
Joined: 2013-12-13T09:54:14-07:00
Authentication code: 6789

Re: Smooth Feathering from black to white over ~6 pixel distance

Post by BrianP007 »

fmw42 wrote:I am sure there should be command in Perlmagick that are equivalent to the command line. But they will not be options for one command. They will be separate commands. The command line processes the image in sequence with these commands above. I do not know Perlmagick and do not know if it supports the Euclidean:4,20! options.

see http://www.imagemagick.org/script/perl- ... manipulate

It lists:

Level (but I do not know if it supports the +level option rather than the usual -level)
Morphology
Negate
WhiteThreshold

see also
http://www.imagemagick.org/Usage/morphology/#distance for command line usage


In further review of my test cases. It appears that the +level 0,100 does not seem to produce any different result from -level 0,100 or leaving the level out altogether in my example. I am not sure why Anthony needed it for his example. It may be needed for other images. But you can try without it if that is not enabled in Perlmagick.

Code: Select all

convert test.png -negate -white-threshold 99 -morphology Distance Euclidean:4,20! -negate test4.png

But the negates are needed if your mask is white on a black background. Also you need the ! for autoscaling.
It does not look like Perl and Bash are playing on the same planet (or I was shroominating when I took these pictures). Bizarre results. Here's the verbatim translation (except the 99 thresh was raised to 25355 because the results were 99% black or white):

Code: Select all

# =============================================================================
# Attempt to translate a Convert bash command into PerlMagick
# convert $IN -negate -white-threshold 99 -morphology Distance Euclidean:4,20!\
# -negate $OUT
sub Euclid_Me()  {
	$dir = "P:/br2/tl-2014.0416/p1/c7";
	$ofn = "$dir/tl-2014.0416-215799.p1.pristine.tif";      # Original file. 
	$oim = &img_fqp_imo($ofn, $debug);  # Read Img, check errs, rtn IM object
	$qrange = $oim->QuantumRange; # Quantum Range on burnt, 65535
	print("Quantum Range = $qrange\n");
	warn "$err" if($err=$oim->Negate());
	$oim->Write("Negato.tif");  # Will it float?
	$white_thresh = 99 * 256;  # Must be 8 bit WHITE value. Convert to 16
	warn "$err" if($err=$oim->WhiteThreshold($white_thresh));
	$oim->Write("thresh25344.tif");  # Will it float?
	warn "$err" if($err=$oim->Morphology(Method=>'Distance', 
		kernel=>"Euclidean:4,20!"));
	$oim->Write("raw.morph.tif");  # Will it float?
	warn "$err" if($err=$oim->Negate());
	$oim->Write("morph.victim.nvert.tif");  # Will it float?
	undef $oim;
}

Code: Select all

Running c:/bin/bb.pl  Wed Jan 14 00:04:44 2015
Quantum Range = 65535
Elapsed time = 46.685 seconds.
Results are on the bottom of the new Feather page They remind me of my Jerry Garcia tie:
https://picasaweb.google.com/1059471996 ... directlink
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Smooth Feathering from black to white over ~6 pixel distance

Post by snibgo »

If you find -morphology Distance "Euclidean:7,6^!" too slow, you could reduce the 7 to 4 or other number. You might try different distance kernels such as Chebyshev. See http://www.imagemagick.org/Usage/morpho ... ce_kernels
snibgo's IM pages: im.snibgo.com
BrianP007
Posts: 49
Joined: 2013-12-13T09:54:14-07:00
Authentication code: 6789

Re: Smooth Feathering from black to white over ~6 pixel distance

Post by BrianP007 »

snibgo wrote:If you find -morphology Distance "Euclidean:7,6^!" too slow, you could reduce the 7 to 4 or other number. You might try different distance kernels such as Chebyshev. See http://www.imagemagick.org/Usage/morpho ... ce_kernels
I was wondering about that. In Photoshop, the select, expand and feather are all nearly instantaneous on the same 68 Mpix file which takes 112 seconds in IM.

It turns out, however, that the time is almost exactly proportional to the Radius with a slope of 1.026. How is this possible? Radius should be squared. These numbers don't lie!

The Euclid-4 gives such smoothness, I don't mind waiting a bit longer for that quality. The chess, taxi, knights, etc are too angular.

I noticed that the process was taking over a gig of memory. For 68 million pixels and 6 bytes/pix -> 408 MB. I have 32gb.

The CPU was maxed at 13% so it's only running on 1 core. This operation could easily be spread over 7 to leave me 1. That should quadruple the speed. Photoshop can run some operations on a GPU. I have 1024 screaming processors just waiting for something like this to devour. How hard could it be?

Sample feather command:
convert mask_lvl_3.tif -threshold 50% -morphology Distance "Euclidean:6,10!" feather.euc.6.10.mask_lvl_3.tif

Resultant mask files. The movie version makes me think of Bacteria growing in a Petri dish.
https://picasaweb.google.com/1059471996 ... directlink

Performance Numbers:
Victim file suffering nasty, 12th degree burns from Sophomoric Software
P:\br2\tl-2014.0416\p1\c8>identify 215799.pclear.q16.tif
215799.pclear.q16.tif TIFF 2100x1300 2100x1300+5400+2900 16-bit sRGB 16.43MB 0.000u 0:00.000

Kernel Rad 4 -> 2.05 seconds ave
Kernel Rad 5 -> 2.82 seconds ave
Kernel Rad 6 -> 3.78 seconds ave
Kernel Rad 7 -> 4.78 seconds ave
Kernel Rad 8 -> 6.18 seconds ave
Kernel Time = 1.026 * Rad + -2.202 Seconds

#####################################################################
Elapsed time=2.0758 Seconds => 7.068% for event "Feather_Kern_Euclidean:4,7!"
Elapsed time=2.0632 Seconds => 7.025% for event "Feather_Kern_Euclidean:4,11!"
Elapsed time=2.0612 Seconds => 7.018% for event "Feather_Kern_Euclidean:4,15!"
Elapsed time=2.0612 Seconds => 7.018% for event "Feather_Kern_Euclidean:4,13!"
Elapsed time=2.0592 Seconds => 7.011% for event "Feather_Kern_Euclidean:4,14!"
Elapsed time=2.0592 Seconds => 7.011% for event "Feather_Kern_Euclidean:4,12!"
Elapsed time=2.0470 Seconds => 6.970% for event "Feather_Kern_Euclidean:4,9!"
Elapsed time=2.0436 Seconds => 6.958% for event "Feather_Kern_Euclidean:4,8!"
Elapsed time=2.0436 Seconds => 6.958% for event "Feather_Kern_Euclidean:4,5!"
Elapsed time=2.0346 Seconds => 6.928% for event "Feather_Kern_Euclidean:4,3!"
Elapsed time=2.0320 Seconds => 6.919% for event "Feather_Kern_Euclidean:4,10!"
Elapsed time=2.0280 Seconds => 6.905% for event "Feather_Kern_Euclidean:4,4!"
Elapsed time=1.9978 Seconds => 6.802% for event "Feather_Kern_Euclidean:4,6!"
Elapsed time=1.0078 Seconds => 3.432% for event "Quantize"
Elapsed time=0.6577 Seconds => 2.239% for event "Compost"
-----------------------
Elapsed time=2.8512 Seconds => 7.007% for event "Feather_Kern_Euclidean:5,8!"
Elapsed time=2.8412 Seconds => 6.983% for event "Feather_Kern_Euclidean:5,13!"
Elapsed time=2.8402 Seconds => 6.980% for event "Feather_Kern_Euclidean:5,15!"
Elapsed time=2.8392 Seconds => 6.978% for event "Feather_Kern_Euclidean:5,14!"
Elapsed time=2.8276 Seconds => 6.949% for event "Feather_Kern_Euclidean:5,9!"
Elapsed time=2.8236 Seconds => 6.939% for event "Feather_Kern_Euclidean:5,11!"
Elapsed time=2.8236 Seconds => 6.939% for event "Feather_Kern_Euclidean:5,10!"
Elapsed time=2.8140 Seconds => 6.916% for event "Feather_Kern_Euclidean:5,6!"
Elapsed time=2.8113 Seconds => 6.909% for event "Feather_Kern_Euclidean:5,3!"
Elapsed time=2.8080 Seconds => 6.901% for event "Feather_Kern_Euclidean:5,5!"
Elapsed time=2.8080 Seconds => 6.901% for event "Feather_Kern_Euclidean:5,12!"
Elapsed time=2.7974 Seconds => 6.875% for event "Feather_Kern_Euclidean:5,7!"
Elapsed time=2.7908 Seconds => 6.859% for event "Feather_Kern_Euclidean:5,4!"
Elapsed time=1.0989 Seconds => 2.701% for event "Compost"
Elapsed time=1.0648 Seconds => 2.617% for event "Quantize"
Elapsed time=0.0842 Seconds => 0.207% for event "Threshold"
-----------------------
Elapsed time=4.0882 Seconds => 7.413% for event "Feather_Kern_Euclidean:6,11!"
Elapsed time=3.8260 Seconds => 6.937% for event "Feather_Kern_Euclidean:6,15!"
Elapsed time=3.8220 Seconds => 6.930% for event "Feather_Kern_Euclidean:6,14!"
Elapsed time=3.7812 Seconds => 6.856% for event "Feather_Kern_Euclidean:6,10!"
Elapsed time=3.7762 Seconds => 6.847% for event "Feather_Kern_Euclidean:6,13!"
Elapsed time=3.7596 Seconds => 6.817% for event "Feather_Kern_Euclidean:6,12!"
Elapsed time=3.7550 Seconds => 6.808% for event "Feather_Kern_Euclidean:6,9!"
Elapsed time=3.7440 Seconds => 6.788% for event "Feather_Kern_Euclidean:6,5!"
Elapsed time=3.7294 Seconds => 6.762% for event "Feather_Kern_Euclidean:6,6!"
Elapsed time=3.7284 Seconds => 6.760% for event "Feather_Kern_Euclidean:6,7!"
Elapsed time=3.7208 Seconds => 6.746% for event "Feather_Kern_Euclidean:6,8!"
Elapsed time=3.7093 Seconds => 6.726% for event "Feather_Kern_Euclidean:6,3!"
Elapsed time=3.6972 Seconds => 6.704% for event "Feather_Kern_Euclidean:6,4!"
Elapsed time=2.1500 Seconds => 3.898% for event "Compost"
Elapsed time=1.0250 Seconds => 1.858% for event "Quantize"
Elapsed time=0.0513 Seconds => 0.093% for event "Threshold"
----------------------------------
Elapsed time=0.0804 Minutes => 7.017% for event "Feather_Kern_Euclidean:7,15!" << 4.824 Seconds
Elapsed time=0.0800 Minutes => 6.986% for event "Feather_Kern_Euclidean:7,11!"
Elapsed time=0.0800 Minutes => 6.982% for event "Feather_Kern_Euclidean:7,13!"
Elapsed time=0.0799 Minutes => 6.978% for event "Feather_Kern_Euclidean:7,9!"
Elapsed time=0.0797 Minutes => 6.961% for event "Feather_Kern_Euclidean:7,12!"
Elapsed time=0.0797 Minutes => 6.955% for event "Feather_Kern_Euclidean:7,8!"
Elapsed time=0.0796 Minutes => 6.950% for event "Feather_Kern_Euclidean:7,7!"
Elapsed time=0.0796 Minutes => 6.949% for event "Feather_Kern_Euclidean:7,14!"
Elapsed time=0.0796 Minutes => 6.946% for event "Feather_Kern_Euclidean:7,10!"
Elapsed time=0.0793 Minutes => 6.923% for event "Feather_Kern_Euclidean:7,5!"
Elapsed time=0.0792 Minutes => 6.918% for event "Feather_Kern_Euclidean:7,3!"
Elapsed time=0.0791 Minutes => 6.904% for event "Feather_Kern_Euclidean:7,4!"
Elapsed time=0.0790 Minutes => 6.901% for event "Feather_Kern_Euclidean:7,6!"
Elapsed time=0.0361 Minutes => 3.148% for event "Compost"
Elapsed time=0.0171 Minutes => 1.489% for event "Quantize"
Elapsed time=0.0008 Minutes => 0.074% for event "Threshold"
-----------------------------
Elapsed time=0.1086 Minutes => 7.288% for event "Feather_Kern_Euclidean:8,13!" << 6.516 seconds
Elapsed time=0.1045 Minutes => 7.011% for event "Feather_Kern_Euclidean:8,14!"
Elapsed time=0.1043 Minutes => 6.997% for event "Feather_Kern_Euclidean:8,12!"
Elapsed time=0.1031 Minutes => 6.915% for event "Feather_Kern_Euclidean:8,15!"
Elapsed time=0.1025 Minutes => 6.875% for event "Feather_Kern_Euclidean:8,9!"
Elapsed time=0.1024 Minutes => 6.870% for event "Feather_Kern_Euclidean:8,8!"
Elapsed time=0.1023 Minutes => 6.861% for event "Feather_Kern_Euclidean:8,11!"
Elapsed time=0.1022 Minutes => 6.856% for event "Feather_Kern_Euclidean:8,7!"
Elapsed time=0.1021 Minutes => 6.849% for event "Feather_Kern_Euclidean:8,3!"
Elapsed time=0.1020 Minutes => 6.845% for event "Feather_Kern_Euclidean:8,6!"
Elapsed time=0.1020 Minutes => 6.841% for event "Feather_Kern_Euclidean:8,10!"
Elapsed time=0.1019 Minutes => 6.838% for event "Feather_Kern_Euclidean:8,4!"
Elapsed time=0.1017 Minutes => 6.824% for event "Feather_Kern_Euclidean:8,5!"
Elapsed time=0.0580 Minutes => 3.889% for event "Compost"
Elapsed time=0.0174 Minutes => 1.165% for event "Quantize"
Elapsed time=0.0010 Minutes => 0.067% for event "Threshold"
=================================

Kernel Feather_Kern_Euclidean:4,03! -> 2.0346 seconds
Kernel Feather_Kern_Euclidean:4,04! -> 2.0280 seconds
Kernel Feather_Kern_Euclidean:4,05! -> 2.0436 seconds
Kernel Feather_Kern_Euclidean:4,06! -> 1.9978 seconds
Kernel Feather_Kern_Euclidean:4,07! -> 2.0758 seconds
Kernel Feather_Kern_Euclidean:4,08! -> 2.0436 seconds
Kernel Feather_Kern_Euclidean:4,09! -> 2.0470 seconds
Kernel Feather_Kern_Euclidean:4,10! -> 2.0320 seconds
Kernel Feather_Kern_Euclidean:4,11! -> 2.0632 seconds
Kernel Feather_Kern_Euclidean:4,12! -> 2.0592 seconds
Kernel Feather_Kern_Euclidean:4,13! -> 2.0612 seconds
Kernel Feather_Kern_Euclidean:4,14! -> 2.0592 seconds
Kernel Feather_Kern_Euclidean:4,15! -> 2.0612 seconds
Kernel Feather_Kern_Euclidean:5,03! -> 2.8113 seconds
Kernel Feather_Kern_Euclidean:5,04! -> 2.7908 seconds
Kernel Feather_Kern_Euclidean:5,05! -> 2.8080 seconds
Kernel Feather_Kern_Euclidean:5,06! -> 2.8140 seconds
Kernel Feather_Kern_Euclidean:5,07! -> 2.7974 seconds
Kernel Feather_Kern_Euclidean:5,08! -> 2.8512 seconds
Kernel Feather_Kern_Euclidean:5,09! -> 2.8276 seconds
Kernel Feather_Kern_Euclidean:5,10! -> 2.8236 seconds
Kernel Feather_Kern_Euclidean:5,11! -> 2.8236 seconds
Kernel Feather_Kern_Euclidean:5,12! -> 2.8080 seconds
Kernel Feather_Kern_Euclidean:5,13! -> 2.8412 seconds
Kernel Feather_Kern_Euclidean:5,14! -> 2.8392 seconds
Kernel Feather_Kern_Euclidean:5,15! -> 2.8402 seconds
Kernel Feather_Kern_Euclidean:6,03! -> 3.7093 seconds
Kernel Feather_Kern_Euclidean:6,04! -> 3.6972 seconds
Kernel Feather_Kern_Euclidean:6,05! -> 3.7440 seconds
Kernel Feather_Kern_Euclidean:6,06! -> 3.7294 seconds
Kernel Feather_Kern_Euclidean:6,07! -> 3.7284 seconds
Kernel Feather_Kern_Euclidean:6,08! -> 3.7208 seconds
Kernel Feather_Kern_Euclidean:6,09! -> 3.7550 seconds
Kernel Feather_Kern_Euclidean:6,10! -> 3.7812 seconds
Kernel Feather_Kern_Euclidean:6,11! -> 4.0882 seconds
Kernel Feather_Kern_Euclidean:6,12! -> 3.7596 seconds
Kernel Feather_Kern_Euclidean:6,13! -> 3.7762 seconds
Kernel Feather_Kern_Euclidean:6,14! -> 3.8220 seconds
Kernel Feather_Kern_Euclidean:6,15! -> 3.8260 seconds
Kernel Feather_Kern_Euclidean:7,03! -> 4.752 seconds
Kernel Feather_Kern_Euclidean:7,04! -> 4.746 seconds
Kernel Feather_Kern_Euclidean:7,05! -> 4.758 seconds
Kernel Feather_Kern_Euclidean:7,06! -> 4.74 seconds
Kernel Feather_Kern_Euclidean:7,07! -> 4.776 seconds
Kernel Feather_Kern_Euclidean:7,08! -> 4.782 seconds
Kernel Feather_Kern_Euclidean:7,09! -> 4.794 seconds
Kernel Feather_Kern_Euclidean:7,10! -> 4.776 seconds
Kernel Feather_Kern_Euclidean:7,11! -> 4.8 seconds
Kernel Feather_Kern_Euclidean:7,12! -> 4.782 seconds
Kernel Feather_Kern_Euclidean:7,13! -> 4.8 seconds
Kernel Feather_Kern_Euclidean:7,14! -> 4.776 seconds
Kernel Feather_Kern_Euclidean:7,15! -> 4.824 seconds
Kernel Feather_Kern_Euclidean:8,03! -> 6.126 seconds
Kernel Feather_Kern_Euclidean:8,04! -> 6.114 seconds
Kernel Feather_Kern_Euclidean:8,05! -> 6.102 seconds
Kernel Feather_Kern_Euclidean:8,06! -> 6.12 seconds
Kernel Feather_Kern_Euclidean:8,07! -> 6.132 seconds
Kernel Feather_Kern_Euclidean:8,08! -> 6.144 seconds
Kernel Feather_Kern_Euclidean:8,09! -> 6.15 seconds
Kernel Feather_Kern_Euclidean:8,10! -> 6.12 seconds
Kernel Feather_Kern_Euclidean:8,11! -> 6.138 seconds
Kernel Feather_Kern_Euclidean:8,12! -> 6.258 seconds
Kernel Feather_Kern_Euclidean:8,13! -> 6.516 seconds
Kernel Feather_Kern_Euclidean:8,14! -> 6.27 seconds
Kernel Feather_Kern_Euclidean:8,15! -> 6.186 seconds


Has anybody else noticed that this grinchy forum host has an annoyingly short timeout period before requiring a new login?
Worse than that, the first thing the little blighter does is to DESTROY THE TEXT BODY? Be nice if it saved it! GRRRRRRRR!!!
"I'm sorry. Were you typing something? Let me DESTROY IT FOR YOU while you freshen your login". ;(

Code: Select all

# =============================================================================
sub try_masks()  {
	$debug = 1;
	$MAX_DARK_PERCENT = 3;  # 3% of the darkest of pixels
	$EUCLID_RADIUS=8;
	$dir = "P:/br2/tl-2014.0416/p1/c8";
	#$ofn = "$dir/tl-2014.0416-215799.p1.pristine.tif";      # Original file. 
	#$bfn = "$dir/tl-2014.0416-215799.p1.pc.landscape.preset.tif";  # Burnt file
	$ofn = "$dir/215799.zero.crop.q16.tif";      # Original file. 
	$bfn = "$dir/215799.pclear.q16.tif";  # Burnt file to fix
	%evt2stime = (_LAST_EVENT => 'INIT', _LAST_TIME => [gettimeofday]);
	$dtime = &sum_event_time("T1", \%evt2stime, $debug=1);
	($bext = $bfn) =~ s/^.*\.([a-z]{3,4})$/$1/i;  # Last 3 or 4 letters are EXT.
	$mfn = "mask_lvl_$MAX_DARK_PERCENT.$bext";  # Mask FileName.

	$oim = new Image::Magick;  # Original, pre-burnt image
	$bim = new Image::Magick;  # Burnt Image
	$mim = new Image::Magick;  # Mask of burnt areas in Burnt Image
	$fim = new Image::Magick;  # Fixed image
	$dtime = &sum_event_time("Read New and Burnt", \%evt2stime, $debug=1);
	$oim = &img_fqp_imo($ofn, $debug);  # Read Img, check errs, rtn IM object
	$bim = &img_fqp_imo($bfn, $debug);  # Read Img, check errs, rtn IM object
	$qrange = $bim->QuantumRange; # Quantum Range on burnt, 65535
	$max_dark = &float_round($qrange * $MAX_DARK_PERCENT / 100.0);
	print("Max_dark=$max_dark, MASK fname=$mfn\n");

	# Clone the MASK object from the Burnt image. Quantize it to grayscale,
	# threshold it at MAX_DARK to make all darks BLACK and the rest WHITE.
	# Turn Alpha on to make GA (Gray, Alpha) channels. Write to Mask File name.
	$dtime = &sum_event_time("Quantize", \%evt2stime, $debug=1);
	$mim = $bim->Clone();  # Copies Burnt image
	$mim->Quantize(colorspace=>'gray');  
	$mim->Write("burnt.to.gray.tif");  # Rough mask.
	$dtime = &sum_event_time("Threshold", \%evt2stime, $debug=1);
	$mim->Threshold(threshold=>$max_dark);  
	$mim->Set(alpha=>'ON', compression=>'None');  
	$mim->Write("$mfn");  # Min mask, darkest N%, no expansion or feathering.

	# Feather the mask with the new secret formula!
	# convert black.white.mask.tif -threshold 50% -morphology Distance \
	#   "Euclidean:7,12!" feathered.tif   # For feathering
	for($ii = 3; $ii < 16; $ii++)  {
		$ffn = "feather.euc.$EUCLID_RADIUS.$ii.$mfn";  # Feather Filename
		$kern = "Euclidean:$EUCLID_RADIUS,$ii!";
		$dtime = &sum_event_time("Feather_Kern_$kern", \%evt2stime, $debug=1);
		$cmd = "convert $mfn -threshold 50% -morphology Distance \"$kern\" $ffn";  # Feathering.  Perf meter shows > 1 GM of memory used!
		print("Feather cmd = '$cmd' ->");
		$rtn = `$cmd`;
		print("$rtn");
	}

	$dtime = &sum_event_time("Dir_to_file", \%evt2stime, $debug=1);
	@m = &dir_to_file_ara($dir, 1, 'DeBuG');  # Don't search subdir
	@m = grep(/mask.*.tif$/, @m);
	@m = grep(!/fix\./, @m);
	printf("Found %d tif mask files in dir $dir\n", scalar @m);
	$ii = -1;
	foreach $mask (@m)  {
		$ii++;
		@$mim = ();  # Clear MASK array
		$dtime = &sum_event_time("Read Mask $ii", \%evt2stime, $debug=1);
		$mim = &img_fqp_imo($mask, $debug);  # Read Img, check errs, rtn IM obj
		$fim = $oim->Clone();  # Copies ORIGINAL image
		$dtime = &sum_event_time("Compost", \%evt2stime, $debug=1);
		$err=$fim->Composite(compose=>'Over', image=>$bim, mask=>$mim);  # 
		warn "$err" if "$err";
		($path, $base, $ext) = @{&pathbaseext($mask)};
		$fn = "fix.$base.$ext";  # Fix filename. 
		$dtime = &sum_event_time("Write fix $fn", \%evt2stime, $debug=1);
		$fim->Write("$fn");  # Expect holes in burnt img
		print("$ii) Fixed file = $fn\n");
		#last;
	}
	undef $oim;  undef $bim;  undef $mim;  undef $fim;
	$dtime = &sum_event_time("Ending", \%evt2stime, $debug=1);
	&show_event_time(\%evt2stime, 1);  # Show sum of time spent on each event. 
}

User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Smooth Feathering from black to white over ~6 pixel distance

Post by fmw42 »

Many people go offline to create their text, then log back in and copy and paste their post.
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Smooth Feathering from black to white over ~6 pixel distance

Post by snibgo »

I use IM forums most days. I've only had to login once this year.

I almost always write my text in a text editor, then copy-paste.

I don't know to what degree morphology is parallelised. I don't understand how IM paralellism works, let alone GPU.
BrianP007 wrote:How hard could it be?
Then I'm sure we can look forward to your contributions to the code. {smiley whotsit}
snibgo's IM pages: im.snibgo.com
BrianP007
Posts: 49
Joined: 2013-12-13T09:54:14-07:00
Authentication code: 6789

Re: Smooth Feathering from black to white over ~6 pixel distance

Post by BrianP007 »

This is 4 years old. Every kernel only works on a tiny radius and is totally independent of that kernel way over there. It's like Hoeing your garden. Mo Hoes, mo better!

A Chunking Method for Euclidean Distance Matrix Calculation on Large Dataset Using Multi-GPU
http://ieeexplore.ieee.org/xpl/login.js ... %3D5708835
Li, Qi ; Dept. of Comput. Sci. Sch. of Eng., Virginia Commonwealth Univ., Richmond, VA, USA ; Kecman, V. ; Salman, R.

...
We first implement a fast GPU algorithm that is suitable for calculating sub matrices of Euclidean distance matrix. Then we utilize a Map-Reduce like framework to split the final distance matrix calculation into many small independent jobs of calculating partial distance matrices, which can be efficiently solved by our GPU algorithm. The framework also dynamically allocates GPU resources to those independent jobs for maximum performance. The experimental results have shown a speed up of 15x on datasets which contain more than half million data points.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Smooth Feathering from black to white over ~6 pixel distance

Post by fmw42 »

Unfortunately, that does not help if you don't have a GPU or GPU algorithm. Can you contribute that into an OpenCL implementation for IM?

Did you ever try coding into Perlmagick. It probably is faster. Or use OpenMP with multiple threads, if you have a multicore system?
BrianP007
Posts: 49
Joined: 2013-12-13T09:54:14-07:00
Authentication code: 6789

Re: Smooth Feathering from black to white over ~6 pixel distance

Post by BrianP007 »

fmw42 wrote:Unfortunately, that does not help if you don't have a GPU or GPU algorithm. Can you contribute that into an OpenCL implementation for IM?

Did you ever try coding into Perlmagick. It probably is faster. Or use OpenMP with multiple threads, if you have a multicore system?
>> ".. you don't have a GPU or GPU algorithm"
GPUs are everywhere. Who does not have a video card on their workstation. The new phones even some fairly heavy duty GPUs at least for 3D (not sure how good they are for general purpose computing). But, now matter how crappy they might be, using whatever compute power they have in addition to the CPU has to be better than the cpu alone. If mean old adobe can get them working in ps6 and have 3rd parties measure a 15x improvement, it can't be that hard.
http://www.tomshardware.com/reviews/pho ... 08-13.html

I had an 18 month contract at AMD working with some of their most hard core GPU engineers. I was their tools and testing guy, no writing openCL, sorry. I have 4 cpu cores, 8 threads and 1024 stream processors and 2 GB video ram. IM uses 1 leaving 1031 idle. What a waste waiting for 2+ minutes seeing 13% cpu and 0% gpu for exactly the same thing Photoshop can do in 1 second of crunching other than waiting for the operator to hit select_color_range, click on black and then launch an action to expand, feather and delete. But, IM is automated so I can run it while I am out playing so the time is much less of a factor.

I try to do everything in Perl instead of shell. I hate bash. I used it for years and every time I figured out something new, I was aghast at what gyrations were necessary to get that unmitigated kludged monstrosity to do the simplest things. Perl shamelessly pirated the few good bash ideas and tons from C and was actually engineered rather than aimlessly cobbled, hacked and jury rigged. Bash always reminded me of the vehicles in Mad Max, piles of random junk parts held together with coat hangers. Perl, by contrast constantly delighted me with great engineering and fanatical support. The quality of the tools on CPAN is astonishing.

Earlier this week, I translated a moderately complicated Convert command piece by piece into PerlMagick. The results were psychedelic but not but not at all realistic; Magical Mystery Tour, not National Geographic. I would bet $10 bucks that they are not using the same code base and do not have the same functions, arguments and parsing.

Look at the documentation. Perl's is scant, incomplete and a tiny fraction of that for Convert, the Million Trick Pony. Try to find PM solutions on the web. It is extremely trying without using many -convert -imagemagick Perl Perl Perl PerlMAgick. ~93% of the discussion here is IM, not PM. Ask a Perl question, get an IM answer.

I am tempted to get the PM source and see how far I can get using that as the documentation.
Post Reply