opencv学习14-16——差分滤波,Sobel滤波,Prewitt滤波

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();
}

效果如下

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值