Setting "feather 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
allexx
Posts: 9
Joined: 2019-01-19T10:39:56-07:00
Authentication code: 1152

Setting "feather distance"

Post by allexx » 2019-01-19T11:20:11-07:00

Hi folks!

I have no background in image processing or Imagemagick and would hugely appreciate help w/ an image processing pipeline I want to build, specifically w/ setting feather distance (my term). Here's my setup:

-- Imagemagick 7.0.7-Q16, 32-bit, on Windows; I'm not tied to this version and can switch
-- sample source image: im1.jpg; https://pasteboard.co/HXcyB1z.jpg
-- supporting image for description: im-combined.jpg; https://pasteboard.co/HXcBbLV.jpg

I have a few images similar to im1.jpg; each has a non-uniform grey-white background w/ some lighting variation; each contains a disc-of-interest at its approximate center; each disc contains a line at an arbitrary angle. My goal is to rotate each image such that the line is approximately horizontal, and to fill in the background-space caused by that rotation.

A process that looks workable would be as follows (pls refer to im-combined.jpg):

-- start w/ source image (panel 1)
-- determine angle by which to rotate (let's assume I've solved for this already)
-- "crop" it to a circle, rotate by angle (panel 2)
-- "feather" edges of circle by a distance "d" (panel 3; the red circle is just annotation to show wherefrom the feathering would start)

<-- stuck here; haven't figured out a way to set feather-distance "d". I've tried vignette, as well as various incantations from here: http://www.imagemagick.org/Usage/morpho ... ce_feather

I can probably figure out what remains, which would be to "site" this feathered image inside a new plain background similar to the original (i.e. similar to original in lighting, but doesn't contain disc; let's assume I can manually create a template background to use across all images)

For actual image manipulation this is is the commandline I have thus far (from trawling this site, mostly):

magick.exe" im1.jpg \
-alpha on -background none \
( +clone -channel a -evaluate multiply 0 +channel -fill white -draw "circle %[fx:w/2],%[fx:h/2] 0,%[fx:h/2]" ) \
( -clone 0,1 -compose DstIn -composite ) \
-delete 0,1
-background none -rotate 45 \
out.png

Thank you!

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

Re: Setting "feather distance"

Post by fmw42 » 2019-01-19T12:38:36-07:00

I do not understand why you do not draw your circle about the center of the yellow line. You have drawn it in the center and the yellow line and black circle are not centered. I do not understand what you want to feather? Is it the gray to transparency?

It should be easy to trim the background to the bounds of the circle. Then rotate, then put the circle back into some gray background in the center. Or into whatever background you want. See -fuzz XX% -trim +repage at https://imagemagick.org/Usage/crop/#trim

Please clarify what you expect for the result. Can you mock it up in GIMP or Photoshop, so we can see what you are trying to do.

allexx
Posts: 9
Joined: 2019-01-19T10:39:56-07:00
Authentication code: 1152

Re: Setting "feather distance"

Post by allexx » 2019-01-19T13:15:48-07:00

Hi fmw42, as the op description states the the black disc is at only the "approximate center" of the original image. That it be sited in the accurate-center of the final output would be a nicety, not necessity. In any case drawing the crop circle centered around the yellow line is beyond my imagemagick-knowledge at the moment.

"It should be easy to trim the background to the bounds of the circle. The rotate, then put the circle back into some gray background in the center."

I've tried this w/ different fuzz values and the result has been too jagged around the edge of the disc in the final output. Which is why I'm now drawing a bigger crop circle, farther out, and looking to feather that bigger circle's edge so the black disc and the perimeter immediately around it are left intact, and it's further out that any old-image + new background blending happens in the final output.

Here are 2 more images, showing start, and desired end. Note that this start image has around the black disc a thin red border that I want to preserve.

start: m1a.jpg; https://pasteboard.co/HXdklep.jpg
desired-end: out.jpg; https://pasteboard.co/HXdm5Km.jpg

Thx!

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

Re: Setting "feather distance"

Post by fmw42 » 2019-01-19T19:45:29-07:00

Here is a Unix approach. Perhaps some Windows user can convert it for you.

Input:
Image


# take the input image, filter it for noise with -morphology (because there is a black spec in the lower left corner). Then convert yellow to white and the rest to black and save as tmp1.png without cropping. Then get the trim size and offset using %@

Code: Select all

vals=`convert m1a.jpeg \
-morphology close diamond:1 \
-fuzz 15% -fill white -opaque "rgb(255,240,0)" -fill black +opaque white +write tmp1.png \
-format "%@\n" info: | tr "x" "+"`

echo "$vals"
104+64+100+144
Image

# next, extract each of the 4 values separately and compute the center and radius of a circle about the yellow line from the diameter of the bounding box

Code: Select all

tw=`echo "$vals" | cut -d+ -f1`
th=`echo "$vals" | cut -d+ -f2`
xo=`echo "$vals" | cut -d+ -f3`
yo=`echo "$vals" | cut -d+ -f4`
cx=`convert xc: -format "%[fx:round($xo+$tw/2)]" info:`
cy=`convert xc: -format "%[fx:round($yo+$th/2)]" info:`
rad=`convert xc: -format "%[fx:round(hypot($tw,$th)/2)+1]" info:`
echo "xo=$xo; yo=$yo; tw=$tw; th=$th; cx=$cx; cy=$cy; rad=$rad;"
xo=100; yo=144; tw=104; th=64; cx=152; cy=176; rad=62;
# then crop the tmp1.png image to the bounding box and save as tmp2.png

Code: Select all

convert tmp1.png +repage -crop ${tw}x${th}+${xo}+${yo} +repage tmp2.png
Image

# next extract the orientation of the line from tm2.png using image moments equivalent ellipse angle

Code: Select all

angle=`identify -verbose -moments tmp2.png | grep "Ellipse angle:" | tr -cs "[0-9.]*" " " | sed 's/^[ ]*//'`
echo "$angle"
test=`echo "$angle>90" | bc`
if [ $test -eq 1 ]; then
angle=`echo "scale=1; 180-$angle" | bc`
else
angle=-$angle
fi
echo "$angle"
30.625
# next create a white circle centered at the center point of the line in the original image (cx,cy) and of radius computed from rad. Put that into the alpha channel of the input image and rotate with background transparent, then trim to its bounding box, which should contain just the rotated circle and save as tmp3.png

Code: Select all

convert m1a.jpeg \
\( +clone -fill black -colorize 100 -fill white \
-draw "translate $cx,$cy circle 0,0 $rad,0" -alpha off \) \
-alpha off -compose copy_opacity -composite \
-background none -rotate $angle \
-trim +repage \
tmp3.png 
Image

# next compute the offset to the top left corner of tmp3.png relative to the input image

Code: Select all

xo2=`convert -ping tmp3.png -format "%[fx:$cx-round(w/2)]" info:`
yo2=`convert -ping tmp3.png -format "%[fx:$cy-round(h/2)]" info:`
echo "xo2=$xo2; yo2=$yo2;"
xo2=88; yo2=112;
# now compose tmp3.png over the input at the offset coordinates just computed and save as tmp4.png

Code: Select all

convert m1a.jpeg tmp3.png -geometry +${xo2}+${yo2} -compose over -composite tmp4.png
Image

# now repeat the process for the red circle to get its trimmed size and offsets, saving as tmp5.png without cropping

Code: Select all

vals=`convert m1a.jpeg -morphology close diamond:1 -depth 8 -fuzz 15% -fill white -opaque "rgb(130,70,80)" -fill black +opaque white +write tmp5.png -format "%@\n" info: | tr "x" "+"`
echo "$vals"
226+227+35+65
# separate the dimensions and offsets again for the red circle

Code: Select all

tw=`echo "$vals" | cut -d+ -f1`
th=`echo "$vals" | cut -d+ -f2`
xo=`echo "$vals" | cut -d+ -f3`
yo=`echo "$vals" | cut -d+ -f4`
cx=`convert xc: -format "%[fx:round($xo+$tw/2)]" info:`
cy=`convert xc: -format "%[fx:round($yo+$th/2)]" info:`
rad=`convert xc: -format "%[fx:round(max($tw,$th)/2)+10]" info:`
echo "xo=$xo; yo=$yo; tw=$tw; th=$th; cx=$cx; cy=$cy; rad=$rad;"
xo=35; yo=65; tw=226; th=227; cx=148; cy=179; rad=119;
# now take tmp4.png and create a white circle on black background whose radius is the radius of the circle plus 10 (as per rad above). Then put that image into the alpha channel of tmp4.png. Then select the alpha channel and blur and level to form the ramp. The select all channels and save as result.png

Code: Select all

convert tmp4.png \
\( +clone -fill black -colorize 100 -fill white \
-draw "translate $cx,$cy circle 0,0 $rad,0" -alpha off \) \
-alpha off -compose copy_opacity -composite \
-channel a -blur 0x10 -level 0x50% +channel \
result.png 
Image

allexx
Posts: 9
Joined: 2019-01-19T10:39:56-07:00
Authentication code: 1152

Re: Setting "feather distance"

Post by allexx » 2019-01-20T02:59:44-07:00

fmw42, no probs re translating to Windows -- I could run this in a unix shell on Windows, or script to one of Imagemagick's apis.

Many thanx for that response -- I truly appreciate the time and certainly writing that went into it, and especially the informative, prefacing comments for each section. All of it is educational.

However, it's the last section that's pertinent to my OP question and immediately applicable to my pipeline: "now take tmp4.png and create a white circle on black background whose radius is the radius of the circle plus 10 ...".

The "10" here represents the distance "d" in my op sample image im-combined/panel-3. So ... this seems to be a mask-and-composit technique.

Is there something simpler? I'd love to be able to use just "vignette": starting w/ op sample im-combined/panel-2 if I could apply a vignette so the perimeter of the circular grey background is feathered (going from solid in the interior to transparent at perimeter), AND specify a distance for that feathering (i.e. a distance "d" inward from the perimeter), I'd be home free.

(Not to seem ungrateful, re-que 2nd para from above: "Many thanx for ..." :-) )

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

Re: Setting "feather distance"

Post by fmw42 » 2019-01-20T12:10:08-07:00

First, 10 in the radius is not your d. It defines a radius that is larger than your red circle by 10 for which the background gray will stay constant. The 10 in the -blur 0x10 controls your d, which is not simply 10. It is the blur sigma for the rolloff/ramp/feathering and is only approximately 2x10 or 20. The Imagemagick vignette works by specifying distance from the edges of the image. So it would be hard to define a round vignette on a rectangular image. I have several vignette type scripts what work differently. But they do things similar to my making a round circle and then blurring. So you do not gain much. Using -morphology distance still needs the white circle on the black background. So again you do not save much, though, the ramp/taper/feather is linear in that case. With my method you can create linear ramp/taper/feather of a given distance, by using -blur dx65000. So for a 20 pixel linear ramp, use -blur 20x65000.

allexx
Posts: 9
Joined: 2019-01-19T10:39:56-07:00
Authentication code: 1152

Re: Setting "feather distance"

Post by allexx » 2019-01-20T15:42:28-07:00

OK, got it, many thanx, fmw42. (And I see a lot more reading-up and experimentation in my immediate future :-/ )

Post Reply