如何在MATLAB中使用mex编译包含.h文件?

时间:2016-01-07 13:48:17

标签: c++ matlab image-processing mex

我正在尝试编译我从网站下载的一段代码。

但是当我使用mex函数进行编译时会出现一些问题 我正在使用mex -I./ -L/lib convolve.cpp (.h和.cpp文件位于同一文件夹中,我当前的文件夹中)

我不知道它是否正确。

但这就是MATLAB所说的

Error using mex
/tmp/mex_100625252862836_11288/convolve.o: In function
`internal_reduce(double*, int, int, double*, double*, int,
int, int, int, int, int, int, int, double*, char*)':
convolve.cpp:(.text+0xa2): undefined reference to
`edge_function(char*)'
/tmp/mex_100625252862836_11288/convolve.o: In function
`internal_expand(double*, double*, double*, int, int, int,
int, int, int, int, int, double*, int, int, char*)':
convolve.cpp:(.text+0xae4): undefined reference to
`edge_function(char*)'
collect2: error: ld returned 1 exit status

这是.h文件

/* 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;  File: convolve.h
;;;  Author: Simoncelli
;;;  Description: Header file for convolve.c
;;;  Creation Date:
;;;  ----------------------------------------------------------------
;;;    Object-Based Vision and Image Understanding System (OBVIUS),
;;;      Copyright 1988, Vision Science Group,  Media Laboratory,  
;;;              Massachusetts Institute of Technology.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
*/

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

#define ABS(x)    (((x)>=0) ? (x) : (-(x)))
#define ROOT2 1.4142135623730951
#define REDUCE 0
#define EXPAND 1
#define IS    ==
#define ISNT  !=
#define AND &&
#define OR ||

typedef  int (*fptr)(register double *,register int ,int ,int ,int ,register double *,int);

typedef struct 
  {
  char *name;
  fptr func;
  } EDGE_HANDLER;

fptr edge_function(char *edges);
int internal_reduce(register double *image,register int x_dim,int y_dim, double *filt, register double *temp,register int x_fdim,int y_fdim,
        int x_start,register int x_step, int x_stop, int y_start,register int y_step,int y_stop,
        register double *result, char *edges);
int internal_expand(register double *image,double *filt,register double *temp,register int x_fdim,int y_fdim,
        int x_start,register int x_step,int x_stop,int y_start,register int y_step,int y_stop,
        register double *result,register int x_dim,int y_dim,char *edges);
int internal_wrap_reduce(double *image,register int x_dim,register int y_dim, register double *filt,register int x_fdim,register int y_fdim,
             int x_start,int x_step,int x_stop,int y_start,int y_step,int y_stop, 
             register double *result);
int internal_wrap_expand(double *image, register double *filt,register int x_fdim,register int y_fdim,
          int x_start,int  x_step,int  x_stop,int  y_start,int  y_step,int  y_stop,
          register double *result,register int x_dim,register int y_dim);

这是.cpp文件

/* 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;  File: convolve.c
;;;  Author: Eero Simoncelli
;;;  Description: General convolution code for 2D images
;;;  Creation Date: Spring, 1987.
;;;  MODIFICATIONS:
;;;     10/89: approximately optimized the choice of register vars on SPARCS.
;;;      6/96: Switched array types to double float.
;;;      2/97: made more robust and readable.  Added STOP arguments.
;;;      8/97: Bug: when calling internal_reduce with edges in {reflect1,repeat,
;;;            extend} and an even filter dimension.  Solution: embed the filter
;;;            in the upper-left corner of a filter with odd Y and X dimensions.
;;;  ----------------------------------------------------------------
;;;    Object-Based Vision and Image Understanding System (OBVIUS),
;;;      Copyright 1988, Vision Science Group,  Media Laboratory,  
;;;              Massachusetts Institute of Technology.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
*/

#include <stdio.h>
#include <math.h>
#include "convolve.h"

/*
  --------------------------------------------------------------------
  Correlate FILT with IMAGE, subsampling according to START, STEP, and
  STOP parameters, with values placed into RESULT array.  RESULT
  dimensions should be ceil((stop-start)/step).  TEMP should be a
  pointer to a temporary double array the size of the filter.
  EDGES is a string specifying how to handle boundaries -- see edges.c.
  The convolution is done in 9 sections, where the border sections use
  specially computed edge-handling filters (see edges.c). The origin 
  of the filter is assumed to be (floor(x_fdim/2), floor(y_fdim/2)).
------------------------------------------------------------------------ */

/* abstract out the inner product computation */
#define INPROD(XCNR,YCNR)  \
        { \
    sum=0.0; \
    for (im_pos=YCNR*x_dim+XCNR, filt_pos=0, x_filt_stop=x_fdim; \
         x_filt_stop<=filt_size; \
         im_pos+=(x_dim-x_fdim), x_filt_stop+=x_fdim) \
        for (; \
         filt_pos<x_filt_stop; \
         filt_pos++, im_pos++) \
          sum+= image[im_pos]*temp[filt_pos]; \
        result[res_pos] = sum; \
    }

int internal_reduce(register double *image,register int x_dim,int y_dim, double *filt, register double *temp,register int x_fdim,int y_fdim,
        int x_start,register int x_step, int x_stop, int y_start,register int y_step,int y_stop,
        register double *result, char *edges)
  /*register double *image, *temp;
  register int x_fdim, x_dim;
  register double *result;
  register int x_step, y_step;
  int x_start, y_start;
  int x_stop, y_stop;     
  double *filt; 
  int y_dim, y_fdim;
  char *edges;*/
  { 
  register double sum;
  register int filt_pos, im_pos, x_filt_stop;
  register int x_pos, filt_size = x_fdim*y_fdim;
  register int y_pos, res_pos;
  register int y_ctr_stop = y_dim - ((y_fdim==1)?0:y_fdim);
  register int x_ctr_stop = x_dim - ((x_fdim==1)?0:x_fdim);
  register int x_res_dim = (x_stop-x_start+x_step-1)/x_step;
  int x_ctr_start = ((x_fdim==1)?0:1);
  int y_ctr_start = ((y_fdim==1)?0:1);
  int x_fmid = x_fdim/2;
  int y_fmid = y_fdim/2;
  int base_res_pos;
  fptr reflect = edge_function(edges);  /* look up edge-handling function */

  if (!reflect) return(-1);

  /* shift start/stop coords to filter upper left hand corner */
  x_start -= x_fmid;   y_start -=  y_fmid;
  x_stop -=  x_fmid;   y_stop -=  y_fmid;

  if (x_stop < x_ctr_stop) x_ctr_stop = x_stop;
  if (y_stop < y_ctr_stop) y_ctr_stop = y_stop;

  for (res_pos=0, y_pos=y_start;          /* TOP ROWS */
       y_pos<y_ctr_start;
       y_pos+=y_step)
    {
    for (x_pos=x_start;               /* TOP-LEFT CORNER */
     x_pos<x_ctr_start;
     x_pos+=x_step, res_pos++)
      {
      (*reflect)(filt,x_fdim,y_fdim,x_pos-1,y_pos-1,temp,REDUCE);
      INPROD(0,0)
      }

    (*reflect)(filt,x_fdim,y_fdim,0,y_pos-1,temp,REDUCE);
    for (;                    /* TOP EDGE */
     x_pos<x_ctr_stop;
     x_pos+=x_step, res_pos++) 
      INPROD(x_pos,0)

    for (;                    /* TOP-RIGHT CORNER */
     x_pos<x_stop;
     x_pos+=x_step, res_pos++) 
      {
      (*reflect)(filt,x_fdim,y_fdim,x_pos-x_ctr_stop+1,y_pos-1,temp,REDUCE);
      INPROD(x_ctr_stop,0)
      }
    } /* end TOP ROWS */   

  y_ctr_start = y_pos;                /* hold location of top */
  for (base_res_pos=res_pos, x_pos=x_start;   /* LEFT EDGE */
       x_pos<x_ctr_start;
       x_pos+=x_step, base_res_pos++)
    {
    (*reflect)(filt,x_fdim,y_fdim,x_pos-1,0,temp,REDUCE);
    for (y_pos=y_ctr_start, res_pos=base_res_pos;
     y_pos<y_ctr_stop;
     y_pos+=y_step, res_pos+=x_res_dim)
      INPROD(0,y_pos)
    }

  (*reflect)(filt,x_fdim,y_fdim,0,0,temp,REDUCE);
  for (;                      /* CENTER */
       x_pos<x_ctr_stop;
       x_pos+=x_step, base_res_pos++) 
    for (y_pos=y_ctr_start, res_pos=base_res_pos;
     y_pos<y_ctr_stop;
     y_pos+=y_step, res_pos+=x_res_dim)
      INPROD(x_pos,y_pos)

  for (;                      /* RIGHT EDGE */
       x_pos<x_stop;
       x_pos+=x_step, base_res_pos++)
    {
    (*reflect)(filt,x_fdim,y_fdim,x_pos-x_ctr_stop+1,0,temp,REDUCE);
    for (y_pos=y_ctr_start, res_pos=base_res_pos;
     y_pos<y_ctr_stop;
     y_pos+=y_step, res_pos+=x_res_dim)
      INPROD(x_ctr_stop,y_pos)
    }

  for (res_pos-=(x_res_dim-1);
       y_pos<y_stop;                  /* BOTTOM ROWS */
       y_pos+=y_step) 
    {
    for (x_pos=x_start;               /* BOTTOM-LEFT CORNER */
     x_pos<x_ctr_start;
     x_pos+=x_step, res_pos++)
      {
      (*reflect)(filt,x_fdim,y_fdim,x_pos-1,y_pos-y_ctr_stop+1,temp,REDUCE);
      INPROD(0,y_ctr_stop)
      }

    (*reflect)(filt,x_fdim,y_fdim,0,y_pos-y_ctr_stop+1,temp,REDUCE);
    for (;                    /* BOTTOM EDGE */
     x_pos<x_ctr_stop;
     x_pos+=x_step, res_pos++) 
      INPROD(x_pos,y_ctr_stop)

    for (;                    /* BOTTOM-RIGHT CORNER */
     x_pos<x_stop;
     x_pos+=x_step, res_pos++) 
      {
      (*reflect)(filt,x_fdim,y_fdim,x_pos-x_ctr_stop+1,y_pos-y_ctr_stop+1,temp,REDUCE);
      INPROD(x_ctr_stop,y_ctr_stop)
      }
    } /* end BOTTOM */
  return(0);
  } /* end of internal_reduce */


/*
  --------------------------------------------------------------------
  Upsample IMAGE according to START,STEP, and STOP parameters and then
  convolve with FILT, adding values into RESULT array.  IMAGE
  dimensions should be ceil((stop-start)/step).  See
  description of internal_reduce (above).

  WARNING: this subroutine destructively modifies the RESULT array!
 ------------------------------------------------------------------------ */

/* abstract out the inner product computation */
#define INPROD2(XCNR,YCNR)  \
        { \
        val = image[im_pos]; \
    for (res_pos=YCNR*x_dim+XCNR, filt_pos=0, x_filt_stop=x_fdim; \
         x_filt_stop<=filt_size; \
         res_pos+=(x_dim-x_fdim), x_filt_stop+=x_fdim) \
        for (; \
         filt_pos<x_filt_stop; \
         filt_pos++, res_pos++) \
          result[res_pos] += val*temp[filt_pos]; \
    }

int internal_expand(register double *image,double *filt,register double *temp,register int x_fdim,int y_fdim,
        int x_start,register int x_step,int x_stop,int y_start,register int y_step,int y_stop,
        register double *result,register int x_dim,int y_dim,char *edges)
  /*register double *result, *temp;
  register int x_fdim, x_dim;
  register int x_step, y_step;
  register double *image; 
  int x_start, y_start;
  double *filt; 
  int y_fdim, y_dim;
  char *edges;*/
  {
  register double val;
  register int filt_pos, res_pos, x_filt_stop;
  register int x_pos, filt_size = x_fdim*y_fdim;
  register int y_pos, im_pos;
  register int x_ctr_stop = x_dim - ((x_fdim==1)?0:x_fdim);
  int y_ctr_stop = (y_dim - ((y_fdim==1)?0:y_fdim));
  int x_ctr_start = ((x_fdim==1)?0:1);
  int y_ctr_start = ((y_fdim==1)?0:1);
  int x_fmid = x_fdim/2;
  int y_fmid = y_fdim/2;
  int base_im_pos, x_im_dim = (x_stop-x_start+x_step-1)/x_step;
  fptr reflect = edge_function(edges);  /* look up edge-handling function */     

  if (!reflect) return(-1);

  /* shift start/stop coords to filter upper left hand corner */
  x_start -= x_fmid;   y_start -=  y_fmid;
  x_stop -=  x_fmid;   y_stop -=  y_fmid;

  if (x_stop < x_ctr_stop) x_ctr_stop = x_stop;
  if (y_stop < y_ctr_stop) y_ctr_stop = y_stop;

  for (im_pos=0, y_pos=y_start;           /* TOP ROWS */
       y_pos<y_ctr_start;
       y_pos+=y_step)
    {
    for (x_pos=x_start;               /* TOP-LEFT CORNER */
     x_pos<x_ctr_start;
     x_pos+=x_step, im_pos++)
      {
      (*reflect)(filt,x_fdim,y_fdim,x_pos-1,y_pos-1,temp,EXPAND);
      INPROD2(0,0)
      }

    (*reflect)(filt,x_fdim,y_fdim,0,y_pos-1,temp,EXPAND);
    for (;                    /* TOP EDGE */
     x_pos<x_ctr_stop;
     x_pos+=x_step, im_pos++) 
      INPROD2(x_pos,0)

    for (;                    /* TOP-RIGHT CORNER */
     x_pos<x_stop;
     x_pos+=x_step, im_pos++) 
      {
      (*reflect)(filt,x_fdim,y_fdim,x_pos-x_ctr_stop+1,y_pos-1,temp,EXPAND);
      INPROD2(x_ctr_stop,0)
      }
    }                                           /* end TOP ROWS */   

  y_ctr_start = y_pos;                /* hold location of top */
  for (base_im_pos=im_pos, x_pos=x_start;     /* LEFT EDGE */
       x_pos<x_ctr_start;
       x_pos+=x_step, base_im_pos++)
    {
    (*reflect)(filt,x_fdim,y_fdim,x_pos-1,0,temp,EXPAND);
    for (y_pos=y_ctr_start, im_pos=base_im_pos;
     y_pos<y_ctr_stop;
     y_pos+=y_step, im_pos+=x_im_dim)
      INPROD2(0,y_pos)
    }

  (*reflect)(filt,x_fdim,y_fdim,0,0,temp,EXPAND);
  for (;                      /* CENTER */
       x_pos<x_ctr_stop;
       x_pos+=x_step, base_im_pos++) 
    for (y_pos=y_ctr_start, im_pos=base_im_pos;
     y_pos<y_ctr_stop;
     y_pos+=y_step, im_pos+=x_im_dim)
      INPROD2(x_pos,y_pos)

  for (;                      /* RIGHT EDGE */
       x_pos<x_stop;
       x_pos+=x_step, base_im_pos++)
    {
    (*reflect)(filt,x_fdim,y_fdim,x_pos-x_ctr_stop+1,0,temp,EXPAND);
    for (y_pos=y_ctr_start, im_pos=base_im_pos;
     y_pos<y_ctr_stop;
     y_pos+=y_step, im_pos+=x_im_dim)
      INPROD2(x_ctr_stop,y_pos)
    }  

  for (im_pos-=(x_im_dim-1);
       y_pos<y_stop;                  /* BOTTOM ROWS */
       y_pos+=y_step) 
    {
    for (x_pos=x_start;               /* BOTTOM-LEFT CORNER */
     x_pos<x_ctr_start;
     x_pos+=x_step, im_pos++)
      {
      (*reflect)(filt,x_fdim,y_fdim,x_pos-1,y_pos-y_ctr_stop+1,temp,EXPAND);
      INPROD2(0,y_ctr_stop)
      }

    (*reflect)(filt,x_fdim,y_fdim,0,y_pos-y_ctr_stop+1,temp,EXPAND);
    for (;                    /* BOTTOM EDGE */
     x_pos<x_ctr_stop;
     x_pos+=x_step, im_pos++) 
      INPROD2(x_pos,y_ctr_stop)

    for (;                    /* BOTTOM-RIGHT CORNER */
     x_pos<x_stop;
     x_pos+=x_step, im_pos++) 
      {
      (*reflect)(filt,x_fdim,y_fdim,x_pos-x_ctr_stop+1,y_pos-y_ctr_stop+1,temp,EXPAND);
      INPROD2(x_ctr_stop,y_ctr_stop)
      }
    } /* end BOTTOM */
  return(0);
  } /* end of internal_expand */


/* Local Variables: */
/* buffer-read-only: t */
/* End: */

非常感谢有人能帮助我。

(我使用g ++进行c ++语言编译)

Ubuntu14.04,MATLAB 2015a 这是&#39; edges.cpp&#39;文件所在&#39; edge_function&#39;实施。

 /* 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;  File: edges.c
;;;  Author: Eero Simoncelli
;;;  Description: Boundary handling routines for use with convolve.c
;;;  Creation Date: Spring 1987.
;;;  MODIFIED, 6/96, to operate on double float arrays.
;;;  MODIFIED by dgp, 4/1/97, to support THINK C.
;;;  MODIFIED, 8/97: reflect1, reflect2, repeat, extend upgraded to 
;;;       work properly for non-symmetric filters.  Added qreflect2 to handle
;;;       even-length QMF's which broke under the reflect2 modification.
;;;  ----------------------------------------------------------------
;;;    Object-Based Vision and Image Understanding System (OBVIUS),
;;;      Copyright 1988, Vision Science Group,  Media Laboratory,  
;;;              Massachusetts Institute of Technology.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
*/

/* This file contains functions which determine how edges are to be
handled when performing convolutions of images with linear filters.
Any edge handling function which is local and linear may be defined,
except (unfortunately) constants cannot be added.  So to treat the
edges as if the image is surrounded by a gray field, you must paste it
into a gray image, convolve, and crop it out...  The main convolution
functions are called internal_reduce and internal_expand and are
defined in the file convolve.c.  The idea is that the convolution
function calls the edge handling function which computes a new filter
based on the old filter and the distance to the edge of the image.
For example, reflection is done by reflecting the filter through the
appropriate axis and summing.  Currently defined functions are listed
below.
*/


#include <stdio.h>
#include <math.h>
#include <string.h>
#include "convolve.h"

#define sgn(a)  ( ((a)>0)?1:(((a)<0)?-1:0) )
#define clip(a,mn,mx)  ( ((a)<(mn))?(mn):(((a)>=(mx))?(mx-1):(a)) )


int nocompute(register double *filt,register int x_dim,int y_dim,int x_pos,int y_pos,register double *result,int r_or_e);
int reflect1(register double *filt,register int x_dim,int y_dim,int x_pos,int y_pos,register double *result,int r_or_e);
int reflect2(register double *filt,register int x_dim,int y_dim,int x_pos,int y_pos,register double *result,int r_or_e);
int repeat(register double *filt,register int x_dim,int y_dim,int x_pos,int y_pos,register double *result,int r_or_e);
int zero(register double *filt,register int x_dim,int y_dim,int x_pos,int y_pos,register double *result,int r_or_e);
int Extend(register double *filt,register int x_dim,int y_dim,int x_pos,int y_pos,register double *result,int r_or_e);
int ereflect(register double *filt,register int x_dim,int y_dim,int x_pos,int y_pos,register double *result,int r_or_e);
int predict(register double *filt,register int x_dim,int y_dim,int x_pos,int y_pos,register double *result,int r_or_e);
int qreflect2(double *filt,int x_dim,int y_dim,int x_pos,int y_pos,double *result,int r_or_e);


/* Lookup table matching a descriptive string to the edge-handling function */
#if !THINK_C
    static EDGE_HANDLER edge_foos[] =
      {
        { "dont-compute", nocompute }, /* zero output for filter touching edge */
        { "zero",     zero     },   /* zero outside of image */
        { "repeat",   repeat   },   /* repeat edge pixel */
        { "reflect1", reflect1 },   /* reflect about edge pixels  */
        { "reflect2", reflect2 },   /* reflect image, including edge pixels  */
        { "qreflect2", qreflect2 },   /* reflect image, including edge pixels
                         for even-length QMF decompositions */
        { "extend",   Extend   },   /* extend (reflect & invert) */
        { "ereflect", ereflect },   /* orthogonal QMF reflection */
      };
#else
    /*
    This is really stupid, but THINK C won't allow initialization of static variables in
    a code resource with string addresses. So we do it this way.
    The 68K code for a MATLAB 4 MEX file can only be created by THINK C.
    However, for MATLAB 5, we'll be able to use Metrowerks CodeWarrior for both 68K and PPC, so this
    cludge can be dropped when we drop support for MATLAB 4.
    Denis Pelli, 4/1/97. 
    */
    static EDGE_HANDLER edge_foos[8];

    void InitializeTable(EDGE_HANDLER edge_foos[])
    {
        static int i=0;

        if(i>0) return;
        edge_foos[i].name="dont-compute";
        edge_foos[i++].func=nocompute;
        edge_foos[i].name="zero";
        edge_foos[i++].func=zero;
        edge_foos[i].name="repeat";
        edge_foos[i++].func=repeat;
        edge_foos[i].name="reflect1";
        edge_foos[i++].func=reflect1;
        edge_foos[i].name="reflect2";
        edge_foos[i++].func=reflect2;
        edge_foos[i].name="qreflect2";
        edge_foos[i++].func=qreflect2;
        edge_foos[i].name="extend";
        edge_foos[i++].func=Extend;
        edge_foos[i].name="ereflect";
        edge_foos[i++].func=ereflect;
    }
#endif

/*
Function looks up an edge handler id string in the structure above, and
returns the associated function 
*/
fptr edge_function(char *edges)
  {
  int i;

#if THINK_C
  InitializeTable(edge_foos);
#endif
  for (i = 0; i<sizeof(edge_foos)/sizeof(EDGE_HANDLER); i++)
    if (strcmp(edges,edge_foos[i].name) IS 0)
      return(edge_foos[i].func);
  printf("Error: '%s' is not the name of a valid edge-handler!\n",edges);
  for (i=0; i<sizeof(edge_foos)/sizeof(EDGE_HANDLER); i++)
      {
      if (i IS 0) printf("  Options are: ");
      else printf(", ");
      printf("%s",edge_foos[i].name);
      }
  printf("\n");
  return(0);
  }

1 个答案:

答案 0 :(得分:2)

您缺少一个函数定义(实际是edge_function),它既可以是外部库的一部分,也可以在单独的 .cpp / .c文件中定义。