Q14:差分滤波
差分滤波使用两像素之间的差值进行中心点赋值,分为三种情况如下,每种情况都是相邻的像素进行差值计算并赋值。符号代表相减,得到差值。
- 水平方向
- 垂直方向
- 对角线方向
为了区分这三种情况,在程序中枚举了三种情况
enum{
horizontal_dir = -1,
vertical_dir = 0,
diagonal_dir = 1
};
不同的情况在函数中调用不同的参数来实现,完整代码如下
#include"opencv2/core/core.hpp"
#include"opencv2/highgui/highgui.hpp"
#include<opencv2/opencv.hpp>
#include "math.h"
#include"iostream"
using namespace std;
using namespace cv;
#define Kernel_size 3
//枚举类型定义三个差分方向
enum{
horizontal_dir = -1,
vertical_dir = 0,
diagonal_dir = 1
};
Mat diff_filter3(Mat img,int dir){
//构建3*3滤波系数矩阵
double K[Kernel_size][Kernel_size];
for(int x=0;x<Kernel_size;x++){
for(int y=0;y<Kernel_size;y++)
K[x][y]=0;
}
//水平方向差分滤波
if(dir==-1){
K[1][1] = 1;
K[1][0] = -1;
}
//垂直方向差分滤波
if(dir==0){
K[1][1] = 1;
K[0][1] = -1;
}
//对角线方向差分滤波
if(dir==1){
K[1][1] = 1;
K[0][0] = -1;
}
int imgrow = img.rows;
int imgcol = img.cols;
Mat out = Mat::zeros(imgrow,imgcol,CV_8UC1);
int dot = floor((float)(Kernel_size/2));
int v;
for(int i=floor((float)(Kernel_size/2));i<imgrow-floor((float)(Kernel_size/2));i++){
for(int j=floor((float)(Kernel_size/2));j<imgcol-floor((float)(Kernel_size/2));j++){
v = 0;
for(int i_=-dot;i_<dot+1;i_++){
for(int j_=-dot;j_<dot+1;j_++){
v += img.at<uchar>(i+i_,j+j_)*K[i_+dot][j_+dot];
}
}
if(v>=0)
out.at<uchar>(i,j) = v;
else
out.at<uchar>(i,j) = -v;
}
}
return out;
}
void main(){
Mat img = imread("ck567.jpg",IMREAD_GRAYSCALE);
Mat out1 = diff_filter3(img,horizontal_dir);
Mat out2 = diff_filter3(img,vertical_dir);
Mat out3 = diff_filter3(img,diagonal_dir);
imshow("diff-filter3-1",out1);
imshow("diff-filter3-2",out3);
imshow("diff-filter3-3",out1);
imshow("original-pic",img);
waitKey(0);
destroyAllWindows();
}
不同情况的滤波结果如下
Q15:Sobel滤波器
Sobel算子应用于图像边缘检测,边缘是指灰度突变的地方,往往是一个区域与另一个区域的临界,利用这个边缘可以进行分割并进行特征提取。
Sobel算子检测也是分成了水平方向和垂直方向,对应的算子分别是两个三乘三的矩阵,如下所示。
- 横向Sobel算子
- 纵向Sobel算子
代码如下
#include"opencv2/core/core.hpp"
#include"opencv2/highgui/highgui.hpp"
#include<opencv2/opencv.hpp>
#include "math.h"
#include"iostream"
using namespace std;
using namespace cv;
#define Kernel_size 3
//枚举类型定义三个差分方向
enum{
horizontal_dir = -1,
vertical_dir = 0
};
Mat sobel3(Mat img,int dir){
//构建3*3滤波系数矩阵
double K[Kernel_size][Kernel_size];
for(int x=0;x<Kernel_size;x++){
for(int y=0;y<Kernel_size;y++)
K[x][y]=0;
}
//水平方向sobel算子
if(dir==-1){
K[0][0] = -1;
K[0][2] = 1;
K[1][0] = -2;
K[1][2] = 2;
K[2][0] = -1;
K[2][2] = 1;
}
//垂直方向sobel算子
if(dir==0){
K[0][0] = 1;
K[0][1] = 2;
K[0][2] = 1;
K[2][0] = -1;
K[2][1] = -2;
K[2][2] = -1;
}
int imgrow = img.rows;
int imgcol = img.cols;
Mat out = Mat::zeros(imgrow,imgcol,CV_8UC1);
int dot = floor((float)(Kernel_size/2));
int v;
for(int i=floor((float)(Kernel_size/2));i<imgrow-floor((float)(Kernel_size/2));i++){
for(int j=floor((float)(Kernel_size/2));j<imgcol-floor((float)(Kernel_size/2));j++){
v = 0;
for(int i_=-dot;i_<dot+1;i_++){
for(int j_=-dot;j_<dot+1;j_++){
v += img.at<uchar>(i+i_,j+j_)*K[i_+dot][j_+dot];
}
}
out.at<uchar>(i,j) = v;
}
}
return out;
}
void main(){
Mat img = imread("ck567.jpg",IMREAD_GRAYSCALE);
Mat out1 = sobel3(img,horizontal_dir);
Mat out2 = sobel3(img,vertical_dir);
imshow("sobel3-1",out1);
imshow("sobel3-2",out2);
imshow("original-pic",img);
waitKey(0);
destroyAllWindows();
}
效果如下
Q16:Prewitt滤波
Prewitt滤波器也应用于边缘检测,分为横向和纵向
- 横向Prewitt算子
- 纵向Prewitt算子
代码如下
#include"opencv2/core/core.hpp"
#include"opencv2/highgui/highgui.hpp"
#include<opencv2/opencv.hpp>
#include "math.h"
#include"iostream"
using namespace std;
using namespace cv;
#define Kernel_size 3
//枚举类型定义三个差分方向
enum{
horizontal_dir = -1,
vertical_dir = 0
};
Mat Prewitt3(Mat img,int dir){
//构建3*3滤波系数矩阵
double K[Kernel_size][Kernel_size];
for(int x=0;x<Kernel_size;x++){
for(int y=0;y<Kernel_size;y++)
K[x][y]=0;
}
//水平方向sobel算子
if(dir==-1){
K[0][0] = -1;
K[1][0] = -1;
K[2][0] = -1;
K[0][2] = 1;
K[1][2] = 1;
K[2][2] = 1;
}
//垂直方向sobel算子
if(dir==0){
K[0][0] = -1;
K[0][1] = -1;
K[0][2] = -1;
K[2][0] = 1;
K[2][1] = 1;
K[2][2] = 1;
}
int imgrow = img.rows;
int imgcol = img.cols;
Mat out = Mat::zeros(imgrow,imgcol,CV_8UC1);
int dot = floor((float)(Kernel_size/2));
int v;
for(int i=floor((float)(Kernel_size/2));i<imgrow-floor((float)(Kernel_size/2));i++){
for(int j=floor((float)(Kernel_size/2));j<imgcol-floor((float)(Kernel_size/2));j++){
v = 0;
for(int i_=-dot;i_<dot+1;i_++){
for(int j_=-dot;j_<dot+1;j_++){
v += img.at<uchar>(i+i_,j+j_)*K[i_+dot][j_+dot];
}
}
if(v>=0)
out.at<uchar>(i,j) = v;
else
out.at<uchar>(i,j) = -v;
}
}
return out;
}
void main(){
Mat img = imread("ck567.jpg",IMREAD_GRAYSCALE);
Mat out1 = Prewitt3(img,horizontal_dir);
Mat out2 = Prewitt3(img,vertical_dir);
imshow("Prewitt3-1",out1);
imshow("Prewitt3-2",out2);
imshow("original-pic",img);
waitKey(0);
destroyAllWindows();
}
效果如下