You can turn the white material transparent:

ImageCompose[img2, ColorReplace[img1, White -> Transparent]]

To change the size, you can ImageResize. Here I have made the resize parameter variable with the slider:

Manipulate[ImageCompose[img2, 
  ImageResize[ColorReplace[img1, White -> Transparent], s]], {s, 50, 300, 1}]

There are also several options for the ImageCompose function and you might try them: you can put the object "on top of" or "xor with", etc.

Answer from bill s on Stack Exchange
🌐
Wolfram Language
reference.wolfram.com › language › ref › ImageCompose.html
ImageCompose: Create an image overlay—Wolfram Documentation
ImageCompose[image,{overlay,α}] effectively sets the alpha value for overlay to α, or multiplies an existing alpha channel by α.
🌐
Wolfram Language
reference.wolfram.com › language › guide › ImageComposition.html
Image Composition - Wolfram Language Documentation
The Wolfram Language includes various image compositing and digital composition techniques, from simple image arithmetic to various modes of alpha compositing. A variety of algorithms in the fields of segmentation, filtering, and feature extraction are also built into the Wolfram Language and can be used to generate different layers of composition.
🌐
Wolfram Documentation
reference.wolfram.com › legacy › v7 › ref › ImageCompose.html
ImageCompose - Wolfram Mathematica 7 Documentation
ImageCompose[image, overlay] gives the result of overlaying obj onto image. ImageCompose[image, {overlay, \[Alpha]}] gives the result of alpha-blending overlay into image using blending fraction \[Alpha]. ImageCompose[image, overlay, pos] places ...
🌐
Wolfram Documentation
reference.wolfram.com › legacy › v8 › ref › ImageCompose.html
ImageCompose - Wolfram Mathematica 8 Documentation
ImageCompose[image, overlay] gives the result of overlaying overlay onto image. ImageCompose[image, {overlay, \[Alpha]}] gives the result of alpha blending overlay into image using blending fraction \[Alpha].ImageCompose[image, overlay, pos] places the center of overlay at position pos in image.ImageCompose[image, overlay, pos, opos] places the point opos in overlay at position pos in image.ImageCompose[image, overlay, pos, opos, {f_i, f_o, mode}] uses the compositing fractions f_k and the specified compositing mode.
Top answer
1 of 2
14

You can use Inset to place the image inside a vector graphics. Inset has various parameters to set the size and position of the image places. To test it you could use a scaled version of an image and overlay it with a grid. You see the lines match exactly:

img = ImageResize[ExampleData[{"TestImage", "Lena"}], {100, 100}];
Graphics[{Inset[img, {0, 0}, {0, 0}, {100, 100}], Line[#], 
    Line[Transpose[#]]}, PlotRange -> {{-1, 101}, {-1, 101}}] &@
 Table[{i, j}, {i, 0, 100, 5}, {j, 0, 100, 5}]

Earth

Using this in your application, you would only have to copy all the code snips:

cart[{lambda_, phi_}] := 
 With[{theta = fc[phi]}, {2/Pi*lambda Cos[theta], Sin[theta]}]
fc[phi_] := 
  Block[{theta}, 
   If[Abs[phi] == Pi/2, phi, 
    theta /. 
     FindRoot[2 theta + Sin[2 theta] == Pi Sin[phi], {theta, phi}]]];

grid = With[{delta = Pi/18/2}, 
   Table[{lambda, phi}, {phi, -Pi/2, Pi/2, delta}, {lambda, -Pi, Pi, 
     delta}]];
gr1 = Graphics[{AbsoluteThickness[0.05], Line /@ grid, 
    Line /@ Transpose[grid]}, AspectRatio -> 1/2];
gr0 = Flatten[{gr1[[1, 2]][[Range[9]*4 - 1]], 
     gr1[[1, 3]][[Range[18]*4 - 3]]}] // 
   Graphics[{AbsoluteThickness[0.2], #}] &;
gr2 = Table[{Hue[t/Pi], Point[{t, t/2}]}, {t, -Pi, Pi, 1/100}] // 
    Flatten // Graphics;
gr = Show[{gr1, gr0, gr2}, Axes -> True];
earthgrid = 
 gr /. Line[pts_] :> {Orange, Line[cart /@ pts]} /. 
  Point[pts_] :> Point[cart[pts]]

Creating an earth-map image

invmollweide[{x_, y_}] := 
 With[{theta = ArcSin[y]}, {Pi x/(2 Cos[theta]), 
   ArcSin[(2 theta + Sin[2 theta])/Pi]}];
img =
 With[{i = 
    Import["https://i.sstatic.net/GaQGa.jpg"]},
  ImageTransformation[i, invmollweide, {512, 256}, 
   DataRange -> {{-Pi, Pi}, {-Pi/2, Pi/2}}, 
   PlotRange -> {{-2, 2}, {-1, 1}}, Padding -> White]
  ];

And then putting all together

Graphics[{Inset[img, {-2, -1}, {0, 0}, {4, 2}], First[earthgrid]}, 
 PlotRange -> {{-2, 2}, {-1, 1}}]

2 of 2
8

Perhaps the StreamPlot is being produced with unwanted margins that can be removed using PlotRangePadding -> 0? This might be one possible source of the apparent misalignment. Compare the left and right halves of this image: on the left, the original; on the right, with PlotRangePadding -> 0.

🌐
Google Groups
groups.google.com › g › comp.soft-sys.math.mathematica › c › FBjZHJrD3Jw
Image processing with ImageCompose
Alternatively, if you are starting with images from somewhere outside Mathmeatica, Argument 5 of ImageCompose (see the help on this function) lets you merge the pixels of the two images in any way desired.
Top answer
1 of 3
18

The $over$ operator correctly implemented

According to the Wikipedia, when composing $A$ $over$ $B$, the output alpha channel value $\alpha_O$ and the output color channel value $C_O$ are calculated as follows:

$\begin{cases}\alpha_O = 1 - (1 - \alpha_A) (1 - \alpha_B) \\C_O = \frac{\alpha_A C_A + (1 - \alpha_A)\alpha_B C_B}{\alpha_O}, \text{if $\alpha_O \neq 0$} \\C_O = 0, \text{if $\alpha_O = 0$} \end{cases}$

where $\alpha_A$ and $\alpha_B$ are alpha channel values of $A$ and $B$, and $C_A$ and $C_B$ – color channel values of $A$ and $B$ correspondingly.

This can be directly implemented in Mathematica 11.1 or above as follows:

imageCompose[b_Image, a_Image] := 
 Module[{alphaA = AlphaChannel@a, alphaB = AlphaChannel@b, alphaO, 
         cA = RemoveAlphaChannel@a, cB = RemoveAlphaChannel@b},
  alphaO = 1 - (1 - alphaA) (1 - alphaB);
  SetAlphaChannel[(alphaA*cA + (1 - alphaA) alphaB*cB)/alphaO, alphaO]]

Let us check the associative property:

{{i0, i1, i2}} = ImagePartition[
  Import["https://i.sstatic.net/r13gh.png"], {Scaled[1/3], Scaled[1]}]

{i0~imageCompose~(i1~imageCompose~i2), (i0~imageCompose~i1)~imageCompose~i2}
Equal @@ %
ColorSeparate /@ %%

True

It holds! So what is the problem with ImageCompose of version 10 and later?

Current implementation of ImageCompose: the diagnosis

When writing the above implementation for the first time I unintentionally made a simple mistake: I forgot to divide the output value for the color channel by $\alpha_O$. Here is what happened:

imageComposeWrong[b_Image, a_Image] := 
 Module[{alphaA = AlphaChannel@a, alphaB = AlphaChannel@b, alphaO, 
         cA = RemoveAlphaChannel@a, cB = RemoveAlphaChannel@b},
  alphaO = 1 - (1 - alphaA) (1 - alphaB);
  SetAlphaChannel[alphaA*cA + (1 - alphaA) alphaB*cB, alphaO]]

{i0~imageComposeWrong~(i1~imageComposeWrong~i2), 
 (i0~imageComposeWrong~i1)~imageComposeWrong~i2}
Equal @@ %
ColorSeparate /@ %%

False

The output looks exactly the same as for the current ImageCompose:

{i0~ImageCompose~(i1~ImageCompose~i2), (i0~ImageCompose~i1)~ImageCompose~i2}
Equal @@ %
ColorSeparate /@ %%

False

Numerical comparison reveals tiny differences due to rounding off errors. But the final diagnosis is clear: the developer just forgot to divide the color channel by the alpha channel!

It is a great shame that during more than three years after the release of version 10.0.0 nobody noticed this in the company! Do they themselves use this functionality – or not?!

Please, do not be lazy to report this to the technical support, so that this shameful bug will be fixed as soon as possible! A high priority is given to bugs, which many users write about...

The remedy

From the above considerations the remedy is obvious: we must just divide the color of the ImageCompose output by the alpha channel:

icFix[img_Image] := img/AlphaChannel[img];

{i0~icFix@*ImageCompose~(i1~icFix@*ImageCompose~i2), (i0~icFix@*ImageCompose~i1)~icFix@*ImageCompose~i2}
Subtract @@ % // MinMax
ColorSeparate /@ %%

{-3.10689*10^-6, 3.08454*10^-6}

As one can see, there are still tiny differences due to rounding-off errors, but the associative property in fact is restored and the output is correct!


Original answer

Citing a comment by Rahul:

Well, that's certainly undesirable! Alpha compositing is supposed to be associative (i0~ImageCompose~(i1~ImageCompose~i2) should equal (i0~ImageCompose~i1)~ImageCompose~i2) and this doesn't do that. One could implement correct alpha compositing manually using ImageApply, but let's see if someone has a better way.

Indeed, in versions 8.0.4 and 9.0.1 ImageCompose is associative:

$Version

{{i0, i1, i2}} = ImagePartition[
  Import["https://i.sstatic.net/r13gh.png"], {Scaled[1/3], Scaled[1]}]

{i0~ImageCompose~(i1~ImageCompose~i2), (i0~ImageCompose~i1)~ImageCompose~i2}

Equal @@ %

ColorSeparate /@ %%
"9.0 for Microsoft Windows (64-bit) (January 25, 2013)"

True

... while starting from version 10.0 it is not:

$Version

{{i0, i1, i2}} = ImagePartition[
  Import["https://i.sstatic.net/r13gh.png"], {Scaled[1/3], Scaled[1]}]

{i0~ImageCompose~(i1~ImageCompose~i2), (i0~ImageCompose~i1)~ImageCompose~i2}

Equal @@ %

ColorSeparate /@ %%
"10.0 for Microsoft Windows (64-bit) (September 9, 2014)"

False

It is also worth to note that despite that Overlay[{i0, i1}] and Show[i0, i1] look the same as the old ImageCompose[i0, i1], they are not the same. But they do (approximately) equal to each other and do approximately hold the associative property:

$Version

overlayCompose[i0_, i1_] := Rasterize[Overlay[{i0, i1}], "Image", Background -> None];
showCompose[i0_, i1_] := Rasterize[Show[i0, i1], "Image", Background -> None];

{overlayCompose[i0, i1], showCompose[i0, i1], i0~ImageCompose~i1}

ColorSeparate /@ %

{i0~overlayCompose~(i1~overlayCompose~i2), (i0~overlayCompose~i1)~ overlayCompose~i2}

ColorSeparate /@ %

{i0~showCompose~(i1~showCompose~i2), (i0~showCompose~i1)~showCompose~ i2}

ColorSeparate /@ %
"9.0 for Microsoft Windows (64-bit) (January 25, 2013)"

As one can see from the above, Overlay introduces artifact at the top, while Show does not.

2 of 3
11

You can get the old ImageCompose behavior by using Overlay instead:

Overlay[{i1, i2}]


Edit:

As pointed out by the comment by ybeltukov the Head of an Overlay is "Overlay" and therefore doesn't match the Head of ImageCompose, which is "Image". I didn't realize this, because exporting to a .png file did handle the transformation.
One can use e.g.

ImportString@ExportString[Overlay[{i1, i2}], "PNG"]

to get an object with Head "Image", and that therefore can be used the same way as an object created with ImageCompose inside the notebook.

Find elsewhere
🌐
Wolfram Language
reference.wolfram.com › language › ref › ImageAssemble.html
ImageAssemble: Layout images in a grid—Wolfram Documentation
ImageAssemble creates a collage from an array images, which can be used to compare the effects of one or two parameters on an image, or to visualize different steps of a procedure.
🌐
Wolfram Language
reference.wolfram.com › language › ref › ImageFocusCombine.html
ImageFocusCombine: Focus stacking of images—Wolfram Documentation
ImageFocusCombine is also known as focus stacking or Z-stacking. It is typically used for combining multiple images of the same scene taken at different focus distances and creates an image with a higher depth of field (DOF).
Top answer
1 of 3
18

Try this:

(* clip white borders *)
img = ImageCrop[Import["https://i.sstatic.net/La8Zs.jpg"]];

Plot[-14/81 x (x - 18), {x, -2, 19},
     PlotRange -> {-2, 16}, PlotStyle -> Directive[Red, Thick, Dashed], 
     Prolog -> {Texture[img],
                Polygon[{Scaled[{0, 0}], Scaled[{1, 0}], Scaled[{1, 1}], Scaled[{0, 1}]},
                        VertexTextureCoordinates -> {{0, 0}, {1, 0}, {1, 1}, {0, 1}}]},
     Ticks -> None]

Notes:

  • If you want to fit in an image as background, you will often want to trim margins; ImageCrop[] is a good function for the purpose.

  • Luckily, your background image has its own coordinate system; you can then adjust PlotRange appropriately.

  • Prolog is most useful for putting primitives in the background.

  • Scaled[] ensures that the background textured polygon is scaled appropriately with respect to the plot range.

2 of 3
11

EDIT: (see below for old version)

New version with alpha channels, the option to lock the graph at the ball, adjustable player position and a button to remove player and basket:

setalpha[im_] := 
 Module[{mask = 
    ChanVeseBinarize[im, TargetColor -> {1., 1., 1.}, 
     "LengthPenalty" -> 10]},
  mask = Blur[Erosion[ColorNegate[mask], 2], 5];
  Rasterize[SetAlphaChannel[im, mask], Background -> None]]

basket = setalpha[
   Import["http://www.hdwallpaperspk.com/wp-content/uploads/2013/02/ basketball_clipart.jpg"]];
guy = setalpha[
   Import["http://www.tu-chemnitz.de/ifm/produkte-medien/basketball_200.png"]];

Manipulate[
 Plot[If[locked, (-c - b pos[[1]] + pos[[2]])/pos[[1]]^2, a] x^2 + 
   b x + c, {x, 0, 16}, PlotRange -> {{0, 17}, {0, 14}},
  Frame -> True,
  ImageSize -> 500,
  BaseStyle -> {20, FontFamily -> "Helvetica"},
  FrameLabel -> {"Distance from Back of hoop (ft)", "Heigth (ft)"},
  GridLines -> {Range@16, Range@14},
  Prolog -> {Inset[If[show, basket, ""], {0.5, 8}, Top, 1], 
    Inset[If[show, guy, ""], pos, Top, 2.5]}],
 Item@Row[{"a  ", 
    Dynamic@Slider[Dynamic@a, {1, 10}, Enabled -> ! locked]}], 
 Item@Row[{"b  ", Dynamic@Slider[Dynamic@b, {1, 10}]}],
 Item@Row[{"c  ", Dynamic@Slider[Dynamic@c, {1, 10}]}],
 {{pos, {16, 6}}, Locator},
 {{locked, True, "Lock graph at ball"}, {True, False}},
 {{show, True, "Show player and basket"}, {True, False}},
 ControlPlacement -> Left]


Old version:

Alternatively, you can also create the whole thing completely in Mathematica. I also added Manipulate for fun:

basket = Import[
        "http://www.hdwallpaperspk.com/wp-content/uploads/2013/02/basketball_clipart.jpg"];
guy = Import["http://www.tu-chemnitz.de/ifm/produkte-medien/basketball_200.png"];

Manipulate[
 Plot[-(c x - b)^2 + a, {x, 0, 16},
  PlotRange -> {{0, 17}, {0, 14}},
  Frame -> True,
  ImageSize -> 500,
  BaseStyle -> {20, FontFamily -> "Helvetica"},
  FrameLabel -> {"Distance from Back of hoop (ft)", "Heigth (ft)"},
  GridLines -> {Range@16, Range@14},
  Prolog -> {Inset[basket, {0.5, 8}, Top, 1],
    Inset[guy, {16, 6}, Top, 2.5]}],
 {a, 8, 20}, {b, 1, 10}, {c, 0.1, 1}]
🌐
Wolfram
wolfram.com › mathematica › newin7 › content › BuiltInImageProcessing
Built-in Image Processing & Analysis: New in Mathematica 7
Full integration of images into Mathematica interface construction system. ... Image Import ImageApply ImageCompose ImagePartition ImageData MorphologicalComponents Dilation Erosion ImageAdd ImageMultiply ImageEffect LaplacianGaussianFilter ...
🌐
Wolfram Language
reference.wolfram.com › language › ref › ImageAdd.html
ImageAdd: Pixel-wise value addition—Wolfram Documentation
ImageAdd[image, x] adds an amount x to each channel value in image. ImageAdd[image1, image2] gives an image in which each pixel is the sum of the corresponding pixels in image1 and image2.
🌐
Wolfram Language
reference.wolfram.com › language › ref › ImageCollage.html
ImageCollage: Create a collage of images—Wolfram Documentation
ImageCollage creates a collage of a list of images and can be used to create a compact visualization of photographs, graphics, etc.
🌐
Wolfram Documentation
reference.wolfram.com › language › workflow › CombineMultipleImages.html
Combine Multiple Images - Wolfram Language Documentation
ImageCompose · ImageAssemble · Rasterize · Scaled · Background · See Also · Combine Graphics · Make a single image from multiple images by collaging, overlaying or assembling an array of image components.