目录
1.中值滤波
1.1 接口设计
//中值滤波函数定义
static BOOL medium_filter(CImageDataset &imgIn, CImageDataset &imgOut,int win_len);
win_len表示滤波器窗口边长
1.2 界面设计
1.3 测试
使用5*5窗口测试
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 界面设计
2.3 测试
使用上图中的参数测试
可见在滤波的同时还保持了边缘。(帽子上)
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 测试
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;
}