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,一经查实,立即删除!

相关文章

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】存储器扩展设计&…

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 表示…

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

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

黑白图片颜色反转并保存

将图像的黑白颜色反转并保存 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

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

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

Error: Flash Download failed - Target DLL has been cancelled

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

我也谈委托与事件

虽然在博客园里面已经有很多关于C#委托和事件的文章&#xff0c;但是为了自己在学习的过程中&#xff0c;加深对委托的理解&#xff0c;我还是决定写一下自己的心得体会。以备他日在回来复习。委托&#xff08;delegate&#xff09;是一个类&#xff0c;但是这个类在声明的时候…

设计合理的实验方案来研究阳离子改性棉织物与未改性棉的染色动力学性能

染色动力学性能研究染色的什么问题?设计合理的实验方案来研究阳离子改性棉织物与未改性棉的染色动力学性能?并指出如何计算反映染色动力学的主要参数? 标准答案: 染色动力学研究染色速率问题。 为了研究阳离子改性棉纤维及未改性棉纤维对活性染料染色动力学性能,首先要测…

SQL SERVER的锁机制(四)——概述(各种事务隔离级别发生的影响)

SQL SERVER的锁机制&#xff08;一&#xff09;——概述&#xff08;锁的种类与范围&#xff09; SQL SERVER的锁机制&#xff08;二&#xff09;——概述&#xff08;锁的兼容性与可以锁定的资源&#xff09; 本文上接SQL SERVER的锁机制&#xff08;三&#xff09;——概述&a…

如何测定拼色染液中,各染料在不同染色时间时,染液中残留染料量及织物上吸附上染的染料量?

如何测定拼色染液中,各染料在不同染色时间时,染液中残留染料量及织物上吸附上染的染料量? 标准答案: 通常依据各染料对特定波长光的吸光度具有加和性;吸光度值符合朗伯比尔定律,吸光度与浓度成正比;吸光度值分光光度计可以读出;通过联立方程,可以求出拼色各染料在染液中…

oracle云数据库 免费的吗,使用免费的Oracle云服务-创建ATP数据库

前面我们讲了在Oracle的云主机安装数据库&#xff0c;虽然现在安装数据库已经很简单了&#xff0c;但是真正要在生产环境使用&#xff0c;还是需要进行很多配置和优化的&#xff0c;这通常需要专业的人员。而ATP(自治事务性数据库服务)正是Oracle云提供的非常强大的数据库云服务…

请分析比较下列四种染料在相同浓度和相同温度的水染液中的聚集度大小?

请分析比较下列四种染料在相同浓度和相同温度的水染液中的聚集度大小? 标准答案: 染料聚集度从大到小的顺序为:3〉1〉4〉2 比较1-4染料结构差异,1、2共轭体系较短,3、4共轭体系较长,1、3磺酸基在端部,2、4磺酸基在中间; 染料3共轭体系长,范德华力大,而水溶性磺酸基团…

VC++动态链接库深入浅出(转)

1.概论  先来阐述一下DLL(Dynamic Linkable Library)的概念&#xff0c;你可以简单的把DLL看成一种仓库&#xff0c;它提供给你一些可以直接拿来用的变量、函数或类。在仓库的发展史上经历了“无库&#xff0d;静态链接库&#xff0d;动态链接库”的时代。 静态链接库与动态链…

《Two Dozen Short Lessons in Haskell》(二十)分数

《Two Dozen Short Lessons in Haskell》&#xff08;Copyright © 1995, 1996, 1997 by Rex Page&#xff0c;有人翻译为Haskell二十四学时教程&#xff0c;该书如果不用于赢利&#xff0c;可以任意发布&#xff0c;但需要保留他们的copyright&#xff09;这本书是学习 Ha…

数字图像课程工程大作业分析

试题分析&#xff1a; 在连续的视频中对火焰及水柱的轨迹检测&#xff0c;效果如图。 ** 提示&#xff1a; 1、火焰可利用亮度和颜色 2、水柱的轨迹需要先用背景差分获得水柱的连通域&#xff0c;然后利用连通域上的像素点进行曲线的拟合&#xff0c;水枪的位置视为已知&#…

设计电子商务网站的10个技巧(转自ITEye)

导读&#xff1a;随着先进科学技术的应用&#xff0c;人们无需外出逛几个小时来“猎”东西&#xff0c;直接坐在家里就可以购买所需商品&#xff0c;支付服务费用。你只需一台电脑就能搞定。人们习惯了周到的服务和漂亮的橱窗&#xff0c;对网店的选择也不例外。因此&#xff0…

C++语法:vector的使用

【1】vector的创建与元素插入【2】vector元素的访问【3】vector的基本使用技巧【4】vector的几个重要操作【1】vector的创建与元素插入 std::vector<cv::Point> points; //vector容器中保存的类型是Point for (int i 0;i < 10;i) {float x rng.uniform(0, img.cols…