将一副图像转换成油画
原创性声明:下面代码是本人改写自C#语言编写的软件改写自PhotoSprite (Version 3.0 。2006。由 联骏 编写)。由使用OpenCV300编写。
先看一下效果
算法未作不论什么优化,优化算法能够看Photoshop 油画效果滤镜。
算法原理也不用细说了,源代码之前,了无秘密。
代码
cv::Mat OilPaint(cv::Mat I,int brushSize, int coarseness)
{
assert(!I.empty());
if (brushSize < 1) brushSize = 1;
if (brushSize > 8) brushSize = 8;
if (coarseness < 1) coarseness = 1;
if (coarseness > 255) coarseness = 255;
int width = I.cols;
int height = I.rows;
int lenArray = coarseness + 1;
int* CountIntensity = new int[lenArray];
uint* RedAverage = new uint[lenArray];
uint* GreenAverage = new uint[lenArray];
uint* BlueAverage = new uint[lenArray];
/// 图像灰度化
Mat gray;
cvtColor(I,gray,COLOR_BGR2GRAY);
/// 目标图像
Mat dst = Mat::zeros(I.size(),I.type());
for(int nY = 0;nY <height; nY++)
{
// 油画渲染范围上下边界
int top = nY - brushSize;
int bottom = nY+ brushSize+1;
if(top<0) top = 0;
if(bottom >=height) bottom = height - 1;
for(int nX = 0;nX<width;nX++)
{
// 油画渲染范围左右边界
int left = nX - brushSize;
int right = nX +brushSize+1;
if(left<0) left = 0;
if(right>=width) right = width - 1;
//初始化数组
for(int i = 0;i <lenArray;i++)
{
CountIntensity[i] = 0;
RedAverage[i] = 0;
GreenAverage[i] = 0;
BlueAverage[i] = 0;
}
// 下面这个内循环相似于外面的大循环
// 也是油画特效处理的关键部分
for(int j = top;j<bottom;j++)
{
for(int i = left;i<right;i++)
{
uchar intensity = static_cast<uchar>(coarseness*gray.at<uchar>(j,i)/255.0);
CountIntensity[intensity]++;
RedAverage[intensity] += I.at<Vec3b>(j,i)[2];
GreenAverage[intensity]+= I.at<Vec3b>(j,i)[1];
BlueAverage[intensity] += I.at<Vec3b>(j,i)[0];
}
}
// 求最大值,并记录下数组索引
uchar chosenIntensity = 0;
int maxInstance = CountIntensity[0];
for(int i=1;i<lenArray;i++)
{
if(CountIntensity[i]>maxInstance)
{
chosenIntensity = (uchar)i;
maxInstance = CountIntensity[i];
}
}
dst.at<Vec3b>(nY,nX)[2] = static_cast<uchar>(RedAverage[chosenIntensity] / static_cast<float>(maxInstance));
dst.at<Vec3b>(nY,nX)[1] = static_cast<uchar>(GreenAverage[chosenIntensity] / static_cast<float>(maxInstance));
dst.at<Vec3b>(nY,nX)[0] = static_cast<uchar>(BlueAverage[chosenIntensity] / static_cast<float>(maxInstance));
}
}
delete [] CountIntensity;
delete [] RedAverage;
delete [] GreenAverage;
delete [] BlueAverage;
#ifdef _DEBUG
imshow("dst",dst);
waitKey();
#endif
return dst;
}
兴许
可是这种油画效果。还是感觉欠缺了什么。好吧,再拿了一张油画纹理渲染一下吧。事实上比較简单你能够使用正片叠底混合算法就能够了。
先看一下效果。(事实上你也能够觉得这种效果不好看,囧)
再来一张
还有一张
界面
界面致谢。人在旅途。
好了,油画滤镜介绍完成。
转载请保留下面信息
作者 | 日期 | 联系方式 |
---|---|---|
风吹夏天 | 2015年10月31日 | wincoder#qq.com |