打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
OpenCV-图像漫画效果

作者:翟天保Steven
版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处

实现原理

       OpenCV中有自带的stylization函数,使图像呈漫画状态,可是有点不太像,于是自己重写了一个。定义Cartoon函数,有4个输入参数:src为输入图像;clevel为轮廓参数,调整可改变轮廓的数量;d为双边滤波中的参数d,sigma同时控制双边滤波中的参数sigmaColor和sigmaSpace;size为漫画同色区域的尺寸大小,该值越大,则同色区域面积越大。

       对图像进行中值滤波减少噪声,用Canny提取轮廓线并适当膨胀,反转后均值滤波处理下;对原图进行双边滤波,平滑感更强,符合漫画特征;将处理后的轮廓线点乘双边滤波图,以达到轮廓线加深的效果。

       话不多说,上代码。

功能函数代码

// 漫画效果
cv::Mat Cartoon(cv::Mat src, double clevel,int d,double sigma,int size)
{
// 中值滤波
cv::Mat m;
cv::medianBlur(src, m, 7);
// 提取轮廓
cv::Mat c;
clevel = max(40., min(80., clevel));
cv::Canny(m, c, clevel, clevel *3);
// 轮廓膨胀加深
cv::Mat k = getStructuringElement(MORPH_RECT, Size(2, 2));
cv::dilate(c, c, k);
// 反转
c = c / 255;
c = 1 - c;
// 类型转化
cv::Mat cf;
c.convertTo(cf, CV_32FC1);
// 均值滤波
cv::blur(cf, cf, Size(5, 5));
// 双边滤波
cv::Mat srcb;
d = max(0, min(10, d));
sigma = max(10., min(250., sigma));
cv::bilateralFilter(src, srcb, d, sigma, sigma);
size = max(10, min(25, size));
cv::Mat temp = srcb / size;
temp = temp * size;
// 通道合并
Mat c3;
Mat cannyChannels[] = { cf, cf, cf };
merge(cannyChannels, 3, c3);
// 类型转化
Mat tempf;
temp.convertTo(tempf, CV_32FC3);
// 图像相乘
multiply(tempf, c3, tempf);
// 类型转化
tempf.convertTo(temp, CV_8UC3);
return temp;
}

C++测试代码

#include <iostream>
#include "opencv2/core.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"

using namespace cv;
using namespace std;

cv::Mat Cartoon(cv::Mat src, double clevel, int d, double sigma, int size);

int main()
{
cv::Mat src = imread("test1.jpg");
double clevel = 80.;
int d = 5;
double sigma = 150.;
int size = 20;
cv::Mat result = Cartoon(src, clevel,d,sigma,size);
imshow("src", src);
imshow("result", result);
waitKey(0);
return 0;
}

// 漫画效果
cv::Mat Cartoon(cv::Mat src, double clevel,int d,double sigma,int size)
{
// 中值滤波
cv::Mat m;
cv::medianBlur(src, m, 7);
// 提取轮廓
cv::Mat c;
clevel = max(40., min(80., clevel));
cv::Canny(m, c, clevel, clevel *3);
// 轮廓膨胀加深
cv::Mat k = getStructuringElement(MORPH_RECT, Size(2, 2));
cv::dilate(c, c, k);
// 反转
c = c / 255;
c = 1 - c;
// 类型转化
cv::Mat cf;
c.convertTo(cf, CV_32FC1);
// 均值滤波
cv::blur(cf, cf, Size(5, 5));
// 双边滤波
cv::Mat srcb;
d = max(0, min(10, d));
sigma = max(10., min(250., sigma));
cv::bilateralFilter(src, srcb, d, sigma, sigma);
size = max(10, min(25, size));
cv::Mat temp = srcb / size;
temp = temp * size;
// 通道合并
Mat c3;
Mat cannyChannels[] = { cf, cf, cf };
merge(cannyChannels, 3, c3);
// 类型转化
Mat tempf;
temp.convertTo(tempf, CV_32FC3);
// 图像相乘
multiply(tempf, c3, tempf);
// 类型转化
tempf.convertTo(temp, CV_8UC3);
return temp;
}

测试效果

图1 原图
图2 漫画效果(重)
图3 漫画效果(轻)

       函数对输入的参数作了限制,阈值是由我个人大量测试后设置的,因人而异。clevel阈值40-80,d阈值0-10,sigma阈值10-250,size阈值10-25。效果相比stylization函数一类的方法已经好很多了,后面给大家做一期stylization函数,看看恐怖风漫画是什么样子的哈哈。

       如果函数有什么可以改进完善的地方,非常欢迎大家指出,一同进步何乐而不为呢~

       如果文章帮助到你了,可以点个赞让我知道,我会很快乐~加油!

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存
猜你喜欢
类似文章
伊朗,真的不是你想象的那样:1、伊朗的主体民族是波斯族,最高领袖
图文:专治上呼吸道感染神奇妙方
图文:多人验证的一个鼻炎药方
军工企业都用什么编程语言?
广东75岁老人摔倒,无人敢扶,急得大喊:我不讹人,公交师傅好心送医,却成凶手
2024年全球机场百强公布:中国占据8席,新加坡樟宜机场退居第二
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服