【图像处理知识复习】13 Sobel一阶微分算法 C++,Matlab实现
程序员文章站
2024-03-25 22:07:34
...
两个模板,分别求水平方向,和竖直方向的梯度信息。
效果如下:
1. Matlab实现:
%一种奇数(3x3)模板下的全方向微分算子。
%%
clc;clear;
f = rgb2gray(imread('D:/Code/Image/classic.jpg'));
figure('name','原图'),imshow(f);
f = double(f);
[row,col] = size(f);
%%
maskx = [-1 -2 -1;0 0 0;1 2 1];
masky = [-1 0 1;-2 0 2;-1 0 1];
g = zeros(row,col);
for i=2:row-1
for j=2:col-1 %当前像素为i,j
tempx = sum(sum(maskx.*f(i-1:i+1, j-1:j+1)));
tempy = sum(sum(masky.*f(i-1:i+1, j-1:j+1)));
g(i,j) = round(sqrt(tempx^2+tempy^2));
end
end
%%
figure('name','多向');
g=mat2gray(g);%将matrix值映射到[0,1]
imshow(g);
2. C++实现:
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main()
{
Mat img = imread("D:/Code/Image/classic.jpg", 0);
imshow("原图", img);
Mat mask_vertical = (cv::Mat_<uchar>(3, 3) << -1, -2, -1, 0, 0, 0, 1, 2, 1);
Mat mask_horizontal = (cv::Mat_<uchar>(3, 3) << -1, 0, 1, -2, 0, 2, -1, 0, 1);
Mat new_img = Mat::zeros(img.size(), CV_64F);
for (int i = 2; i < img.rows-2; i++) // 规定当前像素为中间
{
for (int j = 2; j < img.cols-2; j++)
{
Mat block = img(Range(i - 1, i + 2), Range(j - 1, j + 2));
double vertical = block.dot(mask_vertical);
double horizontal = block.dot(mask_horizontal);
new_img.at<double>(i, j) = sqrt(pow(vertical, 2) + pow(vertical, 2));
//cout << new_img.at<double>(i, j) << endl;
}
}
normalize(new_img, new_img, 255, 0, NORM_MINMAX);
new_img.convertTo(new_img, CV_8UC1);
imshow("效果图", new_img);
waitKey(0);
return 0;
}
知识点:
1)取块操作:
Mat block = img(Range(i - 1, i + 2), Range(j - 1, j + 2));
2)定义3x3模板,并赋值:
Mat mask_vertical = (cv::Mat_<uchar>(3, 3) << -1, -2, -1, 0, 0, 0, 1, 2, 1);
3) 类型问题,点乘再求和后,值会非常大,所以定义double类型,显示时先归一化到0-255,再将类型转化为uchar:
Mat new_img = Mat::zeros(img.size(), CV_64F);
normalize(new_img, new_img, 255, 0, NORM_MINMAX);
new_img.convertTo(new_img, CV_8UC1);
imshow("效果图", new_img);