共有回帖数 0 个
-
准备写一个高斯模糊算法
(依靠高斯分布来进行加权,高斯分布即正态分布,创造正态分布的是德国数学家高斯,高中概率知识,要学以致用。。。。。)
但是大餐准备留在最后,先手写了一个二次模糊(使用1/r^2来进行加权,当r = 0时,加权为1防止除0错误)
但是存在问题…………
我只是看了百度百科的介绍自己摸索的算法,大多数使用不同的图形库和语言(主要是JAVA),所以干脆用SDL2自己写。。。由Surface像素操作实现。。
处理前:

处理后,图片明显变得模糊了,模糊半径为3,但是图片发暗,可能是误差原因造成的。。。

但是根据不同的算法的对比图来看,二次加权处理的图像像近视眼一样,看起来很晕,但是我的结果感觉和正态分布加权(高斯模糊)差不多。。。原因尚不明确。等明天问题解决了,准备出一篇教程如何进行模糊图像处理。。。。
#includeSDL2/SDL.h
#includeSDL2/SDL_ttf.h
#includestdio.h
#includestdlib.h
#includemath.h
const int SCREEN_WIDTH = 500;
const int SCREEN_HEIGHT = 750;
const int FPS = 20;
SDL_Window * window;
SDL_Renderer * render;
SDL_Texture * text = NULL;
unsigned int frame = 0;
Uint8 quit = 0;
/*合并surface*/
void apply_surface(int x, int y, SDL_Surface * source, SDL_Surface * destination)
{
SDL_Rect offset;
offset.x = x;
offset.y = y;
SDL_BlitSurface(source, NULL, destination, &offset);
}
/*将纹理渲染到指定位置和大小*/
void RenderTexture_pos(SDL_Texture * tex, SDL_Renderer * ren, int x, int y,
int w, int h)
{
SDL_Rect dst;
dst.x = x;
dst.y = y;
dst.w = w;
dst.h = h;
SDL_RenderCopy(ren, tex, NULL, &dst);
}
/*将纹理渲染到指定坐标*/
void RenderTexture_pos_auto(SDL_Texture * tex, SDL_Renderer * ren, int x, int y)
{
int w, h;
SDL_QueryTexture(tex, NULL, NULL, &w, &h);
RenderTexture_pos(tex, ren, x, y, w, h);
}
void print_sdl_error()
{
printf("SDL_ERROR:%sn", SDL_GetError());
}
/*绘制像素*/
void set_pixel(SDL_Surface * sur, int x, int y, Uint8 r, Uint8 g, Uint8 b)
{
Uint32 * pixmem32;
Uint32 color;
color = SDL_MapRGB(sur-format, r, g, b);
pixmem32 = (Uint32 *)(sur-pixels) + (y * sur-w) + x;
*pixmem32 = color;
}
/*获得相对半径,这个并不是圆,是一个正方形
毕竟是模糊处理,所以把一个正方形近似看作一个圆*/
int getradius(int x, int y, int x1, int y1)
{
if(abs(x1 - x) abs(y1 - y))
{
return abs(x1 - x);
}
else
{
return abs(y1 - y);
}
}
/*获得相应的权*/
double getwidth(int r)
{
if(r == 0)
return 1;
return 1 / (double)(2 * r * r);
}
/*权的综合*/
double getwidthsum(int r)
{
double sum = 0;
while(r = 0)
{
sum += getwidth(r);
r--;
}
return sum;
}
/*模糊处理*/
void gauss(SDL_Surface * sur, SDL_Surface * des, int radius)
{
double R1; //累计红的
double G1; //累计lvse
double B1; // 累计蓝色
Uint8 R;
Uint8 G;
Uint8 B;
Uint32 * pixmem32;
int x;
int y;
int x1;
int y1;
int r; //临时处理半径
int s = (radius + 1) * (radius + 1); //模糊半径内像素总数
double widthsum; //权总和
double width; //权
for(y = 0; y SCREEN_HEIGHT; y++)
{
for(x = 0; x SCREEN_WIDTH; x++)
{
R1 = G1 = B1 = 0;
y1 = y - radius;
while(y1 = y + radius)
{
x1 = x - radius;
while(x1 = x + radius)
{
r = getradius(x,y, x1, y1);
width = getwidth(r);
pixmem32 = (Uint32 *)(sur-pixels) + (y1 * sur-w) + x1;
SDL_GetRGB(*pixmem32, sur-format, &R, &G, &B);
/*加权累计*/
R1 += (double)R * width;
G1 += (double)G * width;
B1 += (double)B * width;
x1++;
}
y1++;
}
widthsum = getwidthsum(radius);
/*如果RGB大于255,则以255计入*/
if(R1 / widthsum / s = 255)
{
R = (Uint8)(R1 / widthsum / s);
}
else
{
R = 255;
}
if(G1 / widthsum / s = 255)
{
G = (Uint8)(G1 / widthsum / s);
}
else
{
G = 255;
}
if(B1 / widthsum / s = 255)
{
B = (Uint8)(B1 / widthsum / s);
}
else
{
B = 255;
}
set_pixel(des, x,y,R,G,B);
}
}
}
int show(void * data)
{
while(quit == 0)
{
SDL_SetRenderDrawColor(render, 250, 250, 250, 255);
SDL_RenderClear(render);
RenderTexture_pos_auto(text, render, 0,0);
SDL_RenderPresent(render);
frame++;
SDL_Delay(1000 / FPS);
}
return 0;
}
void sdl_clean()
{
SDL_DestroyWindow(window);
SDL_DestroyRenderer(render);
SDL_DestroyTexture(text);
SDL_Quit();
TTF_Quit();
}
int main(int argc, char * arg[])
{
SDL_Event event;
if(SDL_Init(SDL_INIT_VIDEO) != 0 || TTF_Init() != 0)
{
print_sdl_error();
}
else
{
window = SDL_CreateWindow("SDL_GUI", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
render = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
SDL_CreateThread(show, "show", (void *)NULL);
SDL_Surface * bmp = SDL_LoadBMP("h.bmp");
SDL_Surface * sur = SDL_CreateRGBSurface(0, bmp-w, bmp-h, 32, 0,0,0,0);
SDL_Surface * des = SDL_CreateRGBSurface(0, bmp-w, bmp-h, 32, 0,0,0,0);
apply_surface(0,0,bmp, sur);
gauss(sur, des, 2);
text = SDL_CreateTextureFromSurface(render, des);
while(quit == 0)
{
SDL_WaitEvent(&event);
switch(event.type)
{
case SDL_QUIT:
quit = 1;
break;
}
}
}
sdl_clean();
return 0;
}
楼主 2015-07-28 08:25 回复
Copyright © 2010~2015 直线网 版权所有,All Rights Reserved.沪ICP备10039589号
意见反馈 |
关于直线 |
版权声明 |
会员须知