opencv-python Introduction to image processing

I will write that I investigated the preprocessing method of images for machine learning. The content is half-finished, but I think I will add more in the future.

Trial environment

Windows10 python 3.6 opencv-python 4.1.2.30

Threshold processing: cv.Threshold (src, threshold, maxValue, thresholdType)

opencv documentation http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_imgproc/py_thresholding/py_thresholding.html

Binarize by specifying a threshold

I will make an appropriate gradation image and binarize it image.png

# make gray scale picture
im_gray = np.array([np.arange(0, 256, 2) for k in range(100)])
im_gray = im_gray.astype('uint8')
print(im_gray.shape)

# apply threshold
ret, thresh1 = cv2.threshold(im_gray,127,255,cv2.THRESH_BINARY)

# show picture
plt.figure(figsize=(7, 6))

ax = plt.subplot(1, 2, 1)
ax.imshow(im_gray, 'gray')
ax.set_xticks([])
ax.set_yticks([])
ax.set_title('ORIGINAL')

ax = plt.subplot(1, 2, 2)
ax.imshow(thresh1, 'gray')
ax.set_xticks([])
ax.set_yticks([])
ax.set_title('BINARY')

plt.show()

Threshold is automatically set and binarized

Binarize using Otsu's method image.png

# make gray scale picture
im_gray = np.array([np.arange(0, 256, 2) for k in range(100)])
im_gray = im_gray.astype('uint8')
print(im_gray.shape)

# global thresholding
ret1,th1 = cv2.threshold(im_gray,127,255,cv2.THRESH_BINARY)

# Otsu's thresholding
ret2,th2 = cv2.threshold(im_gray,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)


# show picture
plt.figure(figsize=(7, 6))

ax = plt.subplot(1, 2, 1)
ax.imshow(im_gray, 'gray')
ax.set_xticks([])
ax.set_yticks([])
ax.set_title('ORIGINAL')

ax = plt.subplot(1, 2, 2)
ax.imshow(thresh1, 'gray')
ax.set_xticks([])
ax.set_yticks([])
ax.set_title('OTSU')

plt.show()

Binarize with dynamic threshold: adaptiveThreshold (src, maxValue, adaptiveMethod, thresholdType, blockSize, C [, dst])

It is used when there is a gradation of brightness such as a photographic image and the entire image cannot be binarized with one threshold value. image.png http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_imgproc/py_thresholding/py_thresholding.html

import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('../input/dave.jpg',0)
img = cv2.medianBlur(img,5)

ret,th1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
th2 = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_MEAN_C,\
            cv2.THRESH_BINARY,11,2)
th3 = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,\
            cv2.THRESH_BINARY,11,2)

titles = ['Original Image', 'Global Thresholding (v = 127)',
            'Adaptive Mean Thresholding', 'Adaptive Gaussian Thresholding']
images = [img, th1, th2, th3]

plt.figure(figsize=(6.5, 6))
for i in range(4):
    plt.subplot(2,2,i+1),plt.imshow(images[i],'gray')
    plt.title(titles[i])
    plt.xticks([]),plt.yticks([])
plt.show()

Other threshold processing

There are various threshold Types other than the frequently used binarization. image.png

# make gray scale picture
im_gray = np.array([np.arange(0, 256, 2) for k in range(100)])
im_gray = im_gray.astype('uint8')
print(im_gray.shape)

# apply threshold
ret,thresh1 = cv2.threshold(im_gray,127,255,cv2.THRESH_BINARY)
ret,thresh2 = cv2.threshold(im_gray,127,255,cv2.THRESH_BINARY_INV)
ret,thresh3 = cv2.threshold(im_gray,127,255,cv2.THRESH_TRUNC)
ret,thresh4 = cv2.threshold(im_gray,127,255,cv2.THRESH_TOZERO)
ret,thresh5 = cv2.threshold(im_gray,127,255,cv2.THRESH_TOZERO_INV)

# show result
titles = ['Original Image','BINARY','BINARY_INV','TRUNC','TOZERO','TOZERO_INV']
images = [im_gray, thresh1, thresh2, thresh3, thresh4, thresh5]

for i in range(6):
    plt.subplot(2,3,i+1)
    plt.imshow(images[i],'gray')
    plt.title(titles[i])
    plt.xticks([]),plt.yticks([])
plt.show()

Image loading: cv2.imread ()

From here, read an appropriate image file and use it. You can read the image as numpy.array with cv2.imread (). I use cv2.imshow () or plt.imshow () to display the image, but cv2.imshow () doesn't seem to work with jupyter notebook, so I will display it with plt.imshow (). However, while opencv traditionally reads the value in BGR, plt.imshow () displays it as RGB, so after swapping R and B with cv2.cvtColor (src, cv2.COLOR_BGR2RGB) I will display it.

python


import cv2
import matplotlib.pyplot as plt

im = cv2.imread('../input/opencv.png')

plt.imshow(cv2.cvtColor(im, cv2.COLOR_BGR2RGB))
plt.xticks([])
plt.yticks([])
plt.show()

This time I will do it with this image

Blur image: cv2.GaussianBlur (src, (size, size), sigma)

opencv documentation http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_imgproc/py_filtering/py_filtering.html

A filter that blurs the image. size is the vertical and horizontal size, and sigma is the vertical and horizontal standard deviation. You can also specify sigma vertically and horizontally, but if omitted, the same standard deviation will be used for both vertically and horizontally. Increasing both size and sigma will increase the degree of blurring.

python


plt.figure(figsize=(8, 10.4))

for k, size in enumerate([3, 9, 27]):
    for k2, sigma in enumerate([0, 10, 40]):
        blur = cv2.GaussianBlur(im, (size, size), sigma)
        ax = plt.subplot(3, 3, k2*3+k+1)
        ax.imshow(cv2.cvtColor(blur, cv2.COLOR_BGR2RGB))
        ax.set_xticks([])
        ax.set_yticks([])
        ax.set_title('blur size: %d\nsigma: %d' % (size, sigma))
plt.show()

Alpha composition: addWeighted (src1, alpha, src2, beta, gamma)

opencv documentation https://docs.opencv.org/2.4/modules/core/doc/operations_on_arrays.html

You can make a mixed image like this. Also, you can enter a value larger than 1 in alpha and beta, but the value will be shaken off for pixels with a large value, so it will be mixed a little strangely like the image on the right end.

python


im2 = cv2.imread('../input/black_white.png')[:,:,::-1]
plt.imshow(cv2.cvtColor(im2, cv2.COLOR_BGR2RGB))

python


plt.figure(figsize=(15, 20))
for k, alpha in enumerate([0, 0.25, 0.5, 0.75, 1]):
    for k2, gamma in enumerate([0, 0.5, 1, 2, 4]):
        beta = 1 - alpha
        im3 = cv2.addWeighted(im, alpha, im2, beta, gamma)

        ax = plt.subplot(5, 5, 5*k2+k+1)
        ax.imshow(cv2.cvtColor(im3, cv2.COLOR_BGR2RGB))
        ax.set_title('alpha: %1.2f\nbeta: %1.2f\ngamma: %1.2f' % (alpha, beta, gamma))
        ax.set_xticks([])
        ax.set_yticks([])
plt.show()

Contour enhancement with blur and alpha compositing

You can emphasize the outline by drawing the blurred image from the original image.

python


blur = cv2.GaussianBlur(im, (9, 9), 27)
im3 = cv2.addWeighted(im, 1.5, blur, -0.5, 1)

plt.figure(figsize=(10, 5))

ax = plt.subplot(1, 3, 1)
ax.imshow(cv2.cvtColor(im, cv2.COLOR_BGR2RGB))
ax.set_title('base image')
ax.set_xticks([])
ax.set_yticks([])

ax = plt.subplot(1, 3, 2)
ax.imshow(cv2.cvtColor(blur, cv2.COLOR_BGR2RGB))
ax.set_title('gaussianBlur')
ax.set_xticks([])
ax.set_yticks([])

ax = plt.subplot(1, 3, 3)
ax.imshow(cv2.cvtColor(im3, cv2.COLOR_BGR2RGB))
ax.set_title('addWeighted')
ax.set_xticks([])
ax.set_yticks([])

plt.show()

Mixing the original image with alpha = 1.5 and the blurred image with beta = -0.5 will result in an image with enhanced contours.

Filtering: cv2.filter2D (src, kernel)

Convolution filter function. It seems that various filtering can be implemented by changing the value of the array. The gaussianBlur () we were doing above can also be implemented with this function.

Translation

If you set kernel to [1], you can get the same image as the original image. Also, if you set some of the large array to 1 and all others to 0, you can translate as follows.

python


size = 21
kernel = np.zeros(size**2).reshape(size, size)
kernel[0, 0] = 1
kernel = kernel / np.sum(kernel)
print(kernel)

im4 = cv2.filter2D(im, -1, kernel)


# show picture
plt.figure(figsize=(7, 6))

ax = plt.subplot(1, 2, 1)
ax.imshow(cv2.cvtColor(im, cv2.COLOR_BGR2RGB))
ax.set_xticks([])
ax.set_yticks([])
ax.set_title('base image')

ax = plt.subplot(1, 2, 2)
ax.imshow(cv2.cvtColor(im4, cv2.COLOR_BGR2RGB))
ax.set_xticks([])
ax.set_yticks([])
ax.set_title('moved')

plt.show()

image.png If there is not enough, the mirror image will be reversed.

Average filter

If all kernels have the same value and a total of 1, it will be an average filter. Same as cv2.blur ().

python


def average_filter(size, im):
    kernel = np.ones(size**2).reshape(size, size)
    kernel = kernel / np.sum(kernel)
    im4 = cv2.filter2D(im, -1, kernel)
    return im4

plt.figure(figsize=(10, 5))
for k, size in enumerate([1, 21, 101]):
    im4 = average_filter(size, im)
    ax = plt.subplot(1, 3, k+1)

    ax.imshow(cv2.cvtColor(im4, cv2.COLOR_BGR2RGB))
    ax.set_title('size: %d' % size)
    ax.set_xticks([])
    ax.set_yticks([])
plt.show()

image.png

Contour enhancement filter

If you set the total to 1 and all but the center to -1 as shown below, the contour enhancement filter will be created.

\begin{pmatrix}
-1 & -1 & -1 & -1 & -1 & -1 & -1 \\
-1 & -1 & -1 & -1 & -1 & -1 & -1 \\
-1 & -1 & -1 & -1 & -1 & -1 & -1 \\
-1 & -1 & -1 & 49 & -1 & -1 & -1 \\
-1 & -1 & -1 & -1 & -1 & -1 & -1 \\
-1 & -1 & -1 & -1 & -1 & -1 & -1 \\
-1 & -1 & -1 & -1 & -1 & -1 & -1
\end{pmatrix}

image.png

python


def edge_filter(size, im):
    kernel = np.full(size**2, -1).reshape(size, size)
    pos = int((size-1)/2)
    kernel[pos, pos] = size**2
    print(kernel)
    im4 = cv2.filter2D(im, -1, kernel)
    return im4

im4 = edge_filter(7, im)

plt.figure(figsize=(6, 5))

ax = plt.subplot(1, 2, 1)
ax.imshow(cv2.cvtColor(im, cv2.COLOR_BGR2RGB))
ax.set_title('base image')
ax.set_xticks([])
ax.set_yticks([])

ax = plt.subplot(1, 2, 2)
ax.imshow(cv2.cvtColor(im4, cv2.COLOR_BGR2RGB))
ax.set_title('edge added')
ax.set_xticks([])
ax.set_yticks([])

plt.show()

Contour extraction filter

It is similar to the above filter, but if you set the total to zero, it will be a filter that extracts only the outline. image.png

python


def laplacian_filter(size, im):
    kernel = np.ones(size**2).reshape(size, size)
    pos = int((size-1)/2)
    kernel[pos, pos] = -(size**2-1)
    print(kernel)
    im4 = cv2.filter2D(im, -1, kernel)
    return im4

im4 = laplacian_filter(7, im)

plt.figure(figsize=(6, 5))

ax = plt.subplot(1, 2, 1)
ax.imshow(cv2.cvtColor(im, cv2.COLOR_BGR2RGB))
ax.set_title('base image')
ax.set_xticks([])
ax.set_yticks([])

ax = plt.subplot(1, 2, 2)
ax.imshow(cv2.cvtColor(im4, cv2.COLOR_BGR2RGB))
ax.set_title('laplacian filter')
ax.set_xticks([])
ax.set_yticks([])

plt.show()

(Scheduled to be added)

Recommended Posts

opencv-python Introduction to image processing
[Introduction to TensorBoard: image] TensorFlow Visualize image processing to deepen understanding
Introduction to regular expression processing system
Introduction to image analysis opencv python
[Image processing] Posterization
Introduction to Scrapy (1)
Introduction to Scrapy (3)
Introduction to Supervisor
Introduction to Tkinter 1: Introduction
python image processing
Introduction to Python Image Inflating Image inflating with ImageDataGenerator
Introduction to PyQt
Introduction to Scrapy (2)
[Linux] Introduction to Linux
Introduction to Scrapy (4)
Introduction to discord.py (2)
Image processing 100 knocks ①
Introduction to discord.py
[Introduction to TensorBoard] Visualize TensorFlow processing to deepen understanding
How to use PyTorch-based image processing library "Kornia"
Flat Field image processing
Introduction to Lightning pytorch
First Python image processing
Introduction to Web Scraping
Introduction to Nonparametric Bayes
Introduction to EV3 / MicroPython
Read digital image processing
Introduction to Python language
Introduction to TensorFlow-Image Recognition
Introduction to OpenCV (python)-(2)
Introduction to PyQt4 Part 1
Image processing with Python
Introduction to Dependency Injection
Introduction to Private Chainer
Introduction to machine learning
Image Processing with PIL
[Introduction to Python] How to use while statements (repetitive processing)
100 image processing knocks !! (021-030) I want to take a break ...
[Chapter 5] Introduction to Python with 100 knocks of language processing
An introduction to Python distributed parallel processing with Ray
[Chapter 6] Introduction to scikit-learn with 100 knocks of language processing
[Chapter 3] Introduction to Python with 100 knocks of language processing
[Chapter 2] Introduction to Python with 100 knocks of language processing
[Chapter 4] Introduction to Python with 100 knocks of language processing
AOJ Introduction to Programming Topic # 1, Topic # 2, Topic # 3, Topic # 4
Introduction to electronic paper modules
A quick introduction to pytest-mock
Image processing with Python (Part 2)
Introduction to dictionary lookup algorithm
Introduction to Monte Carlo Method
OpenCV-Python detects similar image diffs
Image processing with PIL (Pillow)
Introduction to Python Django (2) Win
Introduction to Cython Writing [Notes]
An introduction to private TensorFlow
Kubernetes Scheduler Introduction to Homebrew
An introduction to machine learning
[Introduction to cx_Oracle] Overview of cx_Oracle
A super introduction to Linux
AOJ Introduction to Programming Topic # 7, Topic # 8
[Introduction to pytorch-lightning] First Lit ♬