Affine and Perspective Transformation

In affine transformation (link, link2), all parallel lines in the original image will still be parallel in the output image. To find the transformation matrix, we need 3 points from input image and their corresponding locations in output image. Then cv2.getAffineTransform will create a 2×3 matrix which is to be passed to cv2.warpAffine. Affine transform can perform rotation, translation, resizing,

pts1 = np.float32([[50,50],[200,50],[50,200]])
pts2 = np.float32([[10,100],[200,50],[100,250]])

M = cv2.getAffineTransform(pts1,pts2)
dst = cv2.warpAffine(img,M,(cols,rows))

For perspective transformation (see links above), you need a 3×3 transformation matrix. Straight lines will remain straight even after the transformation. To find this transformation matrix, you need 4 points on the input image and corresponding points on the output image. Among these 4 points, 3 of them should not be collinear. Then transformation matrix can be found by the function cv2.getPerspectiveTransform. Then apply cv2.warpPerspective with this 3×3 transformation matrix.

pts1 = np.float32([[56,65],[368,52],[28,387],[389,390]])
pts2 = np.float32([[0,0],[300,0],[0,300],[300,300]])

M = cv2.getPerspectiveTransform(pts1,pts2)
dst = cv2.warpPerspective(img,M,(300,300))

In summary,

  • Affine transformation preserves lines and parallelism.
  • Perspective transformation preserves lines. Affine transform is a special case of perspective transformation.
  • PS, affine transformation does not preserve angle. Conformal transformation preserves angle.


Affine and Perspective Transformation

Why openCV uses BGR (not RGB)

When using openCV to load an image, the color information is stored in the order of Blue-Green-Red instead of the currently more popular scheme RGB.

import cv2
image = cv2.imread(args["image"])
cv2.imshow("Image" , image)

This reads in and displays the correct image file. An alternative way to do this using matplotlib is as follows.

import matplotlib.image as mpimg
image = mpimg.imread(args["image"])
# plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))

However, if we read in the image file through cv2 and display it with matplotlib or vice versa, the image will not be displayed correctly, since the R and B channels are flipped (see above link for an example image). Luckily, cv2 has a built-in way to correct this.

import cv2
import matplotlib.image as mpimg
image = cv.imread(args["image"])
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))

Alternatively, we can hack this by swapping the B and R channel since it is the third dimension of the image.

image = image[:, :, ::-1] # or image = image[:, :, (2, 1, 0)]

According to the following post, BGR was introduced to the openCV in a time when BGR was the most popular format, and it got stuck. It is very similar to the funny story why US railway gauge is 4’8.5″.


Why openCV uses BGR (not RGB)

Installing OpenCV3 and Python3 in virtualenv on MacOS Sierra

I spent almost 3 hours today and finally got CV3 installed. I found this detailed tutorial by Andrian Rosebrock early on:

My Hackintosh desktop has not been upgraded for 3 years after it was built in 2013 (running Mountain Lion), and there was no way to get homebrew properly installed due to “Command Line Tool version too old” error. So I decided to upgrade my MacBook Air to the latest MacOS Sierra and install OpenCV on it, also to get a more (physically) portable development environment.

One thing I had installed on my MBA is Anaconda. This, as it proved later on, made my installation a bit more complicated and I had to make adjustment to the tutorial to make OpenCV work.

$ python --version
Python 2.7.10 :: Anaconda 2.3.0 (x86_64)
$ conda --version
conda 3.14.1

Here is a list of adjustments I had to make:

  • is not in /usr/local/bin/, but rather in

    /anaconda/bin/. Specify this path instead in ~/.bash_profile. 

  • After installing virtualenv, when creating virtualenv named cv and later calling workon cv, I got the following error message:
    Usage: source deactivate
    removes the 'bin' directory of the environment activated with 'source
    activate' from PATH. 

The error message is a bit cryptic, but it turns out that anaconda has a command called deactivate in Anaconda’s bin. So I had to rename the activate and deactivate commands.

$ cd /anaconda/bin/
$ mv activate activate_ana 
$ mv deadectivate deactivate_ana

  • OpenCV compiled correctly, but when I tried to import it, it throw an error message “libhdf5.10.dylib not loaded opencv”. The culprit is also the previously installed anaconda.
$ sudo find / -name libhdf5.10.dylib

Luckily I found a blog post in Japanese (日本語ができてよかった!) and the blogger had almost exactly the same problem as this. The problem is solved by

$ brew tap homebrew/science
$ brew install hdf5
$ brew search

(cv) [ llgc @ megatron ~ ]$ python
Python 3.6.0 (default, Dec 24 2016, 08:01:42) 
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.42.1)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import cv2
>>> cv2.__version__

Now I got Python 3.6 + OpenCV 3.2 successfully installed and imported. I will update this post if there are more hiccups caused by Anaconda down the road.

Edit: 01/11/2017

An alternative way to load and display image to cv2 is using matplotlib module. However, the latest version (matplotlib-1.5.3) does not work with virtual environment (e.g., non-system version of Python), and throws a “Framework” error The fix is to install an older version that is compatible with virtual environment (such as 1.4.3).

$ pip uninstall matplotlib
$ pip install matplotlib==1.4.3


Installing OpenCV3 and Python3 in virtualenv on MacOS Sierra