Sobel一阶导数
Sobel操作符是一个离散的微分算子。它计算了图像强度函数的梯度,结合了高斯平滑和微分。
函数Sobel() 检测水平变化、检测垂直变化
函数Scharr() 比传统Sobel函数运算快而且更为准确。
代码示例
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
CommandLineParser parser(argc, argv, // 命令行解析类,减少命令行使用过程中的工作量
"{@input | ../data/lena.jpg|input image}"
"{ksize k | 1 |hit 'K' to increase value}"
"{scale s | 1 |hit 'S' to increase value}"
"{delta d | 0 |hit 'D' to increase value}"
"{help h | false |show help message}");
cout << "The sample uses Sobel or Scharr OpenCV functions for edge detection\n\n";
parser.printMessage();
cout << "\nPress 'ESC' to exit program.\n"
"Press 'R' to reset values ( ksize will be -1 equal to Scharr function )";
Mat image, src, src_gray, grad;
String window_name = "Sobel Demo";
int ksize = parser.get<int>("ksize");
int scale = parser.get<int>("scale");
int delta = parser.get<int>("delta");
int ddepth = CV_16S;
String imageName = parser.get<String>("@input"); // 获取图像路径和图像名
image = imread(imageName, IMREAD_COLOR);
if (image.empty()) { return -1; }
while (1)
{
GaussianBlur(image, src, Size(3, 3), 0, 0, BORDER_DEFAULT); // 高斯模糊
cvtColor(src, src_gray, COLOR_BGR2GRAY); // 转换灰度图像
Mat grad_x, grad_y, abs_grad_x, abs_grad_y;
Sobel(src_gray, grad_x, ddepth, 1, 0, ksize, scale, delta, BORDER_DEFAULT);
Sobel(src_gray, grad_y, ddepth, 0, 1, ksize, scale, delta, BORDER_DEFAULT);
convertScaleAbs(grad_x, abs_grad_x); // 缩放,计算绝对值,并将结果转换为8位
convertScaleAbs(grad_y, abs_grad_y);
addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad);
imshow(window_name, grad);
char key = (char)waitKey(0);
if (key == 27)
{
return 0;
}
if (key == 'k' || key == 'K')
{
ksize = ksize < 30 ? ksize + 2 : -1;
}
if (key == 's' || key == 'S')
{
scale++;
}
if (key == 'd' || key == 'D')
{
delta++;
}
if (key == 'r' || key == 'R')
{
scale = 1;
ksize = -1;
delta = 0;
}
}
return 0;
}
运行结果
拉普拉斯二阶导数
代码示例
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
using namespace cv;
int main(int argc, char** argv)
{
Mat src, src_gray, dst;
int kernel_size = 3;
int scale = 1;
int delta = 0;
int ddepth = CV_16S;
char* window_name = "Laplace Demo";
char* imageName = "../data/lena.jpg";
src = imread(imageName, IMREAD_COLOR);
if (src.empty()) { return -1; }
GaussianBlur(src, src, Size(3, 3), 0, 0, BORDER_DEFAULT); // 高斯模糊
cvtColor(src, src_gray, COLOR_BGR2GRAY); // 转换灰度图像
Mat abs_dst; // 拉普拉斯二阶导数
Laplacian(src_gray, dst, ddepth, kernel_size, scale, delta, BORDER_DEFAULT);
convertScaleAbs(dst, abs_dst); // 绝对值8位
imshow(window_name, abs_dst);
waitKey(0);
return 0;
}
运行结果
Canny
优点:
Low error rate: Meaning a good detection of only existent edges.
Good localization: The distance between edge pixels detected and real edge pixels have to be minimized.
Minimal response: Only one detector response per edge.
代码示例
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
using namespace cv;
Mat src, src_gray, dst, detected_edges;
int lowThreshold = 1;
int max_lowThreshold = 100;
int ratio = 3;
int kernel_size = 3;
char* window_name = "Canny Demo";
void CannyThreshold(int, void*)
{
blur(src_gray, detected_edges, Size(3, 3)); // 平均滤波平滑
Canny(detected_edges, detected_edges, lowThreshold, lowThreshold*ratio, kernel_size);
dst = Scalar::all(0);
src.copyTo(dst, detected_edges);
imshow(window_name, dst);
}
int main(int, char** argv)
{
char* filename = "../data/lena.jpg";
src = imread(filename, IMREAD_COLOR);
if (src.empty()) { return -1;}
dst.create(src.size(), src.type());
cvtColor(src, src_gray, COLOR_BGR2GRAY);
namedWindow(window_name, WINDOW_AUTOSIZE);
createTrackbar("Min Threshold", window_name, &lowThreshold, max_lowThreshold, CannyThreshold);
CannyThreshold(0, 0);
waitKey(0);
return 0;
}
运行结果