一、ROI与泛洪填充
1. ROI操作
ROI(Region Of Interest),感兴趣区域
,从被处理的图像以方框、圆、椭圆、不规则多边形等方式勾勒出需要处理的区域,称为感兴趣区域,经常用来连接图像。
import cv2 as cv
src = cv.imread(r'./test/004.jpg')
cv.imshow('src', src)
sample = src[30:390, 80:400]
gray = cv.cvtColor(sample, cv.COLOR_BGR2GRAY)
back_sample = cv.cvtColor(gray, cv.COLOR_GRAY2BGR)
src[30:390, 80:400] = back_sample
cv.imshow('sample', src)
cv.waitKey(0)
运行效果如下:
2. 彩色图像和二值图像的泛洪填充
泛洪填充:将指定颜色从指定位置开始填充一个连通区域,此时的连通性由像素值的接近程度来衡量。
import cv2 as cv
import numpy as np
def fill_color(image):
copy_image = image.copy()
height, width = image.shape[:2]
mask = np.zeros([height+2, width+2], np.uint8)
cv.floodFill(copy_image, mask, (30, 30), (0, 255, 255), (100, 100, 100), (50, 50, 50), cv.FLOODFILL_FIXED_RANGE)
cv.imshow
('fill_color', copy_image)
src = cv.imread(r'./test/010.png')
fill_color(src)
cv.imshow('src', src)
cv.waitKey(0)
运行效果如下:
import cv2 as cv
import numpy as np
def fill_binary():
image = np.zeros([400, 400, 3], np.uint8)
image[100:300, 100:300, :] = 255
cv.imshow('binary_image', image)
height, width = image
.shape[:2]
print(height, width)
mask = np.ones([height+2, width+2], np.uint8)
mask[101:301, 101:301] = 0
cv.floodFill(image, mask, (200, 200), (0, 0, 255), cv.FLOODFILL_MASK_ONLY)
cv.imshow('filled binary', image)
fill_binary()
cv.waitKey(0)
运行效果如下:
opencv里的 mask 为 uin8 类型的单通道阵列
泛洪填充算法也叫漫水填充算法:floodFill(image, mask, seedPoint, newVal, loDiff=None, upDiff=None, flags=None)
-
image参数表示输入/输出 1 或 3 通道,8位或浮点图像。
-
mask参数表示掩码,该掩码是单通道 8 位图像,比 image 的高度多 2 个像素,宽度多 2 个像素,填充时不能穿过输入掩码中的非零像素。
-
seedPoint参数表示泛洪算法的起始点
-
newVal参数表示在重绘区域像素的新值
-
loDiff参数表示当前观察像素值与其部件邻域像素值或待加入该组件的种子像素之间的亮度或颜色之负差的最大值
-
upDiff参数表示当前观察像素值与其部件邻域像素值或待加入该组件的种子像素之间的亮度或颜色之正差的最大值
个人理解是,参数 seedPoint 起始点的像素值减去参数 loDiff 的像素值表示的是从起始点开始搜索周边范围的像素最低值,参数 seedPoint 起始点的像素值加上参数 upDiff 的像素值表示的是从起始点开始搜索周边范围的像素最大值。有了这个范围,然后该函数就可以在这个连续像素范围内填充指定的颜色 newVal 参数值。
二、模糊操作
模糊操作的基本原理:
-
基于离散卷积,定义好每个卷积核。
-
不同卷积核得到不同的卷积效果,模糊是卷积的一种表象。
1. 均值模糊
对随机噪声有很好的去噪效果!
import
cv2 as cv
def mean_ambiguity(image):
dst1 = cv.blur(image, (20, 1))
dst2 = cv.blur(image, (1, 20))
dst3 = cv.blur(image, (10, 10))
cv.imshow('dst1', dst1)
cv.imshow('dst2', dst2)
cv.imshow('dst3', dst3)
src = cv.imread(r'.\test\004.jpg')
src
= cv.resize(src, None, fx=0.5, fy=0.5)
mean_ambiguity(src)
cv.imshow('src', src)
cv.waitKey(0)
运行效果如下:
2. 中值模糊
对椒盐噪声有很好的去噪效果!
import cv2 as cv
def median_ambiguity(image):
dst = cv.medianBlur(image, 5)
cv.imshow('dst', dst)
src = cv.imread(r'.\test\012.png')
cv.imshow('src', src)
median_ambiguity(src)
cv
.waitKey(0)
运行效果如下:
3. 自定义模糊
自定义卷积核
import cv2 as cv
import numpy as np
def custom_blur_demo(image):
kernel = np.ones([8, 8], np.float32) / 64
dst = cv.filter2D(image, ddepth=-1, kernel=kernel)
cv.imshow('custom_blur_demo', dst)
src = cv.imread(r'.\test\012.png')
cv.imshow('src', src)
custom_blur_demo(src)
cv
.waitKey(0)
运行效果如下:
自定义filter,卷积还可实现锐化 ,锐化算子定义要符合原则,能增强图像,更有立体感!
////
import cv2 as cv
import numpy as np
def custom_blur_demo(image):
kernel = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]], np.float32)
dst = cv.filter2D(image, ddepth=-1, kernel=kernel)
cv.imshow('custom_blur_demo', dst)
src = cv.imread(r'.\test\010.png')
cv.imshow('src', src)
custom_blur_demo(src)
cv
.waitKey(0)
运行效果如下:
三、高斯模糊
高斯模糊本质上是低通滤波器,输出图像的每个像素点是原图像上对应像素点与周围像素点的加权和,原理并不复杂。利用高斯分布权值矩阵与原始图像矩阵做卷积运算,由于高斯分布的傅里叶变换仍然是高斯分布,使用高斯模糊就减少了图像的高频分量,因此高斯模糊是低通滤波器,数学上讲,对图像做高斯模糊等相当于将图像与高斯函数卷积。至于高斯分布权重矩阵,就是对二维正态分布的密度函数(也就是高斯函数)采样再做归一化的产物。
使用 python 与 opencv 实现高斯模糊,只需调用 GaussianBlur 函数,给出高斯矩阵的尺寸和标准差就可以。
cv2.GaussianBlur(src, ksize, sigmaX, dst=None, sigmaY=None, borderType=None)
////
import cv2 as cv
import numpy as np
def clamp(pv):
if pv > 255:
return 255
elif pv < 0:
return 0
else:
return pv
def
gaussion_noise(image):
h, w, c = image.shape
for row in range(h):
for col in range(w):
s = np.random.normal(loc=1.0, scale=9.0, size=3)
b = image[row, col, 0]
g = image[row, col, 1]
r = image[row, col, 2]
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('Gaussian noise', image)
return image
src = cv.imread(r'./test/004.jpg')
src = cv.resize(src, None, fx=0.5, fy=0.5)
cv.imshow('src', src)
dst = cv.GaussianBlur(gaussion_noise(src), (5, 5), 0
)
cv.imshow('Gaussian blur', dst)
t1 = cv.getTickCount()
gaussion_noise(src)
t2 = cv.getTickCount()
time = (t2 - t1) / cv.getTickFrequency()
print(f'用时:{time}s')
cv.waitKey(0)
运行效果如下:
四、边缘保留滤波EPF
1. 高斯双边滤波
前面所用的高斯模糊只考虑了像素空间的分布,而没有考虑差异问题。高斯滤波在滤波时会将图像中各个颜色区域的边缘同区域本身一同模糊掉,而高斯双边滤波则是对各个区域的交界边缘有所保留
python与 opencv 实现
高斯双边滤波
,调用 bilateralFilter 这个API。
cv2.bilateralFilter(src, d, sigmaColor, sigmaSpace, dst=None, borderType=None)
- src:输入图像。
- d:在过滤期间使用的每个像素邻域的直径。如果输入d非0,则sigmaSpace由d计算得出,如果sigmaColor没输入,则sigmaColor由sigmaSpace计算得出。
- sigmaColor:色彩空间的标准方差,一般尽可能大。较大的参数值意味着像素邻域内较远的颜色会混合在一起,从而产生更大面积的半相等颜色。-
-
sigmaSpace::坐标空间的标准方差(像素单位),一般尽可能小。参数值越大意味着只要它们的颜色足够接近,越远的像素都会相互影响。当d > 0时,它指定邻域大小而不考虑sigmaSpace。 否则,d与sigmaSpace成正比。
import cv2 as cv
def bi_filter(image):
dst = cv.bilateralFilter(image, d=0, sigmaColor=100, sigmaSpace=15)
cv.imshow('bi_filter', dst)
src = cv.imread(r'./test/009.png')
cv.imshow('src', src)
bi_filter(src)
cv.waitKey(0)
运行效果如下:
可以非常清楚地看见图像中的脸上的水大部分被滤掉了,皮肤的效果最为明显,就像换了一张皮,并且脸的轮廓都被保留了下来,而没有像均值模糊、中值模糊或者高斯模糊那样得到的图像有些模糊。
2. 均值迁移滤波
均值迁移模糊是图像边缘保留滤波算法中的一种,经常用在对图像进行分水岭分割之前去噪声,可以大幅度提升分水岭分割的效果。均值迁移模糊的主要思想如下: 就是在图像进行开窗的时候,考虑像素值空间范围分布,只有符合分布的像素点才参与计算,计算得到像素均值与空间位置均值,使用新的均值位置作为窗口中心位置继续基于给定像素值空间分布计算均值与均值位置,如此不断迁移中心位置直到不再变化位置(dx=dy=0),但是在实际情况中我们会人为设置一个停止条件比如迁移几次,这样就可以把最后的RGB均值赋值给中心位置。
在n维空间中,有一定数量的样本,我们选定其中的一个样本,以该样本为中心,给长度为半径画一个圆,求取该圆形区域内样本的质心,即密度最大的点,再以该点为中心继续执行上述迭代过程,直至最终收敛。
python与 opencv 实现
均值迁移滤波
,调用 pyrMeanShiftFiltering 这个API。
cv2
.pyrMeanShiftFiltering(src, sp, sr, dst=None, maxLevel=None, termcrit=None)
- src:输入图像
- sp:定义迁移物理空间的半径大小
- sr:定义迁移色彩空间的半径大小
- maxLeval:表示金字塔的最大层数
- termcrit:表示漂移迭代终止条件
以上参数中最后两个很少用到,主要是sp和sr两个参数,二者设置的值越大,对图像色彩的平滑效果越明显,同时函数耗时越多。
import cv2 as cv
def pyr_meanshift_filter(image):
dst = cv.pyrMeanShiftFiltering(image, sp=15, sr=60)
cv.imshow('pyMS', dst)
src = cv.imread(r'./test/009.png')
cv.imshow('src', src)
pyr_meanshift_filter(src)
cv.waitKey(0)
运行效果如下:
与高斯双边滤波的效果比较来看,均值迁移模糊的效果给人一种磨皮过度的感觉,滤波后的图像就像油画那样。
KqwOpenCVFeaturesDemo
Canny边缘检测器是一种被广泛使用的算法,并被认为是边缘检测最优的算法,该方法使用了比高斯差分算法更复杂的技巧,如多向灰度梯度和滞后阈值化。
Python命名规范对于不同类型的数据有着一些细微的区别,总的来讲有2个方面的命名要求,一方面是从命名字符要求方面来规范的,还有一方面是格式方面来规范的,此外还涉及到一些保留关键字我们不能单独出现在命名中。下面来详细聊聊。
保留字也称为关键字,指被编程语言内部定义并保留使用的标识符,程序员编写程序时不能定义与保留字相同的标识符。每种程序设计语言都有一套保留字,保留字一般用来构成程序整体框架、表达关键值和具有结构性的复杂语义等。掌握一门编程语言首先要熟记其所对应的保留字。