c语言和opencv实现图像均值滤波和中值滤波

1,c语言实现中值滤波以及算法实现描述

我们在一个矩阵中去除边缘,在剩余数中求取所有像素点的均值来取代中间的值,我们来举例说明:

  公式:meanvalue = \sum _{i=0,j=0}^{i=2,j=2}a[i][j]         a[i][j]是下面数据除去边缘值的平均值。

12331

3

1023543
22345142
12132281
34423
12331
327.827.827.83
227.827.827.82
127.827.827.81
34423

图像的椒盐化补充:

椒盐噪声是由图像传感器,传输信道,解码处理等产生的黑白相间的亮暗点噪声。椒盐噪声是指两种噪声,一种是盐噪声(salt noise)盐=白色(255),另一种是胡椒噪声(pepper noise),椒=黑色(0)。

 c语言代码实现:


#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include<ctime>

using namespace cv;
using namespace std;

//均值滤波
void AverFiltering(const Mat &src,Mat &dst) {

	if (!src.data) return;

	//at访问像素点
	for (int i = 1; i<src.rows; ++i)

		for (int j = 1; j < src.cols; ++j) {

			if ((i - 1 >= 0) && (j - 1) >= 0 && (i + 1)<src.rows && (j + 1)<src.cols) {//边缘不进行处理

				dst.at<Vec3b>(i, j)[0] = (src.at<Vec3b>(i, j)[0] + src.at<Vec3b>(i - 1, j - 1)[0] + src.at<Vec3b>(i - 1, j)[0] + src.at<Vec3b>(i, j - 1)[0] +

					src.at<Vec3b>(i - 1, j + 1)[0] + src.at<Vec3b>(i + 1, j - 1)[0] + src.at<Vec3b>(i + 1, j + 1)[0] + src.at<Vec3b>(i, j + 1)[0] +

					src.at<Vec3b>(i + 1, j)[0]) / 9;

				dst.at<Vec3b>(i, j)[1] = (src.at<Vec3b>(i, j)[1] + src.at<Vec3b>(i - 1, j - 1)[1] + src.at<Vec3b>(i - 1, j)[1] + src.at<Vec3b>(i, j - 1)[1] +

					src.at<Vec3b>(i - 1, j + 1)[1] + src.at<Vec3b>(i + 1, j - 1)[1] + src.at<Vec3b>(i + 1, j + 1)[1] + src.at<Vec3b>(i, j + 1)[1] +

					src.at<Vec3b>(i + 1, j)[1]) / 9;

				dst.at<Vec3b>(i, j)[2] = (src.at<Vec3b>(i, j)[2] + src.at<Vec3b>(i - 1, j - 1)[2] + src.at<Vec3b>(i - 1, j)[2] + src.at<Vec3b>(i, j - 1)[2] +

					src.at<Vec3b>(i - 1, j + 1)[2] + src.at<Vec3b>(i + 1, j - 1)[2] + src.at<Vec3b>(i + 1, j + 1)[2] + src.at<Vec3b>(i, j + 1)[2] +

					src.at<Vec3b>(i + 1, j)[2]) / 9;

			}

			else {//边缘赋值

				dst.at<Vec3b>(i, j)[0] = src.at<Vec3b>(i, j)[0];

				dst.at<Vec3b>(i, j)[1] = src.at<Vec3b>(i, j)[1];

				dst.at<Vec3b>(i, j)[2] = src.at<Vec3b>(i, j)[2];

			}

		}

}

//图像椒盐化
void salt(Mat &image, int num) {

	if (!image.data) return;//防止传入空图

	int i, j;

	srand(time(NULL));

	for (int x = 0; x < num; ++x) {

		i = rand() % image.rows;

		j = rand() % image.cols;

		image.at<Vec3b>(i, j)[0] = 255;

		image.at<Vec3b>(i, j)[1] = 255;

		image.at<Vec3b>(i, j)[2] = 255;
	}
}

void main() 
{
	Mat image = imread("路飞.jpg");

	Mat Salt_Image;

	image.copyTo(Salt_Image);

	salt(Salt_Image, 3000);

	Mat image1(image.size(), image.type());

	Mat image2;

	AverFiltering(Salt_Image, image1);

	imshow("原图", image);

	imshow("自定义均值滤波", image1);

	waitKey();
}


  运行结果如下: g++ 2_opencv.cpp `pkg-config opencv --cflags` `pkg-config opencv --libs`

 

opencv实现均值滤波:

import cv2
import numpy as np
img = cv2.imread('image11.jpg',1)
cv2.imshow('src',img)
dst = cv2.GaussianBlur(img,(5,5),1.5)
cv2.imshow('dst',dst)
cv2.waitKey(0)

 运行结果如下:

 

2,c语言以及opencv实现中值滤波:

12331  

3

1023543
22345142
12132281
34423
12331

3

1023543
22323142
12132281
34423

 

 

 



对中间的9个数据10,23,54,23,45,14,21,32,28进行排序,所以排序后的数据如下:

 10,14,21,23,23,28,32,45,45    所以我们看到中值是23,我们只需要替换掉中间  

   值,将45替换为23即可。

 

 

c语言代码实现中值滤波:


#include "opencv2/imgproc.hpp"

#include "opencv2/highgui.hpp"

#include<ctime>

using namespace cv;

using namespace std;

typedef unsigned char uchar;

void swap(uchar* p1,uchar* p2)
{
    uchar* temp = p1;
    p1 = p2;
    p2 = temp ;
}
//求九个数的中值

uchar Median(uchar n1, uchar n2, uchar n3, uchar n4, uchar n5,

	uchar n6, uchar n7, uchar n8, uchar n9) {

	uchar arr[9];

	arr[0] = n1;

	arr[1] = n2;

	arr[2] = n3;

	arr[3] = n4;

	arr[4] = n5;

	arr[5] = n6;

	arr[6] = n7;

	arr[7] = n8;

	arr[8] = n9;

	for (int gap = 9 / 2; gap > 0; gap /= 2)//希尔排序

		for (int i = gap; i < 9; ++i)

			for (int j = i - gap; j >= 0 && arr[j] > arr[j + gap]; j -= gap)

				swap(&arr[j], &arr[j + gap]);

	return arr[4];//返回中值

}

//图像椒盐化

void salt(Mat &image, int num) {

	if (!image.data) return;//防止传入空图

	int i, j;

	srand(time(NULL));

	for (int x = 0; x < num; ++x) {

		i = rand() % image.rows;

		j = rand() % image.cols;

		image.at<Vec3b>(i, j)[0] = 255;

		image.at<Vec3b>(i, j)[1] = 255;

		image.at<Vec3b>(i, j)[2] = 255;
	}
}

//中值滤波函数

void MedianFlitering(const Mat &src, Mat &dst) {

	if (!src.data)return;

	Mat _dst(src.size(), src.type());

	for(int i=0;i<src.rows;++i)

		for (int j=0; j < src.cols; ++j) {

			if ((i - 1) > 0 && (i + 1) < src.rows && (j - 1) > 0 && (j + 1) < src.cols) {

				_dst.at<Vec3b>(i, j)[0] = Median(src.at<Vec3b>(i, j)[0], src.at<Vec3b>(i + 1, j + 1)[0],

					src.at<Vec3b>(i + 1, j)[0], src.at<Vec3b>(i, j + 1)[0], src.at<Vec3b>(i + 1, j - 1)[0],

					src.at<Vec3b>(i - 1, j + 1)[0], src.at<Vec3b>(i - 1, j)[0], src.at<Vec3b>(i, j - 1)[0],

					src.at<Vec3b>(i - 1, j - 1)[0]);

				_dst.at<Vec3b>(i, j)[1] = Median(src.at<Vec3b>(i, j)[1], src.at<Vec3b>(i + 1, j + 1)[1],

					src.at<Vec3b>(i + 1, j)[1], src.at<Vec3b>(i, j + 1)[1], src.at<Vec3b>(i + 1, j - 1)[1],

					src.at<Vec3b>(i - 1, j + 1)[1], src.at<Vec3b>(i - 1, j)[1], src.at<Vec3b>(i, j - 1)[1],

					src.at<Vec3b>(i - 1, j - 1)[1]);

				_dst.at<Vec3b>(i, j)[2] = Median(src.at<Vec3b>(i, j)[2], src.at<Vec3b>(i + 1, j + 1)[2],

					src.at<Vec3b>(i + 1, j)[2], src.at<Vec3b>(i, j + 1)[2], src.at<Vec3b>(i + 1, j - 1)[2],

					src.at<Vec3b>(i - 1, j + 1)[2], src.at<Vec3b>(i - 1, j)[2], src.at<Vec3b>(i, j - 1)[2],

					src.at<Vec3b>(i - 1, j - 1)[2]);

			}

			else

				_dst.at<Vec3b>(i, j) = src.at<Vec3b>(i, j);

		}

	_dst.copyTo(dst);//拷贝

}

int main() {

	Mat image = imread("1.JPG");

	Mat Salt_Image;

	image.copyTo(Salt_Image);

	salt(Salt_Image, 3000);

 
	Mat image3, image4;

	MedianFlitering(Salt_Image, image3);

	medianBlur(Salt_Image, image4, 3);

	imshow("自定义中值滤波处理后", image3);

	imshow("openCV自带的中值滤波", image4);

	waitKey();

}

代码实现效果如下:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陌上花开缓缓归以

你的鼓励将是我创作的最大动力,

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值