c++自编函数对图像进行高斯/椒盐模糊,并进行高斯/中值去噪

作业好多TAT
有不懂的可以私信我,现在是没时间详细解释代码了
里面也有opencv的高斯/中值去噪,c++和opencv的都写了
封面就是我处理的那张图片

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <string>
#define PI 3.141592654

using namespace cv;
using namespace std;

void addingGaussianNoise(Mat img) {
	RNG rng;
	Mat noise = Mat::zeros(img.rows, img.cols, img.type());
	rng.fill(noise, RNG::NORMAL, 10, 20);
	img = img + noise;
	return;
}

void addingSaltAndPepperNoise(Mat img) {
	int cols = img.cols;
	int rows = img.rows;
	for (int i = 0; i < cols; i++) {
		for (int j = 0; j < rows; j++) {
			if (rand() / double(RAND_MAX + 1.0) > 0.95) {  // 每个像素有0.05的几率变成噪点
				if (rand() / double(RAND_MAX + 1.0) > 0.5) {  // 随机产生黑白噪点,使用at指针访问图像像素
					img.at<Vec3b>(j, i)[0] = 0;
					img.at<Vec3b>(j, i)[1] = 0;
					img.at<Vec3b>(j, i)[2] = 0;
				}
				else {
					img.at<Vec3b>(j, i)[0] = 255;
					img.at<Vec3b>(j, i)[1] = 255;
					img.at<Vec3b>(j, i)[2] = 255;
				}
			}
		}
	}
	return;
}

void myGaussianBlur(Mat img_gaus, Mat img_blur, int core, double sigma = 0) {
	if (sigma <= 0) {
		sigma = ((core - 1) * 0.5 - 1.0) * 0.3 + 0.8;//若未指定sigma则自行计算
	}
	vector<vector<float>> conv_core(core, vector<float>(core)); //声明一个二维数组
	int center = core / 2;
	for (int i = 0; i < core; i++)//产生高斯卷积核
	{
		for (int j = 0; j < core; j++)
		{
			conv_core[i][j] = exp(-((i - center) * (i - center) + (j - center) * (j - center)) / (2 * sigma * sigma)) / (2 * PI * sigma * sigma);
		}
	}
	uchar* pixel_list = img_gaus.data;//原图像像素值列表(三通道),也可以设成二维数组,但是要分离RGB比较繁琐。
	int count = 0;
	int cols = img_gaus.cols;
	int rows = img_gaus.rows;
	int channels = img_gaus.channels();
	Mat pixel_expand;
	pixel_expand.create(Size(cols + 2 * center, rows + 2 * center), img_gaus.type());
	uchar* pixel_expand_list = pixel_expand.data;//扩张后图像像素列表(三通道),使用data指针访问图像元素,因为要遍历的次数过多,多次使用at指针略为缓慢

	for (int i = 0; i < rows + 2 * center; i++) {//填入扩充后图像
		for (int j = 0; j < cols + 2 * center; j++) {
			if (i >= center && i < rows + center && j >= center && j < cols + center) {
				for (int ch = 0; ch < channels; ch++) {
					pixel_expand_list[(i * (cols + 2 * center) + j) * channels + ch] = pixel_list[((i - center) * cols + j - center) * channels + ch];
				}
			}
			else {
				int m = i < center ? i + center : (i >= rows + center ? i - center : i);
				int n = j < center ? j + center : (j >= rows + center ? j - center : j);
				for (int ch = 0; ch < channels; ch++) {
					pixel_expand_list[(i * (rows + 2 * center) + j) * channels + ch] = pixel_list[((pixel_expand.rows - m) * rows + (pixel_expand.cols - n)) * channels + ch];
				}
			}
		}
	}

	/*
	//检查扩充后图像是否正确
	imshow("test", pixel_expand);
	waitKey(0);
	*/

	uchar* pixel_blur_list = img_blur.data;
	for (int i = 0; i < rows; i++) {//卷积
		for (int j = 0; j < cols; j++) {
			for (int ch = 0; ch < channels; ch++) {
				double conv = 0;//存放单步卷积结果
				for (int x = 0; x < core; x++) {
					for (int y = 0; y < core; y++) {
						conv += saturate_cast<uchar>(conv_core[x][y] * pixel_expand_list[((i + x) * (cols + 2 * center) + j + y) * channels + ch]);
					}
				}
				pixel_blur_list[(i * cols + j) * channels + ch] = conv;
			}
		}
	}
	return;
}


void bubbleSort(int* list, int len){//冒泡排序
	int temp;
	for (int i = 0; i < len - 1; i++)
	{
		for (int j = 0; j < len - i - 1; j++)
		{
			if (list[j + 1] < list[j])
			{
				temp = list[j];
				list[j] = list[j + 1];
				list[j + 1] = temp;
			}
		}
	}
}

void myMedianBlur(Mat& img_salt, Mat& img_blur, int core) {
	img_blur.create(Size(img_salt.cols - core + 1, img_salt.rows - core + 1), img_salt.type());//用于放置滤波后像素
	uchar* img_p = img_salt.data;
	uchar* img_blur_p = img_blur.data;
	int cols = img_salt.cols;
	int rows = img_salt.rows;
	int channels = img_salt.channels();
	int* p = new int[core * core];//由于core为变量,所以只能建立动态数组
	int median;
	for (int ch = 0; ch < channels; ch++) {
		for (int x = 0; x < rows - core + 1; x++) {
			for (int y = 0; y < cols - core + 1; y++) {
				for (int i = 0; i < core; i++) {
					for (int j = 0; j < core; j++) {
						p[i * core + j] = img_p[((x + i) * cols + (y + j)) * channels + ch];
					}
				}
				bubbleSort(p, core * core);
				if (core % 2 == 0) {
					median = (p[core * core / 2] + p[core * core / 2 - 1]) / 2;
				}
				else{
					median = p[core * core / 2];
				}
				img_blur_p[(x * (cols - core + 1) + y) * channels + ch] = median;
			}
		}
	}
	delete [] p;
	return;
}

int main() {
	String str = "C:\\Users\\33507\\Desktop\\sun.jpg";
	Mat image = imread(str);
	Mat image_gaus = image.clone();
	Mat image_gaus_blur = image.clone();
	Mat image_salt = image.clone();
	Mat image_salt_blur = image.clone();
	Mat my_image_gaus_blur = image.clone();
	Mat my_image_salt_blur;
	addingGaussianNoise(image_gaus);
	addingSaltAndPepperNoise(image_salt);
	GaussianBlur(image_gaus, image_gaus_blur, Size(5, 5), 0, 0);
	medianBlur(image_salt, image_salt_blur, 3);
	myGaussianBlur(image_gaus, my_image_gaus_blur, 5);
	myMedianBlur(image_salt, my_image_salt_blur, 5);
	imshow("origin image", image);
	imshow("image of gaus", image_gaus);
	imshow("image of salt", image_salt);
	imshow("image after gausblur", image_gaus_blur);
	imshow("image after saltblur", image_salt_blur);
	imshow("image after my gausblur", my_image_gaus_blur);
	imshow("image after my saltblur", my_image_salt_blur);
	waitKey(0);
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值