做空比特币的网站,广州网站建设正规公司,风云办公ppt模板网站,怎么做私人网站1、前言
边缘检测#xff1a; 图像边缘检测是指在图像中寻找灰度、颜色、纹理等变化比较剧烈的区域#xff0c;它们可能代表着物体之间的边界或物体内部的特征。边缘检测是图像处理中的一项基本操作#xff0c;可以用于人脸识别、物体识别、图像分割等多个领域。
边缘检测…1、前言
边缘检测 图像边缘检测是指在图像中寻找灰度、颜色、纹理等变化比较剧烈的区域它们可能代表着物体之间的边界或物体内部的特征。边缘检测是图像处理中的一项基本操作可以用于人脸识别、物体识别、图像分割等多个领域。
边缘检测实质上是计算当前点和周围点灰度的差别。
图像边缘检测流程主要分为以下几个步骤 1读取待处理图像 1图像滤波例如使用高斯滤波器平滑图像去除噪声 2计算图像中每个像素点的梯度强度和方向 3应用非极大值抑制Non-Maximum Suooression保留梯度方向上的局部最大值抑制非边缘点消除边缘检测带来的杂散响应 4应用双阈值Double-Threshold检测来确定真实的和潜在的边缘即将梯度幅值映射到两个阈值根据梯度值高于高阈值或在高低阈值之间的情况将像素标记为强边缘、弱边缘或非边缘。 5边缘连接通过连接相邻的强边缘像素和与之相连的弱边缘像素形成最终的边缘图像 6显示结果。
在介绍各种边缘检测算子之前先简单阐述下怎么寻找边缘。
下面左图是一张黑白相间的图右图是左图的每个像素的灰度值 我们设定一个卷积核如下关于卷积的介绍请看之前的文章 原图在通过卷积核进行卷积计算后得到的图像如下 可以看到原图在卷积运算后黑色向白色突变的边缘被很好的保留了下来因此可以通过这个卷积核找到图像中垂直的边缘。 同理如果我们用下面的卷积核也可以找到图像中水平的边缘。 卷积运算后
2、Prewitt算子边缘检测 如果我们把上面两个卷积核组合起来再对图像进行卷积便可以同时找到图像中水平和垂直的边缘这种卷积核就是prewitt算子。
标准的 Prewitt 边缘检测算子由以下两个卷积核组成。 下面是用prewitt算子进行边缘检测的案例
#include opencv2/opencv.hpp
#include opencv2/highgui/highgui.hpp
#include opencv2/imgproc/imgproc.hppusing namespace cv;int main() {// 读取图像Mat image imread(your_image.jpg, IMREAD_GRAYSCALE);// 定义Prewitt算子Mat prewitt_x (Mat_float(3, 3) -1, 0, 1, -1, 0, 1, -1, 0, 1);Mat prewitt_y (Mat_float(3, 3) -1, -1, -1, 0, 0, 0, 1, 1, 1);// 对图像应用Prewitt算子Mat edges_x, edges_y;filter2D(image, edges_x, CV_64F, prewitt_x);filter2D(image, edges_y, CV_64F, prewitt_y);// 计算梯度幅值和方向Mat gradient_magnitude, gradient_direction;magnitude(edges_x, edges_y, gradient_magnitude);phase(edges_x, edges_y, gradient_direction, true);// 归一化梯度幅值cv::normalize(gradient_magnitude, gradient_magnitude, 0, 1, cv::NORM_MINMAX);// 显示结果imshow(Original Image, image); //原灰度图imshow(Gradient Magnitude, gradient_magnitude); //prewitt算子边缘检测图waitKey(0);destroyAllWindows();return 0;
}
代码解读 1在代码中我们先分别定义一个水平方向和垂直方向的prewitt算子edges_x和edges_y 2filter2D是对图像进行卷积操作即获取prewitt算子与原图像卷积后的图像edges_x和edges_y 3magnitude 函数的主要用途是计算两个输入数组的逐元素平方和的平方根。在图像处理中常常用于计算图像中每个像素点的梯度幅值。相位Phase在图像处理中通常指的是梯度的方向边缘方向。在梯度计算中梯度向量的方向表示图像在该点上灰度变化最快的方向。在梯度计算中通常使用 magnitude 函数计算梯度的幅值使用 phase 函数计算梯度的方向。这两个信息一起构成了梯度向量提供了有关图像局部变化的重要信息。 4最后归一化梯度幅值图像因为64位图像显示范围为0-1。
最后效果如下左边是原灰度图右边是边缘检测出的图像
3、Roberts算子 常用来处理具有陡峭的低噪声图像当图像边缘接近于正45度或负45度时该算法处理效果更理想。其缺点是对边缘的定位不太准确提取的边缘线条较粗。
下图左边为水平方向Roberts算子也称正对角算子。右边为垂直方向Roberts算子也称斜对角算子。 下面是Roberts算子的使用案例
#include opencv2/opencv.hpp
#include opencv2/highgui/highgui.hpp
#include opencv2/imgproc/imgproc.hppint main() {// 生成一个简单的图像cv::Mat image cv::Mat::zeros(100, 100, CV_8U);cv::rectangle(image, cv::Rect(20, 20, 60, 60), cv::Scalar(255), cv::FILLED);// 定义Sobel算子cv::Mat sobel_x (cv::Mat_float(3, 3) -1, 0, 1, -2, 0, 2, -1, 0, 1);cv::Mat sobel_y (cv::Mat_float(3, 3) -1, -2, -1, 0, 0, 0, 1, 2, 1);// 应用Sobel算子cv::Mat edges_x, edges_y;cv::filter2D(image, edges_x, CV_64F, sobel_x);cv::filter2D(image, edges_y, CV_64F, sobel_y);// 计算梯度幅值和方向cv::Mat gradient_magnitude, gradient_direction;cv::magnitude(edges_x, edges_y, gradient_magnitude);cv::phase(edges_x, edges_y, gradient_direction, true); // true 表示计算角度的弧度值// 归一化梯度方向到[0, 1]范围cv::normalize(gradient_direction, gradient_direction, 0, 1, cv::NORM_MINMAX);// 显示结果cv::imshow(Original Image, image);cv::imshow(Gradient Magnitude, gradient_magnitude);cv::imshow(Gradient Direction, gradient_direction);cv::waitKey(0);cv::destroyAllWindows();return 0;
}
最后效果如下左边是原灰度图右边是边缘检测出的图像
4、Sobel算子边缘检测 Sobel算子在Prewitt算子的基础上增加了权重的概念认为相邻点的距离远近对当前像素点的影响是不同的距离越近的像素点对应当前像素的影响越大从而实现图像锐化并突出边缘轮廓。但Sobel算子并不是基于图像灰度进行处理的因为Sobel算子并没有严格地模拟人的视觉生理特性因此图像轮廓的提取有时并不能让人满意。当对精度要求不是很高时Sobel算子是一种较为常用的边缘检测方法。
它的水平和垂直方向的卷积核如下 接口说明
void cv::Sobel(InputArray src,OutputArray dst,int ddepth,int dx,int dy,int ksize 3,double scale 1,double delta 0,int borderType cv::BORDER_DEFAULT
);src: 输入图像。可以是单通道灰度图或多通道图像。 dst: 输出图像梯度的计算结果将存储在这里。 ddepth: 输出图像的深度通常使用 CV_64F 或 CV_32F 表示。 dx: x方向上的导数阶数设为1表示在水平方向上进行操作。 dy: y方向上的导数阶数设为1表示在垂直方向上进行操作。 ksize: Sobel核的大小。默认为 3表示一个 3x3 的核。通常使用奇数值。 scale: 可选的比例因子用于调整梯度的幅值也表示对比度。 delta: 可选的偏移值用于调整输出图像的亮度。 borderType: 边界处理类型可以使用 cv::BORDER_DEFAULT 或其他合适的边界处理标志。
Sobel算子边缘检测案例
#include opencv2/opencv.hpp
#include opencv2/highgui/highgui.hpp
#include opencv2/imgproc/imgproc.hppint main() {// 读取图像cv::Mat image cv::imread(your_image.jpg, cv::IMREAD_GRAYSCALE);if (image.empty()) {std::cerr Error: Could not read the image. std::endl;return -1;}// 应用Sobel算子cv::Mat edges_x, edges_y;cv::Sobel(image, edges_x, CV_64F, 1, 0, 3); // 1表示在水平方向上进行操作cv::Sobel(image, edges_y, CV_64F, 0, 1, 3); // 1表示在垂直方向上进行操作// 计算梯度幅值cv::Mat gradient_magnitude;cv::magnitude(edges_x, edges_y, gradient_magnitude);// 归一化梯度方向到[0, 1]范围cv::normalize(gradient_magnitude, gradient_magnitude, 0, 1, cv::NORM_MINMAX);// 显示结果cv::imshow(Original Image, image);cv::imshow(Sobel Edges X, edges_x);cv::imshow(Sobel Edges Y, edges_y);cv::imshow(Gradient Magnitude, gradient_magnitude);cv::waitKey(0);cv::destroyAllWindows();return 0;
}