opencv进阶学习笔记5:图像模糊操作,图像锐化,边缘保留滤波EPF(图像滤镜)

基础版传送门:
python3+opencv学习笔记汇总目录(适合基础入门学习)
进阶版笔记目录链接:
python+opencv进阶版学习笔记目录(适合有一定基础)

模糊操作

方法:均值模糊,中值模糊,自定义模糊
模糊原理:
基于离散卷积,不同的卷积得到不同的卷积效果,模糊是卷积的表象。

基础讲解链接
opencv学习笔记11:图像滤波(均值,方框,高斯,中值)

卷积原理示意图:
(2乘1+3乘以1+6乘以1)除以3=3
边缘2和1未被卷积保留
边缘不参与卷积直接保留。

均值模糊

import cv2 as cv
import numpy as np

def blur_demo(image):#均值滤波模糊
    dst = cv.blur(image, (5, 5))
    cv.imshow("blur_demo", dst)
print("--------- Hello Python ---------")
src = cv.imread("yangmi.jpg")
src=cv.resize(src,None,fx=0.4,fy=0.4)
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
blur_demo(src)
cv.waitKey(0)
cv.destroyAllWindows()

(5,5)为卷积核,可以修改。
图片来源于网络。

中值模糊

import cv2 as cv
def median_blur_demo(image):
    dst = cv.medianBlur(image, 5)
    cv.imshow("median_blur_demo", dst)

高斯模糊

numpy 实现高斯模糊

import cv2 as cv
import numpy as np

#截断函数
def clamp(pv):
    if pv > 255:
        return 255
    if pv < 0:
        return 0
    else:
        return pv
#高斯滤波   
def gaussian_noise(image):
    h, w, c = image.shape
    for row in range(h):
        for col in range(w):
            s = np.random.normal(0, 20, 3)#生成随机数
            b = image[row, col, 0]  # blue
            g = image[row, col, 1]  # green
            r = image[row, col, 2]  # red
            image[row, col, 0] = clamp(b + s[0])
            image[row, col, 1] = clamp(g + s[1])
            image[row, col, 2] = clamp(r + s[2])
    cv.imshow("noise image", image)

print("--------- Hello Python ---------")
src = cv.imread("yangmi.jpg")
src=cv.resize(src,None,fx=0.5,fy=0.5)
cv.imshow("input image", src)
gaussian_noise(src)
cv.waitKey(0)
cv.destroyAllWindows()

numpy实现时间较慢,大约4,5秒。

opencv实现高斯模糊
实现方法:GaussianBlur
处理结果=cv2.GaussianBlur(原始图像src,核函数大小ksize,sigmaX)

核函数大小ksize:(N,N)必须是奇数
sigmaX:控制x方向方差,控制权重,一般取0,它自己去计算方差。y轴方差和x一致
在这里插入图片描述

import cv2 as cv

print("--------- Hello Python ---------")
src = cv.imread("yangmi.jpg")
src=cv.resize(src,None,fx=0.5,fy=0.5)
cv.imshow("input image", src)
dst = cv.GaussianBlur(src, (9, 9), 0)
cv.imshow("Gaussian Blur", dst)
cv.waitKey(0)
cv.destroyAllWindows()

dst = cv.GaussianBlur(src, (0, 0), 7)时

import cv2 as cv

print("--------- Hello Python ---------")
src = cv.imread("yangmi.jpg")
src=cv.resize(src,None,fx=0.5,fy=0.5)
cv.imshow("input image", src)
dst = cv.GaussianBlur(src, (0, 0), 7)
cv.imshow("Gaussian Blur", dst)
cv.waitKey(0)
cv.destroyAllWindows()

自定义模糊和图像锐化

dst=cv.filter2D(src, ddepth, kernel[, dst[, anchor[, delta[, borderType]]]])
src: 原图像
dst :目标图像,与原图像尺寸和通过数相同
ddepth: 目标图像的所需深度,-1与原图一样
kernel 卷积核(或相当于相关核),单通道浮点矩阵;如果要将不同的内核应用于不同的通道,请使用拆分将图像拆分为单独的颜色平面,然后单独处理它们。
anchor 内核的锚点,指示内核中过滤点的相对位置;锚应位于内核中;默认值(-1,-1)表示锚位于内核中心。
detal 在将它们存储在dst中之前,将可选值添加到已过滤的像素中。类似于偏置。
borderType 像素外推法,参见BorderTypes

import cv2 as cv
def custom_blur_demo(image):
    #kernel = np.ones([5, 5], np.float32)/25
    kernel = np.array([[0, -1, 0],[-1, 5, -1],[0, -1, 0]], np.float32)
    dst = cv.filter2D(image, -1, kernel=kernel)
    cv.imshow("custom_blur_demo", dst)

使用不同的卷积核有不同的效果。
kernel = np.ones([5, 5], np.float32)/25:模糊

kernel = np.array([[0, -1, 0],[-1, 5, -1],[0, -1, 0]], np.float32):锐化算子,各个数字加起来总和等于0或者1,各个数字为奇数。总和为0做的是边缘;

边缘保留滤波EPF

之前介绍了无论是均值还是高斯都是属于模糊卷积,它们都有一个共同的特点就是模糊之后图像的边缘信息不复存在,受到了破坏。有一种滤波方法有能力通过卷积处理实现图像模糊的同时对图像边缘不会造成破坏,滤波之后的输出完整的保存了图像整体边缘(轮廓)信息,这类卷积滤波算法被称为边缘保留滤波算法(EPF)。
实现方法:高斯双边,均值迁移
使用场景:做图像滤镜。

大白话讲解原理:首先对左边(黑白色图)进行高斯滤波,
高斯滤波为下图,取值范围可以叫做空域

如何当前点与周围像素值差异较大如下图,范围可以叫为值域

则进行截断。得到

最后得到右图(黑巴色)。
高斯滤波参人为添加,像素差多少截断人为设计。

高斯 双边模糊原理
高斯滤波(空间临近)是将二维高斯正态分布放在图像矩阵上做卷积运算。考虑的是邻域内像素值的空间距离关系。通过在核大小范围内,各个点到中心点的空间临近度计算出对应的权值,并将计算好的核与图像矩阵作卷积。最后,图像经过滤波后达到平滑的效果,而图像上的边缘也会有一定程度的平滑,使得整个图像变得模糊,边缘得不到保存。
双边滤波基本思想:将高斯滤波(空间临近)中通过各个点到中心点的空间临近度计算的各个权值进行优化,将其优化为空间临近度计算的权值 和 像素值相似度计算的权值的乘积,优化后的权值再与图像作卷积运算。从而达到保边去噪的效果。

高斯双边模糊
dst=cv2.bilateralFilter(src, d, sigmaColor, sigmaSpace[, dst[, borderType]])
src:输入图像
d:过滤时周围每个像素领域的直径
sigmaColor:在color space中过滤sigma。参数越大,临近像素将会在越远的地方mix。
sigmaSpace:在coordinate space中过滤sigma。参数越大,那些颜色足够相近的的颜色的影响越大。
值域和空域的两个方差sigma可以简单的设置为相等,小于10,无太大效果,大于150效果太强,像卡通片似的。
讲解
滤波器尺寸d:大于5将较慢(5 forreal-time)d 是像素邻域“直径”。
Sigma_color较大,则在邻域中的像素值相差较大的像素点也会用来平均。
Sigma_space较大,则虽然离得较远,但是,只要值相近,就会互相影响。
将sigma_sapce设置较大,sigma_color设置较小,可获得较好的效果(椒盐噪声)。
双边滤波的内在想法是:在图像的值域(range)上做传统滤波器在空域(domain)上做的工作。空域滤波对空间上邻近的点进行加权平均,加权系数随着距离的增加而减少;值域滤波则是对像素值相近的点进行加权平均,加权系数随着值差的增大而减少。同时考虑对空间域与值域进行滤波的意义:将对图像进行平滑化的范围限制在值域较小的部分(也就是 光度/色彩差异较小的部分),如此便能够达到边缘保存的目的。(文字部分有借鉴别人的)

import cv2 as cv
import numpy as np
def bi_demo(image):
    dst = cv.bilateralFilter(image, 0, 100, 15)
    cv.imshow("bi_demo", dst)
print("--------- Hello Python ---------")
src = cv.imread("example.png")
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
bi_demo(src)
cv.waitKey(0)
cv.destroyAllWindows()

可以看到眼睛与周围像素相差很大(属于边界)被保留啦下来。

均值偏移
meanShfit均值漂移算法是一种通用的聚类算法,它的基本原理是:对于给定的一定数量样本,任选其中一个样本,以该样本为中心点划定一个圆形区域,求取该圆形区域内样本的质心,即密度最大处的点,再以该点为中心继续执行上述迭代过程,直至最终收敛。
dst = cv2.pyrMeanShiftFiltering(image, sp, sr,maxLevel,termcrit)
sp:漂移物理空间半径大小;
sr:漂移色彩空间半径大小;
maxLevel:定义金字塔的最大层数
termcrit:漂移迭代终止条件,可以设置为迭代次数满足终止,迭代目标与中心点偏差满足终止,或者两者的结合

步骤:

  1. 迭代空间构建:
    以输入图像上src上任一点P0为圆心,建立物理空间上半径为sp,色彩空间上半径为sr的球形空间,物理空间上坐标2个—x、y,色彩空间上坐标3个—R、G、B(或HSV),构成一个5维的空间球体。
    其中物理空间的范围x和y是图像的长和宽,色彩空间的范围R、G、B分别是0~255。
  2. 求取迭代空间的向量并移动迭代空间球体后重新计算向量,直至收敛:
    在1中构建的球形空间中,求得所有点相对于中心点的色彩向量之和后,移动迭代空间的中心点到该向量的终点,并再次计算该球形空间中所有点的向量之和,如此迭代,直到在最后一个空间球体中所求得的向量和的终点就是该空间球体的中心点Pn,迭代结束。
  3. 更新输出图像dst上对应的初始原点P0的色彩值为本轮迭代的终点Pn的色彩值,如此完成一个点的色彩均值漂移。
  4. 对输入图像src上其他点,依次执行步骤1,、2、3,遍历完所有点位后,整个均值偏移色彩滤波完成,
import cv2 as cv
import numpy as np


def shift_demo(image):
    dst = cv.pyrMeanShiftFiltering(image, 5, 40)
    cv.imshow("shift_demo", dst)
print("--------- Hello Python ---------")
src = cv.imread("example.png")
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
shift_demo(src)
cv.waitKey(0)
cv.destroyAllWindows()

原理文字部分有借鉴他人。

电气专业的计算机萌新。写博文不容易。如果你觉得本文对你有用,请点个赞支持下。谢谢。

猜你喜欢

转载自blog.csdn.net/kobeyu652453/article/details/107295443