6.opencv阈值处理与图像平滑处理

一、阈值处理

阈值处理是指剔除图像内像素值高于一定值或者低于一定值的像素点。
例如,设定阈值为127,然后:

将图像内所有像素值大于127的像素点的值设置为255;

将图像内所有像素值小于等于127的像素点的值设置为0;

通过阈值处理可以把一幅图像二值化,有效的实现前景和背景的分离。

自适应阈值原理
自适应阈值。此时的值是根据图像上的每一个小区域计算与其对应的值。因此在同一幅图像上的不同区域用的是不同的值从而使我们能在亮度不同的情况下得到更好的结果。

代码详情:

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

# img = cv2.imread('dave.jpg', 0)
img = cv2.imread('sudoku.jpg', 0)
# 中值滤波
img = cv2.medianBlur(img, 5) #中值滤波制造明暗差距
ret, th1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
#cv2.THRESH_BINARY:大于阈值的像素点的灰度值设定为maxValue(如8位灰度值最大为255),
# 灰度值小于阈值的像素点的灰度值设定为0。
# adaptiveThreshold:自适应阈值二值化。
# ADAPTIVE_THRESH_MEAN_C阀值取自相邻区域的平均值
#ADAPTIVE_THRESH_GAUSSIAN_C阀值取自相邻区域的加权和,权重为一个高斯窗口
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)
# 11 为 Block size 邻域大小 用来计算阈值的区域大小 ,
# 2 为 C值,常数, 阈值就等于的平均值或者加权平均值减去这个常数。
titles = ['Original Image', 'Global Thresholding (v = 127)',
          'Adaptive Mean Thresholding', 'Adaptive Gaussian Thresholding']
#四个图像的命名
images = [img, th1, th2, th3]#调用四个图像

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.xticks() 表达的是x轴的刻度内容的范围
plt.show()

实验截图:
在这里插入图片描述

简单阈值处理的方法:

  • cv2.THRESH_BINARY 超过阈值部分取maxval(最大值),否则取0
  • cv2.THRESH_BINARY_INV THRESH_BINARY的反转
  • cv2.THRESH_TRUNC 大于阈值部分设为阈值,否则不变
  • cv2.THRESH_TOZERO 大于阈值部分不改变,否则设为0
  • cv2.THRESH_TOZERO_INV THRESH_TOZERO的反转

简单阈值代码实现:

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

img = cv2.imread('grey-gradient.jpg', 0)

ret, thresh1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
ret, thresh2 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY_INV)
ret, thresh3 = cv2.threshold(img, 127, 255, cv2.THRESH_TRUNC)
ret, thresh4 = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO)
ret, thresh5 = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO_INV)
#cv2.THRESH_BINARY        超过阈值部分取maxval(最大值),否则取0
#cv2.THRESH_BINARY_INV    THRESH_BINARY的反转
#cv2.THRESH_TRUNC         大于阈值部分设为阈值,否则不变
#cv2.THRESH_TOZERO        大于阈值部分不改变,否则设为0
#cv2.THRESH_TOZERO_INV    THRESH_TOZERO的反转
titles = ['Original Image', 'BINARY', 'BINARY_INV', 'TRUNC', 'TOZERO', 'TOZERO_INV']
images = [img, 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()

实验截图:

在这里插入图片描述

Otsus 二值化:

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

img = cv2.imread('noisy2.png', 0)
# global thresholding
ret1, th1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
# Otsu's thresholding
ret2, th2 = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

# Otsu's thresholding after Gaussian filtering
# 5,5 为 斯核的大小 0 为标准差
blur = cv2.GaussianBlur(img, (5, 5), 0)
# 阀值一定为 0
ret3, th3 = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

# plot all the images and their histograms
images = [img, 0, th1,
          img, 0, th2,
          blur, 0, th3]
titles = ['Original Noisy Image', 'Histogram', 'Global Thresholding (v=127)',
          'Original Noisy Image', 'Histogram', "Otsu's Thresholding",
          'Gaussian filtered Image', 'Histogram', "Otsu's Thresholding"]
# 使用了 pyplot 中画直方图的方法 plt.hist,
# 注意的是它的参数是一维数组
# 所以使用了 numpy ravel 方法 将多维数组 换成一维 也可以使用 flatten 方法
# ndarray.flat 1-D iterator over an array.
# ndarray.flatten 1-D array copy of the elements of an array in row-major order.

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

二值化截图:在这里插入图片描述

二值化的实现原理:
代码演示:

import cv2
import numpy as np

img = cv2.imread('noisy2.png', 0)
blur = cv2.GaussianBlur(img, (5, 5), 0)
# find normalized_histogram, and its cumulative distribution function
#  算归一化直方图
# CalcHist(image, accumulate=0, mask=NULL)

hist = cv2.calcHist([blur], [0], None, [256], [0, 256])
hist_norm = hist.ravel() / hist.max()
Q = hist_norm.cumsum()

bins = np.arange(256)
fn_min = np.inf
thresh = -1

for i in range(1, 256):
    p1, p2 = np.hsplit(hist_norm, [i])  # probabilities
    q1, q2 = Q[i], Q[255] - Q[i]  # cum sum of classes
    b1, b2 = np.hsplit(bins, [i])  # weights

    # finding means and variances
    m1, m2 = np.sum(p1 * b1) / q1, np.sum(p2 * b2) / q2
    v1, v2 = np.sum(((b1 - m1) ** 2) * p1) / q1, np.sum(((b2 - m2) ** 2) * p2) / q2

    # calculates the minimization function
    fn = v1 * q1 + v2 * q2
    if fn < fn_min:
        fn_min = fn
        thresh = i

# find otsu's threshold value with OpenCV function
ret, otsu = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

print(thresh, ret)

**

二、图像平滑

**
均值滤波
void cv::blur(src,ksize[,dst[,anchor[,borderTyoe]]])
高斯滤波
dst=cv.GaussianBlur(src,ksize,sigmaX[,dst[,[sigmaY[,borderType]]])
中值滤波
dst=cv.medianBlur(src,ksize[,dst])
双边滤波
dst=cv.bilateralFilter(src,d,sigmaColer,sigmaSpace[,dst[,borderType]])
卷积就是循环对图像跟一个核逐个元素相乘再相加得到另一幅图的操作
dst=cv.filter2D(src,ddepth.kernel[,dst[,anchor[,delta[,borderType]]]])

案例分析:

图像模糊

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

img = cv2.imread('lenaNoise.png')

blur = cv2.blur(img, (5, 5))

'''
现在把卷积核换成 斯核 简单来  方框不变 将原来每个方框的值是 相等的 现在  的值是符合 斯分布的 方框中心的值最大 其余方框根据  离中心元素的 离 减 构成一个 斯小山包。原来的求平均数现在变成求 加权平均数 全就是方框 的值 。
'''
# 0 是指根据窗口大小 (5,5) 来计算高斯函数标准差
gaublur = cv2.GaussianBlur(img, (5, 5), 0)  # 高斯模糊

'''
 名思义就是用与卷积框对应像素的中值来替代中心像素的值。 个滤波 器经常用来去 椒盐噪声。前 的滤波器 是用 算得到的一个新值来取代中 心像素的值 而中值滤波是用中心像素周围 也可以使他本  的值来取代他。 他能有效的去 噪声。卷积核的大小也应 是一个奇数。
'''
median = cv2.medianBlur(img, 5)  # 中值模糊

'''
函数 cv2.bilateralFilter() 能在保持边界清晰的情况下有效的去 噪  。
但是 种操作与其他滤波器相比会比 慢。
我们已经知 高斯滤波器是求 中心点 邻近区域像素的高斯加权平均值。
 种 斯滤波器只考虑像素之间的空间关系 
 而不会考虑像素值之间的关系 ,像素的相似度 。
 所以 种方法不会考 虑 一个像素是否位于边界。
 因此边界也会被模糊掉 而 这正不是我们想要。

双边滤波在同时使用空 高斯权重和灰度值相似性 斯权 。
空 高斯函数确保只有邻近区域的像素对中心点有影响
 灰度值相似性高斯函数确保只有与中心像素灰度值相近的才会被用来做模糊运算。
 所以 种方法会确保边界不会被模糊掉
  因为边界处的灰度值变化比较大。
'''

#16.4 双边滤波
#cv2.bilateralFilter(src, d, sigmaColor, sigmaSpace)
# d – Diameter of each pixel neighborhood that is used during filtering. # If it is non-positive, it is computed from sigmaSpace
# 9  域直径 两个 75 分别是空  斯函数标准差 灰度值相似性 斯函数标准差
filterblur = cv2.bilateralFilter(img, 9, 75, 75)

plt.subplot(221), plt.imshow(img), plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(222), plt.imshow(blur), plt.title('Blurred')
plt.xticks([]), plt.yticks([])
plt.subplot(223), plt.imshow(gaublur), plt.title('GaussianBlur')
plt.xticks([]), plt.yticks([])
plt.subplot(224), plt.imshow(median), plt.title('medianBlur')
plt.xticks([]), plt.yticks([])
plt.show()

结果截图:在这里插入图片描述
本次课程主要是对图像的各种处理,需要掌握函数的使用

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值