滤镜之油画Oil Painting

来源:互联网 发布:网络编程java是什么 编辑:程序博客网 时间:2024/04/19 13:28

首先看效果图:


 

油画我的理解是色彩比较重,而且会有一片一片区域的同样色彩,没有什么细节,灰阶降低,只表现为一些特定的色彩。

算法上的原理如下:

1.     统计每个像素领域半径中出现的R,G,B的直方图,以及灰度的直方图,该直方图的bin的大小是设定好的,由此可以统计出落在某个bin上的数量

2.     统计直方图中出现次数最多的R、G、B的均值,就是最要这个像素的结果。

 

从某个人的博客中借用了一个比较形式化的图,便于更好理解:


       http://www.cnblogs.com/hoodlum1980/archive/2011/01/15/1936078.html

 

该算法存在两个参数:

1.     半径:统计像素的矩形框,越大则图像细节越少

2.     平滑度:直方图bin的宽度,越大越平滑

 

算法代码:没有经过任何优化

void OilPaintingRGB(unsigned char* pInput,unsigned char* pOutput,int width,int height,int nStride,int radius,int smooth){int intensity, maxIntensity;unsigned char* src = pInput;unsigned char* dst = pOutput;unsigned char* p;int i,j,x,y,t;int offset = nStride-width*3;double scale = smooth/255.0;int _smooth = smooth + 1;int* red = (int*)malloc(sizeof(int)*_smooth);int* green = (int*)malloc(sizeof(int)*_smooth);int* blue = (int*)malloc(sizeof(int)*_smooth);int* intensities = (int*)malloc(sizeof(int)*_smooth);if(pInput == NULL || pOutput == NULL)return;if(width <= 0 || height <= 0)return;if(radius<1)radius = 1;// for each linefor ( y = 0; y < height; y++ ){// for each pixelfor ( x = 0; x < width; x++, src += 3, dst += 3 ){memset(red,0,sizeof(int)*_smooth);memset(green,0,sizeof(int)*_smooth);memset(blue,0,sizeof(int)*_smooth);memset(intensities,0,sizeof(int)*_smooth);// for each kernel rowfor ( i = -radius; i <= radius; i++ ){t = y + i;// skip rowif ( t < 0 )continue;// breakif ( t >= height )break;// for each kernel columnfor ( j = -radius; j <= radius; j++ ){t = x + j;// skip columnif ( t < 0 )continue;if ( t < width ){p = &src[i * nStride + j * 3];intensity = (int)( 0.2125 * (*p) + 0.7154 * (*(p+1))) + 0.0721 * (*(p+2));intensity = intensity * scale;intensities[intensity] ++;// redred[intensity]+= *p;// greengreen[intensity]+= *(p+1);// blueblue[intensity]+= *(p+2);}}}// get most frequent intesitymaxIntensity = 0;j = 0;for ( i = 0; i < _smooth; i++ ){if ( intensities[i] > j ){maxIntensity = i;j = intensities[i];}}// set destination pixel*dst = (unsigned char)( red[maxIntensity] / intensities[maxIntensity] );*(dst+1) = (unsigned char)( green[maxIntensity] / intensities[maxIntensity] );*(dst+2) = (unsigned char)( blue[maxIntensity] / intensities[maxIntensity] );}src += offset;dst += offset;}free(red);free(green);free(blue);free(intensities);}



原创粉丝点击