数字图像处理(DIP)实验2 图像滤波与形态学

数字图像处理(DIP)实验2 图像滤波与形态学


数字图像处理课程相关文章 传送门

https://blog.csdn.net/qq_46164507/article/details/122503851


博文说明

本文所使用代码或多或少参考了以往博文的同类or相似文章的代码,并非纯原创
本文仅用于记录并提供一种代码思路,供大家参考


文章目录

    • 数字图像处理(DIP)实验2 图像滤波与形态学
      • 数字图像处理课程相关文章 传送门
      • 博文说明
      • 正文
        • 要求
        • 代码
        • 结果


正文

要求

数字图像处理(DIP)实验2 图像滤波与形态学_第1张图片

代码

运行环境:Ubuntu16.04 LTS + OpenCV 3.0.4 + ROS-kinetic-full

代码语言:c++

#include 
#include
#include 
#include 
#include 
#include 
#include "ros/ros.h"
#include "std_msgs/String.h"
#include "std_msgs/Bool.h"
#include "std_msgs/Float32.h"
#include
#include "sensor_msgs/Image.h"
#include 
#define M_pi 3.14159265
#define LINEAR_X 0
using namespace std;
using namespace cv;
//滤波//
// 空域高斯滤波器函数
void Gaussian(Mat input, Mat output, double sigma){
	// 3sigma原则确定模板矩阵大小
	int x0=int(6*sigma+1);
	if(x0%2==1){
		x0=(x0-1)/2;
	}else{
		x0=x0/2;
	}
	double t[2*x0+1][2*x0+1];//定义模板矩阵
	//计算模板矩阵
	for(int i=-x0;i<=x0;i++){
		for(int j=-x0;j<=x0;j++){
			t[x0+i][x0+j]=1/(2*M_pi*pow(sigma,2))*\
						exp(-(pow(i,2)+pow(j,2))/(2*pow(sigma,2)));
		}
	}
	//归一化,3sigma仍然没有归一化
	double temp=0;
	for(int i=-x0;i<=x0;i++){
		for(int j=-x0;j<=x0;j++){
			temp+=t[x0+i][x0+j];
		}
	}
		
	for(int i=0;i<input.rows;i++){
		for(int j=0;j<input.cols;j++){
			//图形边缘采用原图灰度值
			if(i<x0||i>=input.rows-x0||j<x0||j>=input.cols-x0)
			{
				output.at<uchar>(i,j)=input.at<uchar>(i,j);
			}else{
				double sum=0;
				for(int x=-x0;x<=x0;x++){
					for(int y=-x0;y<=x0;y++){
						sum=sum+input.at<uchar>(i+x,j+y)*t[x0+x][x0+y]/temp;
					}
				}
				output.at<uchar>(i,j)=sum;
			}
			
		}
	}
		
}
//形态学//
// 膨胀函数
void Dilate(Mat Src, Mat Tem, Mat Dst){
	int n=Dst.rows;
	int x0=(n-1)/2;int y0=(n-1)/2;//模板中心位置
	//计算 Dst1 反射模板
	Mat Dst1(Dst.rows,Dst.cols, CV_8UC1);
	for (int i=0; i<Dst.rows; i++){
		for (int j=0; j<Dst.cols; j++){
			Dst1.at<uchar>(i,j)=Dst.at<uchar>(2*x0-i,2*y0-j);}}
	
	// 创建扩充矩阵N+2*M+2
	Mat Src2 = Mat::zeros(Src.rows+2*x0, Src.cols+2*y0, CV_8UC1);//Src2 扩充矩阵
	// imshow("kuochongjuzhen1",Src2);
	for (int i=x0; i<Src.rows+x0; i++){
		for (int j=y0; j<Src.cols+y0; j++){
			Src2.at<uchar>(i,j)=Src.at<uchar>(i-x0,j-x0);
		}
	}
	
	// 操作
	for (int i=0; i<Src.rows; i++){
		for (int j=0; j<Src.cols; j++){
			int flag=0;
			for(int x=-x0;x<=x0;x++){
				for(int y=-y0;y<=y0;y++){
					if(Dst1.at<uchar>(x+x0,y+y0)==255){
						if(Src2.at<uchar>(i+x+x0,j+y+y0)==255){
							flag=1;
						}
					}
				}

			}
			if(flag==1){Tem.at<uchar>(i,j)=255;}
		}
	}
}
// 腐蚀函数
void Erode(Mat Src, Mat Tem, Mat Dst){
	int n=Dst.rows;
	int x0=(n-1)/2;int y0=(n-1)/2;//模板中心位置
	// 创建扩充矩阵N+2*M+2
	Mat Src2 = Mat::zeros(Src.rows+2*x0, Src.cols+2*y0, CV_8UC1);//Src2 扩充矩阵
	for (int i=x0; i<Src.rows+x0; i++){
		for (int j=y0; j<Src.cols+y0; j++){
			Src2.at<uchar>(i,j)=Src.at<uchar>(i-x0,j-x0);
		}
	}
	
	// 操作
	for (int i=0; i<Src.rows; i++){
		for (int j=0; j<Src.cols; j++){
			int flag=1;
			for(int x=-x0;x<=x0;x++){
				for(int y=-y0;y<=y0;y++){
					if(Dst.at<uchar>(x0+x,y0+y)==255){
						if(Src2.at<uchar>(i+x+x0,j+y+y0)==255){
						}else{flag=0;}
					}
				}

			}
			if(flag==1){Tem.at<uchar>(i,j)=255;}
		}
	}
}
int main(int argc, char **argv)
{
	VideoCapture capture;
	capture.open(0); // 1 为打开 zed 相机, 0 为打开笔记本摄像头
	ROS_WARN("*****START");
	ros::init(argc,argv,"trafficLaneTrack");//初始化 ROS 节点
	ros::NodeHandle n;
	// ros::Rate loop_rate(10);//定义速度发布频率
	ros::Publisher pub = n.advertise<geometry_msgs::Twist>("/smoother_cmd_vel", 5);//定义速度发布器
	if (!capture.isOpened())
	{
		printf("摄像头没有正常打开,重新插拔工控机上当摄像头\n");
		return 0;
	}
	waitKey(1000);
	Mat frame;//当前帧图片
	int nFrames = 0;//图片帧数
	int frameWidth = capture.get(CV_CAP_PROP_FRAME_WIDTH);//图片宽
	int frameHeight = capture.get(CV_CAP_PROP_FRAME_HEIGHT);//图片高
	while (ros::ok())
	{
		capture.read(frame);
		if(frame.empty())
		{
			break;
		}
		Mat IMG = frame.clone();// 使用笔记本摄像头Mat frIn = frame(cv::Rect(0, 0, frame.cols / 2, frame.rows));//截取 zed 的左目图片
		//使用本地图像文件
		// Mat IMG=imread("./src/img_pkg/src/2.png");
		Mat gray;//灰度图
		cvtColor(IMG, gray, COLOR_BGR2GRAY);
		Mat binary(gray.rows,gray.cols, CV_8UC1);//二值化图像
		threshold(gray, binary, 120, 255, CV_THRESH_BINARY);//二值化
		//图像反相,便于观察
		for (int i=0; i<binary.rows; i++){
			for (int j=0; j<binary.cols; j++){ 
				if(binary.at<uchar>(i,j)==255){
					binary.at<uchar>(i,j)=0;}
				else{binary.at<uchar>(i,j)=255;}
			}
		}
		imshow("1_ordinary image(binary)",binary);
		
		// 	空域滤波函数
		Mat output = binary.clone();
		double sigma=1;//定义高斯滤波方差
		Gaussian(IMG,output,sigma);
		imshow("2_Gaussianed image",output);//高斯处理后图像
		
		//定义膨胀和腐蚀模板
		int n=9;//模板阶数
		Mat temp = 255*Mat::ones(n,n, CV_8UC1);//此处定义为实心模板

		// 膨胀函数
		Mat output1 = Mat::zeros(binary.rows,binary.cols, CV_8UC1);	
		Dilate(binary,output1,temp);
		imshow("3_dilated image",output1);//膨胀后图像
		imshow("4_dilated+",output1-binary);//膨胀与原图差

		// 腐蚀函数
		Mat output2 = Mat::zeros(binary.rows,binary.cols, CV_8UC1);
		Erode(binary,output2,temp);
		imshow("5_eroded image",output2);//腐蚀后图像
		imshow("6_eroded-",binary-output2);//腐蚀与原图差
		
		
		ros::spinOnce();
		waitKey(5);
	}
	return 0;
}


结果

数字图像处理(DIP)实验2 图像滤波与形态学_第2张图片

你可能感兴趣的:(数字图像处理,c++,opencv,linux,图像处理,ubuntu)