标题:写的一个非局部均匀滤波,结果由一小块出现问题
只看楼主
fuxiuliang
Rank: 1
等 级:新手上路
帖 子:3
专家分:0
注 册:2014-6-18
结帖率:0
已结贴  问题点数:20 回复次数:4 
写的一个非局部均匀滤波,结果由一小块出现问题
按照matlab源程序用C写的一段NLM代码,运行结果由一小块出现-2147483648,经过测试发现是在507行开始到511行的第130列到150列左右那矩阵MUL有问题。但是我不知道为啥会出现这样的计算错误,计算的average=1.#INF00,sweight=1.#INF00求大神解答啊。

新建文件夹.rar (317.54 KB)
程序代码:
#define _CRT_SECURE_NO_DEPRECATE
#include <time.h>
#include <stdlib.h>
#include <stdio.h> 
#include <math.h>
#include <windows.h>
#include <iostream>

//定义图像尺寸
#define height 512
#define width 512

//定义相似窗口和搜索窗口维度
#define f 3
#define t 9
#define sigma 25
#define degree 4
#define h degree*sigma


//定义数组

int source[height][width];
int mir_source[height+2*f][width+2*f];
int W1[2*f+1][2*f+1];
int W2[2*f+1][2*f+1];
int MUL[2*f+1][2*f+1];
int SUB1[2*f+1][2*f+1];
int SUB2[2*f+1][2*f+1];
int result[height][width];
int psnr_c[height][width];

//定义变量
double w;
double d;
double wmax;
double sweight;
double average;
double PSNR;

//读入矩阵
void read()
{
    //读入矩阵文件,并将其赋给alldata
    FILE* fp=fopen("baboon_噪声.txt","r");
    //FILE* source=fopen("mat.txt","r");
    if(source==NULL)
    {
        //freopen("runhistory.txt", "a+", stdout);
        printf("ERROR!\n");
        return;
    }
    ////将mat读入二维数组alldata
    int i,j;
    for(i=0;i<height;++i)
        for(j=0;j<width;++j)
        {
            fscanf(fp, "%d ",&source[i][j]);//这里alldata[i][j]前一定要加&,因为这里是取地址的,和之后的输出alldata[i][j]这个数不同
        }
}

//镜像函数;
void mirror()//我把行列搞反了.第三个地方出错
{
    int i,j;
    for(i=0;i<height+2*f;i++)
        for(j=0;j<width+2*f;j++)//在mir_sourcedata[][]里进行遍历
        {
            if(i>(f-1)&&j>(f-1)&&i<(height+f)&&j<(width+f))//顺时针判断i,j
                mir_source[i][j]=source[i-f][j-f];
            else if(i<f&&j<f)//1
                mir_source[i][j]=source[f-i][f-j];
            else if(j>f&&i<f&&j<(width+f-1))//2
                mir_source[i][j]=source[f-i][j-f];
            else if(j>(width+f-1)&&i<f)//3
                mir_source[i][j]=source[f-i][2*width+f-j-2];
            else if(j>(width+f-1)&&i>f&&i<(height+f-1))//4
                mir_source[i][j]=source[i-f][2*width+f-j-2];
            else if(j>(width+f-1)&&i>(height+f-1))//5
                mir_source[i][j]=source[2*height+f-i-2][2*width+f-j-2];
            else if(j>f&&j<(width+f-1)&&i>(height+f-1))//6
                mir_source[i][j]=source[2*height+f-i-2][j-f];
            else if(j<f&&i>(height+f-1))//7
                mir_source[i][j]=source[2*height+f-i-2][f-j];
            else if(j<f&&i>f&&i<(height+f-1))//8
                mir_source[i][j]=source[i-f][f-j];
        }
}

/*
备份,正确的镜像函数
void mirror()//我把行列搞反了.第三个地方出错
{
    int i,j;
    for(i=0;i<height+2*f;i++)
        for(j=0;j<width+2*f;j++)//在mir_sourcedata[][]里进行遍历
        {
            if(i>(f-1)&&j>(f-1)&&i<(height+f)&&j<(width+f))//顺时针判断i,j
                mir_source[i][j]=source[i-f][j-f];
            else if(i<f&&j<f)//1
                mir_source[i][j]=source[f-i][f-j];
            else if(j>f&&i<f&&j<(width+f-1))//2
                mir_source[i][j]=source[f-i][j-f];
            else if(j>(width+f-1)&&i<f)//3
                mir_source[i][j]=source[f-i][2*width+f-j-2];
            else if(j>(width+f-1)&&i>f&&i<(height+f-1))//4
                mir_source[i][j]=source[i-f][2*width+f-j-2];
            else if(j>(width+f-1)&&i>(height+f-1))//5
                mir_source[i][j]=source[2*height+f-i-2][2*width+f-j-2];
            else if(j>f&&j<(width+f-1)&&i>(height+f-1))//6
                mir_source[i][j]=source[2*height+f-i-2][j-f];
            else if(j<f&&i>(height+f-1))//7
                mir_source[i][j]=source[2*height+f-i-2][f-j];
            else if(j<f&&i>f&&i<(height+f-1))//8
                mir_source[i][j]=source[i-f][f-j];
        }
}
*/
//求最大值函数
int max_value(int a,int b)
{
    int L;
    if(a>=b)
        L=a;
    else
        L=b;
    return L;
}
//求最小值
int min_value(int a,int b)
{
    int L;
    if(a<=b)
        L=a;
    else
        L=b;
    return L;
}
//将mir_source的相应数据写入W1,W2的函数,ab代表mir_source的相应块起点
void matrix_write(int W[2*f+1][2*f+1],int a,int b)
{
    int i,j;
    for(i=0;i<2*f+1;i++)
        for(j=0;j<2*f+1;j++)
        {
            W[i][j]=mir_source[i+a][j+b];//!!!!!!这里是不是有点问题
        }
}
//两个矩阵相减
void matrix_sub(int A[2*f+1][2*f+1],int B[2*f+1][2*f+1],int C[2*f+1][2*f+1])
{
    for(int i=0;i<2*f+1;i++)
        for( int j=0;j<2*f+1;j++)
            C[i][j]=abs(A[i][j]-B[i][j]);//有没有可能出现负值
}
//求矩阵的和
double matrix_sum(int A[2*f+1][2*f+1])
{
    double L=0;
    for(int i=0;i<2*f+1;i++)
        for(int j=0;j<2*f+1;j++)
            L+=A[i][j];
    return L;
}
//两个矩阵相乘
/*void matrix_mul(int A[2*f+1][2*f+1],int B[2*f+1][2*f+1],int C[2*f+1][2*f+1])
{
    for(int i=0;i<2*f+1;i++)
        for(int j=0;j<2*f+1;j++)
            for(int k=0;k<2*f+1;k++)
                C[i][j]+=A[i][k]*B[k][j];
}*/
void matrix_mul_point(int A[2*f+1][2*f+1],int B[2*f+1][2*f+1],int C[2*f+1][2*f+1])
{
    for(int i=0;i<2*f+1;i++)
        for(int j=0;j<2*f+1;j++)
                C[i][j]=A[i][j]*B[i][j];
}

//sum_psnr
double psnr_sum(int matrix_data[height][width])
{
    double L=0;
    for(int i=0;i<height;i++)
        for(int j=0;j<width;j++)
            L+=matrix_data[i][j];
    return L;
}
//PSNR
void PSNR_VALUE()
{
    double MSE;
    double sum;
    for(int i=0;i<height;i++)
        for(int j=0;j<width;j++)
            psnr_c[i][j]=(result[i][j]-source[i][j])*(result[i][j]-source[i][j]);
    sum=psnr_sum(psnr_c);
    MSE=sum/(height*width);
    PSNR=10*log10(255*255/MSE);
}
//输出debug时的W1,W2,MUL
/*void print_matrix_debug(int A[2*f+1][2*f+1])
{
    for(int i=0;i<2*f+1;i++)
    {
        for(int j=0;j<2*f+1;j++)
        {
            printf("%d ",A[i][j]);
        }
        printf("\n");
    }
    printf("\n\n\n");
}*/
//NLM算法.将source传入mir_source后,就可以对其进行非局部均匀滤波了。步骤按照matlab程序来
void NLM()
{
    int i,j,i1,j1;
    for(i=0;i<height;i++)
        for(j=0;j<width;j++)
        {
            i1=i+f;
            j1=j+f;
            matrix_write(W1,i1-f,j1-f);//是对的,因为txt里行太长以至于到下一行了
            //对每个点的求权值开始,都average,sweight,wmax进行初始化
            w=0;
            wmax=0;
            average=0;
            sweight=0;
            d=0;

            int rmin=max(i1-t,f+1);
            int rmax=min(i1+t,height+f);
            int smin=max(j1-t,f+1);
            int smax=min(j1+t,width+f);
            //freopen("runhistory.txt","a+",stdout);
            //printf("第%d %d个数据rmin,rmax,smin,smax分别是 %d  %d  %d  %d\n\n",i,j,rmin,rmax,smin,smax);
            
            /*int rmin=max_value(i1-t,f+1);
            int rmax=min_value(i1+t,height+f);
            int smin=max_value(j1-t,f+1);
            int smax=min_value(j1+t,width+f);*/
            

            //在搜索块里进行求权值
            for(int r=rmin;r<(rmax+1);r++)//这里加了个等号,与matlab的矩阵元素表示形式不同
            {
                for(int s=smin;s<(smax+1);s++)
                {
                    if(r==i1&&s==j1)
                        continue;
                    matrix_write(W2,r-f,s-f);
                    //W1和W2相乘
                    matrix_sub(W1,W2,SUB1);
                    matrix_sub(W1,W2,SUB2);
                    matrix_mul_point(SUB1,SUB2,MUL);//乘法这错了!!因为是点乘,是各个元素对应相乘
                    //debug用的输出三个短矩阵.找出来的原因是矩阵出错了,也就是MUL(也不一定)就是这矩阵MUL出错了,而且应该是最后一行出错
                    /*if(i>507&&j>130&&j<153)
                    {
                        freopen("matrix_debug.txt","a+",stdout);
                        print_matrix_debug(W1);
                        print_matrix_debug(W2);
                        print_matrix_debug(MUL);
                    }*/
                    d=matrix_sum(MUL);//d的值比matlab的多一个数量级
                    w=exp(-d/(h*h));
                    //freopen("runhistory1.txt","a+",stdout);
                    //printf("d的值是%f\n",d);
                    //printf("w的值是%f\n",w);
                    if(w>wmax)
                        wmax=w;
                    sweight+=w;
                    average+=w*mir_source[r][s];
                }
            }
            //freopen("runhistory.txt","a+",stdout);//!!!!!!!!!从506,128开始,average和sweight就开始出错了
            //printf("average和sweight分别是%f %f\n",average,sweight);
            average+=wmax*mir_source[i1][j1];
            sweight+=wmax;
            if(sweight>0)
                result[i][j]=(int)(average/sweight);
            else
                result[i][j]=source[i][j];
            /*if(i>506&&j>132&&j<153)
            {
                freopen("runhistory.txt","a+",stdout);
                printf("average=%f\n",average);
                printf("sweight=%f\n",sweight);
                printf("第%d %d个数=%d\n\n",i,j,result[i][j]);
            }*/
            //freopen("history.txt","a+",stdout);
            printf("%d %d--%d:\n",i,j,result[i][j]);
        }
}

//打印滤波后的结果
 void print_result()

 {
    FILE* fp;
    fp=fopen("滤波结果.txt","w");
    if(!fp)
    {
        printf("打开输入镜像结果错误!\n");
        exit(-1);
    }
    for(int i=0;i<height;i++)
    {
        for(int j=0;j<width;j++)
        {
            fprintf(fp,"%d ",result[i][j]);
        }
        fputc('\n',fp);
    }
    fclose(fp);

 }

 //打印镜像结果
 void print_mir()

 {
    FILE* fp;
    fp=fopen("镜像结果.txt","w");
    if(!fp)
    {
        printf("打开输入镜像结果错误!\n");
        exit(-1);
    }
    for(int i=0;i<height+2*f;i++)
    {
        for(int j=0;j<width+2*f;j++)
        {
            fprintf(fp,"%d ",mir_source[i][j]);
        }
        fputc('\n',fp);
    }
    fclose(fp);

 }
//主函数
void main()
{
    clock_t start,end;
    start=clock();
    read();
    mirror();
    NLM();
    PSNR_VALUE();
    end=clock();
    print_result();
    print_mir();
    printf("%d 毫秒\n",end-start);
    printf("PSNR是%f db\n",PSNR);
}
搜索更多相关主题的帖子: average matlab 源程序 左右 
2014-06-18 09:51
砖家的谎言
Rank: 12Rank: 12Rank: 12
等 级:禁止访问
威 望:30
帖 子:693
专家分:3898
注 册:2013-12-6
得分:10 
比较专业类的问题,还请楼主描述问题详细点,这样便于大家帮忙解答

我不是砖家,要努力成为砖家。
2014-06-18 15:22
embed_xuel
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:58
帖 子:3845
专家分:11385
注 册:2011-9-13
得分:10 
max和min是宏吧?怎么定义的?
            int rmin=max(i1-t,f+1);
            int rmax=min(i1+t,height+f);
            int smin=max(j1-t,f+1);
            int smax=min(j1+t,width+f);

总有那身价贱的人给作业贴回复完整的代码
2014-06-18 15:43
fuxiuliang
Rank: 1
等 级:新手上路
帖 子:3
专家分:0
注 册:2014-6-18
得分:0 
回复 2 楼 砖家的谎言
第一次发帖,还请见谅。是一个非局部均匀滤波,对没个像素,在一定区域内,也就是算法中的rmin,rmax,smin,smax区域里进行加权求和,但是很奇怪,在其他区域都算的对的,滤波效果也很好,偏偏就是从507行到511行的130列到150列那儿出现的数据特别大
2014-06-18 16:58
fuxiuliang
Rank: 1
等 级:新手上路
帖 子:3
专家分:0
注 册:2014-6-18
得分:0 
回复 3 楼 embed_xuel
貌似可以直接用。其他区域上这算法是对的,就是一小块数据上出现错误。我用自己写的求最大最小值函数也一样的问题
2014-06-18 16:59



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-433071-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.239913 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved