# How to Annotate an Image in LaTeX

This tutorial is about annotating figures in LaTeX using TikZ and Pgfplots packages. It reviews different methods and issues that you may face when you overlying text over an image (PNG, JPEG, PDF or any supported file). Not only writing text into a graphic but also drawing arrows, shapes and overlying two images, one over another!

The Basic Idea: To annotate a picture using TikZ, we need to follow 3 simple steps:

1. Include the image in a node.
2. Add axis to simplify labels' positioning.
3. Add labels, shapes and arrows.

Let's get into the detail!

## Step 1: Include an image in TikZ

In LaTeX, we use $\verb|\includegraphics[options]{imageName}|$ command to add an image which requires loading the package graphicx. In TikZ, we will use the same command inside a node. Here is an illustrative example:

\documentclass{standalone}
\usepackage{tikz}

\begin{document}

\begin{tikzpicture}

\node (image) at (0,0) {
\includegraphics[width=\textwidth]{example-image}
};

\end{tikzpicture}

\end{document}


• We loaded the TikZ package using $\verb|\usepackage{tikz}|$. It should be noted that there is no need to load graphicx package as it is already loaded by TikZ.
• We created a node at the point with coordinates (0,0) and we named it $\verb|(image)|$
• The image, with name $\verb|example-image|$, is added using $\verb|\includegraphics|$ command with a width equal to the text width of the document. I invite you to check the set of images that can be used for creating a minimal working example (MWE).

Interesting question: I am having trouble locating points in TikZ, Where is the (0,0) with respect to the image?

By default, the (0,0) is located at the center of the image. We are talking about the point (0,0) as it's the one used to create the node. For example, if you create a node at the point (x,y) then (x,y) is located at the center of the image.

### 1.1 Positioning Nodes using Anchors

For easier positioning, It is better to put the origin at the bottom left corner of the image. This can be achieved by modifying the anchor of the node as follows:

\node[anchor=south west] (image) at (0,0) {
\includegraphics[width=\textwidth]{example-image}
};


We simply added the option $\verb|anchor=south west|$ to the $\verb|\node|$ command. Here is a list of different cases. We used the word $\verb|text|$ instead of an image without loss of generality.

To be honest, I prefer to use the basic placement options instead of the anchoring mechanism as It provides the location of the text (or the image) with respect to the coordinates. Here is a list that compares both positioning approaches and for more details, check the manual "section: Positioning Nodes".

Using the basic placement option, we put the image above and right of the (0,0). Here is the corresponding code in this case:

\node[above right] (image) at (0,0) {
\includegraphics[width=\textwidth]{example-image}
};


It should be noted that $\verb|[above right]|$ is different than $\verb|[above,right]|$. In the latter, the option $\verb|right|$ will be used as it is the last option for positioning.

### 1.2 Remove Inner Separation

You may remarked in the previous illustration a small white margin induced by the node command. It can be controlled by adding the option $\verb|inner sep=0|$ to the $\verb|\node|$ command. This allows us to precisely put the origin at the bottom left corner of the image.

## Step 2: Image with axes

Now, we need to add axes with a grid in order to be able to put labels at specific positions in the image. These positions are relative to the image size which allows us to resize our illustration without any issues (arrows and shapes will also be resized automatically).

This can be done using a scope environment as below:

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}

\begin{document}

\begin{tikzpicture}
% Include the image in a node
\node [
above right,
inner sep=0] (image) at (0,0) {\includegraphics[width=\textwidth]{example-image}};

% Create scope with normalized axes
\begin{scope}[
x={($0.1*(image.south east)$)},
y={($0.1*(image.north west)$)}]

% Grid
\draw[lightgray,step=1] (image.south west) grid (image.north east);
\end{scope}

\end{tikzpicture}

\end{document}


where we get an image with 10x10 grid:

• In the scope, we specified $x$ and $y$ for axes units. The x-axis unit is chosen one tenth the image width. The y-axis unit is chosen one tenth the image height. The image width and height are obtained from $\verb|(image.south west)|$ and $\verb|(image.north east)|$, respectively.
• For coordinate calculations, we loaded the TikZ library $\verb|calc|$. It allows us to choose the one tenth of the image size as units for the axes.
• We created a grid using the command $\verb|(\draw)|$ between the image corners: $\verb|(image.south west)|$ and $\verb|(image.north east)|$. Grid lines are chosen with a light gray color and a step of 1(normalized unit). For a more precision, you can modify the step to a smaller value.

Let's add labels and as it is a repetitive thing we will use a for loop (read this post to learn how to use foreach loop).

#### Final code of step 2

and the corresponding image:

• We used two $\verb|(\foreach)|$ loops, one for the x-axis labels and one for the y-axis labels. The loop counter varies from 0 to 10 with an increment equal to 1.
• The loop counter ($\verb|\x|$ and $\verb|\y|$) is used for coordinates and for printing labels.
• At each value of the loop counter of the x-axis, we add a node below the coordinates by providing the option $\verb|[below]|$, check above the basic placement options.
• The same for the y-axis, we use the option $\verb|[left]|$ to print labels on the left of the y-axis.

Labels, circles and arrows will be added inside the scope in question, which is the aim of the next section!

## Step 3: Add labels, circles and arrows

In this part, we will learn how to add different labels to annotate our illustration. Let's start by the first label "circled number".

The line code:

\node[circle,fill=green] at (7.25,6.75){\small 2};


adds a node at the point with coordinates $(7.25,6.75)$. The node shape is a circle filled with a green color (check this post for predefined shapes and this post for predefined colors).

The line code:

\draw[stealth-, very thick,green] (5,1.75) -- ++(0.5,-0.5)
node[right,black,fill=white]{\small Dspace card};

• draws a very thick arrow with a green color. The arrow tip style is specified by the option $\verb|stealth-|$, we used also $\verb|latex-|$. $\verb|stealth-|$ means the arrow tip is on the starting point of the straight line, $\verb|-stealth|$ means that the arrow tip is on the end point and $\verb|stealth-stealth|$ means the straight line has arrow tips on both extremities.
• The arrow starts from the point with coordinates $(5,1.75)$ and increased by $0.5$ along the x-axis and decreased by $0.5$ along the y-axis.
• We added a node on the right of the end point of the straight line (we used basic placement for that).
• The node contains a small text "Dspace card" which is written with black color.
• By default, the node shape is a rectangle (we change it to a circle in the previous line code), we filled it with a white color using the option $\verb|fill=white|$.

The line code:

\draw[latex-, very thick,green] (2.5,1) -- ++(-0.5,0)
node[left,black,fill=white]{\small Voltage source};


adds the label "Voltage source" to the illustration. In this case, we used the arrow tip $\verb|latex-|$.

The line code:

\draw[very thick,green] (0.5,2.5) rectangle (4,9.5)
node[below left,black,fill=green]{\small 1};

• draws a rectangle from its two opposite corners ($\verb|(0.5,2.5)|$ and $\verb|(4,9.5)|$). The rectangle is drawn with a green very thick line (check the next illustration about different options of line thickness).
• We added a node at the bottom left of the point $\verb|(4,9.5)|$. It is filled with green color and it has the rectangular shape (by default).

Here is the code of the annotated image (you can comment the grid and axes' labels to get the final results). In the next section, we will highlight another method based on Pgfplots package

## Can we do the same using Pgfplots?

We have published a post about plotting functions in LaTeX using Pgfplots, I deeply invite you to check it. Moreover, Pgfplots package has the feature to include external graphics. The above annotated image is recreated using Pgfplots package, here is the LaTeX code:

#### LaTeX Code: Using Pgfplots Package

Inside the $\verb|tikzpicture|$ environment we created an axis with the options:

• xmin =0, xmax=10, ymin=0, ymax=10: to set axes min and max labels.
• width=\textwidth, height=0.6\textwidth:  to fix the figure size
• scale only axis: to force the axis box to fills the above desired dimensions. Without this option, the figure size corresponds to the axis box, axes' ticks and x-y labels.
• grid=both: to add a grid to the axis box.
• axis on top: without this option the grid will be hidden by the image
• hide axis: this option should be commented to display the grid. once we annotate our illustration we will use this option to hide the axis box, ticks and the grid.

The image is added using the line code:

\addplot graphics[xmin=0,ymin=0,xmax=10,ymax=10] {ExpSetup};


Coordinates can be accessed using the syntax $\verb|(axis cs:x,y)|$. Hence, adding labels is the same as in the previous method with slight modification. Instead of using the point with coordinates $\verb|(x,y)|$, we use $\verb|(axis cs:x,y)|$. That's all!

For now, we reached the end of this tutorial and I hope you learned something ❤️. The post will be extended in near future to include these points:

• How to superimpose data to a given graph provided in an image format.
• Useful packages for figures annotation in LaTeX such as tikz-imagelabels package and overpic package.
• Online LaTeX overlay generator.

If you have any remarks or suggestions, please feel free to use the comment section, I will be happy to hear from you!

Thanks and Stay safe!

### This Post Has 4 Comments

1. Thanks a ton

1. You’re welcome 🙂!

2. Thanks you! Really appreciate your guides.

1. Thanks Moritz for your feedback!