将一副图像转换成油画
来源:互联网 发布:许蕾姆 知乎 编辑:程序博客网 时间:2024/04/26 07:43
原创性声明:以下代码是本人改写自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;}
后续
但是这样的油画效果,还是感觉欠缺了什么。好吧,再拿了一张油画纹理渲染一下吧。其实比较简单你可以使用正片叠底混合算法就可以了。
先看一下效果。(其实你也可以认为这种效果不好看,囧)
再来一张
另一张
界面
界面致谢,人在旅途。
好了,油画滤镜介绍完毕。
转载请保留以下信息
1 0
- 将一副图像转换成油画
- 新建一副图像
- java 图像特效之油画
- 图像特效---Oilpaint油画滤镜
- 【C#】将Byte转换成图像
- Matlab将图像转换成GIF
- 将图像转换成lmdb格式
- matlab将视频转换成图像帧
- 将jpg图像转换成yuv420p格式
- 在opencv中,如何将二维数组转化为一副图像进行显示?
- [GDI+]如何将一个彩色图像转换成黑白图像
- 如何将一个彩色图像转换成黑白图像
- 如何将一个彩色图像转换成黑白图像
- [GDI+]如何将一个彩色图像转换成黑白图像
- 如何将一个彩色图像转换成黑白图像
- 如何显示一副超大图像
- 将BGR图像转换成HSV颜色空间的转换
- 油画
- 莫比乌斯反演 两种形式
- hdu-1269
- POJ 1789 Truck History 最小生成树 prim
- Keepalived+nginx+redis主从+tomcat一机多实例实现会话共享
- TCP多线程简单聊天系统
- 将一副图像转换成油画
- hdoj 1269 迷宫城堡 【强连通】&&【dfs】
- ZOJ 3469 Food Delivery(区间DP)
- Android ActionBar的基本用法
- 接口和抽象类的区别—Java
- Vickate_Swift2.0的方法总结 及 与C/OC的语法区别
- 动态规划-------最长公共子序列
- C++字符串(Unicode/TCHAR/WCHAR/ASCII/LPSTR/LPCSTR等转换)
- ASP获取数据库表名、库名、字段名的方法