在图像中,通过邻接点的相互平均可以去掉一些突然变化的点,从而过滤掉一定的噪声,达到平滑的目的,但图像有一定程度上的模糊。
本实验使用模板
1 1 1
1 1 1
1 1 1
即每一个像素的灰度都是自身和周围8个像素的平均值。
图像锐化处理的目的是使模糊的图像变得更加清晰起来,而图像模糊的实质就是图像受到平均或积分运算造成的,因此可以对图像进行逆运算(如微分)来使图像清晰化。梯度锐化是一种常用的微分锐化方法。
Sobel 初步尝试,其卷积计算核有两个,
Sx =
-1 0 1
-2 0 2
-1 0 1
Sy =
1 2 1
0 0 0
-1 -2 -1
一个对垂直边缘影响最大,一个对水平边缘影响最大。图像中每点均分别用这两个算子作卷积,取两个卷积绝对值的和。
图像中的边缘及急剧变化部分与图像高频分量有关,利用低通滤波减弱高频部分能实现图像平滑,利用高通滤波减弱低频部分能实现图像锐化。
图像FFT 后注意原点。
原图
FFT 后
FFT 后高通滤波
高通滤波
FFT 后低通滤波
低通滤波
平滑
Sobel
/*
ProcessFilterZ.h
Copyright (C) 2011, coreBugZJ, all rights reserved.
滤波。
*/
#ifndef __PROCESSFILTER_Z_H_INCLUDED__
#define __PROCESSFILTER_Z_H_INCLUDED__
#include "TypeZ.h"
#include "ClassImageZ.h"
/* 高通 低通 滤波器 */
/* 对宽为 (1<<lgw) 高为 (1<<lgh) 且 2d FFT 后的矩阵 */
/* 点的定位同 2d FFT */
/* 会修改矩阵 */
/* if 参数highPass then 高通 else 低通 */
/* == radius 也通过 */
/* 成功返回 ROK */
PublicFuncZ R32 highLowPassFilterZ( CF64 *mat, U32 lgw, U32 lgh, F64 radius, B32 highPass );
/* 在图像上使用 n * n 的模板 mat,然后 乘以 mulFactor 除以 divFactor */
/* 假设 n 为奇数 */
/* 会修改图像 */
/* 模板 mat 中第 y 行第 x 列的点(x,y)为 mat[ y * n + x ] */
/* 图像边缘无法使用模板处,保持不变 */
/* 成功返回 ROK */
PublicFuncZ R32 templateFilterZ( ImageZ img, I32 *mat, U32 n, I32 mulFactor, I32 divFactor );
/* 平滑 */
/* 会修改图像 */
/* 成功返回 ROK */
PublicFuncZ R32 smoothImageZ( ImageZ img );
/* 锐化 sobel */
/* 会修改图像 */
/* 成功返回 ROK */
PublicFuncZ R32 sharpImageZ( ImageZ img );
#endif /* __PROCESSFILTER_Z_H_INCLUDED__ */
/*
ProcessFilterZ.c
Copyright (C) 2011, coreBugZJ, all rights reserved.
滤波。
*/
#include "stdafx.h"
#include "ProcessFilterZ.h"
#include "ProcessGrayZ.h"
#include <malloc.h>
PublicFuncZ R32 highLowPassFilterZ( CF64 *mat, U32 lgw, U32 lgh, F64 radius, B32 highPass ) {
U32 x, y, w, h, xc, yc;
F64 r2m4, d2m4, f0, f1;
I32 cmp;
if ( (NULL == mat) ) {
return RERR;
}
w = PWR2_U32_Z( lgw );
h = PWR2_U32_Z( lgh );
MUL_F64_Z( r2m4, radius, radius );
MUL_F64_U32_Z( r2m4, r2m4, 4 );
for ( y = 0; y < h; ++y ) {
yc = ( y + (h>>1) ) % h;
for ( x = 0; x < w; ++x ) {
xc = ( x + (w>>1) ) % w;
MOV_F64_U32_Z( f0, xc );
ADD_F64_U32_Z( f0, f0, xc );
SUB_F64_U32_Z( f0, f0, w );
MUL_F64_Z( f0, f0, f0 );
MOV_F64_U32_Z( f1, yc );
ADD_F64_U32_Z( f1, f1, yc );
SUB_F64_U32_Z( f1, f1, h );
MUL_F64_Z( f1, f1, f1 );
ADD_F64_Z( d2m4, f0, f1 );
CMP_F64_Z( cmp, d2m4, r2m4 );
if ( highPass ) {
if ( cmp < 0 ) {
MOV_CF64_U32_Z( mat[ y * w + x ], 0, 0 );
}
}
else {
if ( cmp > 0 ) {
MOV_CF64_U32_Z( mat[ y * w + x ], 0, 0 );
}
}
}
}
return ROK;
}
PublicFuncZ R32 templateFilterZ( ImageZ img, I32 *mat, U32 n, I32 mulFactor, I32 divFactor ) {
U32 w, h, x, y, ix, iy, nha;
I32 pix, *ptrmat;
U08 *ptrimg, *ptrpix;
if ( (!isImageValidZ(img)) || (NULL == mat) || (0 == divFactor) || (3 > n) ) {
return RERR;
}
if ( GRAY_NUM_Z != img->colorNum ) {
return RERR; /* 目前只支持 256 灰度 */
}
nha = n / 2 + 1;
w = img->width;
h = img->height;
for ( y = n; y <= h; ++y ) {
ptrpix = img->pPixel + (y - nha) * img->linePitch + (n - nha);
for ( x = n; x <= w; ++x ) {
pix = 0;
ptrmat = mat;
for ( iy = y-n; iy < y; ++iy ) {
ptrimg = img->pPixel + iy * img->linePitch + (x - n);
for ( ix = x-n; ix < x; ++ix ) {
pix += (*ptrimg) * (*ptrmat);
++ptrimg;
++ptrmat;
}
}
pix = pix * mulFactor / divFactor;
if ( pix >= GRAY_NUM_Z ) {
pix = GRAY_NUM_Z - 1;
}
*ptrpix = (U08)(pix);
++ptrpix;
}
}
return ROK;
}
PublicFuncZ R32 smoothImageZ( ImageZ img ) {
I32 mat[] = {
1, 1, 1,
1, 1, 1,
1, 1, 1
};
return templateFilterZ( img, mat, 3, 1, 9 );
}
PublicFuncZ R32 sharpImageZ( ImageZ img ) {
I32 *mat = NULL;
U32 width, height, x, y;
I32 v0, v1;
R32 res;
if ( !isImageValidZ(img) ) {
return RERR;
}
if ( GRAY_NUM_Z != img->colorNum ) {
return RERR; /* 256 级灰度 */
}
width = img->width;
height = img->height;
mat = (I32*)malloc( width * height * sizeof(I32) );
if ( NULL == mat ) {
return RERR;
}
#define PIX(ix,iy) ((I32)(img->pPixel[(iy) * img->linePitch + (ix)]))
for ( y = 0; y < height; ++y ) {
for ( x = 0; x < width; ++x ) {
v0 = ( PIX(x+1, y-1) + 2*PIX(x+1, y) + PIX(x+1, y+1) ) -
( PIX(x-1, y-1) + 2*PIX(x-1, y) + PIX(x-1, y+1) );
if ( 0 > v0 ) v0 = -v0;
v1 = ( PIX(x-1, y+1) + 2*PIX(x, y+1) + PIX(x+1, y+1) ) -
( PIX(x-1, y+1) + 2*PIX(x, y+1) + PIX(x+1, y-1) );
if ( 0 > v1 ) v1 = -v1;
mat[ y * width + x ] = v0 + v1;
}
}
#undef PIX
res = scaleImageZ( img, mat, width, height );
free( mat );
mat = NULL;
return res;
}
PublicFuncZ ImageZ createImageScaleZ( I32 *mat, U32 width, U32 height ) {
ImageZ img = NULL;
if ( (NULL == mat) || (1 > width) || (1 > height) ) {
return NULL;
}
img = createImageZ( width, height, GRAY_NUM_Z );
if ( NULL == img ) {
return NULL;
}
if ( ROK == scaleImageZ(img, mat, width, height) ) {
return img;
}
destroyImageZ( img );
img = NULL;
return NULL;
}
PublicFuncZ R32 scaleImageZ( ImageZ img, I32 *mat, U32 width, U32 height ) {
U32 x, y, i;
I32 matMin, matMax, mv;
if ( (NULL == mat) || (1 > width) || (1 > height) ||
(!isImageValidZ(img)) || (GRAY_NUM_Z != img->colorNum) ||
(width != img->width) || (height != img->height)
) {
return RERR;
}
for ( i = 0; i < GRAY_NUM_Z; ++i ) {
img->pPalette[ i * IMAGEZ_COLOR_SIZE_Z + IMAGEZ_OFFSET_BLUE_Z ] =
img->pPalette[ i * IMAGEZ_COLOR_SIZE_Z + IMAGEZ_OFFSET_GREEN_Z ] =
img->pPalette[ i * IMAGEZ_COLOR_SIZE_Z + IMAGEZ_OFFSET_RED_Z ] = (U08)(i);
img->pPalette[ i * IMAGEZ_COLOR_SIZE_Z + IMAGEZ_OFFSET_ALPHA_Z ] = 255;
}
matMin = matMax = mat[ 0 ];
for ( y = 0; y < height; ++y ) {
for ( x = 0; x < width; ++x ) {
mv = mat[ y * width + x ];
if ( matMin > mv ) {
matMin = mv;
}
if ( matMax < mv ) {
matMax = mv;
}
}
}
mv = matMax - matMin;
if ( 0 == mv ) {
mv = 1;
}
for ( y = 0; y < height; ++y ) {
for ( x = 0; x < width; ++x ) {
img->pPixel[ y * img->linePitch + x ] = (U08)(
(mat[ y * width + x ] - matMin) * (GRAY_NUM_Z-1) / mv );
}
}
return ROK;
}
PublicFuncZ ImageZ createImageFromFftDataZ( CF64 *mat, U32 lgw, U32 lgh ) {
ImageZ img = NULL;
U32 w, h, x, y, i, tu;
F64 tf255, tf;
U08 *ptrimg;
CF64 *ptrmat;
if ( NULL == mat ) {
return NULL;
}
w = PWR2_U32_Z( lgw );
h = PWR2_U32_Z( lgh );
img = createImageZ( w, h, GRAY_NUM_Z );
if ( NULL == img ) {
return NULL;
}
ptrimg = img->pPalette;
for ( i = 0; i < GRAY_NUM_Z; ++i ) {
ptrimg[ IMAGEZ_OFFSET_BLUE_Z ] =
ptrimg[ IMAGEZ_OFFSET_GREEN_Z ] =
ptrimg[ IMAGEZ_OFFSET_RED_Z ] = (U08)(i);
ptrimg[ IMAGEZ_OFFSET_ALPHA_Z ] = 255;
ptrimg += IMAGEZ_COLOR_SIZE_Z;
}
MOV_F64_U32_Z( tf255, 255 );
for ( y = 0; y < h; ++y ) {
ptrimg = img->pPixel + ((y+(h>>1))%h) * img->linePitch;
ptrmat = mat + y * w;
for ( x = 0; x < w; ++x ) {
M_CF64_Z( tf, *ptrmat );
++ptrmat;
DIV_F64_U32_Z( tf, tf, 100 );
MIN_F64_Z( tf, tf, tf255 );
MOV_U32_F64_Z( tu, tf );
*(ptrimg + (x+(w>>1))%w ) = (U08)(tu);
}
}
return img;
}