机器学习项目1图片卡通化

图片转为漫画

翻译链接图片漫画化

第一步:导入需要的库

导入OpenCV库用于图片处理
导入easygui
导入numpy 图片存储和处理为数字
导入imageio
导入matplotlib
OS 操作系统交互,这里主要时读取和存储图片路径

import cv2  #用于图像处理
import easygui #
import numpy
import imageio
import sys
import matplotlib.pyplot as plt
import os
import tkinter as tk
from tkinter import filedialog
from tkinter import *
from PIL import ImageTk, Image

第二步 创建一个文件盒用于选择指定文件

构建应用程序的主窗口,按钮、标签和图像将驻留在该窗口中。

top = tk.Tk()
# 窗口大小
top.geometry('400x400')
# 窗口名字
top.title('Cartoonify your Image')
# 窗口背景色
top.configure(background='white')
""" fileopenbox opens the box to choose file
and help us store file path as string """
def upload():
    ImagePath=easygui.fileopenbox()
    cartoonify(ImagePath)

第三步 读取图片

用imreadj将图像读入存为numpy, 颜色顺序是BGR,用cvtColor转换为RGB

# 读取图片
    originalmage = cv2.imread(ImagePath)
    originalmage = cv2.cvtColor(originalmage, cv2.COLOR_BGR2RGB)
#print(image)  #  图片以数字形式存储
# 确认选中了图片
    if originalmage is None:
        print("Can not find any image. Choose appropriate file")
        sys.exit()
    # 第一个状态图,最后输出的3行2列图每个图的大小统一设置为960*540
    ReSized1 = cv2.resize(originalmage, (960, 540))
#plt.imshow(ReSized1, cmap='gray')

第四步 转为灰度图

漫画效果有两个特色:1、显著的边缘 2、平滑的颜色
为了将图片转为漫画,需要做多种转换。首先,转化成灰度图,灰度图更平滑;然后我们获取图片中得边缘部分;最后我们形成一个彩色图并用边缘来mask它。

#转为灰度图
grayScaleImage = cv2.cvtColor(originalmage, cv2.COLOR_BGR2GRAY)
# 在第一个状态上改为灰度图
ReSized2 = cv2.resize(grayScaleImage, (960, 540))
#plt.imshow(ReSized2, cmap='gray')

平滑灰度图

图像平滑处理(归一化块滤波、高斯滤波、中值滤波、双边滤波)
中值滤波:在核范围内所有点的平均值取代中心像素点,核大小一般为基数,这里是5。

#applying median blur to smoothen an image
smoothGrayScale = cv2.medianBlur(grayScaleImage, 5)
ReSized3 = cv2.resize(smoothGrayScale, (960, 540))
#plt.imshow(ReSized3, cmap='gray')

第五步 检索图片的边缘

实现第一个漫画特征 显著的边缘
通过自适应阈值技术adaptiveThreshold()检索边缘并使他们更显著。
cv2.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C, dst=None)
scr:需要进行转换的灰度图,
maxValue,超过阈值设置的颜色(灰度值),
adaptiveMethod(自适应阈值算法)采用ADAPTIVE_THRESH_MEAN_C 即求局部领域块的平均值,
threshold Type 指定阈值类型为THRESH_BINARY即二进制阈值
blockSize:领域大小
C:adaptiveMethod计算出的值减去C为最终的阈值

#retrieving the edges for cartoon effect
#by using thresholding technique
getEdge = cv2.adaptiveThreshold(smoothGrayScale, 255, 
  cv2.ADAPTIVE_THRESH_MEAN_C, 
  cv2.THRESH_BINARY, 9, 9)
ReSized4 = cv2.resize(getEdge, (960, 540))
#plt.imshow(ReSized4, cmap='gray')

第六步 准备蒙版图片

实现第二个漫画特征 平滑的颜色
将上一步得到的边缘盖在一个高亮的图片上,实现漫画化。用双边滤波器bilateralFilter去除噪声使图片在一定上更平滑。
双边滤波是一种非线性的滤波方法,是结合图像的空间邻近度和像素值相似度的一种折衷处理,达到保边去噪的目的,可以做边缘保,一般用高斯滤波去降噪,会较明显地模糊边缘,对于高频细节的保护效果并不明显。9 邻域大小,后面两个300 分别是sigmaColor和SigmaSpace, 用来产生西格玛效果,也就是让图像看起来很糟糕,像水彩一样,消除颜色的粗糙性。

bilateralFilter( InputArray src, OutputArray dst, int d, double sigmaColor,double sigmaSpace,int borderType = BORDER_DEFAULT );
sigmaColor:颜色空间滤波器的sigma值。数值越大,就表明该像素邻域内有更宽广的颜色会被混合到一起,产生较大的半相等颜色区域。
sigmaSpace坐标空间中滤波器的sigma值,数值越大,越远的像素会相互影响.

#applying bilateral filter to remove noise 
#and keep edge sharp as required
colorImage = cv2.bilateralFilter(originalmage, 9, 300, 300)
ReSized5 = cv2.resize(colorImage, (960, 540))
#plt.imshow(ReSized5, cmap='gray')

第七步 漫画化

结合上两步得到的图片
bitwise_and(src1, src2, dst=None, mask=None)
src1、src2:为输入图像
dst:可选输出变量
mask:图像掩膜,可选参数,为8位单通道的灰度图像,用于指定要更改的输出图像数组的元素,即输出图像像素只有mask对应位置元素不为0的部分才输出,否则该位置像素的所有通道分量都设置为0

#masking edged image with our "BEAUTIFY" image
cartoonImage = cv2.bitwise_and(colorImage, colorImage, mask=getEdge)
ReSized6 = cv2.resize(cartoonImage, (960, 540))
#plt.imshow(ReSized6, cmap='gray')

全部代码

import cv2  #用于图像处理
import easygui #
import numpy
import imageio
import sys
import matplotlib.pyplot as plt
import os
import tkinter as tk
from tkinter import filedialog
from tkinter import *
from tkinter import messagebox
from PIL import ImageTk, Image

top = tk.Tk()
# 窗口大小
top.geometry('400x400')
top.title('Cartoonify your Image')
top.configure(background='white')
label = Label(top, background='#CDCDCD', font=('arial', 20, 'bold'))
# fileopenbox 以字符串形式返回选择的路径
def upload():
    ImagePath = easygui.fileopenbox()
    cartoonify(ImagePath)

def cartoonify(ImagePath):
    # 读取图片 imread是cv2通常用于以数字形式保存图片
    originalmage = cv2.imread(ImagePath)
    originalmage = cv2.cvtColor(originalmage, cv2.COLOR_BGR2RGB)

    if originalmage is None:
        print("Can not find any image. Choose appropriate file")

    Resized1 = cv2.resize(originalmage, (960,540))
    #
    plt.imshow(Resized1, cmap='gray')
    # 转成灰度图
    # cvtColor(image,flag)是cv2中将图片转化为flag中提到的色彩空间中的颜色
    grayScaleImage = cv2.cvtColor(originalmage, cv2.COLOR_BGR2GRAY)
    Resized2 = cv2.resize(grayScaleImage, (960,540))
    plt.imshow(Resized2, cmap='gray')
    # 平滑图片用的是模糊效果,用了中值模糊medianBlur()这个函数来平滑一个图片,
    smoothGrayScale = cv2.medianBlur(grayScaleImage, 5)
    Resized3 = cv2.resize(smoothGrayScale,(960,540))
    plt.imshow(Resized3, cmap='gray')
    # 用阈值技术检索卡通效果的边缘
    getEdge = cv2.adaptiveThreshold(smoothGrayScale,255,cv2.ADAPTIVE_THRESH_MEAN_C,
                                    cv2.THRESH_BINARY, 9, 9)
    Resized4 =cv2.resize(getEdge, (960,540))
    plt.imshow(Resized4, cmap='gray')
    # 用一个双边滤波器(bilateraFilter())去除噪声保持边缘锐度
    colorImage =cv2.bilateralFilter(originalmage, 9, 300, 300)
    Resized5 = cv2.resize(colorImage, (960,540))
    plt.imshow(Resized5, cmap='gray')
    cartoonImage = cv2.bitwise_and(colorImage, colorImage, mask=getEdge)
    Resized6 = cv2.resize(cartoonImage, (960,540))
    plt.imshow(Resized6, cmap='gray')
    plt.show()
    images = [Resized1, Resized2, Resized3, Resized4, Resized5, Resized6]
    fig, axes = plt.subplots(3,2, figsize=(8,8), subplot_kw={'xticks':[], 'yticks':[]},
                             gridspec_kw=dict(hspace=0.1, wspace=0.1))

    for i, ax in enumerate(axes.flat):
        ax.imshow(images[i], cmap='gray')

    save1 = Button(top, text='save cartoon image', command=lambda: save(Resized6, ImagePath),
                   padx=30, pady=5)
    save1.configure(background='#364156', foreground='white', font=('arial', 10, 'bold'))
    # 放置位置
    save1.pack(side=TOP, pady=50)

    plt.show()

def save(Resized6, ImagePath):
    # 用imwrite存储图片
    newName = "cartoonified_Image"
    path1 = os.path.dirname(ImagePath)
    extension = os.path.splitext(ImagePath)[1]
    path = os.path.join(path1, newName + extension)
    cv2.imwrite(path, cv2.cvtColor(Resized6, cv2.COLOR_RGB2BGR))
    I = "Image saved by name " + newName + " at " + path
    tk.messagebox.showinfo(title=None, message=I)


# 创建按钮
upload = Button(top, text='Cartoonify an image', command=upload, padx=10, pady=5)
# 背景色、前景色、字体配置
upload.configure(background='#364156', foreground='white', font=('arial',10,'bold'))
upload.pack(side=TOP,pady=50)
top.mainloop()
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值