//边缘是像素发生阶跃的地方,使图像的显著特征之一,对图像求一阶导数,提取边缘。
//对图像求导,如下图。左边是原图像素图像,右边是像素变化率的图像。
//Sobel 算子:计算图像灰度的近似梯度。
//Sobel 算子集合了高斯平滑和微分求导,在x,y
方向上求导,得到X,Y方向上的梯度。
//下图是Sobel算子的卷积核,引入权重增大像素差异,提取边缘,左边是X梯度,右边是Y梯度。
//最后将X,Y方向的梯度融合,绝对值和的形式可以减小运算量。优化算法
//以下代码是,像素梯度平方和开根号的结果
for (int row = 0; row < height; row++)
{
for (int column = 0; column <width ; column++)
{
int xg=Xgrad.at<char>(row, column);
int yg = Ygrad.at<char>(row, column);
int xyg = sqrt(xg*xg + yg*yg);
imgmix.at<char>(row, column) = saturate_cast<char>(xyg);
}
}
//Sobel API
Sobel(输入图像(灰度图),输出图像,输出图像深度,X方向导数,Y方向导数, ksize(卷积核大小),scale=1(图像缩放),delta=0(像素增亮),borderType=BORDER_DEFAULT);
//此处对图像深度做特殊说明,输出图像深度应该大于输入图像深度。(-1是默认值,这里通常不取)
//但输出图像的类型仍然是八位.
//代码步骤:
1.因为Sobel对噪声格外敏感,先对图像高斯模糊。
2.装灰度
3.求梯度X,Y
4.混合X,Y梯度
//convertScaleAbs(对像素梯度取绝对值,梯度有可能是负的)
//以下是操作的两种方式,一种是基于API,一种是基于像素搜索。
Mat src = imread("C:\\Users\\Administrator\\Pictures\\Saved Pictures\\timg6ZAGKYHR.jpg");
if (src.empty())
{
printf("ould not find image \n");
return -1;
}
namedWindow("opencv set up demo", WINDOW_AUTOSIZE);
imshow("opencv set up demo", src);
Mat dst, gray_sc;
GaussianBlur(src, dst, Size(3, 3), 0, 0);
cvtColor(dst, gray_sc, COLOR_BGR2GRAY);
Sobel(gray_sc, Xgrad, CV_32F, 1, 0, 3);
Sobel(gray_sc, Ygrad, CV_32F, 1, 0, 3);
convertScaleAbs(Xgrad, Xgrad);
convertScaleAbs(Ygrad, Ygrad);
printf("%d", Ygrad.type());
imshow("xgrad", Xgrad);
imshow("ygrad", Ygrad);
Mat imgmix;
addWeighted(Xgrad, 1, Ygrad, 1,0, imgmix);
//基于像素搜索
Mat src = imread("C:\\Users\\Administrator\\Pictures\\Saved Pictures\\timg6ZAGKYHR.jpg");
if (src.empty())
{
printf("ould not find image \n");
return -1;
}
namedWindow("opencv set up demo", WINDOW_AUTOSIZE);
imshow("opencv set up demo", src);
Mat dst, gray_sc;
GaussianBlur(src, dst, Size(3, 3), 0, 0);
cvtColor(dst, gray_sc, COLOR_BGR2GRAY);
Sobel(gray_sc, Xgrad, CV_32F, 1, 0, 3);
Sobel(gray_sc, Ygrad, CV_32F, 1, 0, 3);
convertScaleAbs(Xgrad, Xgrad);
convertScaleAbs(Ygrad, Ygrad);
printf("%d", Ygrad.type());
imshow("xgrad", Xgrad);
imshow("ygrad", Ygrad);
Mat imgmix;
//addWeighted(Xgrad, 1, Ygrad, 1,0, imgmix);
Mat imgmix=Mat(Xgrad.size(),Xgrad.type());
int height = Xgrad.rows;
int width = Ygrad.cols;
for (int row = 0; row < height; row++)
{
for (int column = 0; column <width ; column++)
{
int xg=Xgrad.at<char>(row, column);
int yg = Ygrad.at<char>(row, column);
int xyg = xg + yg;
imgmix.at<char>(row, column) = saturate_cast<char>(xyg);
}
}
imshow("sobel", imgmix);
//opencv 自己有Scharr(输入灰度图,输出,输出图向深度,x方向梯度,y方向梯度,缩放scale,delta(像素增值))
Scharr(gray_sc, Ygrad, CV_32F, 1, 0, 1, 0);
Soble易受噪声影响,Scharr不易受影响
Mat src = imread("C:\\Users\\Administrator\\Pictures\\Saved Pictures\\timg6ZAGKYHR.jpg");
if (src.empty())
{
printf("ould not find image \n");
return -1;
}
namedWindow("opencv set up demo", WINDOW_AUTOSIZE);
imshow("opencv set up demo", src);
Mat dst, gray_sc;
GaussianBlur(src, dst, Size(3, 3), 0, 0);
cvtColor(dst, gray_sc, COLOR_BGR2GRAY);
Mat Xgrad, Ygrad;
Scharr(gray_sc, Xgrad, CV_32F, 1, 0, 1, 0);
Scharr(gray_sc, Ygrad, CV_32F, 1, 0, 1, 0);
//Sobel(gray_sc, Xgrad, CV_32F, 1, 0, 3);
//Sobel(gray_sc, Ygrad, CV_32F, 1, 0, 3);
convertScaleAbs(Xgrad, Xgrad);
convertScaleAbs(Ygrad, Ygrad);
printf("%d", Ygrad.type());
imshow("xgrad", Xgrad);
imshow("ygrad", Ygrad);
Mat imgmix;
//addWeighted(Xgrad, 1, Ygrad, 1,0, imgmix);
Mat imgmix=Mat(Xgrad.size(),Xgrad.type());
int height = Xgrad.rows;
int width = Ygrad.cols;
for (int row = 0; row < height; row++)
{
for (int column = 0; column <width ; column++)
{
int xg=Xgrad.at<char>(row, column);
int yg = Ygrad.at<char>(row, column);
int xyg = xg + yg;
imgmix.at<char>(row, column) = saturate_cast<char>(xyg);
}
}
imshow("sobel", imgmix);
waitKey(0);
//saturate_cast(xyg);将像素值限制在0-255之间。