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

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

卷积

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

图像的读取与处理

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

python 复制代码
image = cv2.imread(args["image"])
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

自定义卷积函数的实现

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

python 复制代码
def convolve(image, kernel):
	# 输入图像和核的尺寸
	(iH, iW) = image.shape[:2]
	(kH, kW) = kernel.shape[:2]

	# 选择pad,卷积后图像大小不变
	pad = (kW - 1) // 2
	# 重复最后一个元素,top, bottom, left, right
	image = 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)**卷积核用于边缘检测。
python 复制代码
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)
)

# 更多卷积核...

结果的展示

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

python 复制代码
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()





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

完整代码

python 复制代码
# 导入工具包
from skimage.exposure import rescale_intensity
import numpy as np
import argparse
import cv2

def convolve(image, kernel):
	# 输入图像和核的尺寸
	(iH, iW) = image.shape[:2]
	(kH, kW) = kernel.shape[:2]

	# 选择pad,卷积后图像大小不变
	pad = (kW - 1) // 2
	# 重复最后一个元素,top, bottom, left, right
	image = 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()
相关推荐
jndingxin7 小时前
OpenCV CUDA模块图像处理------创建一个模板匹配(Template Matching)对象函数createTemplateMatching()
图像处理·人工智能·opencv
吴声子夜歌8 小时前
OpenCV——Mat类及常用数据结构
数据结构·opencv·webpack
新知图书13 小时前
OpenCV为图像添加边框
人工智能·opencv·计算机视觉
空中湖15 小时前
免费批量图片格式转换工具
图像处理·python·程序人生
东皇太星1 天前
SIFT算法详细原理与应用
图像处理·算法·计算机视觉
audyxiao0011 天前
计算机视觉顶刊《International Journal of Computer Vision》2025年5月前沿热点可视化分析
图像处理·人工智能·opencv·目标检测·计算机视觉·大模型·视觉检测
..活宝..1 天前
【Emgu CV教程】11.2、Scharr边缘检测
图像处理·计算机视觉·c#·emgu cv·图像分析
whoarethenext1 天前
使用 C/C++ 和 OpenCV 实现滑动条控制图像旋转
c语言·c++·opencv
SuperW1 天前
Opencv中的copyto函数
人工智能·opencv·计算机视觉
whoarethenext1 天前
使用 OpenCV (C++) 进行人脸边缘提取
c++·人工智能·opencv