[opencv][python] 学习手册3:练习代码2

[opencv][python] 学习手册3:练习代码2

46_图像降噪-均值滤波.py
47_图像降噪-均值滤波api.py
48_图像降噪-中值滤波api.py
49_图像降噪-加权均值滤波.py
50_高斯模糊.py
51_Sobel算子.py
52_Sobel算子_api.py
53_Scharr函数_Sobel改进版.py
54_拉普拉斯算子.py
55_补充-锐化滤波.py




46_图像降噪_椒盐噪声原理

原理

  1. 创建和原图同大小随机矩阵点 pepper_noise,点的总个数 height X width,每个点的随机取值范围 [0, 255]
  2. 定义噪声率 ratio = 0.1,即 椒噪声的分界值为 25.6
  3. 将 pepper_noise 随机矩阵中的点二值化,小于 25.6 的噪声位置赋值 -255(椒噪声)

代码

"""
需求:
1. 生成椒盐噪声
"""
import logging

import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np

# 配置日志
logging.basicConfig(level=logging.INFO)

height = 600
width = 800

# 创建和原图同大小随机矩阵
pepper_noise = np.random.randint(0, 256, (height, width))
pepper_noise = pepper_noise.astype(np.uint8)
logging.info("pepper_noise:[{0}]\nshape:[{1}]\ndtype:[{2}]".format(pepper_noise,
                                                                   pepper_noise.shape,
                                                                   pepper_noise.dtype))

# 计算直方图,方式一,并绘制 api: cv.calcHist([src_gray], [0], None, [256], [0, 256])
hist_pepper_noise = cv.calcHist([pepper_noise], [0], None, [256], [0, 256])

fig1 = plt.figure()
fig1.canvas.set_window_title("hist_pepper_noise")
plt.plot(hist_pepper_noise)

# 计算直方图,方式二,并绘制
fig2 = plt.figure()
fig2.canvas.set_window_title("hist_pepper_noise_plt")
plt.hist(pepper_noise.ravel(), bins=256, rwidth=0.5)

# # 定义10%的噪声 256×10%=25.6
ratio = 0.1
# 若值小于25.6 则置为-255,否则为0
pepper_noise = np.where(pepper_noise < ratio * 256, -255, 0)

# 计算直方图,方式二,并绘制
fig3 = plt.figure()
fig3.canvas.set_window_title("hist_pepper_noise_plt_ratio")
plt.hist(pepper_noise.ravel(), bins=256, rwidth=0.5)

# cv.imshow("pepper_noise", pepper_noise)

plt.show()

# cv.waitKey(0)

运行结果

E:\Software\A_anaconda\envs\python3\python.exe E:/WorkSpace/WS_CV_2D/day03/46_图像降噪_生成噪声.py
INFO:root:pepper_noise:[[[219 149 177 ...  55   3  74]
 [147 137 198 ... 118 143 181]
 [ 28 244 119 ... 208 101 206]
 ...
 [203 219 166 ...  27 107  18]
 [182  69 245 ... 208 241 144]
 [ 98   3   3 ... 187 198 172]]]
shape:[(600, 800)]
dtype:[uint8]

在这里插入图片描述

  • 左上,右上图显示的是二值化之前随机噪声直方图,横坐标表示颜色值范围 [0, 255],纵坐标表示矩阵中对应的颜色个数
  • 左下图显示的是二值化之后的噪声直方图,可以看见,横坐标只有两个有效值 [0, -255],纵坐标对应的二值化后的颜色个数

46_图像降噪-生成椒盐噪声_单通道

原理

  1. 根据之前的椒噪声原理,椒噪声被赋值 -255,盐噪声被赋值 255,类型为 int(整数)
  2. 将目标图像,椒噪声,盐噪声的的类型转化为 float(浮点类型),并相加,则图像矩阵值是包含正负的浮点数
  3. 在对结果矩阵进行越界处理时,将大于 255 的值设置为 255(盐点、盐噪声), 小于 0 的值设置为 0(椒点、椒噪声)

代码

"""
需求:
对图像加上噪声
单通道图像
"""

import cv2 as cv
import numpy as np

filename = r"../img/mountain.jpg"
img = cv.imread(filename, cv.IMREAD_GRAYSCALE)
height = img.shape[0]
width = img.shape[1]

# 创建和原图同大小随机矩阵 胡椒噪声
pepper_noise = np.random.randint(0, 256, (height, width))
# 创建和原图同大小随机矩阵 盐噪声
salt_noise = np.random.randint(0, 256, (height, width))
# 定义10%的噪声 256×10%=25.6
ratio = 0.1
# 若值小于25.6 则置为-255,否则为0
pepper_noise = np.where(pepper_noise < ratio * 256, -255, 0)
# 若值大于25.6 则置为255,否则为0
salt_noise = np.where(salt_noise < ratio * 256, 255, 0)

# 将uint8类型转成浮点类型
img.astype("float")
pepper_noise.astype("float")
salt_noise.astype("float")

# 将 胡椒噪声 添加到原图中
dst_img = img + pepper_noise
# 校验越界问题
dst_img = np.where(dst_img > 255, 255, dst_img)
dst_img = np.where(dst_img < 0, 0, dst_img)

cv.imshow("pepper img", dst_img.astype("uint8"))

# 将 盐噪声 添加到原图中
dst_img = img + salt_noise
# 校验越界问题
dst_img = np.where(dst_img > 255, 255, dst_img)
dst_img = np.where(dst_img < 0, 0, dst_img)

cv.imshow("salt img", dst_img.astype("uint8"))

# 将 椒盐噪声 添加到原图中
dst_img = img + pepper_noise + salt_noise
# 校验越界问题
dst_img = np.where(dst_img > 255, 255, dst_img)  # 设置盐噪声
dst_img = np.where(dst_img < 0, 0, dst_img)  # 设置椒噪声

cv.imshow("pepper salt img", dst_img.astype("uint8"))

cv.waitKey(0)

运行结果
在这里插入图片描述


46_图像降噪-生成椒盐噪声_三通道

原理

对于三通道图像,需要将椒盐噪声矩阵通过 merge 函数融合成三通道矩阵,然后才能与原图像相加,否则会报错(无法广播)
在这里插入图片描述

代码

"""
需求:
对图像加上噪声
三通道图像
"""

import logging
import cv2 as cv
import numpy as np

logging.basicConfig(level=logging.INFO)

filename = r"../img/grbq.jpg"
img = cv.imread(filename, cv.IMREAD_COLOR)
height = img.shape[0]
width = img.shape[1]

cv.imshow("src", img)

# 创建和原图同大小随机矩阵 胡椒噪声
pepper_noise = np.random.randint(0, 256, (height, width))
# 创建和原图同大小随机矩阵 盐噪声
salt_noise = np.random.randint(0, 256, (height, width))
# 定义10%的噪声 256×10%=25.6
ratio = 0.1
# 若值小于25.6 则置为-255,否则为0
pepper_noise = np.where(pepper_noise < ratio * 256, -255, 0)
# 若值大于25.6 则置为255,否则为0
salt_noise = np.where(salt_noise < ratio * 256, 255, 0)

# 将uint8类型转成浮点类型
img.astype("float")
pepper_noise.astype("float")
salt_noise.astype("float")

pepper_noise_c3 = cv.merge([pepper_noise, pepper_noise, pepper_noise])
salt_noise_c3 = cv.merge([salt_noise, salt_noise, salt_noise])
logging.info("pepper_noise_c3\nshape::[{0}]\ndtype::[{1}]".format(pepper_noise_c3.shape, pepper_noise_c3.dtype))
logging.info("salt_noise_c3\nshape::[{0}]\ndtype::[{1}]".format(salt_noise_c3.shape, salt_noise_c3.dtype))

# 将 胡椒噪声 添加到原图中
dst_img = img + pepper_noise_c3
# 校验越界问题
dst_img = np.where(dst_img > 255, 255, dst_img)
dst_img = np.where(dst_img < 0, 0, dst_img)

dst_pepper = dst_img.copy()
cv.imshow("pepper img", dst_img.astype("uint8"))

# 将 盐噪声 添加到原图中
dst_img = img + salt_noise_c3
# 校验越界问题
dst_img = np.where(dst_img > 255, 255, dst_img)
dst_img = np.where(dst_img < 0, 0, dst_img)

dst_salt = dst_img.copy()
cv.imshow("salt img", dst_img.astype("uint8"))

# 将 椒盐噪声 添加到原图中
dst_img = img + pepper_noise_c3 + salt_noise_c3
# 校验越界问题
dst_img = np.where(dst_img > 255, 255, dst_img)
dst_img = np.where(dst_img < 0, 0, dst_img)

dst_salt_pepper = dst_img.copy()
cv.imshow("pepper salt img", dst_img.astype("uint8"))

# cv.imwrite("../img/room_salt.jpg", dst_salt)
# cv.imwrite("../img/room_pepper.jpg", dst_pepper)
# cv.imwrite("../img/room_salt_pepper.jpg", dst_salt_pepper)

cv.waitKey(0)

运行结果

E:\Software\A_anaconda\envs\python3\python.exe E:/WorkSpace/WS_CV_2D/day03/46_图像降噪_生成噪声_3.py
INFO:root:pepper_noise_c3
shape::[(421, 704, 3)]
dtype::[int32]
INFO:root:salt_noise_c3
shape::[(421, 704, 3)]
dtype::[int32]

Process finished with exit code 0

在这里插入图片描述


46_图像降噪-均值滤波.py

原理(截取自课件)

  • 线性滤波是图像处理最基本的方法,它允许我们对图像进行处理,产生很多不同的效果。
  • 首先,我们需要一个二维的滤波器矩阵(卷积核)和一个要处理的二维图像。
  • 然后,对于图像的每一个像素点,计算它的邻域像素和滤波器矩阵的对应元素的乘积,
  • 然后加起来,作为该像素位置的值。这样就完成了滤波过程。
    在这里插入图片描述
    在这里插入图片描述
  • 对图像和滤波矩阵进行逐个元素相乘再求和的操作就相当于将一个二维的函数移动到另一个二维函数的所有位置,这个操作就叫卷积
    在这里插入图片描述

均值滤波
在这里插入图片描述

代码

"""
均值滤波
将卷积核内的所有灰度值加起来,然后计算出平均值,用这个平均值填充卷积核正中间的值,
这样做可以降低图像的噪声,同时也会导致图像变得模糊

        [
        [1, 1, 1],
        [1, 1, 1],
        [1, 1, 1]
        ] x 1/9

进行卷积操作时,使用 cv 的 api filter2D

需求:
进行单通道降噪操作
1. 读取图像噪声图,将图像装换成灰度图
2. 定义均值滤波卷积核
3. 使用 api filter2D 进行卷积运算
4. 显示图像,等待按键
"""

import logging
import cv2 as cv
import numpy as np


logging.basicConfig(level=logging.INFO)

# 1. 读取图像噪声图,将图像装换成灰度图
filename_org = r"../img/room.jpg"
filename = r"../img/room_salt_pepper.jpg"
org = cv.imread(filename_org, cv.IMREAD_COLOR)
src = cv.imread(filename, cv.IMREAD_COLOR)
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)

# 2. 定义均值滤波卷积核
kernel = np.array([
    [1, 1, 1],
    [1, 1, 1],
    [1, 1, 1]
]) / 9

# 3. 使用 api filter2D 进行卷积运算
"""
dst	=	cv.filter2D(	src, ddepth, kernel[, dst[, anchor[, delta[, borderType]]]]	)
    src	input image.
    dst	output image of the same size and the same number of channels as src.
    when ddepth=-1, the output image will have the same depth as the source.
"""
dst = cv.filter2D(gray, -1, kernel)
dst_c3 = cv.filter2D(src, -1, kernel)

# 4. 显示图像,等待按键
cv.imshow("org", org)
cv.imshow("src", src)
cv.imshow("gray", gray)
cv.imshow("dst", dst)
cv.imshow("dst_c3", dst_c3)

key = cv.waitKey(0)
logging.info("key = [{0}]".format(key))

运行结果
在这里插入图片描述
在这里插入图片描述


47_图像降噪-均值滤波_api.py

代码

"""
均值滤波
将卷积核内的所有灰度值加起来,然后计算出平均值,用这个平均值填充卷积核正中间的值,
这样做可以降低图像的噪声,同时也会导致图像变得模糊

        [
        [1, 1, 1],
        [1, 1, 1],
        [1, 1, 1]
        ] x 1/9

进行卷积操作时,使用 cv 的 api filter2D

需求:
进行单通道降噪操作
1. 读取图像噪声图,将图像装换成灰度图
2. 定义均值滤波卷积核
3. 使用 api filter2D 进行卷积运算
4. 显示图像,等待按键
"""

import logging
import cv2 as cv
import numpy as np


logging.basicConfig(level=logging.INFO)

# 1. 读取图像噪声图,将图像装换成灰度图
filename_org = r"../img/room.jpg"
filename = r"../img/room_salt_pepper.jpg"
org = cv.imread(filename_org, cv.IMREAD_COLOR)
src = cv.imread(filename, cv.IMREAD_COLOR)
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)

# 2. 定义均值滤波卷积核
kernel = np.array([
    [1, 1, 1],
    [1, 1, 1],
    [1, 1, 1]
]) / 9

# 3. 使用 api filter2D 进行卷积运算
"""
dst	=	cv.filter2D(	src, ddepth, kernel[, dst[, anchor[, delta[, borderType]]]]	)
    src	input image.
    dst	output image of the same size and the same number of channels as src.
    when ddepth=-1, the output image will have the same depth as the source.
"""
dst = cv.filter2D(gray, -1, kernel)
dst_c3 = cv.filter2D(src, -1, kernel)

# 4. 显示图像,等待按键
cv.imshow("org", org)
cv.imshow("src", src)
cv.imshow("gray", gray)
cv.imshow("dst", dst)
cv.imshow("dst_c3", dst_c3)

key = cv.waitKey(0)
logging.info("key = [{0}]".format(key))

运行结果(同上)


48_图像降噪-中值滤波_api.py

中值滤波

  • 对邻近的像素点进行灰度排序,然后取中间值,它能有效去除图像中的椒盐噪声
  • 操作原理: 卷积域内的像素值从小到大排序 取中间值作为卷积输出

代码

"""
需求:
1. 使用 medianBlur 函数对图像进行处理
"""

import logging

import cv2 as cv

logging.basicConfig(level=logging.INFO)

src = cv.imread(r"../img/room_salt.jpg", cv.IMREAD_COLOR)
src = cv.imread(r"../img/room_pepper.jpg", cv.IMREAD_COLOR)
src = cv.imread(r"../img/room_salt_pepper.jpg", cv.IMREAD_COLOR)

# 中值滤波
dst = cv.medianBlur(src, 3)

cv.imshow("src", src)
cv.imshow("dst", dst)

key = cv.waitKey(0)
logging.info("key = [{0}]".format(key))

运行结果
在这里插入图片描述

中值滤波能够很好的消除椒盐噪声


49_图像降噪-加权均值滤波.py

加权均值滤波

同均值滤波,增加了权重

# 当前使用的卷积核
# 定义卷积核、 滤波器、滤波矩阵

kernel = np.array([[1, 2, 1],
                   [2, 4, 2],
                   [1, 2, 1]]) / 16

代码

"""
需求:
1.
"""

import logging

import cv2 as cv
import numpy as np

logging.basicConfig(level=logging.INFO)

# src = cv.imread(r"../img/room_salt.jpg", cv.IMREAD_COLOR)
# src = cv.imread(r"../img/room_pepper.jpg", cv.IMREAD_COLOR)
src = cv.imread(r"../img/room_salt_pepper.jpg", cv.IMREAD_COLOR)

# 定义卷积核、 滤波器、滤波矩阵
kernel = np.array([[1, 2, 1],
                   [2, 4, 2],
                   [1, 2, 1]]) / 16

# 执行运算
dst = cv.filter2D(src, -1, kernel)

cv.imshow("src", src)
cv.imshow("dst", dst)

key = cv.waitKey(0)
logging.info("key = [{0}]".format(key))

运行结果
在这里插入图片描述

效果没有中值滤波好


50_高斯模糊.py

原理
在这里插入图片描述

代码

"""
需求:
1.
"""

import cv2 as cv


def change_value(value):
    #                              标准差
    dst = cv.GaussianBlur(src, (5, 5), value)
    cv.imshow("dst", dst)


src = cv.imread("../img/room.jpg")

cv.imshow("src", src)
# cv.imshow("dst", src)
cv.namedWindow("dst", cv.WINDOW_AUTOSIZE)
cv.createTrackbar("constant", "dst", 0, 100, change_value)
change_value(0)

cv.waitKey()
cv.destroyAllWindows()

运行结果
在这里插入图片描述


51_Sobel算子.py

原理

  • Sobel算子是像素图像边缘检测中最重要的算子之一。
  • 在技术上,它是一个离散的一阶差分算子,用来计算图像亮度函数的一阶梯度之近似值。
  • 在图像的任何一点使用此算子,将会产生该点对应的梯度矢量

在这里插入图片描述

为了提高计算机效率我们通常会使用: G = |Gx|+|Gy|

代码

使用自定义 sobel 算子 + filter2D api 进行图像梯度处理(计算图像的边缘)

# 水平梯度
kernel = np.array([[1, 2, 1],
                   [0, 0, 0],
                   [-1, -2, -1]])

# 垂直梯度
kernel = np.array([[1, 0, -1],
                   [2, 0, -2],
                   [1, 0, -1]])
"""
需求:
1.
"""

import cv2 as cv
import numpy as np

src = cv.imread("../img/brain.jpg")
cv.imshow("src", src)

# 水平梯度
kernel = np.array([[1, 2, 1],
                   [0, 0, 0],
                   [-1, -2, -1]])

dst1 = cv.filter2D(src, -1, kernel)
cv.imshow("dst1", dst1)

# 垂直梯度
kernel = np.array([[1, 0, -1],
                   [2, 0, -2],
                   [1, 0, -1]])

dst2 = cv.filter2D(src, -1, kernel)
cv.imshow("dst2", dst2)

result = dst1 + dst2

cv.imshow("result", result)

cv.waitKey()

运行结果
在这里插入图片描述

dst1 水平梯度图,dst2 竖直梯度图


52_Sobel算子_api.py

水平梯度 – x方向
竖直梯度 – y方向

代码

"""
需求:
1. 使用 Sobel api 进行图像梯度处理(计算图像的边缘)
"""

import cv2 as cv

src = cv.imread("../img/brain.jpg")
cv.imshow("src", src)

#     1.图像 2.输出类型与输入一致,3.计算x方向(水平)梯度,4.计算y方向(竖直)的梯度
dst1 = cv.Sobel(src, -1, 0, 1)
cv.imshow("dst1", dst1)

#     1.图像 2.输出类型与输入一致,3.计算x方向梯度,4.计算y方向的梯度
dst2 = cv.Sobel(src, -1, 1, 0)
cv.imshow("dst2", dst2)

result = dst1 + dst2
cv.imshow("result", result)

cv.waitKey()

运行结果(同上)


53_Scharr函数_Sobel改进版.py

由于使用Sobel算子计算的时候有一些偏差, 所以opencv提供了sobel的升级版Scharr函数,计算比sobel更加精细.

代码

"""
需求:
Sobel计算梯度的时候存在误差
"""
import cv2 as cv

src = cv.imread("../img/brain.jpg")

# x 方向(水平)进行梯度运算
x_h_dst = cv.Scharr(src, -1, 1, 0)

# y 方向(竖直)进行梯度运算
y_v_dst = cv.Scharr(src, -1, 0, 1)

dst = x_h_dst + y_v_dst

cv.imshow("src", src)
cv.imshow("x_dst", x_h_dst)
cv.imshow("y_dst", y_v_dst)

cv.imshow("dst", dst)

cv.waitKey()

运行结果
在这里插入图片描述


54_拉普拉斯算子.py

原理

  • 通过拉普拉斯变换后增强了图像中灰度突变处的对比度,使图像中小的细节部分得到增强,使图像的细节比原始图像更加清晰。
  • 普通算子,增强算子
    在这里插入图片描述

代码

尝试手动实现拉普拉斯算子运算(自定义算子 + filter2D函数)

"""
需求:
1. 拉普拉斯函数 api 对图像进行处理
"""

import cv2 as cv

src = cv.imread("../img/grbq.jpg")
# src = cv.imread("../img/brain.jpg")
cv.imshow("src", src)

# 使用拉普拉斯算子
dst = cv.Laplacian(src, cv.CV_32F)
# dst = cv.Laplacian(src, -1)

# 取绝对值,将数据转到uint8类型
# Scales, calculates absolute values, and converts the result to 8-bit.
dst = cv.convertScaleAbs(dst)

cv.imshow("dst", dst)

cv.waitKey()
cv.destroyAllWindows()

运行结果
在这里插入图片描述
在这里插入图片描述


55_补充-锐化滤波.py

原理

  • 图像的锐化和边缘检测很像,首先找到边缘,然后把边缘加到原来的图像上面,这样就强化了图像的边缘,使图像看起来更加锐利了
  • 实际上是计算当前点和周围点的差别,然后将这个差别加到原来的位置上。另外,中间点的权值要比所有的权值和大于1,意味着这个像素要保持原来的值。
  • 算子、卷积核
    在这里插入图片描述
  • 我们还可以按照公式来创建锐化滤波核:
    在这里插入图片描述

代码

"""
需求:
1.
"""

import cv2 as cv
import numpy as np

src = cv.imread("../img/hehua.jpg")

# 锐化卷积核
kernel = np.array([[-1, -1, -1],
                   [-1, 9, -1],
                   [-1, -1, -1]])

# Convolves an image with the kernel. 使用卷积核对图像进行卷积
# applies an arbitrary linear filter to an image. 利用线性滤波器处理图像
dst = cv.filter2D(src, -1, kernel)

cv.imshow("src", src)
cv.imshow("dst", dst)

cv.waitKey()

运行结果
在这里插入图片描述


&&_参考


&&_问题解决

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值