C++多线程实现中值滤波,双边滤波,拉普拉斯锐化,附源代码

目录

1.中值滤波

1.1 接口设计

//中值滤波函数定义
	static BOOL medium_filter(CImageDataset &imgIn, CImageDataset &imgOut,int win_len);

win_len表示滤波器窗口边长

1.2 界面设计

C++多线程实现中值滤波,双边滤波,拉普拉斯锐化,附源代码

1.3 测试

使用5*5窗口测试
C++多线程实现中值滤波,双边滤波,拉普拉斯锐化,附源代码

1.4 源代码

//多线程中值滤波                                                                            
BOOL CImageProcessingEx::medium_filter(CImageDataset &imgIn, CImageDataset &imgOut,int win_len)
{
	/* 确保输入图像不为空 */ 
	if(imgIn.empty()) 
	{ 
		return FALSE; 
	} 

	//记录输入图像的尺寸
	init(imgIn);

	/* 创建输出图像 */ 
	if(FALSE == imgOut.create(n_col,n_row,n_band))
	{ 
		return FALSE; 
	} 

	int win_area=win_len*win_len;   //窗口面积
	int border=win_len/2;			//边框宽度
	int num_of_threads = 8;

	//给传入进程的参数结构体数组赋值
	parameters* p = new parameters[num_of_threads];
	for (int i = 0; i < num_of_threads; ++i)
	{
		p[i].win_len = win_len;
		p[i].output = imgOut.m_data;
		p[i].input = imgIn.m_data;
		p[i].num_of_threads = num_of_threads;//线程数,也是处理的间隔
		//上面的每个进程都一样

		p[i].start = i;//每个进程的开始处理的位置不一样
	}

	//多线程并行///

	HANDLE* Threads=new HANDLE[num_of_threads];//线程池
	for(int i=0;i< num_of_threads;++i)
	{
		Threads[i] = CreateThread(NULL, 0, medium_filter_thread, p+i, 0, NULL);
		SetThreadAffinityMask(Threads[i], (DWORD_PTR)pow(2.0,i));//附加到第i个CPU内核
	}

	DWORD state;
	do{//等待全部进程结束
		state=WaitForMultipleObjects(num_of_threads, Threads,TRUE,INFINITE);
	}while(state!=WAIT_OBJECT_0);

	//关闭进程
	for(int i=0;i< num_of_threads;++i)
		CloseHandle(Threads[i]);

	//释放空间
	delete[]p;
	delete[]Threads;

	return TRUE;
	
}
DWORD WINAPI CImageProcessingEx::medium_filter_thread(LPVOID lpParamter)
{
	parameters*p = (parameters*)lpParamter;

	int index,band,row,col,i,j,k=0;		//用于遍历

	int win_len=p->win_len;
	int win_area=win_len*win_len;   //窗口面积
	int border=p->win_len/2;		//边框宽度

	double* input_data=p->input;
	double* output_data=p->output;

	int start=p->start;
	int num_of_threads = p->num_of_threads;

	vector<double> window(win_area);//窗口

	for (band = 0; band < n_band; band++) {
		for (row = border + start; row < n_row - border; row += num_of_threads) {//每隔num_of_threads行处理一行,遍历全图
			for (col = border; col < n_col - border; ++col) {

				for (i = row - win_len / 2; i <= row + win_len / 2; ++i) {
					for (j = col - win_len / 2; j <= col + win_len / 2; ++j)//遍历窗口
					{
						index = coo2ind(band,i,j);
						window[k++] = input_data[index];//记入window数组
					}
				}

				index = coo2ind(band,row,col);
				std::nth_element(window.begin(), window.begin() + win_area / 2 + 1, window.end());//用STL找中值
				output_data[index] = window[win_area / 2 + 1];
				k = 0;
			}
		}
	}


	return 0L;
}

2.双边滤波

2.1 接口设计

//双边滤波函数定义
	static BOOL bilateral_filter(CImageDataset &imgIn, CImageDataset &imgOut,int N,double sigma_r,double sigma_s);

N=(滤波器边长-1)/2
sigma_r为像素值权重
sigma_s为空间距离权重

2.2 界面设计

C++多线程实现中值滤波,双边滤波,拉普拉斯锐化,附源代码

2.3 测试

使用上图中的参数测试
C++多线程实现中值滤波,双边滤波,拉普拉斯锐化,附源代码
可见在滤波的同时还保持了边缘。(帽子上)

2.4 源代码

//多线程双边滤波
BOOL CImageProcessingEx::bilateral_filter(CImageDataset &imgIn, CImageDataset &imgOut,int N,double sigma_r,double sigma_s)
{
	/* 确保输入图像不为空 */ 
	if(imgIn.empty()) 
	{ 
		return FALSE; 
	} 

	//记录输入图像的尺寸
	init(imgIn);

	/* 创建输出图像 */ 
	if(FALSE == imgIn.duplicate(imgOut))
	{ 
		return FALSE; 
	} 

	int num_of_threads = 8;
	int win_len = 2 * N + 1;

	//传入进程的参数结构体数组
	bilateral_filter_parameters* p = new bilateral_filter_parameters[num_of_threads];
	for (int i = 0; i < num_of_threads; ++i)
	{
		p[i].win_len = win_len;
		p[i].output = imgOut.m_data;
		p[i].input = imgIn.m_data;
		p[i].num_of_threads = num_of_threads;//线程数,也是处理的间隔
		p[i].N = N;
		p[i].sigma_r = sigma_r;
		p[i].sigma_s = sigma_s;

		p[i].start = i;//每个进程的开始处理的位置不一样
	}

	//多线程并行处理/

	HANDLE* Threads = new HANDLE[num_of_threads];//进程池
	for (int i = 0; i < num_of_threads; ++i)
	{
		Threads[i] = CreateThread(NULL, 0, bilateral_filter_thread, p + i, 0, NULL);
		SetThreadAffinityMask(Threads[i], (DWORD_PTR)pow(2.0, i));//附加到第i个CPU内核
	}

	DWORD state;
	do {//等待全部进程结束
		state = WaitForMultipleObjects(num_of_threads, Threads, TRUE, INFINITE);
	} while (state != WAIT_OBJECT_0);

	//关闭进程
	for (int i = 0; i < num_of_threads; ++i)
		CloseHandle(Threads[i]);

	//释放空间
	delete[]p;
	delete[]Threads;

	return TRUE;
}
DWORD WINAPI CImageProcessingEx::bilateral_filter_thread(LPVOID lpParamter)
{
	bilateral_filter_parameters* p = (bilateral_filter_parameters*)lpParamter;

	int index, row, col, i, j, band,k = 0;		//用于遍历
	int win_len = p->win_len;
	int win_area = win_len * win_len;   //窗口面积
	vector<double> window(win_area);//窗口
	int border = p->win_len / 2;		//边框宽度
	double* input_data = p->input;
	double* output_data = p->output;
	int start = p->start;
	int num_of_threads = p->num_of_threads;
	int N = p->N;
	double sigma_r = p->sigma_r;
	double sigma_s = p->sigma_s;

	double molecules;//分子
	double denominatores;//分母

	for (band = 0; band < n_band; band++) {
		for (row = N + start; row < n_row - N; row += num_of_threads) {//每隔num_of_threads行处理一行
			for (col = N; col < n_col - N; ++col) {//遍历全图

				//分子分母置零
				molecules = 0;
				denominatores = 0;

				for (i = row - N; i <= row + N; ++i) {
					for (j = col - N; j <= col + N; ++j)//遍历窗口
					{
						double w = W(band, row, col, i, j, sigma_r, sigma_s, input_data);

						index = coo2ind(band, i, j);

						//累加
						molecules += w * input_data[index];
						denominatores += w;
					}
				}

				index = coo2ind(band, row, col);
				output_data[index] = molecules / denominatores;
			}
		}
	}
	return 0L;
}

3.拉普拉斯锐化

3.1 接口设计

	//拉普拉斯锐化
	static BOOL Laplace(CImageDataset &imgIn, CImageDataset &imgOut);

3.2 测试

C++多线程实现中值滤波,双边滤波,拉普拉斯锐化,附源代码

3.3 源代码

//拉普拉斯
BOOL CImageProcessingEx::Laplace(CImageDataset &imgIn, CImageDataset &imgOut)
{
	/* 确保输入图像不为空 */ 
	if(imgIn.empty()) 
	{ 
		return FALSE; 
	} 

	//记录输入图像的尺寸
	init(imgIn);

	/* 创建输出图像 */ 
	if(FALSE == imgOut.create(n_col,n_row,n_band))
	{ 
		return FALSE; 
	} 

	double *output_data = imgOut.m_data; 
	const double *input_data=imgIn.m_data;

	int index,row,col,i,j,band,k=0;	//用于遍历,k用于在拉普拉斯算子中遍历

	int laplacian[9]={0,1,0,1,-4,1,0,1,0};

	double intermediate=0;//中间结果

	for(band=0;band<n_band;band++)
		for(row=1; row<n_row-1; ++row){
			for(col=1; col<n_col-1; ++col){//遍历全图


				for(i=row-1;i<=row+1;++i){
					for(j=col-1;j<=col+1;++j)//遍历窗口
					{	
						//跳过laplace算子中的0
						if(laplacian[k]==0) 
						{
							++k;
							continue;
						}
						index=coo2ind(band,i,j);
						intermediate+=input_data[index]*laplacian[k++];
					}
				}

			
				index=coo2ind(band,row,col);
				output_data[index]=input_data[index]-intermediate;

				//置0
				intermediate=0;
				k=0;
			}
	}


	return TRUE;
}

上一篇:谱函数拟合程序


下一篇:FASTREPORT自动换行及行高自适应