今天给大家分享我最近写的几行代码,用C语言实现的1*3、3*1以及3*3最大值滤波....
首先,什么是最大值滤波?
做图像研究的人都知道,常用的一个平滑操作是中值滤波,比如3*3中值滤波就是用当前位置的3*3领域内9个像素值的中间大小的值来替代当前位置像素值。 同理,3*3最大值滤波就是用当前位置3*3领域内9个像素值的最大的值来替代当前位置像素值。
其次,我为什么要写这个代码?
实不相瞒,鄙人常用openCV,但是我发现CV里面只提供了中值滤波,没有提供最大值滤波(matlab里面倒是有个ordfilt2函数提供了该功能),因为要用,就写了这么个函数。
以前我写过一些代码放到资源里去给人下载,别人用的时候提了很多意见,我又懒得改了再传,所以这次直接贴到博客,大家给点意见,我觉得合理就直接改了。下面开始贴代码。
<hr/>
// 第一段代码:第一种版本的1*3最大值滤波
#include <stdio.h>
#ifndef MAX
#define MAX(a,b) (a>b?a:b)
#endif
/*
1*3 maximum filter;
B(i,j) is set to local maximum of A(i,j) neighborhood;
suppose: A's size is rows*cols, A(i,j) (i<rows,j<cols) is indexed by A[i*witdhstepA+j],
i.e. A's element is arranged in memory like: the first row, the second row, ... so on. B is alike. widthstep should be no smaller than cols.
(the memory arrangement actually accords with that in openCV)
by: Yu Xianguo, NUDT, 2014/6/19
*/
template<typename T>
void _rowMaxFilter( const T *A, int rows, int cols, T *B, int witdhstepA, int widthstepB )
{
int i = 0, j = 0;
const T *Apt = A;
T *Bpt = B;
// copy A into B
while( i++<rows ){
j = 0;
while( j++<cols )
*(Bpt++) = *(Apt++);
Apt += witdhstepA - cols;
Bpt += widthstepB - cols;
}
// apply row-max to each row
Apt = A, Bpt = B;
for( i=0; i<rows; i++ ){
if( Apt[0]>Apt[1] )
Bpt[1] = Apt[0];
else
Bpt[0] = Apt[1];
for( j=2; j<cols; j++ )
if( Apt[j-1]>Apt[j] )
Bpt[j] = Apt[j-1];
else
Bpt[j-1] = MAX( Apt[j-2], Apt[j] );
Apt += witdhstepA;
Bpt += widthstepB;
}
}
void rowMaxFilter( const int *A, int rows, int cols, int *B, int widthstepA, int witdhstepB)
{
_rowMaxFilter(A,rows,cols,B,widthstepA,witdhstepB);
}
void rowMaxFilter( const float *A, int rows, int cols, float *B, int widthstepA, int witdhstepB)
{
_rowMaxFilter(A,rows,cols,B,widthstepA,witdhstepB);
}
void rowMaxFilter( const double *A, int rows, int cols, double *B, int widthstepA, int witdhstepB)
{
_rowMaxFilter(A,rows,cols,B,widthstepA,witdhstepB);
}
/* >>>TEST<<<
int main()
{
// use matlab to generate a random array: A = rand(5,6)
float A[5*6] = { 1.0347, 0.8884, 1.4384, -0.1022, -0.0301, -0.8637, 0.7269, -1.1471, 0.3252, -0.2414, -0.1649, 0.0774, -0.3034, -1.0689, -0.7549, 0.3192, 0.6277, -1.2141, 0.2939, -0.8095, 1.3703, 0.3129, 1.0933, -1.1135, -0.7873, -2.9443, -1.7115, -0.8649, 1.1093, -0.0068 };
float B[30];
rowMaxFilter( A, 5, 6, B, 6, 6 );
for( int i=0; i<5; i++ ){
for( int j=0; j<6; j++ )
printf("%g\t",B[i*6+j]);
printf("\n");
}
// true result is:
//1.0347 1.4384 1.4384 1.4384 -0.0301 -0.0301
//0.7269 0.7269 0.3252 0.3252 0.0774 0.0774
//-0.3034 -0.3034 0.3192 0.6277 0.6277 0.6277
//0.2939 1.3703 1.3703 1.3703 1.0933 1.0933
//-0.7873 -0.7873 -0.8649 1.1093 1.1093 1.1093
return 0;
}
*/
//===================corresponding matlab code========================================
/*
function B = colMaxFilter(A)
%% 3*1 maximum filter
%% B(i,j) is set to local maximum of A(i,j) neighborhood
B = A;
[M,N] = size(A);
for i=1:N
% apply col-max to each col
if A(1,i)>A(2,i)
B(2,i) = A(1,i);
else
B(1,i) = A(2,i);
end
for j=3:M
if A(j-1,i)>A(j,i)
B(j,i) = A(j-1,i);
else
B(j-1,i) = max(A(j-2,i),A(j,i));
end
end
end
%% TEST
% A = rand(50,60);
% B1 = ordfilt2(A,3,[1;1;1]);
% B2 = colMaxFilter(A);
% C = B1 - B2;
% max(abs(C(:))) % should be ZERO
*/
<hr/>
// 第二段代码:第二种版本的1*3滤波
#include <stdio.h>
/*
1*3 maximum filter;
if A(i,j) is local maximum, then B(i,j)=A(i,j); else B(i,j)=0
suppose: A's size is rows*cols, A(i,j) (i<rows,j<cols) is indexed by A[i*witdhstepA+j],
i.e. A's element is arranged in memory like: the first row, the second row, ... so on. B is alike. widthstep should be no smaller than cols.
(the memory arrangement actually accords with that in openCV)
by: Yu Xianguo, NUDT, 2014/6/19
*/
template<typename T>
void _rowMaxFilter2( const T *A, int rows, int cols, T *B, int witdhstepA, int widthstepB )
{
int i = 0, j = 0;
const T *Apt = A;
T *Bpt = B;
// copy A into B
while( i++<rows ){
j = 0;
while( j++<cols )
*(Bpt++) = *(Apt++);
Apt += witdhstepA - cols;
Bpt += widthstepB - cols;
}
// apply row-max to each row
Apt = A, Bpt = B;
for( i=0; i<rows; i++ ){
for( j=1; j<cols; j++ )
if( Apt[j-1]>Apt[j] )
Bpt[j] = 0;
else
Bpt[j-1] = 0;
Apt += witdhstepA;
Bpt += widthstepB;
}
}
void rowMaxFilter2( const int *A, int rows, int cols, int *B, int widthstepA, int witdhstepB)
{
_rowMaxFilter2(A,rows,cols,B,widthstepA,witdhstepB);
}
void rowMaxFilter2( const float *A, int rows, int cols, float *B, int widthstepA, int witdhstepB)
{
_rowMaxFilter2(A,rows,cols,B,widthstepA,witdhstepB);
}
void rowMaxFilter2( const double *A, int rows, int cols, double *B, int widthstepA, int witdhstepB)
{
_rowMaxFilter2(A,rows,cols,B,widthstepA,witdhstepB);
}
/* >>>TEST<<<
int main()
{
// use matlab to generate a random array: A = rand(5,6)
float A[5*6] = { 1.0347, 0.8884, 1.4384, -0.1022, -0.0301, -0.8637, 0.7269, -1.1471, 0.3252, -0.2414, -0.1649, 0.0774, -0.3034, -1.0689, -0.7549, 0.3192, 0.6277, -1.2141, 0.2939, -0.8095, 1.3703, 0.3129, 1.0933, -1.1135, -0.7873, -2.9443, -1.7115, -0.8649, 1.1093, -0.0068 };
float B[30];
rowMaxFilter2( A, 5, 6, B, 6, 6 );
for( int i=0; i<5; i++ ){
for( int j=0; j<6; j++ )
printf("%g\t",B[i*6+j]);
printf("\n");
}
// true result is:
//1.0347 0 1.4384 0 -0.0301 0
//0.7269 0 0.3252 0 0 0.0774
//-0.3034 0 0 0 0.6277 0
//0.2939 0 1.3703 0 1.0933 0
//-0.7873 0 0 0 1.1093 0
return 0;
}
*/
//===================corresponding matlab code========================================
/*
function B = rowMaxFilter2(A)
%% 1*3 maximum filter
%% if A(i,j) is local maximum, then B(i,j)=A(i,j); else B(i,j)=0
B = A;
[M,N] = size(A);
for i=1:M
% apply row-max to each row
for j=2:N
if A(i,j-1)>A(i,j)
B(i,j) = 0;
else
B(i,j-1) = 0;
end
end
end
%% TEST
% A = rand(30,40);
% B1 = ordfilt2(A,3,[1 1 1]);
% B1(B1~=A) = 0;
% B2 = rowMaxFilter2(A);
% B1-B2 % should be all zero
*/
<hr/>
// 第三段代码:第一种版本的3*1滤波
#include <math.h>
#ifndef MAX
#define MAX(a,b) (a>b?a:b)
#endif
/*
3*1 maximum filter;
B(i,j) is set to local maximum of A(i,j) neighborhood;
suppose: A's size is rows*cols, A(i,j) (i<rows,j<cols) is indexed by A[i*witdhstepA+j],
i.e. A's element is arranged in memory like: the first row, the second row, ... so on. B is alike. widthstep should be no smaller than cols.
(the memory arrangement actually accords with that in openCV)
by: Yu Xianguo, NUDT, 2014/6/19
*/
template<typename T>
void _colMaxFilter( const T *A, int rows, int cols, T *B, int witdhstepA, int widthstepB )
{
int i = 0, j = 0;
const T *Apt = A;
T *Bpt = B;
// copy A into B
while( i++<rows ){
j = 0;
while( j++<cols )
*(Bpt++) = *(Apt++);
Apt += witdhstepA - cols;
Bpt += widthstepB - cols;
}
// apply col-max to each col
Apt = A, Bpt = B;
for( i=0; i<cols; i++ ){
if( Apt[0]>Apt[witdhstepA] )
Bpt[widthstepB] = Apt[0];
else
Bpt[0] = Apt[witdhstepA];
for( j=2; j<rows; j++ )
if( Apt[(j-1)*witdhstepA]>Apt[j*witdhstepA] )
Bpt[j*widthstepB] = Apt[(j-1)*witdhstepA];
else
Bpt[(j-1)*widthstepB] = MAX( Apt[j*witdhstepA], Apt[(j-2)*witdhstepA] );
Apt++, Bpt++;
}
}
void colMaxFilter( const int *A, int rows, int cols, int *B, int widthstepA, int witdhstepB)
{
_colMaxFilter(A,rows,cols,B,widthstepA,witdhstepB);
}
void colMaxFilter( const float *A, int rows, int cols, float *B, int widthstepA, int witdhstepB)
{
_colMaxFilter(A,rows,cols,B,widthstepA,witdhstepB);
}
void colMaxFilter( const double *A, int rows, int cols, double *B, int widthstepA, int witdhstepB)
{
_colMaxFilter(A,rows,cols,B,widthstepA,witdhstepB);
}
/* >>>TEST<<<
int main()
{
// use matlab to generate a random array: A = rand(5,6)
float A[5*6] = { 1.0347, 0.8884, 1.4384, -0.1022, -0.0301, -0.8637, 0.7269, -1.1471, 0.3252, -0.2414, -0.1649, 0.0774, -0.3034, -1.0689, -0.7549, 0.3192, 0.6277, -1.2141, 0.2939, -0.8095, 1.3703, 0.3129, 1.0933, -1.1135, -0.7873, -2.9443, -1.7115, -0.8649, 1.1093, -0.0068 };
float B[30];
colMaxFilter( A, 5, 6, B, 6, 6 );
for( int i=0; i<5; i++ ){
for( int j=0; j<6; j++ )
printf("%g\t",B[i*6+j]);
printf("\n");
}
// true result is:
//1.0347 0.8884 1.4384 -0.1022 -0.0301 0.0774
//1.0347 0.8884 1.4384 0.3192 0.6277 0.0774
//0.7269 -0.8095 1.3703 0.3192 1.0933 0.0774
//0.2939 -0.8095 1.3703 0.3192 1.1093 -0.0068
//0.2939 -0.8095 1.3703 0.3129 1.1093 -0.0068
return 0;
}
*/
//===================corresponding matlab code========================================
/*
function B = rowMaxFilter(A)
%% 1*3 maximum filter
%% B(i,j) is set to local maximum of A(i,j) neighborhood
B = A;
[M,N] = size(A);
for i=1:M
% apply row-max to each row
if A(i,1)>A(i,2)
B(i,2) = A(i,1);
else
B(i,1) = A(i,2);
end
for j=3:N
if A(i,j-1)>A(i,j)
B(i,j) = A(i,j-1);
else
B(i,j-1) = max(A(i,j-2),A(i,j));
end
end
end
%% TEST
% A = rand(50,60);
% B1 = ordfilt2(A,3,[1 1 1]);
% B2 = rowMaxFilter(A);
% C = B1 - B2;
% max(abs(C(:))) % should be ZERO
*/
<hr/>
// 第四段代码:第二种版本的3*1滤波
#include <stdio.h>
/*
3*1 maximum filter;
if A(i,j) is local maximum, then B(i,j)=A(i,j); else B(i,j)=0
suppose: A's size is rows*cols, A(i,j) (i<rows,j<cols) is indexed by A[i*witdhstepA+j],
i.e. A's element is arranged in memory like: the first row, the second row, ... so on. B is alike. widthstep should be no smaller than cols.
(the memory arrangement actually accords with that in openCV)
by: Yu Xianguo, NUDT, 2014/6/19
*/
template<typename T>
void _colMaxFilter2( const T *A, int rows, int cols, T *B, int witdhstepA, int widthstepB )
{
int i = 0, j = 0;
const T *Apt = A;
T *Bpt = B;
// copy A into B
while( i++<rows ){
j = 0;
while( j++<cols )
*(Bpt++) = *(Apt++);
Apt += witdhstepA - cols;
Bpt += widthstepB - cols;
}
// apply col-max to each col
Apt = A, Bpt = B;
for( i=0; i<cols; i++ ){
for( j=1; j<rows; j++ )
if( Apt[(j-1)*witdhstepA]>Apt[j*witdhstepA] )
Bpt[j*widthstepB] = 0;
else
Bpt[(j-1)*widthstepB] = 0;
Apt++;
Bpt++;
}
}
void colMaxFilter2( const int *A, int rows, int cols, int *B, int widthstepA, int witdhstepB)
{
_colMaxFilter2(A,rows,cols,B,widthstepA,witdhstepB);
}
void colMaxFilter2( const float *A, int rows, int cols, float *B, int widthstepA, int witdhstepB)
{
_colMaxFilter2(A,rows,cols,B,widthstepA,witdhstepB);
}
void colMaxFilter2( const double *A, int rows, int cols, double *B, int widthstepA, int witdhstepB)
{
_colMaxFilter2(A,rows,cols,B,widthstepA,witdhstepB);
}
/* >>>TEST<<<
int main()
{
// use matlab to generate a random array: A = rand(5,6)
float A[5*6] = { 1.0347, 0.8884, 1.4384, -0.1022, -0.0301, -0.8637, 0.7269, -1.1471, 0.3252, -0.2414, -0.1649, 0.0774, -0.3034, -1.0689, -0.7549, 0.3192, 0.6277, -1.2141, 0.2939, -0.8095, 1.3703, 0.3129, 1.0933, -1.1135, -0.7873, -2.9443, -1.7115, -0.8649, 1.1093, -0.0068 };
float B[30];
colMaxFilter2( A, 5, 6, B, 6, 6 );
for( int i=0; i<5; i++ ){
for( int j=0; j<6; j++ )
printf("%g\t",B[i*6+j]);
printf("\n");
}
// true result is:
//1.0347 0.8884 1.4384 -0.1022 -0.0301 0
//0 0 0 0 0 0.0774
//0 0 0 0.3192 0 0
//0.2939 -0.8095 1.3703 0 0 0
//0 0 0 0 1.1093 -0.0068
return 0;
}
*/
//===================corresponding matlab code========================================
/*
function B = colMaxFilter2(A)
%% 3*1 maximum filter
%% if A(i,j) is local maximum, then B(i,j)=A(i,j); else B(i,j)=0
B = A;
[M,N] = size(A);
for i=1:N
% apply col-max to each col
for j=2:M
if A(j-1,i)>A(j,i)
B(j,i) = 0;
else
B(j-1,i) = 0;
end
end
end
%% TEST
% A = rand(30,40);
% B1 = ordfilt2(A,3,[1;1;1]);
% B1(B1~=A) = 0;
% B2 = colMaxFilter2(A);
% B1-B2 % should be all zero
*/
<hr/>
// 第五段代码:3*3最大值滤波 ~ 应该是属于第一种版本
#include <stdlib.h>
#ifndef MAX
#define MAX(a,b) (a>b?a:b)
#endif
/*
1*3 maximum filter;
B(i,j) is set to local maximum of A(i,j) neighborhood;
suppose: A's size is rows*cols, A(i,j) (i<rows,j<cols) is indexed by A[i*witdhstepA+j],
i.e. A's element is arranged in memory like: the first row, the second row, ... so on. B is alike. widthstep should be no smaller than cols.
(the memory arrangement actually accords with that in openCV)
by: Yu Xianguo, NUDT, 2014/6/19
*/
template<typename T>
void _rowMaxFilter( const T *A, int rows, int cols, T *B, int witdhstepA, int widthstepB )
{
int i = 0, j = 0;
const T *Apt = A;
T *Bpt = B;
// copy A into B
while( i++<rows ){
j = 0;
while( j++<cols )
*(Bpt++) = *(Apt++);
Apt += witdhstepA - cols;
Bpt += widthstepB - cols;
}
// apply row-max to each row
Apt = A, Bpt = B;
for( i=0; i<rows; i++ ){
if( Apt[0]>Apt[1] )
Bpt[1] = Apt[0];
else
Bpt[0] = Apt[1];
for( j=2; j<cols; j++ )
if( Apt[j-1]>Apt[j] )
Bpt[j] = Apt[j-1];
else
Bpt[j-1] = MAX( Apt[j-2], Apt[j] );
Apt += witdhstepA;
Bpt += widthstepB;
}
}
/*
3*1 maximum filter;
B(i,j) is set to local maximum of A(i,j) neighborhood;
suppose: A's size is rows*cols, A(i,j) (i<rows,j<cols) is indexed by A[i*witdhstepA+j],
i.e. A's element is arranged in memory like: the first row, the second row, ... so on. B is alike. widthstep should be no smaller than cols.
(the memory arrangement actually accords with that in openCV)
by: Yu Xianguo, NUDT, 2014/6/19
*/
template<typename T>
void _colMaxFilter( const T *A, int rows, int cols, T *B, int witdhstepA, int widthstepB )
{
int i = 0, j = 0;
const T *Apt = A;
T *Bpt = B;
// copy A into B
while( i++<rows ){
j = 0;
while( j++<cols )
*(Bpt++) = *(Apt++);
Apt += witdhstepA - cols;
Bpt += widthstepB - cols;
}
// apply col-max to each col
Apt = A, Bpt = B;
for( i=0; i<cols; i++ ){
if( Apt[0]>Apt[witdhstepA] )
Bpt[widthstepB] = Apt[0];
else
Bpt[0] = Apt[witdhstepA];
for( j=2; j<rows; j++ )
if( Apt[(j-1)*witdhstepA]>Apt[j*witdhstepA] )
Bpt[j*widthstepB] = Apt[(j-1)*witdhstepA];
else
Bpt[(j-1)*widthstepB] = MAX( Apt[j*witdhstepA], Apt[(j-2)*witdhstepA] );
Apt++, Bpt++;
}
}
/*
3*3 maximum filter;
B(i,j) is set to local maximum of A(i,j) neighborhood.
by: Yu Xianguo, NUDT, 2014/6/19
*/
template<typename T>
void _maximumFilter( const T *A, int rows, int cols, T *B, int witdhstepA, int widthstepB )
{
T *tmp = new T [rows*cols] ();
_rowMaxFilter( A, rows, cols, tmp, witdhstepA, cols );
_colMaxFilter( tmp, rows, cols, B, cols, widthstepB );
delete [] tmp;
}
void maximumFilter( const int *A, int rows, int cols, int *B, int widthstepA, int witdhstepB)
{
_maximumFilter(A,rows,cols,B,widthstepA,witdhstepB);
}
void maximumFilter( const float *A, int rows, int cols, float *B, int widthstepA, int witdhstepB)
{
_maximumFilter(A,rows,cols,B,widthstepA,witdhstepB);
}
void maximumFilter( const double *A, int rows, int cols, double *B, int widthstepA, int witdhstepB)
{
_maximumFilter(A,rows,cols,B,widthstepA,witdhstepB);
}
/* >>>TEST<<<
int main()
{
// use matlab to generate a random array: A = rand(5,6)
float A[5*6] = { 1.0347, 0.8884, 1.4384, -0.1022, -0.0301, -0.8637, 0.7269, -1.1471, 0.3252, -0.2414, -0.1649, 0.0774, -0.3034, -1.0689, -0.7549, 0.3192, 0.6277, -1.2141, 0.2939, -0.8095, 1.3703, 0.3129, 1.0933, -1.1135, -0.7873, -2.9443, -1.7115, -0.8649, 1.1093, -0.0068 };
float B[30];
maximumFilter( A, 5, 6, B, 6, 6 );
for( int i=0; i<5; i++ ){
for( int j=0; j<6; j++ )
printf("%g\t",B[i*6+j]);
printf("\n");
}
// true result is:
//1.0347 1.4384 1.4384 1.4384 0.0774 0.0774
//1.0347 1.4384 1.4384 1.4384 0.6277 0.6277
//0.7269 1.3703 1.3703 1.3703 1.0933 1.0933
//0.2939 1.3703 1.3703 1.3703 1.1093 1.1093
//0.2939 1.3703 1.3703 1.3703 1.1093 1.1093
return 0;
}
*/