当前位置: 首页 > article >正文

OpenCV4.8 开发实战系列专栏之 32 - 图像梯度-更多梯度算子

欢迎大家学习OpenCV4.8 开发实战专栏,长期更新,不断分享源码。
专栏代码全部基于C++ 与Python双语演示。

送相关学习资料, V: OpenCVXueTang_Asst

本文关键知识点:图像梯度-更多梯度算子

图像的一阶导数算子除了sobel算子之外,常见的还有robert算子与prewit算子,它们也都是非常好的可以检测图像的梯度边缘信息,通过0penCV中自定义滤波器,使用自定义创建的robert与prewitt算子就可以实现图像的rober与prewitt梯度边缘检测,OpenCV中的自定义算子滤波函数如下:
在这里插入图片描述
Roberts算子与Prewitt算子都是图像处理中用于边缘检测的重要工具,它们在边缘检测方面各有特点和适用场景。以下是对这两种算子的详细比较:

一、定义与原理

  1. Roberts算子

    • 定义:Roberts算子是一种基于图像梯度的边缘检测算法,由Lawrence Roberts在1963年提出。它是一种一阶微分算子,通过计算图像中每个像素的局部灰度变化来识别图像的边缘。
    • 原理:Roberts算子采用局部差分方法来计算图像中的梯度,从而检测边缘。它使用两个3x3的矩阵,分别用于检测水平和垂直方向的边缘。这两个矩阵分别是水平方向(Gx)[1, 0; 0, -1]和垂直方向(Gy)[0, 1; -1, 0]。通过对图像中的每个像素及其周围的像素进行卷积操作,分别计算水平和垂直方向上的梯度分量,然后根据这两个梯度分量计算梯度幅度,表示图像在该像素的边缘强度。
  2. Prewitt算子

    • 定义:Prewitt算子也是一种一阶微分算子的边缘检测,它利用像素点上下、左右邻点的灰度差,在边缘处达到极值来检测边缘。
    • 原理:Prewitt算子的原理是在图像空间利用两个方向模板与图像进行邻域卷积来完成的。这两个方向模板一个检测水平边缘,一个检测垂直边缘。通过对图像中的像素应用这两个模板,可以计算出水平和垂直方向上的梯度分量,从而确定边缘的位置。

二、特点与适用场景

  1. Roberts算子

    • 特点:对边缘明显且噪声较少的图像效果较好,尤其是边缘±45°较多的图像。但由于它对噪声较为敏感,因此在实际应用中通常需要进行降噪处理。
    • 适用场景:适用于边缘明显、噪声较少的图像场景,如某些特定的工业检测、医学影像分析等。
  2. Prewitt算子

    • 特点:Prewitt算子对噪声具有一定的平滑作用,能够去除部分伪边缘。同时,由于它采用3x3的模板进行计算,因此在一定程度上能够抑制噪声的影响。
    • 适用场景:适用于噪声较多、边缘不太明显的图像场景,如自然场景下的物体识别、图像分割等。

三、性能比较

  • 在边缘检测效果方面,Roberts算子对边缘的定位较为准确,但容易受到噪声的影响;而Prewitt算子则能够在一定程度上抑制噪声,但可能会损失一些边缘细节。
  • 在计算复杂度方面,由于Roberts算子和Prewitt算子都采用卷积操作进行计算,因此它们的计算复杂度相对较低,适用于实时性要求较高的应用场景。

四、总结

Roberts算子和Prewitt算子都是图像处理中常用的边缘检测算子。它们各自具有不同的特点和适用场景。在实际应用中,需要根据具体的图像特点和需求选择合适的算子进行边缘检测。同时,也可以考虑结合其他图像处理技术(如降噪、形态学处理等)来提高边缘检测的效果和准确性。

演示代码

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main(int artc, char** argv) {
	Mat src = imread("D:/images/test.png");
	if (src.empty()) {
		printf("could not load image...\n");
		return -1;
	}
	namedWindow("input", CV_WINDOW_AUTOSIZE);
	imshow("input", src);

	Mat robert_x = (Mat_<int>(2, 2) << 1, 0, 0, -1);
	Mat robert_y = (Mat_<int>(2, 2) << 0, -1, 1, 0);

	Mat prewitt_x = (Mat_<char>(3, 3) << -1, 0, 1,
		-1, 0, 1,
		-1, 0, 1);
	Mat prewitt_y = (Mat_<char>(3, 3) << -1, -1, -1,
		0, 0, 0,
		1, 1, 1);

	Mat robert_grad_x, robert_grad_y, prewitt_grad_x, prewitt_grad_y;
	filter2D(src, robert_grad_x, CV_16S, robert_x);
	filter2D(src, robert_grad_y, CV_16S, robert_y);
	convertScaleAbs(robert_grad_x, robert_grad_x);
	convertScaleAbs(robert_grad_y, robert_grad_y);

	filter2D(src, prewitt_grad_x, CV_32F, prewitt_x);
	filter2D(src, prewitt_grad_y, CV_32F, prewitt_y);
	convertScaleAbs(prewitt_grad_x, prewitt_grad_x);
	convertScaleAbs(prewitt_grad_y, prewitt_grad_y);
	printf("image gradient...");

	imshow("robert x", robert_grad_x);
	imshow("robert y", robert_grad_y);
	imshow("prewitt x", prewitt_grad_x);
	imshow("prewitt y", prewitt_grad_y);

	waitKey(0);
	return 0;
}

python 代码演示

import cv2 as cv
import numpy as np

src = cv.imread("D:/images/test.png")
cv.namedWindow("input", cv.WINDOW_AUTOSIZE)
cv.imshow("input", src)

robert_x = np.array([[1, 0],[0, -1]], dtype=np.float32)
robert_y = np.array([[0, -1],[1, 0]], dtype=np.float32)

prewitt_x = np.array([[-1, 0, 1], [-1, 0, 1], [-1, 0, 1]], dtype=np.float32)
prewitt_y = np.array([[-1, -1, -1], [0, 0, 0], [1, 1, 1]], dtype=np.float32)

robert_grad_x = cv.filter2D(src, cv.CV_16S, robert_x)
robert_grad_y = cv.filter2D(src, cv.CV_16S, robert_y)
robert_grad_x = cv.convertScaleAbs(robert_grad_x)
robert_grad_y = cv.convertScaleAbs(robert_grad_y)

prewitt_grad_x = cv.filter2D(src, cv.CV_32F, prewitt_x)
prewitt_grad_y = cv.filter2D(src, cv.CV_32F, prewitt_y)
prewitt_grad_x = cv.convertScaleAbs(prewitt_grad_x)
prewitt_grad_y = cv.convertScaleAbs(prewitt_grad_y)

# cv.imshow("robert x", robert_grad_x);
# cv.imshow("robert y", robert_grad_y);
# cv.imshow("prewitt x", prewitt_grad_x);
# cv.imshow("prewitt y", prewitt_grad_y);

h, w = src.shape[:2]
robert_result = np.zeros([h, w*2, 3], dtype=src.dtype)
robert_result[0:h,0:w,:] = robert_grad_x
robert_result[0:h,w:2*w,:] = robert_grad_y
cv.imshow("robert_result", robert_result)

prewitt_result = np.zeros([h, w*2, 3], dtype=src.dtype)
prewitt_result[0:h,0:w,:] = prewitt_grad_x
prewitt_result[0:h,w:2*w,:] = prewitt_grad_y
cv.imshow("prewitt_result", prewitt_result)

cv.imwrite("D:/prewitt.png", prewitt_result)
cv.imwrite("D:/robert.png", robert_result)

cv.waitKey(0)
cv.destroyAllWindows()

结束语

学习贵在坚持,学习OpenCV贵在每一天的代码练习,原理跟基本的函数解释,相关知识,后续更新边学边理解,搞技术永远要坚持做长期主义者!我们一起努力!!!

送相关学习资料,V: OpenCVXueTang_Asst


http://www.kler.cn/a/548879.html

相关文章:

  • pytest asyncio 支持插件 pytest-asyncio
  • Linux之【网络I/O】前世今生(二)
  • 基于巨控GRM242Q-4D4I4QHE模块的农村供水自动化监控技术方案
  • 【计算机网络】网络层数据包(Packet)格式
  • 箭头函数(js)
  • 软件运维资料-系统移交运维计划(原件)
  • pandas(11 分类数据和数据可视化)
  • 仿叮咚买菜鸿蒙原生APP
  • AAOS Audio 快问快答,快速理解系统特点
  • 【第10章:自然语言处理高级应用—10.3 NLP在智能客服、舆情分析与情感倾向判断中的应用案例】
  • ECharts 实战指南:组件封装+地图轮廓高亮 + 自定义 Tooltip+轮播+锥形柱子
  • 【MODIS\VIIRS】h5文件信息查看python代码
  • Pytorch深度学习教程_3_初识pytorch
  • 基于AWS云平台的法律AI应用系统开发方案
  • 【iOS】包大小和性能稳定性优化
  • 如何测试和验证CVE-2024-1430:Netgear R7000 路由器信息泄露漏洞分析
  • 详细介绍:封装简易的 Axios 函数获取省份列表
  • 【云安全】云原生-K8S(四)安全问题分析
  • 【前端】自己从头实现一个gpt聊天页面
  • 用命令模式设计一个JSBridge用于JavaScript与Android交互通信