# Composing an image with a plot

I'm trying to illustrate the solutions to a textbook problem dealing with quadratic functions.

This will involve plotting a quadratic and overlaying the plot and the image.

Here is the textbook scan..... The idea of the problem is to find several possible quadratic models that would go through the hoop.

I imported this image into a variable, call it img1

I wanted to establish a "baseline" so I started with a simple plot, x intercepts of 0 and 18, and vertex at (9,14). I know, NOT a solution to the problem but I wanted to see how the plot and image would match up.

I created the plot

g2 = Plot[-14/81 x (x - 18), {x, -1, 19}, PlotStyle -> Thick]


Then I put them together and tweaked the placement of the plot based on the image size.

ImageCompose[img1, g2, {983/2, 811/2}]


Which gives me this... The vertex is in the right place, but the axes don't line up.

Sorry if this is a dumb question, I'm not at all sure how I could get my plot to match the background image so the axes in the image would be the same as the axes in my plot....

Do I need to scale my plot, or scale my image.. or something obvious that I am missing.

Any help is appreciated

• If you right click a graphic or an image, there's a tool to "get coordinates". You can click on a number of points, then use Control-C to copy the coordinates. This can be helpful for aligning the image coordinate system with Plot's coordinate system. Alternatively, instead of using an image with a grid on it, could use only an image of a boy with a basketball, and place that image on the plot using the Epilog option. You could also place a basket :-) – Szabolcs Apr 9 '13 at 15:11
• @Szabolcs I just read your comment after I did exactly that for my answer. :) – einbandi Apr 9 '13 at 15:26
• The answers with Manipulate reminded me of this question: Animate ParametricPlot3D for two different parametric equations – Jens Apr 9 '13 at 18:38

Try this:

(* clip white borders *)
img = ImageCrop[Import["http://i.stack.imgur.com/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.

• Thanks so much, that helps a TON. I'll be using this question in just a few hours, so I can get it to work NOW, and think about some of the ideas you mentioned. I really appreciate the help! – Tom De Vries Apr 9 '13 at 15:01
• Such a superior answer. It. Hurts. Me. :) – BoLe Apr 9 '13 at 17:53
• I know we shouldn't write comments like "Thanks!" and so on, but thanks. That has just saved me probably a week of work and workarounds. – yohbs May 13 '13 at 15:24
• @yohbs, you're welcome! I'm glad my attempt saved you some effort. :) – J. M. is in limbo May 13 '13 at 15:25

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_] :=
ChanVeseBinarize[im, TargetColor -> {1., 1., 1.},
"LengthPenalty" -> 10]},

guy = setalpha[

Manipulate[
Plot[If[locked, (-c - b pos[] + pos[])/pos[]^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[

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}]

• Wow! Looks fantastic, I'll check that out later today when I have time. This is nice since I could have buttons to show the "guy" and "hoop", take them off once the student gets into the problem. Really nice. I really appreciate seeing solutions like this since I can really connect to the commands being used since they apply directly to my problem. Thanks for your time! – Tom De Vries Apr 9 '13 at 15:47
• Now the player only needs a tad alpha channel to remove the white background – Yves Klett Apr 9 '13 at 16:01
• @YvesKlett the new version comes with alpha channels. Thanks for the link, btw. It's really useful! :) – einbandi Apr 9 '13 at 18:01

I enlarge the image canvas if throw flies outside.

together[i, {4, 22, 10}] Parabola with zeroes x1, x2 and vertex at {(x1 + x2)/2, y3}:

y[{x1_, x2_, y3_}, x_] := -4 (x - x1) (x - x2) y3/(x1 - x2)^2

i = ImageCrop@Import@"http://i.stack.imgur.com/La8Zs.jpg";


Note ImageCrop, it ensured me constant ImageDimensions[i]/{21, 18} pixels for each unit.

together[i_Image, {x1_, x2_, y3_}] :=
Module[{p, r, u, v},
{u, v} = ImageDimensions@i/{21., 18.};
p = Plot[y[{x1, x2, y3}, x], {x, x1, x2},
PlotRange -> {{x1, x2}, {0, y3}},
AspectRatio -> Automatic,
PlotStyle -> Directive[Red, AbsoluteThickness]];
r = PlotRange /. AbsoluteOptions[p, PlotRange];
p = Image[p, ImageSize -> u Abs[Subtract @@ First[r]]];
p = SetAlphaChannel[p, Dilation[ColorNegate@Binarize@p, 1]];
With[{pl = Max[0, -1 - x1]}, 