Opencv实战【4】——图片动漫化处理

博主联系方式:
QQ:1540984562
微信:wxid_nz49532kbh9u22 QQ交流群:750313950

目录

    • 动漫化风格的特点
    • 处理手段
    • 代码
    • 实现效果
    • 总结

动漫化风格的特点

(1)动漫中的细节相对少;
(2)动漫中的边缘轮廓更突出;
(3)动漫的色彩更鲜艳;

处理手段

(1)突出边缘线条
利用canny算子找出边缘,然后利用copyTo函数将边缘加到原图上。
这里用到copyTo函数的第二种用法:

copyTo(roi , mask)

作用是把mask和image重叠以后把mask中像素值为非0(black)的点对应的image中的点变为透明,而保留为0的点。
然而我们发现,canny算子得到的结果是二值化图,其中边缘像素值为255,是白色,非边缘像素是0,是黑色。
若是直接将canny算子得到的结果进行累加,则会是这样的结果。
结果

所以我们要进行处理:

change_g_cannyImage = 255 - g_cannyImage;

非边缘转化为255,边缘转化为0;非边缘会在之后的处理会变为透明,而边缘则会保持原有的数据0,为黑色,这样就会有强化边缘的效果。
主要代码:

//【1】运行canny算子Canny(g_grayImage, g_cannyImage, g_nThresholdValue, g_nThresholdValue/3, 3);cv::Mat g_canny3Image(g_srcImage.rows, g_srcImage.cols, CV_8UC3, cv::Scalar(0,0,0));//【2】贴图//(将边缘变为黑色)Mat change_g_cannyImage;change_g_cannyImage = 255 - g_cannyImage;//将单通道转化为三通道cvtColor(change_g_cannyImage, g_canny3Image, COLOR_GRAY2BGR);//image.copyTo(imageROI,mask), 作用是把mask和image重叠以后把mask中像素值为0(black)的点对应的image中的点变为透明,而保留其他点。Mat bianyuan_dst;g_srcImage.copyTo(bianyuan_dst, g_canny3Image);

效果:
效果
(2)弱化与去除细节
这里的细节是除了边缘外的,只在区域的内部进行弱化。这时就需要使用双边滤波。

所谓“细节”,从图像处理的角度看来就是图像中的高频成分。要想去除高频成分,自然而然就要用到滤波(filtering)的方法。常用的滤波器有均值滤波器、高斯滤波器、中值滤波器等。但是,这些常用滤波器都有一个共同的问题——会弱化所有的高频信息。而很不幸的是,图像中的边缘也属于高频信息(因为边缘意味着图像在这里产生了突变,突变就意味着高频)。因此常用滤波器会将我们本应突出的边缘一起弱化模糊。
这种情况下就要让双边滤波器(Bilateral filter)出场了。这种滤波器的特点是可以“保边滤波”(或者叫“区域平滑”,Region smoothing)。顾名思义,就是可以只模糊区域内部而保留清晰的边缘。为了搞明白双边滤波器为什么有这样的效果,首先来说一下高斯滤波器。高斯滤波器,或者说高斯滤波模板,其中的各个点的值仅与该点到模板中心点的空间距离有关,而并没有考虑各个点与中心点的相似度(即像素值的接近程度),这样就导致无论是变化不大的区域内部点,还是突变的边缘点,只要和中心的距离相同,那就同等对待。
而双边滤波器就是在高斯滤波器基础上加上了相似度权重,在高斯滤波模板的每个点上再乘以一个与中心点的相似度系数(即“相似度权重”),从而将边缘与内部区分处理。相似度权重计算方法和高斯滤波模板中各点值(可以称为“高斯权重”)的计算方法相同,只不过高斯权重是将该点到中心的距离代入高斯函数计算,而相似度权重是将该点与中心的像素相似度(比如该点像素值与中心像素值的欧氏距离,或者直接求二者的差值)代入高斯函数计算得到。

//【3】双边滤波Mat lvbo_dst;bilateralFilter(bianyuan_dst, lvbo_dst, g_nkernelValue, g_nkernelValue * 2, g_nkernelValue / 2);

(3)让图像色彩更鲜艳
提高色彩饱和度。
方法:
1、RGB转HSV,且提取原图像的S通道
2、乘上一个大于1的数,并且对值进行限幅
3、将修改后的S通道替换掉原本的S通道,并将3个通道合并
4、HSV转为RGB

//【4】修改图像的颜色的饱和度Mat hsv_image,hsv_dst;cvtColor(lvbo_dst, hsv_image, COLOR_BGR2HSV);vector<Mat> channels;split(hsv_image, channels);Mat S_Mat;float k = g_nS*1.0f / 100;channels.at(1).copyTo(S_Mat);cv::Mat S_dst(S_Mat.rows, S_Mat.cols, CV_8UC1, cv::Scalar(0));//S_dst = S_Mat * k;H_mul_k(&S_Mat, &S_dst,k);//将修改后的S与原来的H,V进行mergechannels[1] = S_dst.clone();	//深复制merge(channels, hsv_dst);//将修改后的HSV转为RGB图Mat RGB_dst;cvtColor(hsv_dst, RGB_dst, COLOR_HSV2BGR);

代码

#include <opencv2/opencv.hpp>
#include "opencv2/features2d.hpp"
#include <iostream>
#include "windows.h"
#include <stdio.h>
#include <time.h>
#include <math.h>  
#define WINDOW_NAME "【程序窗口】"			
using namespace cv;
using namespace std;
//RNG g_rng(12345);//对照片进行动漫化一般需要四个步骤
//1、边缘检测
//2、将边缘检测得到的边缘 以黑色的形式贴在原来的画上。
//3、对贴了边缘的图进行双边滤波,双边滤波可以较好的滤波的同时保留边缘。
//4、修改图像的颜色的饱和度,本文采用的是将RGB转化为HSV空间,然后调整S分量。//*--------------------------【全局变量声明】-------------------------------------*/
int g_nThresholdValue = 100;	//canny参数值
int g_nkernelValue = 3;	//双边滤波核大小
int g_nS = 100;	//双边滤波核大小
Mat g_srcImage, g_grayImage,g_cannyImage,g_dstImage;//*--------------------------【全局函数声明】-------------------------------------*/
void on_CannyThreshold(int, void*);	//回调函数/****照片动漫化示例**********/
int main()
{//载入原图g_srcImage = imread("D:\\opencv_picture_test\\HOG行人检测\\timg.jpg");//加载原图if (g_srcImage.empty()){printf("Could not find the image!\n");return -1;}g_grayImage.create(g_srcImage.size(), g_srcImage.type());		//创建一个同大小类型的矩阵cvtColor(g_srcImage, g_grayImage,COLOR_BGR2GRAY);//imshow("【原图的灰度图】", g_grayImage);//进行均值滤波操作blur(g_grayImage, g_grayImage, Size(3, 3));namedWindow(WINDOW_NAME, WINDOW_NORMAL);//WINDOW_NORMAL允许用户自由伸缩窗口//【3】创建窗口 并 显示原图//imshow("原始图", g_srcImage);//【4】创建滑动条来控制阈值createTrackbar("canny参数值", WINDOW_NAME, &g_nThresholdValue, 255, on_CannyThreshold);createTrackbar("双边滤波核", WINDOW_NAME, &g_nkernelValue, 25, on_CannyThreshold);createTrackbar("S扩大", WINDOW_NAME, &g_nS, 300, on_CannyThreshold);//【5】初始化自定义的阈值回调函数on_CannyThreshold(0, 0);while (1){if (waitKey(10) == 27) break;		//按下Esc 退出}return 0;}void H_mul_k(Mat* srcImage, Mat* dstImage, float k)
{int height = (*srcImage).rows;int width = (*srcImage).cols;for (int j = 0; j < height; j++){for (int i = 0; i < width; i++){int zhi = (*srcImage).at<uchar>(j, i) * k;if (zhi >= 255) zhi = 255;else if (zhi <= 0) zhi = 0;else zhi = zhi;(*dstImage).at<uchar>(j, i) = zhi;}}
}
//*--------------------------【on_Threshold 函数】-------------------------------------*/
void on_CannyThreshold(int, void*)
{//【1】运行canny算子Canny(g_grayImage, g_cannyImage, g_nThresholdValue, g_nThresholdValue/3, 3);cv::Mat g_canny3Image(g_srcImage.rows, g_srcImage.cols, CV_8UC3, cv::Scalar(0,0,0));//【2】贴图//将canny图反转(将边缘变为黑色)Mat change_g_cannyImage;//change_g_cannyImage = g_cannyImage < 100;		//非边缘转化为255,边缘转化为0;非边缘会在之后的处理会变为透明,而边缘则会保持原有的数据0change_g_cannyImage = 255 - g_cannyImage;//将单通道转化为三通道cvtColor(change_g_cannyImage, g_canny3Image, COLOR_GRAY2BGR);//image.copyTo(imageROI,mask), 作用是把mask和image重叠以后把mask中像素值为0(black)的点对应的image中的点变为透明,而保留其他点。Mat bianyuan_dst;g_srcImage.copyTo(bianyuan_dst, g_canny3Image);//【3】双边滤波Mat lvbo_dst;bilateralFilter(bianyuan_dst, lvbo_dst, g_nkernelValue, g_nkernelValue * 2, g_nkernelValue / 2);//【4】修改图像的颜色的饱和度Mat hsv_image,hsv_dst;cvtColor(lvbo_dst, hsv_image, COLOR_BGR2HSV);vector<Mat> channels;split(hsv_image, channels);Mat S_Mat;float k = g_nS*1.0f / 100;channels.at(1).copyTo(S_Mat);cv::Mat S_dst(S_Mat.rows, S_Mat.cols, CV_8UC1, cv::Scalar(0));//S_dst = S_Mat * k;H_mul_k(&S_Mat, &S_dst,k);//将修改后的S与原来的H,V进行mergechannels[1] = S_dst.clone();	//深复制merge(channels, hsv_dst);//将修改后的HSV转为RGB图Mat RGB_dst;cvtColor(hsv_dst, RGB_dst, COLOR_HSV2BGR);imshow(WINDOW_NAME, RGB_dst);
}

实现效果

原图

漫画图

总结

这种方法其实只能对部分景象图有比较好的漫画效果,对人的脸部面容效果其实并不是很好。
似乎是有根据深度学习训练出来的算法,能够对人脸面容实现很好的动漫化:
如何用深度学习模型为自己做个漫画画像
零门槛人像转卡通、GIF表情包
这两个链接并没有相关代码,原理还是很复杂的,以后再进行研究。

Reference:

图片动漫化处理原理
opencv 照片动漫风格
RGB、HSV、HSI颜色空间
OpenCV cvtColor()函数
opencv中的merge函数
openCv——copyTo()的形式详解

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/378524.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

nextshort_Java扫描仪的nextShort()方法与示例

nextshort扫描器类的nextShort()方法 (Scanner Class nextShort() method) Syntax: 句法&#xff1a; public short nextShort();public short nextShort(int rad);nextShort() method is available in java.util package. nextShort()方法在java.util包中可用。 nextShort() …

php 生成css文件怎么打开,php生成html文件的多种步骤介绍

//定义日期函数functiongetdatetime(){$datetimegetdate();$strReturn$datetime["year"]."-";$strReturn$strReturn.$datetime["mon"]."-";$strReturn$strReturn.$datetime["mday"];return$strReturn;}//定义时间函数(文件名…

08-KNN手写数字识别

标签下载地址 文件内容备注train-images-idx3-ubyte.gz训练集图片&#xff1a;55000张训练图片&#xff0c;5000张验证图片train-labels-idx1-ubyte.gz训练集图片对应的数字标签t10k-images-idx3-ubyte.gz测试集图片&#xff1a;10000张图片t表示test&#xff0c;测试图片&…

MFC odbc访问远程数据库

首先&#xff0c;MFC通过ODBC访问数据库&#xff0c;主要使用两个类&#xff0c;一个是CDataBase&#xff0c;一个是CRecordset。第一个是用于建立数据库连接的&#xff0c;第二个是数据集&#xff0c;用来查询的。步骤如下&#xff1a;1.实例化一个CDataBase对象&#xff0c;并…

微机原理——扩展存储器设计

目录【1】存储器的层次结构【2】存储器的分类【3】SRAM1、基本原理&#xff1a;2、结构&#xff1a;3、芯片参数与引脚解读&#xff1a;4、CPU与SRAM的连接方式【4】DRAM1、基本原理&#xff1a;2、结构3、芯片引脚解读&#xff1a;【5】存储器系统设计【6】存储器扩展设计&…

floatvalue 重写_Java Number floatValue()方法与示例

floatvalue 重写Number类floatValue()方法 (Number Class floatValue() method) floatValue() method is available in java.lang package. floatValue()方法在java.lang包中可用。 floatValue() method is used to return the value denoted by this Number object converted …

array_column php什么版本可以用,array_column兼容php5.5以下版本

gistfile1.txt// ----------------------------------------------------------------------// |获取二维数组中指定的一列&#xff0c;PHP5.5以后有专用函数array_column()// ----------------------------------------------------------------------// |param array $arr// …

。net学习之控件的使用注意点

jQuery使用 1、自定义属性的使用<script>$(#xwjj_i_main br[brinfoPd_KangQiao_Subject_Xwjj_br_1]).hide();</script> 2、ready代码块$(document).ready(function(){ //你的代码}); 3、简单的特效hide&#xff08;&#xff09;$("a").click(function()…

09-CNN手写数字识别

CNN卷积神经网络的本质就是卷积运算 维度的调整&#xff1a; tf.reshape(imageInput,[-1,28,28,1]) imageInput为[None,784]&#xff0c;N行* 784维 调整为 M28行28列*1通道 即&#xff1a;二维转化为四维数据 参数一&#xff1a;等价于运算结果M 参数二&#xff1a;28 28 表示…

【转】左值与右值

出处&#xff1a;http://www.embedded.com/electronics-blogs/programming-pointers/4023341/Lvalues-and-Rvalues C and C enforce subtle differences on the expressions to the left and right of the assignment operator If youve been programming in either C or C for…

Opencv将处理后的视频保存出现的问题

问题描述&#xff1a; 代码运行过程中&#xff0c;imshow出来的每帧的效果图是正确的&#xff0c;但是按照网上的方法保存下来却是0kb&#xff0c;打开不了。 参考的网上的一些方法&#xff0c;均是失败的&#xff0c;具体原因我也不清楚&#xff1a; 1、例如我这样设置&#x…

Java Number shortValue()方法与示例

Number类shortValue()方法 (Number Class shortValue() method) shortValue() method is available in java.lang package. shortValue()方法在java.lang包中可用。 shortValue() method is used to return the value denoted by this Number object converted to type short (…

MATLAB可以打开gms文件吗,gms文件扩展名,gms文件怎么打开?

.gms文件类型&#xff1a;Gesture and Motion Signal File扩展名为.gms的文件是一个数据文件。文件说明&#xff1a;Low-level, binary, minimal but generic format used to organize and store Gesture and Motion Signals in a flexible and optimized way; gesture-related…

黑白图片颜色反转并保存

将图像的黑白颜色反转并保存 import cv2 # opencv读取图像 img cv2.imread(rE:\Python-workspace\OpenCV\OpenCV/YY.png, 1) cv2.imshow(img, img) img_shape img.shape # 图像大小(565, 650, 3) print(img_shape) h img_shape[0] w img_shape[1] # 彩色图像转换为灰度图…

家猫WEB系统

现在只放源码在些.为它写应用很简单有空整理文档演示地址:jiamaocode.com/os/ 源码&#xff1a;http://jiamaocode.com/ProCts/2011/04/14/1918/1918.html转载于:https://www.cnblogs.com/jiamao/archive/2011/04/16/2018339.html

C# DataRow数组转换为DataTable

public DataTable ToDataTable(DataRow[] rows) { if (rows null || rows.Length 0) return null; DataTable tmp rows[0].Table.Clone(); // 复制DataRow的表结构 foreach (DataRow row in rows) tmp.Rows.Add(row); // 将DataRow添加…

plesk 运行不了php,如何在Plesk中使用composer(使用其他版本的PHP运行Composer)

对于基于Plesk的服务器, composer的默认安装将使用系统安装的PHP版本, 而不使用Plesk所安装的任何版本。尽管Composer至少需要PHP 5.3.2, 但是当你尝试在需要特定版本PHP的项目中安装依赖项时, 就会出现问题。例如, 如果你有一个至少需要PHP 7.2的项目, 并且系统的默认PHP安装是…

Java Calendar hashCode()方法与示例

日历类hashCode()方法 (Calendar Class hashCode() method) hashCode() method is available in java.util package. hashCode()方法在java.util包中可用。 hashCode() method is used to retrieve the hash code value of this Calendar. hashCode()方法用于检索此Calendar的哈…

Error: Flash Download failed - Target DLL has been cancelled

博主联系方式: QQ:1540984562 QQ交流群:892023501 群里会有往届的smarters和电赛选手,群里也会不时分享一些有用的资料,有问题可以在群里多问问。 由于换了新电脑,keil重装了下,然而之前的MCU的支持包没有安装,以及一些其他的问题,导致可以编译但是不能将程序烧录到单片…

设计一个较为合理的实验方案来研究芳纶纤维的染色热力学性能

请你设计一个较为合理的实验方案来研究芳纶纤维的染色热力学性能?包括吸附等温线、亲和力、染色热和染色熵的测定,并指出实验中应注意哪些事项来减少实验误差? 标准答案: 染色热力学理论研究染色平衡问题。研究染色热力学性能:首先研究选择适宜的染料 吸附等温线类型测定…