OpenCV从入门到精通实战(七)——探索图像处理:自定义滤波与OpenCV卷积核

devtools/2024/11/27 16:11:29/

本文主要介绍如何使用Python和OpenCV库通过卷积操作来应用不同的图像滤波效果。主要分为几个步骤:图像的读取与处理、自定义卷积函数的实现、不同卷积核的应用,以及结果的展示。

卷积

图像处理中,卷积是一种重要的操作,它通过将图像与一个小的矩阵(称为卷积核或滤波器)进行运算来影响图像的各种属性。这种操作可以用于实现模糊、锐化、边缘检测等效果。今天,我们将探讨如何在Python中使用OpenCV库来自定义卷积核,并将其应用于图像处理任务中。

图像的读取与处理

首先,我们需要读取一张图像,并将其转换成灰度图,因为在这个例子中我们将使用灰度图像来简化处理过程:

image = cv2.imread(args["image"])
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

自定义卷积函数的实现

接下来,我们实现一个名为convolve的函数,该函数接收一个图像和一个卷积核作为输入,并返回卷积后的结果。在这个过程中,我们通过为图像添加边界,然后对每个像素应用卷积核来完成卷积操作:

def convolve(image, kernel):# 输入图像和核的尺寸(iH, iW) = image.shape[:2](kH, kW) = kernel.shape[:2]# 选择pad,卷积后图像大小不变pad = (kW - 1) // 2# 重复最后一个元素,top, bottom, left, rightimage = cv2.copyMakeBorder(image, pad, pad, pad, pad,cv2.BORDER_REPLICATE)output = np.zeros((iH, iW), dtype="float32")# 卷积操作for y in np.arange(pad, iH + pad):for x in np.arange(pad, iW + pad):# 提取每一个卷积区域roi = image[y - pad:y + pad + 1, x - pad:x + pad + 1]# 内积运算k = (roi * kernel).sum()# 保存相应的结果output[y - pad, x - pad] = k# 将得到的结果放缩到[0, 255]output = rescale_intensity(output, in_range=(0, 255))output = (output * 255).astype("uint8")return output

不同卷积核的应用

为了展示不同的图像处理效果,我们定义了几种不同的卷积核:

  • **小模糊(Small Blur)大模糊(Large Blur)**用于创建模糊效果。
  • **锐化(Sharpen)**卷积核可以使图像看起来更清晰。
  • **拉普拉斯(Laplacian)索贝尔(Sobel)**卷积核用于边缘检测。
smallBlur = np.ones((7, 7), dtype="float") * (1.0 / (7 * 7))
largeBlur = np.ones((21, 21), dtype="float") * (1.0 / (21 * 21))
# 尝试不同的卷积核
sharpen = np.array(([0, -1, 0],[-1, 5, -1],[0, -1, 0]), dtype="int")laplacian = np.array(([0, 1, 0],[1, -4, 1],[0, 1, 0]), dtype="int")sobelX = np.array(([-1, 0, 1],[-2, 0, 2],[-1, 0, 1]), dtype="int")sobelY = np.array(([-1, -2, -1],[0, 0, 0],[1, 2, 1]), dtype="int")# 尝试不同结果
kernelBank = (("small_blur", smallBlur),("large_blur", largeBlur),("sharpen", sharpen),("laplacian", laplacian),("sobel_x", sobelX),("sobel_y", sobelY)
)# 更多卷积核...

结果的展示

最后,我们遍历每一个卷积核,将其应用于原始图像,并显示结果:

for (kernelName, kernel) in kernelBank:convoleOutput = convolve(gray, kernel)opencvOutput = cv2.filter2D(gray, -1, kernel)# 展示结果# 分别展示结果cv2.imshow("original", gray)cv2.imshow("{} - convole".format(kernelName), convoleOutput)cv2.imshow("{} - opencv".format(kernelName), opencvOutput)cv2.waitKey(0)cv2.destroyAllWindows()

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

可以看到卷积核在图像处理中的强大作用,以及如何通过调整卷积核来实现不同的视觉效果。

完整代码

# 导入工具包
from skimage.exposure import rescale_intensity
import numpy as np
import argparse
import cv2def convolve(image, kernel):# 输入图像和核的尺寸(iH, iW) = image.shape[:2](kH, kW) = kernel.shape[:2]# 选择pad,卷积后图像大小不变pad = (kW - 1) // 2# 重复最后一个元素,top, bottom, left, rightimage = cv2.copyMakeBorder(image, pad, pad, pad, pad,cv2.BORDER_REPLICATE)output = np.zeros((iH, iW), dtype="float32")# 卷积操作for y in np.arange(pad, iH + pad):for x in np.arange(pad, iW + pad):# 提取每一个卷积区域roi = image[y - pad:y + pad + 1, x - pad:x + pad + 1]# 内积运算k = (roi * kernel).sum()# 保存相应的结果output[y - pad, x - pad] = k# 将得到的结果放缩到[0, 255]output = rescale_intensity(output, in_range=(0, 255))output = (output * 255).astype("uint8")return output# 指定输入图像
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", default="lanpangzi.jpg",help="path to the input image")
args = vars(ap.parse_args())# 分别构建两个卷积核
smallBlur = np.ones((7, 7), dtype="float") * (1.0 / (7 * 7))
largeBlur = np.ones((21, 21), dtype="float") * (1.0 / (21 * 21))# 尝试不同的卷积核
sharpen = np.array(([0, -1, 0],[-1, 5, -1],[0, -1, 0]), dtype="int")laplacian = np.array(([0, 1, 0],[1, -4, 1],[0, 1, 0]), dtype="int")sobelX = np.array(([-1, 0, 1],[-2, 0, 2],[-1, 0, 1]), dtype="int")sobelY = np.array(([-1, -2, -1],[0, 0, 0],[1, 2, 1]), dtype="int")# 尝试不同结果
kernelBank = (("small_blur", smallBlur),("large_blur", largeBlur),("sharpen", sharpen),("laplacian", laplacian),("sobel_x", sobelX),("sobel_y", sobelY)
)# 简单起见,用灰度图来玩
image = cv2.imread(args["image"])
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# 遍历每一个核
for (kernelName, kernel) in kernelBank:print("[INFO] applying {} kernel".format(kernelName))convoleOutput = convolve(gray, kernel)# -1 表示深度一致opencvOutput = cv2.filter2D(gray, -1, kernel)# 分别展示结果cv2.imshow("original", gray)cv2.imshow("{} - convole".format(kernelName), convoleOutput)cv2.imshow("{} - opencv".format(kernelName), opencvOutput)cv2.waitKey(0)cv2.destroyAllWindows()

http://www.ppmy.cn/devtools/137434.html

相关文章

计算机毕业设计Hadoop+Spark音乐推荐系统 音乐预测系统 音乐可视化大屏 音乐爬虫 HDFS hive数据仓库 机器学习 深度学习 大数据毕业设计

温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 作者简介:Java领…

C#中面试的常见问题007

1.在EF中实现一个实体对应多个表 1. 表拆分(Table Splitting) 表拆分是指将一个实体映射到两个或多个表中的行。这通常发生在实体的属性分布在不同的表中,但这些表通过外键关联到同一个主表。在EF Core中,可以通过Fluent API来配…

44.扫雷第二部分、放置随机的雷,扫雷,炸死或成功 C语言

按照教程打完了。好几个bug都是自己打出来的。比如统计周围8个格子时,有一个各自加号填成了减号。我还以为平移了,一会显示是0一会显示是2。结果单纯的打错了。debug的时候断点放在scanf后面会顺畅一些。中间多放一些变量名方便监视。以及mine要多显示&a…

初阶数据结构之队列的实现

1 队列的定义 什么是队列呢?队列只允许在一端进行插入数据操作,在另一端进行删除数据操作。队列具有先进先出FIFO(First In First Out)的特性。 队头:删除数据的一端称为队头。 队尾:插入数据的一端称为队尾。 2 队列底层结构…

upload-labs 靶场(1~5)

免责声明 本博客文章仅供教育和研究目的使用。本文中提到的所有信息和技术均基于公开来源和合法获取的知识。本文不鼓励或支持任何非法活动,包括但不限于未经授权访问计算机系统、网络或数据。 作者对于读者使用本文中的信息所导致的任何直接或间接后果不承担任何…

【已解决】python面试、竞赛编程问题:最长递增子序列和旅行商问题(TSP)

在面试、竞赛以及实际应用中,有几个常见的问题,比如今天尝试解决的:最长递增子序列和旅行商问题(TSP)。本文针对这两个问题如何分析和求解并使用python编程实现给出了详细的步骤,供参考学习。 一、最长递增子序列问题 问题背景 一个经典的算法问题:“最长递增子序列(…

vue实现滚动条滑动到底部分页调取后端接口加载数据

一、案例效果 二、前提条件 接口返回数据 三、案例代码 子组件 const $emit defineEmits([cloneItem, updateList]);const props defineProps({rightList: {type: Array,},chartTableData: {type: Array as () > ChartListType[],},deleteChartInfo: {type: Object,}…

LeetCode 3206.交替组 I:遍历

【LetMeFly】3206.交替组 I:遍历 力扣题目链接:https://leetcode.cn/problems/alternating-groups-i/ 给你一个整数数组 colors ,它表示一个由红色和蓝色瓷砖组成的环,第 i 块瓷砖的颜色为 colors[i] : colors[i] …