OpenCV - Read, Write and Edit Images

wordcloud

Installing OpenCV in Anaconda

It is advisable to create a new environment for every project. So create a new enviroment called "opencv" for example. Open Anaconda prompt and enter the following command.

conda create --name opencv

Activate the newly created environment "opencv".

conda activate opencv

Install OpenCV from conda-forge. conda-forge is the preferred channel to install OpenCV and not menpo anymore (menpo is outdated).

conda install -c conda-forge opencv

Installing OpenCV in Anaconda

Reading an image from a file to OpenCV

We will explore basic image reading and display options with OpenCV. More info at OpenCV docs.

In [1]:
# Importing libraries
import cv2 # OpenCV library
import numpy as np # NumPy
In [2]:
cv_img=cv2.imread("../../files/ml/001/cat_eye.jpg") # relative or absolute path to the image file
cv_img
Out[2]:
array([[[ 42,  73,  70],
        [ 45,  70,  72],
        [ 57,  76,  83],
        ...,
        [ 42,  56,  52],
        [ 43,  54,  51],
        [ 34,  47,  45]],

       [[ 47,  76,  80],
        [ 48,  72,  78],
        [ 71,  89,  96],
        ...,
        [ 37,  57,  52],
        [ 49,  63,  61],
        [ 51,  63,  63]],

       [[ 47,  77,  82],
        [ 51,  74,  82],
        [ 84, 101, 110],
        ...,
        [ 20,  42,  37],
        [ 32,  46,  44],
        [ 34,  46,  46]],

       ...,

       [[ 53,  94,  96],
        [ 44,  82,  86],
        [ 43,  81,  85],
        ...,
        [  1,  16,   8],
        [  0,  10,   6],
        [  4,  21,  17]],

       [[ 53,  91,  93],
        [ 67, 104, 108],
        [ 57,  93,  99],
        ...,
        [  0,   9,   0],
        [  3,  16,   8],
        [  0,  15,   7]],

       [[ 45,  78,  81],
        [ 67, 102, 106],
        [ 72, 108, 116],
        ...,
        [ 11,  19,  12],
        [  8,  19,   9],
        [  8,  22,  10]]], dtype=uint8)

The above output shows a numpy array of RGB values of the image.

Display the image with OpenCV

OpenCV has a imshow() to display an Image from an OpenCV array in a new window.

In [3]:
cv2.imshow("Image",cv_img)
cv2.waitKey(delay=5000) # Display image for 5 seconds
cv2.destroyAllWindows() # Close all image windows

The image opens in a new window and looks like the following:

imshow() output

Closing the imshow() window using an ESCAPE key instead of a timer. The ASCII value of the ESC key is 27.

In [4]:
cv2.imshow("Image",cv_img)
if cv2.waitKey()==27:
    cv2.destroyAllWindows()

The image displayed in a seperate window until I pressed the ESC key.

Display using PIL

We need to convert the OpenCV image array to a PIL image. If PIL is not installed, you can install it by entering the following command in Anaconda prompt.

conda install pillow

OpenCV stores images in BGR format whereas image files store them in RGB format. We need to convert BGR to RGB first. If not, this is how the image file is written.

In [5]:
from PIL import Image
Image.fromarray(cv_img)
Out[5]:
No description has been provided for this image
In [6]:
# Converting BGR to RGB
img_array=cv2.cvtColor(cv_img,cv2.COLOR_BGR2RGB)
# Converting to PIL image
img=Image.fromarray(img_array)
img
Out[6]:
No description has been provided for this image
Display using matplotlib

If not already installed, Matplotlib can be installed by typing the following command in Anaconda prompt.

conda install matplotlib

In [7]:
from matplotlib import pyplot as plt
In [8]:
#Show the image with matplotlib
plt.imshow(cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB)) # convert from BGR to RGB before plotting
plt.show()
No description has been provided for this image
Reading in grayscale
In [9]:
cv_img=cv2.imread("../../files/ml/001/cat_eye.jpg",0) # the second argument '0' is for grayscale
cv_img
Out[9]:
array([[ 69,  68,  76, ...,  53,  52,  45],
       [ 74,  71,  89, ...,  53,  61,  62],
       [ 75,  74, 102, ...,  38,  44,  45],
       ...,
       [ 90,  79,  78, ...,  12,   7,  18],
       [ 87, 101,  91, ...,   5,  12,  11],
       [ 75,  99, 106, ...,  16,  15,  17]], dtype=uint8)
In [10]:
plt.imshow(cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB)) # convert from BGR to RGB before plotting
plt.show()
No description has been provided for this image

[^top]

Reading in reduced grayscale
In [11]:
cv_img=cv2.imread("../../files/ml/001/cat_eye.jpg",64) # the second argument '64' is for reduced grayscale 8
cv_img
Out[11]:
array([[ 70,  78,  91, ...,  37,  39,  36],
       [ 74,  90, 108, ...,  54,  39,  26],
       [ 89, 104, 125, ...,  57,  40,  32],
       ...,
       [113, 118, 134, ...,  52,  44,  34],
       [104, 111, 127, ...,  63,  46,  36],
       [104, 104, 109, ...,  32,  25,  20]], dtype=uint8)
In [12]:
plt.imshow(cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB)) # convert from BGR to RGB before plotting
plt.show()
No description has been provided for this image

[^top]

Reading in reduced colour
In [13]:
cv_img=cv2.imread("../../files/ml/001/cat_eye.jpg",65) # the second argument '65' is for reduced colour 8
cv_img
Out[13]:
array([[[ 47,  71,  77],
        [ 46,  81,  85],
        [ 59,  94,  98],
        ...,
        [ 23,  38,  41],
        [ 23,  40,  43],
        [ 25,  38,  36]],

       [[ 46,  75,  82],
        [ 56,  92, 100],
        [ 71, 110, 118],
        ...,
        [ 35,  54,  62],
        [ 23,  39,  45],
        [ 12,  28,  27]],

       [[ 59,  91,  97],
        [ 70, 106, 112],
        [ 86, 128, 133],
        ...,
        [ 34,  57,  65],
        [ 24,  40,  46],
        [ 16,  33,  36]],

       ...,

       [[ 81, 116, 120],
        [ 84, 121, 125],
        [100, 137, 141],
        ...,
        [ 33,  56,  52],
        [ 25,  48,  44],
        [ 18,  37,  34]],

       [[ 72, 107, 111],
        [ 74, 115, 118],
        [ 92, 130, 135],
        ...,
        [ 42,  66,  66],
        [ 28,  49,  46],
        [ 20,  40,  35]],

       [[ 70, 107, 111],
        [ 69, 107, 111],
        [ 74, 111, 119],
        ...,
        [ 16,  34,  33],
        [ 11,  28,  25],
        [  9,  24,  16]]], dtype=uint8)
In [14]:
plt.imshow(cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB)) # convert from BGR to RGB before plotting
plt.show()
No description has been provided for this image

[^top]

Writing an image to a file with OpenCV

cv2.imwrite() takes the arguments file path and OpenCV image array.

In [15]:
cv_img=cv2.imread("../../files/ml/001/cat_eye.jpg") # reading an image from a file
cv2.imwrite("../../files/ml/001/cat_eye_new.jpg",cv_img) # writing an image to a file
Out[15]:
True
In [16]:
Image.open("../../files/ml/cat_eye_new.jpg")
Out[16]:
No description has been provided for this image

Both images look the same but they are not the same as you notice below. Why?

In [17]:
cv_img_new=cv2.imread("../../files/ml/001/cat_eye_new.jpg")
np.array_equal(cv_img,cv_img_new)
Out[17]:
False

[^top]

Reading an image from a URL to OpenCV

We are going to attempt to read an image directly from a URL in to OpenCV. It is possible to download the images manually in to a local drive and then read them with the cv2.imread() method, but at times we will need to read files directly from a URL.

Here is a link to an image of my cat's eye that we are going to access: https://go.allika.eu.org/cateye

NumPy and OpenCV are required, so they are imported.

In [18]:
# Importing libraries
import cv2
import numpy as np 

# Image URL
url="https://go.allika.eu.org/cateye"

There is more than one way to read images to OpenCV from URLs. We explore a few.

1. Using urllib3

In [19]:
# Importing libraries
import urllib.request as urlRequest 

Specify header type

In [20]:
url_request = urlRequest.Request(url, headers={'User-Agent': 'Mozilla/5.0'})

Get URL response.

In [21]:
url_response=urlRequest.urlopen(url_request).read()

Convert URL data in to a NumPy array

In [22]:
img_array = np.array(bytearray(url_response), dtype=np.uint8)

Read the array in to OpenCV

In [23]:
cv_img = cv2.imdecode(img_array, -1)

View image in OpenCV

In [24]:
cv_img
Out[24]:
array([[[ 42,  73,  70],
        [ 45,  70,  72],
        [ 57,  76,  83],
        ...,
        [ 42,  56,  52],
        [ 43,  54,  51],
        [ 34,  47,  45]],

       [[ 47,  76,  80],
        [ 48,  72,  78],
        [ 71,  89,  96],
        ...,
        [ 37,  57,  52],
        [ 49,  63,  61],
        [ 51,  63,  63]],

       [[ 47,  77,  82],
        [ 51,  74,  82],
        [ 84, 101, 110],
        ...,
        [ 20,  42,  37],
        [ 32,  46,  44],
        [ 34,  46,  46]],

       ...,

       [[ 53,  94,  96],
        [ 44,  82,  86],
        [ 43,  81,  85],
        ...,
        [  1,  16,   8],
        [  0,  10,   6],
        [  4,  21,  17]],

       [[ 53,  91,  93],
        [ 67, 104, 108],
        [ 57,  93,  99],
        ...,
        [  0,   9,   0],
        [  3,  16,   8],
        [  0,  15,   7]],

       [[ 45,  78,  81],
        [ 67, 102, 106],
        [ 72, 108, 116],
        ...,
        [ 11,  19,  12],
        [  8,  19,   9],
        [  8,  22,  10]]], dtype=uint8)

[^top]

2. Using urllib3 and PIL

In [25]:
# Importing libraries
import urllib.request as urlRequest 
from PIL import Image

Specify header type

In [26]:
url_request = urlRequest.Request(url, headers={'User-Agent': 'Mozilla/5.0'})

The image is read directly from the URL in to a PIL image.

In [27]:
img = Image.open(urlRequest.urlopen(url_request))

Since this is a PIL image, we can view the image here. Let's make sure we have the correct image.

In [28]:
img
Out[28]:
No description has been provided for this image

We can view the RGB values of an image by converting it to a NumPy array

In [29]:
np.asarray(img)
Out[29]:
array([[[ 70,  73,  42],
        [ 72,  70,  45],
        [ 83,  76,  57],
        ...,
        [ 52,  56,  42],
        [ 51,  54,  43],
        [ 45,  47,  34]],

       [[ 80,  76,  47],
        [ 78,  72,  48],
        [ 96,  89,  71],
        ...,
        [ 52,  57,  37],
        [ 61,  63,  49],
        [ 63,  63,  51]],

       [[ 82,  77,  47],
        [ 82,  74,  51],
        [110, 101,  84],
        ...,
        [ 37,  42,  20],
        [ 44,  46,  32],
        [ 46,  46,  34]],

       ...,

       [[ 96,  94,  53],
        [ 86,  82,  44],
        [ 85,  81,  43],
        ...,
        [  8,  16,   1],
        [  6,  10,   0],
        [ 17,  21,   4]],

       [[ 93,  91,  53],
        [108, 104,  67],
        [ 99,  93,  57],
        ...,
        [  0,   9,   0],
        [  8,  16,   3],
        [  7,  15,   0]],

       [[ 81,  78,  45],
        [106, 102,  67],
        [116, 108,  72],
        ...,
        [ 12,  19,  11],
        [  9,  19,   8],
        [ 10,  22,   8]]], dtype=uint8)

However, OpenCV uses BGR format instead of RGB format. We need to specify the color code when we convert the image to OpenCV format.

In [30]:
cv_img=cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)

View image in OpenCV

In [31]:
cv_img
Out[31]:
array([[[ 42,  73,  70],
        [ 45,  70,  72],
        [ 57,  76,  83],
        ...,
        [ 42,  56,  52],
        [ 43,  54,  51],
        [ 34,  47,  45]],

       [[ 47,  76,  80],
        [ 48,  72,  78],
        [ 71,  89,  96],
        ...,
        [ 37,  57,  52],
        [ 49,  63,  61],
        [ 51,  63,  63]],

       [[ 47,  77,  82],
        [ 51,  74,  82],
        [ 84, 101, 110],
        ...,
        [ 20,  42,  37],
        [ 32,  46,  44],
        [ 34,  46,  46]],

       ...,

       [[ 53,  94,  96],
        [ 44,  82,  86],
        [ 43,  81,  85],
        ...,
        [  1,  16,   8],
        [  0,  10,   6],
        [  4,  21,  17]],

       [[ 53,  91,  93],
        [ 67, 104, 108],
        [ 57,  93,  99],
        ...,
        [  0,   9,   0],
        [  3,  16,   8],
        [  0,  15,   7]],

       [[ 45,  78,  81],
        [ 67, 102, 106],
        [ 72, 108, 116],
        ...,
        [ 11,  19,  12],
        [  8,  19,   9],
        [  8,  22,  10]]], dtype=uint8)

We can see the difference between the NumPy array output of the image and the OpenCV output. The RGB values are reversed.

[^top]

3. Using PIL, requests and BytesIO

In [32]:
# Importing libraries
from PIL import Image
import requests
from io import BytesIO

Read data from URL

In [33]:
response = requests.get(url)

Read URL response in to a PIL image using BytesIO

In [34]:
img = Image.open(BytesIO(response.content))

Let's view the image.

In [35]:
img
Out[35]:
No description has been provided for this image

Rest is same as the method 2. Images have pixels in RGB format but OpenCV uses BGR. We need to specify the color code when we convert the image to OpenCV format.

In [36]:
cv_img=cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)
cv_img
Out[36]:
array([[[ 42,  73,  70],
        [ 45,  70,  72],
        [ 57,  76,  83],
        ...,
        [ 42,  56,  52],
        [ 43,  54,  51],
        [ 34,  47,  45]],

       [[ 47,  76,  80],
        [ 48,  72,  78],
        [ 71,  89,  96],
        ...,
        [ 37,  57,  52],
        [ 49,  63,  61],
        [ 51,  63,  63]],

       [[ 47,  77,  82],
        [ 51,  74,  82],
        [ 84, 101, 110],
        ...,
        [ 20,  42,  37],
        [ 32,  46,  44],
        [ 34,  46,  46]],

       ...,

       [[ 53,  94,  96],
        [ 44,  82,  86],
        [ 43,  81,  85],
        ...,
        [  1,  16,   8],
        [  0,  10,   6],
        [  4,  21,  17]],

       [[ 53,  91,  93],
        [ 67, 104, 108],
        [ 57,  93,  99],
        ...,
        [  0,   9,   0],
        [  3,  16,   8],
        [  0,  15,   7]],

       [[ 45,  78,  81],
        [ 67, 102, 106],
        [ 72, 108, 116],
        ...,
        [ 11,  19,  12],
        [  8,  19,   9],
        [  8,  22,  10]]], dtype=uint8)

[^top]

Last updated 2020-12-16 16:37:03.467510 IST

Comments