Code Monkey home page Code Monkey logo

photo-cartoonization's Introduction

原始图片 漫画风格生成后

图像漫画风格生成算法

山东大学(威海) 18级 数据科学与人工智能 孙易泽

项目简介

本项目通过对原有图片进行处理后,生成具有漫画风格的图片。

具体处理方法如下:先将原有图像进行双边滤波,在保留边缘特征的同时对图像进行模糊处理;接着通过Sobel算子对图像进行边缘检测,对图片边缘区域进行加重处理;最后再增强图像颜色饱和度,达到漫画的效果。

本项目使用Matlab语言进行编程,有关项目更多信息和完整代码,可以查看文章结尾附录,或个人github:

关键词:图像滤波 边缘提取

图片分析

要想将图片处理成漫画风格,首先要了解漫画风格构图特点。漫画相比于真实图片,主要存在以下几点差异:

  • 相比于真实图片,漫画细节较少
  • 漫画色彩相对真实图片更为鲜明
  • 漫画在物品边缘处存在线条勾勒

接下来我们将对于以上三点,逐步对图片进行效果处理。

图像滤波

在图像滤波过程中,我们要使图片细节变少,进行模糊化处理,同时保留图像一定的边缘特征。最为常见的模糊化处理图像的算法为高斯算法,但是高斯算法无法对图像进行边缘保持,会将整体图像模糊化。边缘保持的图像平滑算法主要有双边滤波、导向滤波等,在本项目中选取双边滤波对图像进行处理。

双边滤波在高斯滤波的基础上,将高斯权系数替换为高斯函数和图像亮度信息的乘积,优化过的权系数再进行卷积计算。相比于普通的高斯函数,增加了亮度差值的考虑,使得当点与点直接亮度存在较大差异时,通过权重能较好的保留原有的边缘信息。有关双边滤波的具体计算公式如下:

  • 各点对应权重: $$ w(i,j,k,l)=w_d(i,j,k,l)*w_r(i,j,k,l)=exp(-\frac{(i-k)^2+(j-l)^2}{2\sigma_d^2}-\frac{||f(i,j)-f(k,l)||^2}{2\sigma_r^2}) $$ 其中$w_d$为像素位置欧式距离决定的权值,$w_r$为像素值的差值决定的权值

  • 最后计算公式如下: $$ g(i,j) = \frac{\sum_{kl}f(k,l)w(i,j,k,l)}{\sum_{kl}w(i,j,k,l)} $$

根据以上原理,我们通过Matlab对双边滤波进行编程,代码如下:

% 双边滤波函数
function img_f = bilateral_filter(img,d,arg) 
    img = applycform(img,makecform('srgb2lab'));  
    [x,y,~]=size(img);
    img_f=zeros(x,y);
    % 扩大整体图像边界,保证生成后图像与原有图像维度一致
    extract = extract_region(img,d,x,y);
    length = 2*d+1;
    % 根据欧式距离,用高斯函数计算距离权重
    G = fspecial('gaussian',[length,length],arg(1));
    S = zeros(length,length);
	% 对图像逐个计算值权重
    for i=1+d:x+d  
        for j=1+d:y+d
        	% 彩色图像分三通道进行计算
            rawvalue = extract(i-d:i+d,j-d:j+d,1:3);   
            da = rawvalue(:,:,1)-extract(i,j,1);  
            db = rawvalue(:,:,2)-extract(i,j,2);  
            dc = rawvalue(:,:,3)-extract(i,j,3);  
            S = exp(-(da.^2+db.^2+dc.^2)/(2*(arg(2)*100)^2));  
            % 计算总权重
            H = S.*G;  
            % 权重归一化
            H = H./sum(H(:));  
            % 计算各点值
            img_f(i-d,j-d,1) = sum(sum(rawvalue(:,:,1).*H));   
            img_f(i-d,j-d,2) = sum(sum(rawvalue(:,:,2).*H));      
            img_f(i-d,j-d,3) = sum(sum(rawvalue(:,:,3).*H));   
        end   
    end  
    img_f = applycform(img_f,makecform('lab2srgb'));  
end

% 扩大图像边界
function extract = extract_region(img,w,x,y)
    extract = zeros(x + 2 * w, y + 2 * w, 3); 
    % 中间保留原图像
    extract(w +1:w + x,w + 1:w + y,1:3) = img;  
    % 四周分别扩大值为(窗口边长+1)/2
    extract(1:w,w + 1:w + y,1:3) = img(w:-1:1,:,1:3);  
    extract(end - w:end,w + 1:w + y,1:3) = img(end:-1:end - w,:,1:3);  
    extract(:,1:w,1:3) = extract(:,2 * w:-1:w + 1,1:3);  
    extract(:,y + w+1:y + 2*w,1:3) = extract(:,y + w:-1:y + 1,1:3);  
end

最后完成后,可以适当的对图像重复进行本步骤,增加其模糊度。具体效果如下:

原始图片 一次双边滤波 两次双边滤波

边缘提取

接着我们需要对图像的边缘提取,并勾勒出其边缘。

有关边缘提取算法主要有Sobel算子、Laplace算子和Canny算子。Sobel算子相对于其他两种算子来说,在提取边缘时,产生的边缘有强弱,更符合画笔的特征,且其具有一定的抗噪性。所以这里我们选用Sobel算子进行计算,分别计算x方向和y方向上的梯度,并通过平方和开根得到最后的梯度。

提取到边缘后,我们直接用原有图像减去边缘,营造边缘加粗描重的效果,代码如下:

% 提取图像边缘
function img_f = edge_detect(img)
    img_gray = rgb2gray(img);
    % 设定为sobel算子,阈值为0.02
    edge_m = uint8(edge(img_gray, 'sobel', 0.02));
    img_blur = uint8(img*255);
    % 对每个图层减去边缘
    img_f(:,:,1) = img_blur(:,:,1) - img_blur(:,:,1) .* edge_m;
    img_f(:,:,2) = img_blur(:,:,2) - img_blur(:,:,2) .* edge_m;
    img_f(:,:,3) = img_blur(:,:,3) - img_blur(:,:,3) .* edge_m;
end

勾勒完成的图片效果如下:

双边滤波后 边缘提取后

颜色调整

漫画风格对应着较为鲜明的色彩,色彩饱和度指的是色彩的鲜艳程度。我们可以通过调高饱和度,近似达到漫画风格的效果。改变饱和度,意味着像素分量必须朝着或远离像素的亮度值移动。

对于饱和度更改,通常使用原始图像的灰度图像作为模板,来完成内插和外推。具体的实现代码如下:

% 图像饱和度调整
function img_res = color_adjust(img)
    img_double = double(img);
    img_gray = double(rgb2gray(img));
    S_template = img_double;
    % 使用原始图像的灰度图像作为模板,来完成插值和外推
    S_template(:,:,1)=img_gray; 
    S_template(:,:,2)=img_gray;
    S_template(:,:,3)=img_gray;
    % 插值和外推 
    img_res = (-1).*S_template  +2.*img_double;
    img_res = uint8(img_res);
end

颜色调整完成的图片效果如下:

边缘提取后 颜色调整后

总结

以上就是漫画风格图像生成的全部步骤,以下展示这个算法在实际图片中的应用效果如何,以下分别选取了风景照、人物照、静物照进行效果的展示:

原始图片 滤波边缘提取后 最终图像
原始图片 滤波边缘提取后 最终图像
原始图片 滤波边缘提取后 最终图像

附录

以下是完整的matlab源码,或可以访问github:https://github.com/Sun-Yize-SDUWH/Photo-Cartoonization 进行查看。

bilateral_filter.m文件

% 双边滤波函数
function img_f = bilateral_filter(img,d,arg) 
    img = applycform(img,makecform('srgb2lab'));  
    [x,y,~]=size(img);
    img_f=zeros(x,y);
    % 扩大整体图像边界,保证生成后图像与原有图像维度一致
    extract = extract_region(img,d,x,y);
    length = 2*d+1;
    % 根据欧式距离,用高斯函数计算距离权重
    G = fspecial('gaussian',[length,length],arg(1));
    S = zeros(length,length);
	% 对图像逐个计算值权重
    for i=1+d:x+d  
        for j=1+d:y+d
        	% 彩色图像分三通道进行计算
            rawvalue = extract(i-d:i+d,j-d:j+d,1:3);   
            da = rawvalue(:,:,1)-extract(i,j,1);  
            db = rawvalue(:,:,2)-extract(i,j,2);  
            dc = rawvalue(:,:,3)-extract(i,j,3);  
            S = exp(-(da.^2+db.^2+dc.^2)/(2*(arg(2)*100)^2));  
            % 计算总权重
            H = S.*G;  
            % 权重归一化
            H = H./sum(H(:));  
            % 计算各点值
            img_f(i-d,j-d,1) = sum(sum(rawvalue(:,:,1).*H));   
            img_f(i-d,j-d,2) = sum(sum(rawvalue(:,:,2).*H));      
            img_f(i-d,j-d,3) = sum(sum(rawvalue(:,:,3).*H));   
        end   
    end  
    img_f = applycform(img_f,makecform('lab2srgb'));  
end

% 扩大图像边界
function extract = extract_region(img,w,x,y)
    extract = zeros(x + 2 * w, y + 2 * w, 3); 
    % 中间保留原图像
    extract(w +1:w + x,w + 1:w + y,1:3) = img;  
    % 四周分别扩大值为(窗口边长+1)/2
    extract(1:w,w + 1:w + y,1:3) = img(w:-1:1,:,1:3);  
    extract(end - w:end,w + 1:w + y,1:3) = img(end:-1:end - w,:,1:3);  
    extract(:,1:w,1:3) = extract(:,2 * w:-1:w + 1,1:3);  
    extract(:,y + w+1:y + 2*w,1:3) = extract(:,y + w:-1:y + 1,1:3);  
end

edge_detect.m文件

% 提取图像边缘
function img_f = edge_detect(img)
    img_gray = rgb2gray(img);
    % 设定为sobel算子,阈值为0.02
    edge_m = uint8(edge(img_gray, 'sobel', 0.02));
    img_blur = uint8(img*255);
    % 对每个图层减去边缘
    img_f(:,:,1) = img_blur(:,:,1) - img_blur(:,:,1) .* edge_m;
    img_f(:,:,2) = img_blur(:,:,2) - img_blur(:,:,2) .* edge_m;
    img_f(:,:,3) = img_blur(:,:,3) - img_blur(:,:,3) .* edge_m;
end

color_adjust.m文件

% 图像饱和度调整
function img_res = color_adjust(img)
    img_double = double(img);
    img_gray = double(rgb2gray(img));
    S_template = img_double;
    % 使用原始图像的灰度图像作为模板,来完成插值和外推
    S_template(:,:,1)=img_gray; 
    S_template(:,:,2)=img_gray;
    S_template(:,:,3)=img_gray;
    % 插值和外推 
    img_res = (-1).*S_template  +2.*img_double;
    img_res = uint8(img_res);
end

main.m文件

clc,clear,close all;

img = imread('image path here');
figure,subplot(2,2,1),imshow(img);
title('原始图像')

img = double(img)/255;
result = bilateral_filter(double(img),8,[3 0.1]);
subplot(2,2,2),imshow(result);
title('双边滤波后')

result = edge_detect(result);
subplot(2,2,3),imshow(result);
title('边缘加重')

result = color_adjust(result);
subplot(2,2,4),imshow(result);
title('颜色调整')
imwrite(result,'result.png')

除此之外,代码还编写了GUI界面,以下是程序GUI截图

GUI界面

photo-cartoonization's People

Contributors

sun-yize avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

photo-cartoonization's Issues

cartoon???

which difference is your cartoon.m file? it is not made in the main.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.