[OpenCV-Python] Tutorial: 3-4 smoothing denoising, Gaussian smoothing, mean filtering, median filtering

OpenCV Python smooth denoising

【Target】

  • Smooth and denoise images with different low-pass filters (average, Gaussian, median, bilateral)
  • Use your own custom filters

  • 5x5 averaging filter

K = 1 25 [ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ] K= \frac{1}{25} \begin{bmatrix} 1 & 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{bmatrix} K=251 1111111111111111111111111

  • 3x3 average filter

K = 1 9 [ 1 1 1 1 1 1 1 1 1 ] K= \frac{1}{9} \begin{bmatrix} 1 & 1 & 1\\ 1 & 1 & 1\\ 1 & 1 & 1 \end{bmatrix} K=91 111111111

【Code】

  • custom smoothing filter

insert image description here

Like one-dimensional signals, images can also be filtered by low-pass filters and high-pass filters; low-pass filters can blur images and remove noise, and high-pass filters can be used to find image edges.

import numpy as np
import cv2

img = cv2.imread('opencv-logo-white.png')
kernel = np.ones((5, 5), np.float32)/25
dst = cv2.filter2D(img, -1, kernel)

cv2.imshow("src", img)
cv2.imshow("filter2D", dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
  • Vague

insert image description here

Take a pixel as the center, and take the average value of the surrounding pixels as the pixel value of the pixel.
If you don’t want to use a normalized filter, use cv2.boxFilter and pass innormalize=False

import cv2
import numpy as np

img = cv2.imread('opencv-logo-white.png')
blur = cv2.blur(img,(5,5))

cv2.imshow("src", img)
cv2.imshow("blur", blur)
cv2.waitKey(0)
cv2.destroyAllWindows()
  • Gaussian blur

insert image description here

import cv2
import numpy as np

img = cv2.imread('opencv-logo-white.png')
blur = cv2.GaussianBlur(img, (5, 5), 0)

cv2.imshow("src", img)
cv2.imshow("GaussianBlur", blur)
cv2.waitKey(0)
cv2.destroyAllWindows()
  • median filter

insert image description here

The median filter is different from other filters. The pixel value of the median filter is the pixel value inside the image, and other filters are obtained by calculation. The kernel width of the median filter is a positive odd number. Great for handling salt and pepper noise.

import numpy as np
import cv2

def addPepperSalt(src: cv2.Mat, snr: float = 0.99) -> cv2.Mat:
    """
    addPepperSalt 给彩色图像添加黑白椒盐噪声

    _extended_summary_

    Args:
        src (cv2.Mat): 输入图像
        snr (float): 信噪比
    """
    if src is None:
        return None

    dst = src.copy()

    h, w, _ = src.shape
    imgsz = h * w
    pepperSaltNum = int(imgsz * (1.0 - snr))

    for i in range(pepperSaltNum):
        randx = np.random.randint(1, w-1)
        randy = np.random.randint(1, h-1)

        if np.random.random() <= 0.5:
            dst[randy, randx] = 0
        else:
            dst[randy, randx] = 255
    return dst


img = cv2.imread('sheets.png')
cv2.imshow("src", img)

pepperSaltIm = addPepperSalt(img, 0.99)
cv2.imshow("peppersalt", pepperSaltIm)

median = cv2.medianBlur(pepperSaltIm, 5)
blur = cv2.bilateralFilter(pepperSaltIm, 15, 180, 180)

cv2.imshow("median", median)
cv2.imshow("blur", blur)

cv2.waitKey(0)
cv2.destroyAllWindows()
  • bilateral filtering

insert image description here

insert image description here

It can effectively remove noise while retaining edge information, but it is very time-consuming.
NOTE: Bilateral filtering is very unfriendly to salt and pepper noise. Please refer to Reference 2 for specific principles.

import cv2
import numpy as np

img = cv2.imread('bilateral.png')
blur = cv2.bilateralFilter(img,9,75,75)

cv2.imshow("src", img)
cv2.imshow("bilateralFilter", blur)
cv2.waitKey(0)
cv2.destroyAllWindows()

insert image description here

【interface】

  • cv2.filter2D
void cv::filter2D	(	InputArray 	src,
OutputArray 	dst,
int 	ddepth,
InputArray 	kernel,
Point 	anchor = Point(-1,-1),
double 	delta = 0,
int 	borderType = BORDER_DEFAULT 
);
cv2.filter2D(	src, ddepth, kernel[, dst[, anchor[, delta[, borderType]]]]	) ->	dst

Convolve an image with a convolution kernel

  • src : input image
  • dst : output image
  • ddepth : the depth of the output image
  • kernel : convolution kernel
  • anchor : the default is (-1, -1) at the center of the convolution kernel
  • delta : added to the filtered pixel value before storing
  • borderType : padding type, not supportedBORDER_WRAP

ddepth:

borderType:

insert image description here

  • cv2.blur
void cv::blur	(	InputArray 	src,
OutputArray 	dst,
Size 	ksize,
Point 	anchor = Point(-1,-1),
int 	borderType = BORDER_DEFAULT 
);
cv2.blur(	src, ksize[, dst[, anchor[, borderType]]]	) ->	dst

boxFilterBlur the image with

  • src : input image
  • dst : output image
  • ksize : the size of the blur kernel
  • anchor : the default is (-1, -1) at the center of the convolution kernel
  • borderType : padding type, not supportedBORDER_WRAP
  • cv2.boxFilter
void cv::boxFilter	(	InputArray 	src,
OutputArray 	dst,
int 	ddepth,
Size 	ksize,
Point 	anchor = Point(-1,-1),
bool 	normalize = true,
int 	borderType = BORDER_DEFAULT 
);
cv2.boxFilter(	src, ddepth, ksize[, dst[, anchor[, normalize[, borderType]]]]	) ->	dst
  • src : input image
  • dst : output image
  • ddepth : the depth of the output image
  • ksize : the size of the blur kernel
  • anchor : the default is (-1, -1) at the center of the convolution kernel
  • normalize : normalization flag
  • borderType : padding type, not supportedBORDER_WRAP
  • cv2.GaussianBlur
void cv::GaussianBlur	(	InputArray 	src,
OutputArray 	dst,
Size 	ksize,
double 	sigmaX,
double 	sigmaY = 0,
int 	borderType = BORDER_DEFAULT 
);
cv2.GaussianBlur(	src, ksize, sigmaX[, dst[, sigmaY[, borderType]]]	) ->	dst

Gaussian blur

  • src : input image
  • dst : output image
  • ksize : the size of the blur kernel
  • sigmaX : the variance of the Gaussian kernel in the X direction
  • sigmaY : The variance of the Gaussian kernel in the Y direction, if set to 0, it is set to sigmaX, if both are set to 0, it is calculated through the window. It is best to set both.
  • borderType : padding type, not supportedBORDER_WRAP
  • cv2.bilateralFilter
void cv::bilateralFilter	(	InputArray 	src,
OutputArray 	dst,
int 	d,
double 	sigmaColor,
double 	sigmaSpace,
int 	borderType = BORDER_DEFAULT 
);
cv2.bilateralFilter(	src, d, sigmaColor, sigmaSpace[, dst[, borderType]]	) ->	dst

Apply bilateral filtering to an image

  • src : input image
  • dst : output image
  • d : The diameter of the pixel neighborhood used for filtering, if it is a negative number, it will sigmaSpacebe calculated .
  • sigmaColor : The variance of the color space, if the setting is large, the pixel with a large pixel difference is considered to be a neighboring pixel;
  • sigmaSpace : The variance of the coordinate space. If it is set to be large, it means that the pixels far away are neighbor pixels. If it is d > 0, it is determined by the coordinates whether it is a neighbor.
  • borderType : padding type, not supportedBORDER_WRAP

【reference】

  1. OpenCV Official Documentation
  2. Introduction and application of bilateral filtering

Guess you like

Origin blog.csdn.net/zhoujinwang/article/details/127935511