1.卷积应用-图像边缘提取
1.1 边缘
- 边缘是什么 – 是像素值发生跃迁的地方,是图像的显著特征之一,在图像特征提取、对象检测、模式识别等方面都有重要的作用。
如何捕捉/提取边缘 – 对图像求它的一阶导数delta = f(x) – f(x-1), delta越大,说明像素在X方向变化越大,边缘信号越强,我已经忘记啦,不要担心,用Sobel算子就好!卷积操作!
1.2 Sobel算子
Sobel算子是离散微分算子(discrete differentiation operator),用来计算图像灰度的近似梯度,Soble算子功能集合高斯平滑和微分求导又被称为一阶微分算子,求导算子,在水平和垂直两个方向上求导,得到图像X方法与Y方向梯度图像求取导数的近似值,kernel=3时不是很准确,OpenCV使用改进版本Scharr函数,算子如下:
API说明cv::Sobel
cv::Sobel (
InputArray Src // 输入图像
OutputArray dst// 输出图像,大小与输入图像一致
int depth // 输出图像深度.
Int dx. // X方向,几阶导数
int dy // Y方向,几阶导数.
int ksize, SOBEL算子kernel大小,必须是1、3、5、7、
double scale = 1
double delta = 0
int borderType = BORDER_DEFAULT
)
API说明cv::Scharr
cv::Scharr (
InputArray Src // 输入图像
OutputArray dst// 输出图像,大小与输入图像一致
int depth // 输出图像深度.
Int dx. // X方向,几阶导数
int dy // Y方向,几阶导数.
double scale = 1
double delta = 0
int borderType = BORDER_DEFAULT
)
GaussianBlur( src, dst, Size(3,3), 0, 0, BORDER_DEFAULT );
cvtColor( src, gray, COLOR_RGB2GRAY );
addWeighted( A, 0.5,B, 0.5, 0, AB);
convertScaleAbs(A, B)// 计算图像A的像素绝对值,输出到图像B
2.示列:
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int main(int argc, char** argv) {
Mat src, dst;
src = imread("test.jpg");
if (!src.data)
{
printf("could not find the image...");
//cerr << "not find teh data.." << endl;
//cout << "not find teh data.." << endl;
return -1;
}
char INPUT_TITLE[] = "input image";
char OUTPUT_TITLE[] = "sobel demo";
namedWindow(INPUT_TITLE, CV_WINDOW_AUTOSIZE);
//namedWindow(OUTPUT_TITLE, CV_WINDOW_AUTOSIZE);
imshow(INPUT_TITLE, src);
Mat src_gray;
GaussianBlur(src, dst, Size(3, 3), 0, 0);
cvtColor(dst, src_gray, CV_BGR2GRAY);
imshow("gray image", src_gray);
Mat Xgrad, Ygrad;
Scharr(src_gray, Xgrad, CV_16S, 1, 0, 3);
Scharr(src_gray, Ygrad, CV_16S, 0, 1, 3);
//Sobel(src_gray, Xgrad, CV_16S, 1, 0, 3);
//Sobel(src_gray, Ygrad, CV_16S, 0, 1, 3);
convertScaleAbs(Xgrad, Xgrad);
convertScaleAbs(Ygrad, Ygrad);
imshow("xgrad image", Xgrad);
imshow("ygrad image",Ygrad);
Mat XYgrad = Mat(Xgrad.size(),Xgrad.type());
printf("type: X=%d ,Y=%d", Xgrad.type(),Ygrad.type());//0 cv8u
int height = Xgrad.rows;
int width = Ygrad.cols;
for (int row = 0; row < height; row++){
for (int col = 0; col < width; col++) {
int x_g = Xgrad.at<uchar>(row, col);//char判断像素灰度值的类型
int y_g = Ygrad.at<uchar>(row, col);
int xy_g = x_g + y_g;
XYgrad.at<uchar>(row, col) = saturate_cast<uchar>(xy_g);
}
}
//addWeighted(Xgrad, 0.5, Ygrad, 0.5,0,XYgrad);
imshow("XYgrad image", XYgrad);
waitKey(0);
return 0;
}