基于双线性插值的拉格朗日像素修复算法

工程编译环境vc6.0+opencv1.0

 #include <stdlib.h>
#include <stdio.h>
#include <iostream.h>
#include <math.h>
#include <cv.h>
#include <highgui.h> 

#ifdef _CH_
#pragma package <opencv>
#endif

#include <stdio.h>
#include <stdlib.h>

struct record//两个代表偏移
{
    int up,down,left,right;//差距
    unsigned char dataup;
    unsigned char datadown;
    unsigned char dataleft;
    unsigned char dataright;//  int **BT;
};//负责记录空间位置,和边界像素值//换成指针结构体?

IplImage* inpaint_mask = 0;
IplImage* img0 = 0;
IplImage* img = 0;
IplImage* inpainted = 0;
CvPoint prev_pt = {-1,-1};
unsigned char aver(unsigned char *data,unsigned char *bill,IplImage* masktt,int i,int j,int k,int step,int channels);
void scan(unsigned char *data,unsigned char *bill,IplImage* masktt,record *re,int i,int j,int k,int step,int channels);//分别扫描出左右上下最短距离赋给t采样
unsigned char biline(record *re,int wh,int i,int j);
double lagrange(double *x,double *y,double xx,int n);
double xlag(record re[],int i);
double ylag(record re[],int j);
void cvrepair(IplImage* img,IplImage* mask,IplImage* masktt);//img破坏图像,mask轨迹母板,masktt2值图像
void on_mouse( int event, int x, int y, int flags, void* zhang)
{
    if( !img )
        return;

    if( event == CV_EVENT_LBUTTONUP || !(flags & CV_EVENT_FLAG_LBUTTON) )
        prev_pt = cvPoint(-1,-1);
    else if( event == CV_EVENT_LBUTTONDOWN )
        prev_pt = cvPoint(x,y);
    else if( event == CV_EVENT_MOUSEMOVE && (flags & CV_EVENT_FLAG_LBUTTON) )
    {
        CvPoint pt = cvPoint(x,y);
        if( prev_pt.x < 0 )
            prev_pt = pt;
        cvLine( inpaint_mask, prev_pt, pt, cvScalarAll(255), 15, 8);
        cvLine( img, prev_pt, pt, CV_RGB(0, 255, 0), 15, 8);
        prev_pt = pt;
        cvShowImage( "image", img );
    }
}


int main()
{

  char strIn[1024]; char strOut[1024];

  cout<<"请输入原始图片路径:";
  cin>>strIn;
  //cout<<endl;
  cout<<"请输入结果图片路径: ";
  cin>>strOut;

    if( (img0 = cvLoadImage(strIn,-1)) == 0 )
        return 0;

    printf( "Hot keys: \n"
            "\tESC - quit the program\n"
            "\tr - restore the original image\n"
            "\ti or ENTER - run inpainting algorithm\n"
            "\t\t(before running it, paint something on the image)\n" );

    cvNamedWindow( "image", 1 );

    img = cvCloneImage( img0 );
    inpainted = cvCloneImage( img0 );
    inpaint_mask = cvCreateImage( cvGetSize(img), 8, 1 );

    cvZero( inpaint_mask );
    cvZero( inpainted );
    cvShowImage( "image", img );
    //cvShowImage( "watershed transform", inpainted );
    cvSetMouseCallback( "image", on_mouse, 0 );

    for(;;)
    {
        int c = cvWaitKey(0);

        if( (char)c == 27 )
            break;

        if( (char)c == 'r' )
        {
            cvZero( inpaint_mask );
            cvCopy( img0, img,0 );
            cvShowImage( "image", img );
        }

        if( (char)c == 'i' || (char)c == '\n' )
        {
            cvNamedWindow( "Mask image", 1 );
            cvShowImage( "Mask image", inpaint_mask );
            cvWaitKey(0);

            cvNamedWindow( "inpainted image", 1 );

            cvrepair( img, inpaint_mask,inpainted);
            //cvInpaint( img, inpaint_mask, inpainted, 3, CV_INPAINT_TELEA );
            cvShowImage( "inpainted image", inpainted );
            cvSaveImage(strOut, inpainted);
        }
    }

    return 1;
}

void cvrepair(IplImage* img,IplImage* mask,IplImage* inpainted)//img破坏图像,mask轨迹母板,masktt2值图像
{   int x=img->height;
    int y=img->width;
    int step=img->widthStep;
    int channels=img->nChannels;
    unsigned char *origin=(uchar *)inpainted->imageData;
    unsigned char *data=(uchar *)img->imageData;
    int i,j,k;
    unsigned char *bill=(uchar *)mask->imageData;


    for(i=0;i<x;i++) 
        for(j=0;j<y;j++) 
        {   for( k=0;k<channels;k++)
                origin[i*step+j*channels+k]=data[i*step+j*channels+k];//原图
        }
    for(i=0;i<x;i++)//边界
    {   for(j=0;j<y;j++)
        {   if(bill[i*step+j*channels]==1)
            {   for(k=0;k<channels;k++)
                {   unsigned char buff=aver(origin,bill,mask,i,j,k,step,channels);
                    origin[i*step+j*channels+k]=buff;//像素点覆
                }
            }
        }
    }
}


unsigned char aver(unsigned char data[],unsigned char bill[],IplImage* masktt,int i,int j,int k,int step,int channels)
{   record re[2];
    scan(data,bill,masktt,re,i,j,k,step,channels);//扫描采样->re
    int len=re[1].down-re[1].up;
    int lon=re[1].right-re[1].left;
    int wh=len/(lon+len);//高宽比
    return biline(re,wh,i,j);//目标还原像素值
}

void scan(uchar data[],uchar bill[],IplImage* masktt,record *re,int i,int j,int k,int step,int channels)//分别扫描出左右上下最短距离赋给t采样
{   int m,p,n,q;
    int h=masktt->height;
    int w=masktt->width;

    for(m=0;m<i;m++)
    {   if(bill[(i-m)*step+j*channels]==0)
        {   if(m!=i)//上边界有像素            完成2个采样,边缘记0
            {   re[1].dataup=data[(i-m)*step+j*channels+k];
                re[1].up=m;//上边界第1个最近
                if((bill[(i-m-1)*step+j*channels]==0)&&((m+1)!=i))
                {   re[2].dataup=data[(i-m-1)*step+j*channels+k];re[2].up=m+1;}//上边界第2个最近
                else{   re[2].dataup=0;re[2].up=i;}
            }
            else//上边界有像素破坏
            {   re[1].up=i;re[1].dataup=0;
                re[2].up=i;re[2].dataup=0;
            }
            printf("find up");break;
        }
    }

    for(p=i;p<h;p++)
    {   if(bill[p*step+j*channels]==0)
        {   if(p!=h)//下边界有像素
            {   re[1].datadown=data[p*step+j*channels+k];//下边界第1个最近
                re[1].down=p;
                if((bill[(p+1)*step+j*channels]==0)&&((p+1)!=h))
                {   re[2].datadown=data[(p+1)*step+j*channels+k];re[2].down=p+1;    }//下边界第2个最近
                else{   re[2].datadown=0;re[2].down=h;}
            }
            else
            {   re[1].down=h;re[1].datadown=0;
                re[2].down=h;re[2].datadown=0;          
            }
        printf("find down");break;
        }
    }

    for(n=0;n<j;n++)
    {   if(bill[i*step+(j-n)*channels]==0)
        {   if(n!=j)//上边界有像素            完成2个采样,边缘记0
            {   re[1].dataleft=data[i*step+(j-n)*channels+k];
                re[1].left=n;//上边界第1个最近
                if((bill[i*step+(j-n-1)*channels]==0)&&((n+1)!=j))
                {   re[2].dataleft=data[i*step+(j-n-1)*channels+k];re[2].left=n+1;}//上边界第2个最近
                else {  re[2].dataleft=0;re[2].left=j;}             
            }
            else//上边界有像素破坏
            {   re[1].left=j;re[1].dataleft=0;
                re[2].left=j;re[2].dataleft=0;
            }
            break;
        }
    }

    for(q=j;q<w;q++)
    {   if(bill[i*step+q*channels]==0)
        {   if(q!=w)//下边界有像素
            {   re[1].dataright=data[i*step+q*channels+k];//下边界第1个最近
                re[1].right=q;
                if((bill[i*step+(q+1)*channels]==0)&&((q+1)!=w))
                {   re[2].dataright=data[i*step+(q+1)*channels+k];re[2].right=q+1;  }//下边界第2个最近
                else{   re[2].dataright=0;re[2].right=w;}               
            }
            else
            {   re[1].right=w;re[1].dataright=0;
                re[2].right=w;re[2].dataright=0;            
            }
            break;
        }
    }
}

unsigned char biline(record *re,int wh,int i,int j)//双线性插值算法
{   double temp=(double)wh*ylag(re,j)+(double)(1-wh)*xlag(re,i);//强制转型
    return (uchar)temp;
}

double ylag(record re[],int j)
{   double x[3],y[3];
    x[0]=re[2].left;y[0]=re[2].dataleft;
    x[1]=re[1].left;y[1]=re[1].dataleft;
    x[2]=re[1].left;y[2]=re[1].dataleft;
    x[3]=re[2].left;y[3]=re[2].dataleft;
    return lagrange(x,y,j,4);
}

double xlag(record re[],int i)
{   double x[3],y[3];
    x[0]=re[2].up;y[0]=re[2].dataup;
    x[1]=re[1].up;y[1]=re[1].dataup;
    x[2]=re[1].down;y[2]=re[1].datadown;
    x[3]=re[2].down;y[3]=re[2].datadown;
    return lagrange(x,y,i,4);
}

double lagrange(double *x,double *y,double xx,int n)     /*拉格朗日插值算法*/
{   int i,j;     
    double *a,yy=0.0;    /*a作为临时变量,记录拉格朗日插值多项式*/
    a=(double *)malloc(n*sizeof(double));
    for(i=0;i<=n-1;i++)
    {   a[i]=y[i];     
        for(j=0;j<=n-1;j++)
            if(j!=i) a[i]*=(xx-x[j])/(x[i]-x[j]);
        yy+=a[i];   
    }
    free(a);
    return yy;
}

然后在调试的时候报错
unhandled exception in tss3.exe:0xC0000005:Access Violation.
停下的位置在scan()函数里的

 for(p=i;p<h;p++)
    {   if(bill[p*step+j*channels]==0)
        {   if(p!=h)//下边界有像素
            {   re[1].datadown=data[p*step+j*channels+k];//下边界第1个最近
                re[1].down=p;
                if((bill[(p+1)*step+j*channels]==0)&&((p+1)!=h))
                {   re[2].datadown=data[(p+1)*step+j*channels+k];re[2].down=p+1;    }//下边界第2个最近
                else{   re[2].datadown=0;re[2].down=h;}
            }
            else
            {   re[1].down=h;re[1].datadown=0;
                re[2].down=h;re[2].datadown=0;          
            }
        printf("find down");break;
        }
    }

的第二次循环
时间比较紧迫所以就不等了

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐