OpenCV Processing

2 minute read

These are my notes based on Jason Dsouza’s excellent OpenCV video course.

Installation

python3 -m pip install opencv-contrib-python

Colorspaces

OpenCV represents pixels in a BGR (blue, green, red) colorspace, use cv.cvtColor when you need to represent pixels in other colorspaces.

import cv2 as cv
import matplotlib.pyplot as plt

img = cv.imread('Photos/profile.jpg')
cv.imshow('Profile', img)

# Matplotlib uses RGB
plt.imshow(cv.cvtColor(img, cv.COLOR_BGR2RGB))
plt.show()

Split/Merge

Colors can be split into each individual channel.

import cv2 as cv
import numpy as np

img = cv.imread('Photos/profile.jpg')
cv.imshow('Park', img)

b, g, r = cv.split(img)

# Show colors for split images
blank = np.zeros(img.shape[:2], dtype='uint8')
cv.imshow('Blue', cv.merge([b, blank, blank]))
cv.imshow('Green', cv.merge([blank, g, blank]))
cv.imshow('Red', cv.merge([blank, blank, r]))

merged = cv.merge([b, g, r])
cv.imshow('Merged', merged)

cv.waitKey(0)

Smoothing

Typically, we use smoothing to remove noise.

Smoothing functions use a kernal size which defines the local pixels which are used for the smoothing operation.

For each example, assume we start with:

import cv2 as cv

img = cv.imread('Photos/profile.jpg')

Averaging

Each pixel is the average of the neighbouring pixels.

average = cv.blur(img, [11,11])
cv.imshow('AverageBlur', average)

Gaussian

Each pixel is the gaussian weighted average of the neighbouring pixels.

gaussian = cv.GaussianBlur(img, [11,11], sigmaX=0)
cv.imshow('GaussianBlur', gaussian)

Median Blur

Each pixel is the median of the neighbouring pixels.

median = cv.medianBlur(img, 11)
cv.imshow('MedianBlur', median)

Bilateral Blur

Applies a bilateral blur which provides smooth transitions.

bilateral = cv.bilateralFilter(img, 11, 35, 25)
cv.imshow('Bilateral', bilateral)

Bitwise Operations

Can apply AND, OR, NOT and XOR.

import cv2 as cv
import numpy as np

blank = np.zeros((400, 400), dtype='uint8')
rectangle = cv.rectangle(blank.copy(), (30, 30), (370, 370), 255, -1)
circle = cv.circle(blank.copy(), (200, 200), 200, 255, -1)

bitwiseAnd = cv.bitwise_and(rectangle, circle)
cv.imshow('Bitwise AND', bitwiseAnd)

bitwiseOr = cv.bitwise_or(rectangle, circle)
cv.imshow('Bitwise OR', bitwiseOr)

bitwiseXor = cv.bitwise_xor(rectangle, circle)
cv.imshow('Bitwise XOR', bitwiseXor)

bitwiseNot = cv.bitwise_not(rectangle)
cv.imshow('Bitwise NOT', bitwiseNot)

cv.waitKey(0)

Masking

Can use bitwise functions to mask an image.

import cv2 as cv
import numpy as np

img = cv.imread('Photos/profile.jpg')

mask = cv.circle(np.zeros(img.shape[:2], dtype='uint8'), 
  (img.shape[1]//2, img.shape[0]//2), img.shape[0]//3, 
  255, -1)

masked = cv.bitwise_or(img, img, mask=mask)
cv.imshow('Masked image', masked)

cv.waitKey(0)

Histogram

import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np

img = cv.imread('Photos/profile.jpg')
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

gray_hist = cv.calcHist([gray], [0], None, [256], [0,256])
fig = plt.figure()
plt.title('Grayscale histogram')
plt.xlabel('Bins')
plt.ylabel('Num pixels')
plt.plot(gray_hist)
plt.xlim([0,256])
plt.show()

Thresholding

Thresholding allows us to process an image based on pixel intensity.

For each example, assume we start with:

import cv2 as cv

img = cv.imread('Photos/profile.jpg')
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

Simple

th, thresh = cv.threshold(gray, 150, 255, cv.THRESH_BINARY)
cv.imshow('Simple Threshold', thresh)

Inverted

th, thresh = cv.threshold(gray, 150, 255, cv.THRESH_BINARY_INV)
cv.imshow('Inverted Threshold', thresh)

Adaptive

thresh = cv.adaptiveThreshold(gray, 255, cv.ADAPTIVE_THRESH_MEAN_C, cv.THRESH_BINARY, 11, 3)
cv.imshow('Adaptive threshold', thresh)

Gradient Detection

Gradient detection is similar to edge detection; and is useful for simple object detection.

For each example, assume we start with:

import cv2 as cv
import numpy as np

img = cv.imread('Photos/park.jpg')
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

Lapacian

lap = cv.Laplacian(gray, cv.CV_64F)
lap = np.uint8(np.absolute(lap))
cv.imshow('Laplacian', lap)

Sobel

sobelx = cv.Sobel(gray, cv.CV_64F, 1, 0)
sobely = cv.Sobel(gray, cv.CV_64F, 0, 1)
combined_sobel = cv.bitwise_or(sobelx, sobely)
cv.imshow('Sobel Combined', combined_sobel)

Canny

canny = cv.Canny(gray, 150, 175)
cv.imshow('Canny', canny)