If you see this, something is wrong
To get acquainted with the document, the best thing to do is to select the "Collapse all sections" item from the "View" menu. This will leave visible only the titles of the top-level sections.
Clicking on a section title toggles the visibility of the section content. If you have collapsed all of the sections, this will let you discover the document progressively, from the top-level sections to the lower-level ones.
Generally speaking, anything that is blue is clickable.
Clicking on a reference link (like an equation number, for instance) will display the reference as close as possible, without breaking the layout. Clicking on the displayed content or on the reference link hides the content. This is recursive: if the content includes a reference, clicking on it will have the same effect. These "links" are not necessarily numbers, as it is possible in LaTeX2Web to use full text for a reference.
Clicking on a bibliographical reference (i.e., a number within brackets) will display the reference.
Speech bubbles indicate a footnote. Click on the bubble to reveal the footnote (there is no page in a web document, so footnotes are placed inside the text flow). Acronyms work the same way as footnotes, except that you have the acronym instead of the speech bubble.
By default, discussions are open in a document. Click on the discussion button below to reveal the discussion thread. However, you must be registered to participate in the discussion.
If a thread has been initialized, you can reply to it. Any modification to any comment, or a reply to it, in the discussion is signified by email to the owner of the document and to the author of the comment.
First published on Saturday, Jan 11, 2025 and last modified on Wednesday, Jan 15, 2025 by Fabienne Chaplais.
Mathedu
shear, fast rotation
In that assessment, you will decompose the matrix of a rotation of angle in \( [0,\pi)\) into the product of three matrices of "shears", that act on just one axis at the time.
And at the end, you will be invited to paste and run the given Python script to vizualise two ways to rotate the famous ’lena’ image (in grayscale).
For the scope of that text, the rotations and shears are identified with their matrices in the canonical basis of the plane.
A horizontal shear is a matrix of the form \( S^H_{\alpha} =\begin{bmatrix}1&\alpha\\ 0&1 \end{bmatrix}\) , with its parameter \( \alpha\) being a given real number.
Consider the column vector \( X=\begin{bmatrix} x\\ y \end{bmatrix}\) , and prove that \( Y=S^H_{\alpha} X\) has the same ordinate as \( X\) .
\( Y=S^H_{\alpha} X =\begin{bmatrix}1&\alpha\\ 0&1 \end{bmatrix} \begin{bmatrix} x\\ y \end{bmatrix} =\begin{bmatrix} x+\alpha y\\ y \end{bmatrix}\) .
The ordinate of \( Y\) is \( y\) , like the ordinate of \( X\) .
Consider the horizontal shears \( S^H_{\alpha} =\begin{bmatrix}1&\alpha\\ 0&1 \end{bmatrix}\) of parameter \( \alpha\) , and \( S^H_{\alpha'} =\begin{bmatrix}1&\alpha'\\ 0&1 \end{bmatrix}\) of parameter \( \alpha'\) , and prove that \( S^H_{\alpha}S^H_{\alpha'}=S^H_{\alpha+\alpha'}\) .
\( S^H_{\alpha}S^H_{\alpha'} =\begin{bmatrix}1&\alpha\\ 0&1 \end{bmatrix} \begin{bmatrix}1&\alpha'\\ 0&1 \end{bmatrix} =\begin{bmatrix}1&\alpha'+\alpha\\ 0&1 \end{bmatrix} =S^H_{\alpha+\alpha'}\)
A vertical shear is a matrix of the form \( S^V_{\beta} =\begin{bmatrix}1&0\\ \beta&1 \end{bmatrix}\) , with its parameter \( \beta\) being a given real number.
Consider the column vector \( X=\begin{bmatrix} x\\ y \end{bmatrix}\) , and prove that \( Y=S^V_{\beta} X\) has the same abscissa as \( X\) .
\( Y=S^V_{\beta} X =\begin{bmatrix}1&0\\ \beta&1 \end{bmatrix} \begin{bmatrix} x\\ y \end{bmatrix} =\begin{bmatrix} x\\ \beta x+y \end{bmatrix}\) .
The abscissa of \( Y\) is \( x\) , like the abscissa of \( X\) .
Consider the vertical shears \( S^V_{\beta} =\begin{bmatrix}1&0\\ \beta&1 \end{bmatrix}\) of parameter \( \beta\) , and \( S^V_{\beta} =\begin{bmatrix}1&0\\ \beta&1 \end{bmatrix}\) of parameter \( \beta'\) , and prove that \( S^V_{\beta}S^V_{\beta'}=S^V_{\beta+\beta'}\) .
\( S^V_{\beta}S^V_{\beta'} =\begin{bmatrix}1&0\\ \beta&1 \end{bmatrix} \begin{bmatrix}1&0\\ \beta'&1 \end{bmatrix} =\begin{bmatrix}1&0\\ \beta+\beta'&1 \end{bmatrix} =S^V_{\beta+\beta'}\)
Consider the horisontal shear \( S^H_{\alpha} =\begin{bmatrix}1&\alpha\\ 0&1 \end{bmatrix}\) of prarmeter \( \alpha\) , and the vertical shear \( S^V_{\beta} =\begin{bmatrix}1&0\\ \beta&1 \end{bmatrix}\) of parameter \( \beta\) .
Consider the product \( A=S^H_{\alpha}S^V_{\beta}S^H_{\alpha}\) .
The following calculations may be performed.
\( A=\begin{bmatrix}1&\alpha\\ 0&1 \end{bmatrix} \begin{bmatrix}1&0\\ \beta&1 \end{bmatrix} \begin{bmatrix}1&\alpha\\ 0&1 \end{bmatrix}\)
\( =\begin{bmatrix}1+\alpha\beta&\alpha\\ \beta&1 \end{bmatrix} \begin{bmatrix}1&\alpha\\ 0&1 \end{bmatrix}\)
\( =\begin{bmatrix}1+\alpha\beta& (1+\alpha\beta)\alpha+\alpha\\ \beta&\beta\alpha+1 \end{bmatrix}\)
\( A=\begin{bmatrix}1+\alpha\beta& \alpha(2+\alpha\beta)\\ \beta&1+\alpha\beta \end{bmatrix}\)
Consider the following formulae.
\( \tan(\theta/2)=\frac{\sin(\theta/2)}{\cos(\theta/2)}\) , that is well defined because \( -\frac{\pi}{2}<\frac{\theta}{2}<\frac{\pi}{2}\) , so that \( \cos(\theta/2)\ne 0\) .
\( \sin(\theta)=2\sin(\theta/2)\cos(\theta/2)\) .
\( \cos(\theta)=1-2\sin^2(\theta/2)\) .
\( \cos^2(\theta)+\sin^2(\theta)=1\) .
Prove the following formulae (in that order).
\( 1+\alpha\beta=\cos(\theta)\) .
\( \alpha(2+\alpha\beta)=-\sin(\theta)\) .
The following calculation may be performed.
\( 1+\alpha\beta= 1-\tan(\theta/2)\sin(\theta) =1-\frac{\sin(\theta/2)}{\cos(\theta/2)}(2\sin(\theta/2)\cos(\theta/2))\)
\( =1-2\sin^2(\theta/2) =\cos(\theta)\) .
\( \alpha(2+\alpha\beta)=-\tan(\theta/2)(1+\cos(\theta)) =-\frac{\sin(\theta/2)}{\cos(\theta/2)}(1+1-2\sin^2(\theta/2))\)
\( =-2\frac{\sin(\theta/2)}{\cos(\theta/2)}(1-\sin^2(\theta/2)) =-2\frac{\sin(\theta/2)}{\cos(\theta/2)}\cos^2(\theta/2) =-2\sin(\theta/2)\cos(\theta/2)\)
\( \alpha(2+\alpha\beta)=-\sin(\theta)\) .
Use the fact that \( R_{\theta}= \begin{bmatrix}\cos(\theta)&-\sin(\theta)\\ \sin(\theta)&\cos(\theta) \end{bmatrix}\) .
\( A=\begin{bmatrix}1+\alpha\beta& \alpha(2+\alpha\beta)\\ \beta&1+\alpha\beta \end{bmatrix} =\begin{bmatrix}\cos(\theta)&-\sin(\theta)\\ \sin(\theta)&\cos(\theta) \end{bmatrix} =R_{\theta}\) .
For an image, the rotation of \( \pi/2\) involves both row and column indexes together, making the parallelisation impossible.
As the horizontal (resp. vertical) shears act only on the row (resp. column) indexes, making it possible to parallelise the process.
So that it is interesting to decompose the rotation into shears, for the sake of fastness of the computation.
In the script below, the parallelisation is not performed of course. It is just a little Python script for the pleasure of the eyes.
In Python, a \( 512\times 512\) image is a \( 512\times 512\times 3\) tensor with \( 3\) layers.
For an image in colors, each layer is an RGB component of a color, red, green and blue.
For a grayscale image, as we have, only the layer \( 0\) conains information, and it is the level of gray of each pixel.
To import it, we need the function ’imread’ in the library ’imageo’.
Then we extract the layout ’0’ to obtain a \( 512\times 512\) matrix.
That matrix can then be visualized we the function ’imshow’ of the library ’matplotlib.pyplot’.
We shall rotate by \( \pi/2\) the image, both directely and with the help of 3 sucessive shears.
The matrix of the rotation of angle \( \pi/2\) is \( R=\begin{bmatrix} 0&-1\\ 1&0 \end{bmatrix}\) .
To rotate the image ’lena’, each vector ’array([i,j])’, with i and j calculated from the center of the image, must be multiplied to the right by the matrix \( R\) . Indeed, the indexes (i,j) are analog to the vectors of the canonical basis in the plane of the image.
As \( \tan(\pi/4)=1\) , the matrix of the horizontal shear is \( HS=\begin{bmatrix} 1&-1\\ 0&1 \end{bmatrix}\) .
To shear horizontally the image ’lena’, we must first set margins of \( 255\) pixels at each side of the image,
to obtain a \( 1024\times 1024\) image. Then each vector ’array([i,j])’ with customed ranges
must be multiplied to the right by the matrix \( HS\) . We obtain an image called ’lena1_sheared’.
And as \( \sin(\pi/2)=1\) , the matrix of the vertical shear is \( VS=\begin{bmatrix} 1&0\\ 1&1 \end{bmatrix}\) .
To shear vertically the image ’lena1_sheared’, we must first set margins of \( 512\) pixels at each side of the image,
to obtaine a \( 2048\times 2048\) image. Then each vector ’array([i,j])’ with customed ranges
must be multiplied to the right by the matrix \( VS\) .
After a crop to the size \( 1024\times 1024\) , we obtain an image called ’lena2_sheared’.
Then we shear horizontally the image ’lena2_sheared’ to obtain the image ’lena3_rotated’.
To do that, we must first set margins of \( 512\) pixels at each side of the image,
to obtain a \( 2048\times 2048\) image. Then each vector ’array([i,j])’ with customed ranges
must be multiplied to the right by the matrix \( HS\) .
After a crop to the size \( 512\times 512\) , we obtain an image called ’lena3_rotated’.
You are invited to copy that script in a .py file, that you will store in the same directory as the image ’lena_gray.gif’ that you have previously downloaded from the course.
Then, run and enjoy!
import imageio as iio
from matplotlib.pyplot import *
from numpy import *
# Read 'lena_gray.gif'
lena0=iio.imread('lena_gray.gif')
# Extract the first layer of the image, in gray
lena=lena0[:,:,0]
# Visualize in figure 1 the image as a matrix 512x512 pixels
imshow(lena,cmap='gray')
# Direct rotation of pi/2
R=array([[0,-1],[1,0]])
lena_rotated=zeros([512,512])
for i in arange(-255,256):
for j in arange(-255,256):
V=array([i,j])@R
lena_rotated[256+i,256+j]=lena[256+V[0],256+V[1]]
# Visualize in figure 2 the rotated image as a 512x512 matrix
figure()
imshow(lena_rotated,cmap='gray')
# margins of 256 pixels at each side
lena1=zeros([1024,1024])
lena1[256:768,256:768]=lena
# First horizontal shear
HS=array([[1,-1],[0,1]])
lena1_sheared=zeros([1024,1024])
for i in arange(-255,255):
for j in arange(-255+i,255+i):
U=array([i,j])@HS
lena1_sheared[512+i,512+j]=lena1[512+U[0],512+U[1]]
# Visualize in figure 3 the sheared image as a 1024x1024 marix
figure()
imshow(lena1_sheared,cmap='gray')
# margins of 512 pixels at each side
lena2=zeros([2048,2048])
lena2[512:1536,512:1536]=lena1_sheared
# Vertical shear
VS=array([[1,0],[1,1]])
lena2_sheared=zeros([2048,2048])
for j in arange(-511,511):
for i in arange(-255-j,255-j):
W=array([i,j])@VS
lena2_sheared[1024+i,1024+j]=lena2[1024+W[0],1024+W[1]]
# crop to 1024 over 1024 pixels
lena2_sheared=lena2_sheared[512:1536,512:1536]
# Visualize in figure 4 the double sheared image as a 1024x1024 marix
figure()
imshow(lena2_sheared,cmap='gray')
# margins of 512 pixels at each side
lena3=zeros([2048,2048])
lena3[512:1536,512:1536]=lena2_sheared
# Second horiaontal shear
lena3=zeros([2048,2048])
lena3[512:1536,512:1536]=lena2_sheared
lena3_rotated=zeros([2048,2048])
for i in arange(-511,511):
for j in arange(-511+i,511+i):
U=array([i,j])@HS
lena3_rotated[1024+i,1024+j]=lena3[1024+U[0],1024+U[1]]
# Crop to 512 over 512 pixels
lena3_rotated=lena3_rotated[768:1280,768:1280]
# Visualize in figure 5 the rotated image obtained by 3 shears as a 512x512
matrix
figure()
imshow(lena3_rotated,cmap='gray')The decomposition of a rotation of \( \frac{\pi}{2}\) into three shears allow fast rotation of an image.
We discovered how to do it theoretically and how to implement it in Python, with the famous ’Lena’ image.
I am normally hidden by the status bar