ordfilt2.c
来自「有关matlab的电子书籍有一定的帮助希望有用」· C语言 代码 · 共 680 行 · 第 1/2 页
C
680 行
/* Copyright 1993-1998 The MathWorks, Inc. All Rights Reserved. */
/* $Revision: 5.13 $ $Date: 1997/11/24 16:14:43 $ $Author: eddins $ */
static char rcsid[] = "$Id: ordfilt2.c,v 5.13 1997/11/24 16:14:43 eddins Exp $";
/*
ordfilt2.c .MEX file
Implements 2-D order-statistic filtering with
arbitrary domain and optional additive offsets.
Y = ORDFILT2(X, ORDER, DOMAIN) replaces each
element in X by the ORDER-th element in the sorted set
of neighbors specified by the nonzero elements
in DOMAIN.
For example, Y=ORDFILT2(X,5,ones(3,3)) implements
a 3-by-3 median filter.
Y=ORDFILT2(X,1,[0 1 0; 1 0 1; 0 1 0]) replaces each
element in X by the minimum of its north, east, south,
and west neighbors.
Y = ORDFILT2(X,ORDER,DOMAIN,S), where S must be the
same size as DOMAIN, uses the values of S corresponding
to the nonzero values of DOMAIN as additive offsets.
X must be a real, double or uint8, 2-D, numeric array.
Steven L. Eddins 12-8-94
Revised March 1996
*/
#include <math.h>
#include "mex.h"
double **Make2SubscriptMatrix(double *array, int rowDim, int colDim) {
double **matrix;
int i;
matrix = (double **) mxCalloc(colDim, sizeof(double *));
for (i = 0; i < colDim; i++) {
matrix[i] = array + i*rowDim;
}
return(matrix);
}
uint8_T **Make2SubscriptMatrix8(uint8_T *array, int rowDim, int colDim) {
uint8_T **matrix;
int i;
matrix = (uint8_T **) mxCalloc(colDim, sizeof(uint8_T *));
for (i = 0; i < colDim; i++) {
matrix[i] = array + i*rowDim;
}
return(matrix);
}
mxArray *ConvertToDouble(const mxArray *A)
{
int nrhs = 1;
int nlhs = 1;
mxArray *prhs[1];
mxArray *plhs[1];
mxArray *result;
int errorFlag;
if (A == NULL)
{
mexErrMsgTxt("NULL array passed to ConvertToDouble()");
}
prhs[0] = (mxArray *) A;
errorFlag = mexCallMATLAB(nlhs, plhs, nrhs, prhs, "double");
if (errorFlag == 0) {
/* Successful operation */
result = plhs[0];
} else {
/* double conversion failed */
/* We should never get here; error should have long-jumped */
/* back to the command prompt */
mexErrMsgTxt("Conversion to double failed");
}
return(result);
}
/*
* input array must be double
*/
int NumNonzeros(const mxArray *A) {
int result = 0;
int lengthA;
int i;
double *pr;
double *pi;
if (A == NULL)
{
mexErrMsgTxt("NULL array passed to NumNonzeros()");
}
if (! mxIsDouble(A))
{
mexErrMsgTxt("Nondouble array passed to NumNonzeros()");
}
lengthA = mxGetNumberOfElements(A);
if (mxIsComplex(A)) {
pr = mxGetPr(A);
pi = mxGetPi(A);
for (i = 0; i < lengthA; i++) {
if ((*pr != 0.0) || (*pi != 0.0)) {
result++;
}
pr++;
pi++;
}
} else {
pr = mxGetPr(A);
for (i = 0; i < lengthA; i++) {
if (*pr != 0.0) {
result++;
}
pr++;
}
}
return(result);
}
/* Selection algorithm using QuickSort-style partitioning. */
/* Based on discussion in Sedgewick, Algorithms, 2d ed, 1988, pp. 115-130 */
/* This function modifies the values in a[]. */
static double order_select(double *a, int N, int order)
{
int i;
int j;
int left;
int right;
int mid;
double key;
double tmp;
mxAssert(order >= 1, "");
mxAssert(order <= N, "");
/* Compensate for the fact that the input array is zero-based, */
/* while order is one-based. */
order--;
/* The initial partition is the entire array. */
left = 0;
right = N - 1;
/* Perform the scanning only if the current partition has at least */
/* three elements. */
while (right > (left+1))
{
/* Use median-of-three method to select the partitioning key. */
/* This method makes worst-case behavior much less likely and */
/* avoids the needs for sentinel values outside the array. */
/* First we sort the first, middle, and last element of the */
/* partition. */
mid = (left + right) >> 1;
if (a[left] > a[mid])
{
tmp = a[left];
a[left] = a[mid];
a[mid] = tmp;
}
if (a[left] > a[right])
{
tmp = a[left];
a[left] = a[right];
a[right] = tmp;
}
if (a[mid] > a[right])
{
tmp = a[mid];
a[mid] = a[right];
a[right] = tmp;
}
/* Now swap the middle value with the next-to-last value. */
tmp = a[mid];
a[mid] = a[right - 1];
a[right - 1] = tmp;
/* Use the median of the three values as the partitioning key */
key = a[right - 1];
/* Start the partitioning scan. Note that because we sorted */
/* the left and right values, we can start the comparisons */
/* with (left+1) and (right-2). This is how we avoid the */
/* need for sentinel values. */
i = left;
j = right - 1;
for (;;)
{
while (a[++i] < key) ; mxAssert(i <= (N-1), "");
while (a[--j] > key) ; mxAssert(j >= 0, "");
if (i >= j) break; /* pointers crossed; end scan */
/* swap values at end of current interval */
tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
/* One last swap needed at end of scan */
tmp = a[i];
a[i] = a[right-1];
a[right-1] = tmp;
/* Select the left or right subpartition depending on */
/* the value of order. */
if (i >= order) right = i-1;
if (i <= order) left = i+1;
}
if ((right - left) == 1)
{
/* Last partition has two elements that may not be sorted. */
if (a[left] > a[right])
{
tmp = a[left];
a[left] = a[right];
a[right] = tmp;
}
}
return(a[order]);
}
static void
ValidateInputs(int nlhs, int nrhs, const mxArray *prhs[], const mxArray **X,
const mxArray **Order, const mxArray **Domain,
const mxArray **S)
{
int i;
/* The number of input arguments must be between 3 and 4 */
if (nrhs < 3) {
mexErrMsgTxt("Three input arguments are required");
}
if (nrhs > 4) {
mexErrMsgTxt("Too many input arguments");
}
/* ORDFILT2 has only one output argument */
if (nlhs > 1) {
mexErrMsgTxt("Too many output arguments");
}
/* All inputs must be numeric */
for (i = 0; i < nrhs; i++) {
if (!mxIsNumeric(prhs[i])) {
mexErrMsgTxt("Inputs must be numeric");
}
}
/* All inputs must be real */
for (i = 0; i < nrhs; i++) {
if (mxIsComplex(prhs[i])) {
mexErrMsgTxt("Inputs must be real");
}
}
/* First input must be double or uint8 */
if (!mxIsDouble(prhs[0]) && !mxIsUint8(prhs[0])) {
mexErrMsgTxt("X must be 'double' or 'uint8' class");
}
*X = prhs[0];
*Order = prhs[1];
*Domain = prhs[2];
if (nrhs == 4) {
*S = prhs[3];
} else {
*S = NULL;
}
/* Validate domain */
if (mxIsEmpty(*Domain)) {
mexErrMsgTxt("Domain cannot be empty");
}
}
int GetOrder(const mxArray *Order, int domainSize)
{
int result;
double tmp;
/* Validate Order */
if ((mxGetM(Order) * mxGetN(Order)) > 1) {
mexWarnMsgTxt("ORDER should be a scalar");
}
tmp = mxGetScalar(Order);
result = (int) tmp;
if ((double) result != tmp) {
mexWarnMsgTxt("ORDER should be an integer");
}
if (result < 1) {
mexErrMsgTxt("Order must be at least 1");
}
if (result > domainSize) {
mexErrMsgTxt("ORDER must no bigger than the number "
"of nonzero domain elements");
}
return(result);
}
double **MakeZeroPaddedInput(double **xx, int mx, int nx, int md, int nd) {
double **aa;
int maa;
int naa;
int rowOrigin;
int colOrigin;
int row;
int col;
maa = mx + md - 1;
naa = nx + nd - 1;
rowOrigin = (md - 1) / 2;
colOrigin = (nd - 1) / 2;
aa = Make2SubscriptMatrix((double *) mxCalloc(maa*naa, sizeof(double)),
maa, naa);
for (col = 0; col < nx; col++) {
for (row = 0; row < mx; row++) {
aa[col+colOrigin][row+rowOrigin] = xx[col][row];
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?