📄 imagemanip.c
字号:
{ /* // 0 0 0 0 1 1 1 1 1 0 // 1 0 1 1 1 1 1 0 // 1 1 1 0 1 0 0 0 1 0 */ if (p[P(x-1,y-1)]==0 && p[P(x,y-1)]==0 && p[P(x+1,y-1)]==0 && p[P(x-1,y+1)]!=0 && p[P(x,y+1)]!=0 && p[P(x+1,y+1)]!=0) REMOVE_P; if (p[P(x-1,y-1)]!=0 && p[P(x,y-1)]!=0 && p[P(x+1,y-1)]!=0 && p[P(x-1,y+1)]==0 && p[P(x,y+1)]==0 && p[P(x+1,y+1)]==0) REMOVE_P; if (p[P(x-1,y-1)]==0 && p[P(x-1,y)]==0 && p[P(x-1,y+1)]==0 && p[P(x+1,y-1)]!=0 && p[P(x+1,y)]!=0 && p[P(x+1,y+1)]!=0) REMOVE_P; if (p[P(x-1,y-1)]!=0 && p[P(x-1,y)]!=0 && p[P(x-1,y+1)]!=0 && p[P(x+1,y-1)]==0 && p[P(x+1,y)]==0 && p[P(x+1,y+1)]==0) REMOVE_P; /* // 0 0 0 0 1 1 // 1 1 0 0 1 1 0 1 1 1 1 0 // 1 1 0 0 0 0 */ if (p[P(x,y-1)]==0 && p[P(x+1,y-1)]==0 && p[P(x+1,y)]==0 && p[P(x-1,y)]!=0 && p[P(x,y+1)]!=0) REMOVE_P; if (p[P(x-1,y-1)]==0 && p[P(x,y-1)]==0 && p[P(x-1,y)]==0 && p[P(x+1,y)]!=0 && p[P(x,y+1)]!=0) REMOVE_P; if (p[P(x-1,y+1)]==0 && p[P(x-1,y)]==0 && p[P(x,y+1)]==0 && p[P(x+1,y)]!=0 && p[P(x,y-1)]!=0) REMOVE_P; if (p[P(x+1,y+1)]==0 && p[P(x+1,y)]==0 && p[P(x,y+1)]==0 && p[P(x-1,y)]!=0 && p[P(x,y-1)]!=0) REMOVE_P; } } } ImageRemoveSpurs(image); return ImageSetFlag(image, FvsImageThinned);}
/* modified
*/
FvsError_t FingerprintGetFrequency1(const FvsImage_t image, const FvsFloatField_t direction,
FvsFloatField_t frequency)
{
/* 输入图像的宽度和高度 */
FvsError_t nRet = FvsOK;
FvsInt_t w = ImageGetWidth (image);
FvsInt_t h = ImageGetHeight(image);
FvsInt_t pitchi = ImageGetPitch (image);
FvsByte_t* p = ImageGetBuffer(image);
FvsFloat_t* out;
FvsFloat_t* freq;
FvsFloat_t* orientation = FloatFieldGetBuffer(direction);
FvsFloat_t dir,dir1,dir2;
FvsFloat_t cosdir,sindir,cosdir1,sindir1,cosdir2,sindir2;
FvsInt_t x, y, u, v, d, k;
size_t size;
if (p==NULL)
return FvsMemory;
/* 输出图像的内存申请 */
nRet = FloatFieldSetSize(frequency, w, h);
if (nRet!=FvsOK) return nRet;
(void)FloatFieldClear(frequency);
freq = FloatFieldGetBuffer(frequency);
if (freq==NULL)
return FvsMemory;
/* 输出的内存申请 */
size = w*h*sizeof(FvsFloat_t);
out = (FvsFloat_t*)malloc(size);
if (out!=NULL)
{
FvsInt_t peak_pos[BLOCK_L]; /* 顶点 */
FvsInt_t peak_cnt; /* 顶点数目 */
FvsFloat_t peak_freq,save[50]; /* 顶点频率 */
FvsFloat_t Xsig[BLOCK_L]; /* x signature */
FvsFloat_t pmin, pmax;
memset(out, 0, size);
memset(freq, 0, size);
/* 1 - 图像分块 BLOCK_W x BLOCK_W - (16 x 16) */
for (y = BLOCK_L2; y < h-BLOCK_L2; y++)
for (x = BLOCK_L2; x < w-BLOCK_L2; x++)
{
/* 2 - 脊线方向的窗口 l x w (32 x 16) */
dir = orientation[x+y*w];
cosdir = cos(dir);
sindir = sin(dir);
u=(FvsInt_t)(-sindir*BLOCK_L2/2)+x;
v=(FvsInt_t)(cosdir*BLOCK_L2/2)+y;
dir1= orientation[u+v*w];
cosdir1 = cos(dir1);
sindir1 = sin(dir1);
u=(FvsInt_t)(sindir*BLOCK_L2/2)+x;
v=(FvsInt_t)(-cosdir*BLOCK_L2/2)+y;
dir2= orientation[u+v*w];
cosdir2 = cos(dir2);
sindir2 = sin(dir2);
/* 3 - 计算 x-signature X[0], X[1], ... X[l-1] */
for (k = 0; k < BLOCK_L; k++)
{
Xsig[k] = 0.0;
for (d = 0; d < BLOCK_W; d++)
{
if(d-BLOCK_W2>0)
{
u = (FvsInt_t)(x + (k-BLOCK_L2)*cosdir1-(d-BLOCK_W2)*sindir1);
v = (FvsInt_t)(y + (k-BLOCK_L2)*sindir1+(d-BLOCK_W2)*cosdir1);
}
else
{
u = (FvsInt_t)(x + (k-BLOCK_L2)*cosdir2-(d-BLOCK_W2)*sindir2);
v = (FvsInt_t)(y + (k-BLOCK_L2)*sindir2+(d-BLOCK_W2)*cosdir2);
}
/* clipping */
if (u<0) u = 0; else if (u>w-1) u = w-1;
if (v<0) v = 0; else if (v>h-1) v = h-1;
Xsig[k] += p[u + (v*pitchi)];
}
Xsig[k] /= BLOCK_W;
}
/* 计算 T(i,j) */
/* 寻找 x signature 中的顶点 */
peak_cnt = 0;
pmax = pmin = Xsig[0];
for (k = 1; k < BLOCK_L; k++)
{
if (pmin>Xsig[k]) pmin = Xsig[k];
if (pmax<Xsig[k]) pmax = Xsig[k];
}
if ((pmax - pmin)>64.0)
{
for (k = 1; k < BLOCK_L-1; k++)
if ((Xsig[k-1] < Xsig[k]) && (Xsig[k] >= Xsig[k+1]))
{
peak_pos[peak_cnt++] = k;
}
}
/* 计算均值 */
peak_freq = 0.0;
if (peak_cnt>2)
{
for (k = 0; k < peak_cnt-1; k++)
peak_freq += peak_pos[k+1]-peak_pos[k];
peak_freq /= peak_cnt-1;
}
/* 4 - 验证频率范围 [1/25-1/3] */
/* 可以扩大到 [1/30-1/2] */
if (peak_freq > 25.0 && peak_freq < 3.0)
peak_freq = 0.0;
if (peak_freq == 0.0)
out[x+y*w] = 0.0;
else
out[x+y*w] = 1.0/peak_freq;
if(x<230 && x>220 && y==46)
x=x;
}
/* 5 - 未知点 */
/* for (y = BLOCK_L2; y < h-BLOCK_L2; y++)
for (x = BLOCK_L2; x < w-BLOCK_L2; x++)
{
if (out[x+y*w]<EPSILON)
{
if (out[x+(y-1)*w]>EPSILON)
{
out[x+(y*w)] = out[x+(y-1)*w];
}
else
{
if (out[x-1+(y*w)]>EPSILON)
out[x+(y*w)] = out[x-1+(y*w)];
}
}
}
/* 6 - 频率插值 */
for (y = BLOCK_L2; y < h-BLOCK_L2; y++)
for (x = BLOCK_L2; x < w-BLOCK_L2; x++)
{
k = x + y*w;
peak_freq = 0.0;
for ( v = -LPSIZE; v <= LPSIZE; v++)
for ( u = -LPSIZE; u <= LPSIZE; u++)
{
save[(v+LPSIZE)*(LPSIZE*2+1)+u+LPSIZE]= out[(x+u)+(y+v)*w];
peak_freq += out[(x+u)+(y+v)*w];
}
freq[k] = peak_freq*LPFACTOR;
if(x<230 && x>220 && y==46)
x=x;
}
free(out);
}
return nRet;
}
/* modified
*/
struct mycomplex{
FvsFloat_t real;
FvsFloat_t imag;
};
static fft(FvsFloat_t data[32])
{
FvsInt_t i,j,k,bfsize,p,count,r=5;
FvsFloat_t angle;
struct mycomplex *w,*x1,*x2,*x;
count=1<<r;
w=(struct mycomplex*)malloc(sizeof(struct complex)*count/2);
x1=(struct mycomplex*)malloc(sizeof(struct complex)*count);
x2=(struct mycomplex*)malloc(sizeof(struct complex)*count);
for(i=0;i<count/2;i++)
{
angle=-i*M_PI*2/count;
w[i].real=cos(angle);
w[i].imag=sin(angle);
}
for(j=0;j<count;j++)
{
p=0;
for(i=0;i<r;i++)
{
if(j&(1<<i))
{
p+=1<<(r-i-1);
}
}
x1[p].real=data[j];
x1[p].imag=0;
}
for(k=0;k<r;k++)
{
bfsize=1<<(k+1);
for(j=0;j<1<<(r-k-1);j++)
{
for(i=0;i<bfsize/2;i++)
{
p=j*bfsize;
x2[i+p].real=x1[i+p].real+x1[i+p+bfsize/2].real*w[i*1<<(r-k-1)].real \
-x1[i+p+bfsize/2].imag*w[i*1<<(r-k-1)].imag;
x2[i+p].imag=x1[i+p].imag+x1[i+p+bfsize/2].imag*w[i*1<<(r-k-1)].real \
+x1[i+p+bfsize/2].real*w[i*1<<(r-k-1)].imag;
x2[i+p+bfsize/2].real=x1[i+p].real-x1[i+p+bfsize/2].real*w[i*1<<(r-k-1)].real \
+x1[i+p+bfsize/2].imag*w[i*1<<(r-k-1)].imag;
x2[i+p+bfsize/2].imag=x1[i+p].imag-x1[i+p+bfsize/2].imag*w[i*1<<(r-k-1)].real \
-x1[i+p+bfsize/2].real*w[i*1<<(r-k-1)].imag;
}
}
x=x1;
x1=x2;
x2=x;
}
for(j=0;j<count;j++)
{
data[j]=sqrt(x1[j].real*x1[j].real+x1[j].imag*x1[j].imag)/10;
}
free(w);
free(x1);
free(x2);
}
FvsError_t FingerprintGetFrequency2(const FvsImage_t image, const FvsFloatField_t direction,
FvsFloatField_t frequency)
{
/* 输入图像的宽度和高度 */
FvsError_t nRet = FvsOK;
FvsInt_t w = ImageGetWidth (image);
FvsInt_t h = ImageGetHeight(image);
FvsInt_t pitchi = ImageGetPitch (image);
FvsByte_t* p = ImageGetBuffer(image);
FvsFloat_t* out;
FvsFloat_t* freq;
FvsFloat_t* orientation = FloatFieldGetBuffer(direction);
FvsInt_t x, y, u, v, d, k;
size_t size;
if (p==NULL)
return FvsMemory;
/* 输出图像的内存申请 */
nRet = FloatFieldSetSize(frequency, w, h);
if (nRet!=FvsOK) return nRet;
(void)FloatFieldClear(frequency);
freq = FloatFieldGetBuffer(frequency);
if (freq==NULL)
return FvsMemory;
/* 输出的内存申请 */
size = w*h*sizeof(FvsFloat_t);
out = (FvsFloat_t*)malloc(size);
if (out!=NULL)
{
FvsFloat_t dir = 0.0;
FvsFloat_t cosdir = 0.0;
FvsFloat_t sindir = 0.0;
FvsInt_t peak_pos[BLOCK_L]; /* 顶点 */
FvsInt_t peak_cnt; /* 顶点数目 */
FvsFloat_t peak_freq; /* 顶点频率 */
FvsFloat_t Xsig[BLOCK_L]; /* x signature */
FvsFloat_t pmin, pmax;
memset(out, 0, size);
memset(freq, 0, size);
/* 1 - 图像分块 BLOCK_W x BLOCK_W - (16 x 16) */
for (y = BLOCK_L2; y < h-BLOCK_L2; y++)
for (x = BLOCK_L2; x < w-BLOCK_L2; x++)
{
/* 2 - 脊线方向的窗口 l x w (32 x 16) */
// dir = orientation[(x+BLOCK_W2) + (y+BLOCK_W2)*w];
dir = orientation[(x) + (y)*w];
cosdir = cos(dir);
sindir = sin(dir);
/* 3 - 计算 x-signature X[0], X[1], ... X[l-1] */
for (k = 0; k < BLOCK_L; k++)
{
Xsig[k] = 0.0;
for (d = 0; d < BLOCK_W; d++)
{
u = (FvsInt_t)(x + (k-BLOCK_L2)*cosdir-(d-BLOCK_W2)*sindir);
v = (FvsInt_t)(y + (k-BLOCK_L2)*sindir+(d-BLOCK_W2)*cosdir);
/* clipping */
if (u<0) u = 0; else if (u>w-1) u = w-1;
if (v<0) v = 0; else if (v>h-1) v = h-1;
Xsig[k] += p[u + (v*pitchi)];
}
Xsig[k] /= BLOCK_W;
}
if(x==130 && y==100)
x=x;
// for(k=0;k<32;k++)
// Xsig[k]=cos(2*M_PI*7*k/32)+cos(2*M_PI*3*k/32);
fft(Xsig);
if (peak_freq > 30.0)
out[x+y*w] = 0.0;
else if (peak_freq < 2.0)
out[x+y*w] = 0.0;
else
out[x+y*w] = 1.0/peak_freq;
}
/* 5 - 未知点 */
for (y = BLOCK_L2; y < h-BLOCK_L2; y++)
for (x = BLOCK_L2; x < w-BLOCK_L2; x++)
{
if (out[x+y*w]<EPSILON)
{
if (out[x+(y-1)*w]>EPSILON)
{
out[x+(y*w)] = out[x+(y-1)*w];
}
else
{
if (out[x-1+(y*w)]>EPSILON)
out[x+(y*w)] = out[x-1+(y*w)];
}
}
}
/* 6 - 频率插值 */
for (y = BLOCK_L2; y < h-BLOCK_L2; y++)
for (x = BLOCK_L2; x < w-BLOCK_L2; x++)
{
k = x + y*w;
peak_freq = 0.0;
for ( v = -LPSIZE; v <= LPSIZE; v++)
for ( u = -LPSIZE; u <= LPSIZE; u++)
peak_freq += out[(x+u)+(y+v)*w];
freq[k] = peak_freq*LPFACTOR;
}
free(out);
}
return nRet;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -