Python+OpenCV实现照片卡通化:从边缘检测到颜色量化
简介:本资源是一个基于Python实现的照片卡通化转换系统,面向图像处理初学者、计算机视觉爱好者及数字艺术创作者,解决真人照片自动转为卡通风格图像的技术需求,适用于社交头像生成、游戏素材制作与AI艺术创作等场景。压缩包共24个文件,包含15个核心Python脚本(涵盖人脸检测、分割、特征提取、风格迁移模型调用等模块)、3个JPG/PNG示例图(含测试原图与效果对比图)、3份Markdown文档(含英文README与技术说明)、1个LICENSE和1个.gitignore,整体仅2.07MB,轻量易部署。已有116人学习下载,资源结构清晰:models目录封装UGATIT等轻量化网络,utils与dataset模块提供数据预处理与工具函数,train/test脚本支持端到端训练与推理,还额外提供ONNX导出支持。读者可直接运行复现完整卡通化流程,深入理解图像风格迁移的关键环节与工程实践细节。 很多人问过我,一张普普通通的照片,到底是怎么变成漫画风格的?网上那些卡通头像生成器背后到底做了什么?其实用 Python 就能自己写一套完整的 photo-to-cartoon 卡通化图像转换程序,而且核心代码量远比想象中少。这个项目是我在给朋友批量做头像时捣鼓出来的,前前后后踩了不少坑,今天把我的实现思路、完整源码、还有调参经验全部整理出来。如果你正在学 OpenCV,或者手上正好有一批图片需要卡通化处理,这篇文章可以直接照着抄作业。
1. 项目整体设计与技术选型
1.1 卡通化处理的三条主流技术路线
开门见山,Python 做卡通化并不是只有一种办法,我捋了捋目前市面上常用的路线,大概分成三类。第一类是传统图像处理路线,基于 OpenCV 的边缘提取加颜色量化,也就是我今天要分享的方案。第二类是深度学习路线,比如 AnimeGAN、CartoonGAN 这类生成对抗网络模型,效果确实更接近商业软件,但需要准备训练好的模型权重,运行环境也得有 GPU 才舒服。第三类是混合方案,先用 OpenCV 做预处理,再引入深度学习模型做风格迁移。
这三条路线各有各的道理。深度学习方案效果好,但入门门槛高,一张图跑下来在 CPU 上可能得等十几秒,而且模型文件动辄几百兆。传统 OpenCV 方案胜在轻量、速度快、依赖少,一张 1080p 的图在普通笔记本上也就几百毫秒到一两秒,并且每一步都可以手动干预调参,非常适合作学习和二次开发的基础。
我最终选择以 OpenCV 为主,核心原因是这个方案在“代码量、效果、可解释性”三者之间拿到了最好的平衡。你不需要懂神经网络的反向传播,只需要清楚边缘检测和颜色聚类这两个基础概念,就能完全掌控输出的效果。
1.2 项目目标与功能边界
在动笔写代码之前,先明确这个项目要解决什么问题、不解决什么问题。我的目标是:输入一张彩色照片,输出一张具有漫画线条感和色块感的结果图。线条要有手绘的笔触感,颜色要干净、色块要分明,整体视觉上让人觉得“这是画出来的,不是照片滤镜套出来的”。
那不解决什么问题呢?比如生成日漫风格的大眼睛萌妹,这不是 OpenCV 传统方案能搞定的,那是深度生成模型的活儿。遇到低照度和暗光下的照片,传统方案处理效果也一般,因为暗部细节本来就少,提取出来的边缘会很碎。
搞清楚边界之后,你的心态就不一样了,不会拿它跟商业软件硬比效果,而是把它当成一个可控、可定制的图像处理流水线,这一点非常关键。
1.3 为什么用 OpenCV 而不用 PIL
很多人第一反应是用 Pillow(PIL) 处理图像,毕竟 API 简单。但我要说,做卡通化这种涉及多步滤波和边缘检测的任务,PIL 真的不是首选。OpenCV 在底层做了大量 C++ 优化,像双边滤波、Canny 边缘检测、distanceTransform 这些操作都是高度优化过的,性能比 PIL 里手工实现快一个数量级。
而且 OpenCV 提供了一整套图像处理函数库,读图、滤波、边缘检测、颜色空间转换、形态学操作全部覆盖。PIL 擅长的是图像格式转换和基础几何变换,真要实现双边滤波或者自适应阈值,就得自己写循环遍历像素,那速度简直没法看。
我举个实际例子:一张 1920x1080 的图片,用 OpenCV 的 cvtColor 转换颜色空间大概耗时 10 毫秒,但用 PIL 的 point 操作逐像素处理,可能要好几秒。在图像处理领域,性能就是生产力,选 OpenCV 是没什么悬念的。
2. 卡通化核心流程与原理拆解
2.1 整体流程:三条线的汇合
整个卡通化流程可以拆成三条并行处理的线,最后再汇合。第一条线是边缘检测线,用来提取照片里的轮廓信息;第二条线是颜色平滑线,对原始图像进行保边滤波和颜色量化;第三条线是基础线,保留原图的尺寸和通道信息,最后把边缘和颜色合成到一起。
为什么拆成三条线而不是一条线走到底?因为边缘提取和颜色处理的目标是矛盾的。边缘检测需要的是梯度信息,它希望图像里有明显的像素跳变,所以它对噪点非常敏感。而颜色平滑要做的是把大片区域的颜色统一成一个色块,它需要消除细节纹理。如果在同一条流水线上先做颜色量化再做边缘检测,边缘会被量化过程破坏;反过来先提取边缘再做颜色平滑,边缘图的分辨率可能对不上。
所以正确的做法是分头处理,最后一步做融合,这样每一步的参数都可以独立调节,互不干扰。这也是整套方案设计上最关键的一个点。
2.2 边缘提取:让轮廓有手绘感
边缘提取是整个卡通化效果里最影响“画感”的一步。照片里的大量高-frequency 细节,比如头发丝、衣服褶皱、树叶纹理,如果不处理,直接套用传统 Canny 边缘检测,出来的线条会又细又碎,非常像电路板走线,完全没有手绘的味道。
我的做法是先用中值滤波去除噪点,再用自适应阈值替代固定阈值 Canny。自适应阈值(adaptiveThreshold)的核心思路是:每个像素的阈值由它周围一个小窗口的像素均值决定,这样做的好处是对光照变化不敏感。同一张图里,亮部和暗部的边缘都能被捕捉到,不会出现亮部边缘断掉、暗部边缘糊成一团的情况。
拿到边缘二值图之后,我会对边缘线做两步形态学处理。第一步用 dilate(膨胀)让线条变粗一点,模拟画笔的宽度;第二步用 GaussianBlur(高斯模糊)让线条边缘有一点点柔和渐变。为什么要模糊?手绘线条不是绝对硬边,是有一点笔触的,模糊一点,线条跟色块之间能有过渡,视觉上更接近马克笔的效果。
这里有一个关键细节,边缘提取的模式我用的是 adaptiveThreshold 的 THRESH_BINARY 模式,提取出来的边缘区域像素值是 255,也就是白色。因为后面合成的时候,我希望最终白色线条能够叠加在彩色色块上方,形成“线稿 + 色块”的漫画效果,而用白色做线条色是最自然的选择。
2.3 颜色平滑与量化:把照片变成色块
颜色处理是卡通化的灵魂。照片是连续渐变的色调,而卡通画是扁平化的色块拼接。要把照片变成色块,最直接的方法是做颜色量化,把所有像素的颜色映射到一个有限的调色板上。OpenCV 里最常用的就是 k-means 聚类。
具体来说,我把图片的每个像素当作三维空间的一个点,三维分别对应 B、G、R 通道的值。然后运行 k-means 算法,把所有像素聚成 K 类(比如 K=8 就代表最终只保留 8 种主色调)。每个像素的颜色被替换成它所属类别的中心颜色。这样整张图的颜色就变成了几个大的色块。
不过这里有一个大坑,直接用 k-means 量化会产生大量的椒盐噪点。因为在颜色过渡区域,相邻像素可能会被分到两个不同的类,导致色块边缘出现杂色的孤立点。我的解决办法是结合双边滤波(bilateralFilter)做前置平滑。双边滤波是一种保边滤波器,它在平滑颜色噪声的同时,会保留边缘信息,不会把图像糊成一团。
实操时我把双边滤波重复做了两次,效果会好很多。第一次过滤掉细小的纹理,第二次进一步统一大区域的色调。配合后面 k-means 量化,色块成果会比较干净,不会出现太多杂色点。
2.4 细节加强:弥补卡通化的空间层次感
照片和卡通画之间还有一个重要区别是空间层次感。照片有光影渐变,卡通画则通过不同纯度的色块叠加来体现层次。单纯做边缘检测加颜色量化,输出结果会显得比较“平”,缺少立体感。
我这里补了一步:对量化后的图像做一个轻微的对比度增强,通过调整 cv2.convertScaleAbs 的 alpha 和 beta 参数,让深色区域更深、亮色区域更亮。这一步能让色块之间的边界更明确,视觉上的层次感就出来了。同时,在合成阶段我会把合成图的饱和度适当调高一点,因为卡通画的颜色一般比真实照片更鲜艳。
当然,这个步骤并不是万能的,如果原图本身就非常灰暗,再怎么调对比度也补不回来。比较合适的使用场景是日常拍摄的、光照充足的人像或风景照。遇到特殊光线条件,还是要回头调前面的滤波和量化参数。
3. 完整源码实现与运行说明
3.1 环境依赖准备
开始写代码前,先把环境准备好。这个项目依赖很少,只需要 Python 3.7 以上版本和 OpenCV 库。安装命令如下,Python 3.7 以上版本都兼容,实测没问题。
pip install opencv-python pip install numpy安装时要注意,opencv-python 和 opencv-contrib-python 不要混装,否则可能因为命名空间冲突导致某些函数报出奇怪的错误。另外 numpy 一般会作为 opencv 的依赖自动装好,但为了保险,还是手动装一下,版本尽量新一些,避免 OpenCV 的调用接口对不上。
如果你跑代码的时候提示 module 'cv2' has no attribute 'xxx',八成是 OpenCV 版本太旧了,用下面的命令升级到最新版即可。
pip install --upgrade opencv-python3.2 核心代码实现与逐段解读
直接上核心代码。我把完整的 photo_to_cartoon 实现放在下面,每一段都有注释说明,建议先大致扫一遍,再看后面的参数解读。
import cv2 import numpy as np def photo_to_cartoon(image_path, save_path): # 1. 读取图片 img = cv2.imread(image_path) if img is None: raise ValueError(f"无法读取图片: {image_path}") # 获取尺寸用于后续恢复 h, w = img.shape[:2] # 2. 边缘提取线 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) gray = cv2.medianBlur(gray, 5) edges = cv2.adaptiveThreshold( gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, blockSize=9, C=2 ) # 边缘加粗 + 柔化 kernel = np.ones((3, 3), np.uint8) edges = cv2.dilate(edges, kernel, iterations=1) edges = cv2.GaussianBlur(edges, (3, 3), 0) # 3. 颜色平滑线(双边滤波两次) color = cv2.bilateralFilter(img, d=9, sigmaColor=75, sigmaSpace=75) color = cv2.bilateralFilter(color, d=9, sigmaColor=75, sigmaSpace=75) # 4. 颜色量化(k-means聚类) data = color.reshape((-1, 3)).astype(np.float32) K = 8 criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0) _, labels, centers = cv2.kmeans( data, K, None, criteria, 3, cv2.KMEANS_RANDOM_CENTERS ) centers = np.uint8(centers) quantized = centers[labels.flatten()] quantized = quantized.reshape((h, w, 3)) # 5. 对比度与饱和度增强 quantized = cv2.convertScaleAbs(quantized, alpha=1.15, beta=10) hsv = cv2.cvtColor(quantized, cv2.COLOR_BGR2HSV) hsv[:, :, 1] = cv2.add(hsv[:, :, 1], 30) quantized = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR) # 6. 合成:边缘叠加到颜色图上 edges_inv = cv2.bitwise_not(edges) cartoon = cv2.bitwise_and(quantized, quantized, mask=edges_inv) # 7. 保存结果 cv2.imwrite(save_path, cartoon) print(f"卡通化完成,结果已保存至: {save_path}") return cartoon if __name__ == "__main__": photo_to_cartoon("input.jpg", "output.jpg")3.3 关键参数含义与取值经验
看到代码了,可能有朋友觉得参数太多、不知道从哪调起。我按自己的经验,把最关键、最影响效果的五组参数整理成表格,每个参数都给一个实测过的范围,你调的时候有个方向。
| 参数 | 代码位置 | 作用 | 建议取值范围 | 我的默认值 |
|---|---|---|---|---|
| 中值滤波核直径 | medianBlur 的第二个参数 | 去除灰度图中的噪点 | 3 ~ 9,必须是奇数 | 5 |
| 自适应阈值 blockSize | adaptiveThreshold 的第四个参数 | 决定局部阈值计算窗口大小 | 7 ~ 15,必须是奇数 | 9 |
| 自适应阈值 C | adaptiveThreshold 的第五个参数 | 阈值偏移量,越大边缘越少 | 2 ~ 5 | 2 |
| k-means 聚类数 K | kmeans 的 K | 最终保留的主色调数量 | 4 ~ 12 | 8 |
| 双边滤波 d | bilateralFilter 的第一个参数 | 滤波窗口直径,影响平滑程度 | 5 ~ 15 | 9 |
我详细说说这几个参数的实际体感。
中值滤波核直径如果太小,比如等于 3,基本起不到降噪作用;如果太大,会损失过多细节,边缘线会糊在一起。5 是一个比较平衡的值,大部分场景都不用动。
自适应阈值的 blockSize 非常关键。它决定了每个像素计算阈值时参考的邻域范围。取 7 的时候边缘线条会比较细、容易断;取 15 的时候线条更粗、更连贯,但也会把一些不想要的纹理圈进来。9 是兼顾线条连贯性和干净度的一个经典取值,Adobe 系的卡通滤镜内部也有类似的设置。
C 值是阈值减法偏移量,C 越小边缘越容易检测出来。默认 2 在光线均匀的图上效果很好,如果你的图偏暗,我建议调成 1;如果偏亮,可以把 C 调到 3 或 4,减少过度检测。
聚类数 K 决定了画面的颜色丰富程度。K=4 时色块非常单调,偏扁平插画;K=12 时颜色接近照片,卡通感变弱。如果你的目标是那种海报感的粗颗粒卡通,K=6 会更好;一般的人像卡通化,K=8 我的经验里是最稳妥的。
双边滤波 d 是滤波窗口直径,sigmaColor 和 sigmaSpace 也值得单独说。
3.4 双边滤波参数到底怎么调
双边滤波的 sigmaColor 和 sigmaSpace 是老生常谈但最容易翻车的参数。sigmaColor 控制颜色相似的像素被平滑的范围,sigmaSpace 控制空间距离,两者一起决定了滤波的强度。我把这两个参数的调法做个通俗类比:sigmaColor 像是“容忍度”,容忍度越高,越多的颜色差异会被当作噪声抹平;sigmaSpace 像是“刷子的扫过范围”,范围越大,一次刷掉的区域越大。
我的经验是,对人像照片,sigmaColor 取 60~90、sigmaSpace 取 60~90 比较合适。取小了,皮肤上的瑕疵和噪点压不下去;取大了,整张图会变成蜡像质感,眼睛嘴巴都糊掉。实际调的时候,从 50 开始逐步加,每次加 10,看到边缘开始发虚就回退到上一次的值。
这里有个小技巧,我可以分享给读者:如果想让皮肤显得光滑但眼睛和嘴唇的边界依然分明,可以对图像的不同区域用不同的滤波参数。先粗略地做人脸检测,把皮肤区域单独进行强滤波,其他区域保持弱滤波。不过这属于进阶玩法,入门阶段先用全局参数就够用了。
4. 实操过程与效果调优
4.1 从一张照片到成品:完整操作记录
我拿一张真实的生活照来走一遍完整流程。这张照片是白天户外的半身人像,背景有绿植和天空,脸部皮肤有轻微瑕疵,整体光线偏暖。原图尺寸 2400x1600,对于处理来说信息量很足。
第一步运行默认参数的代码,输出结果整体看下来轮廓线比较明显,但背景绿植的区域出现了大量细碎的边缘线,树叶子一片一片全被勾出来了,显得很乱。第二步我把自适应阈值的 blockSize 从 9 调大到 11,C 值从 2 调到 3,相当于让边缘检测变得更“迟钝”,细碎的小纹理不被当作边缘,背景里的树叶立刻干净了不少。
第三步我把 K 值从 8 调成 7,因为背景的绿色块本来就不需要太多层次,K 值越高背景越细碎。脸部肤色保持得很自然,K=7 没有让肤色的层次感丢失。第四步针对脸部,我调高了双边滤波的 sigmaColor 到 85,皮肤上的细小瑕疵基本消失了,整个面部显得很平滑,但五官边缘依然清晰。
最后把对比度增强的 alpha 从 1.15 调到 1.2,beta 保持不变。输出结果整体画感已经非常接近日系卡通滤镜的风格。整个调优过程大概用了几分钟,每调一版看一眼,很快就到位了。
4.2 遇到负片效果和色调断层怎么处理
调参过程中我遇到一个阴间效果——合成之后的图像像照相底片,颜色完全反转了。排查下来发现是通道顺序的问题。OpenCV 默认读图是 BGR 通道顺序,我一开始在 k-means 量化后没有注意通道顺序,导致后面叠加和保存时颜色对不上。
解决方式很简单,在量化处理时用 BGR 保持原通道顺序,不要在中途转换成 RGB。如果一定要转 RGB 处理,那最后必须转回 BGR 再保存。
另一个常见问题是色调断层,也就是色块与色块之间的过渡位置出现明显的色带,像等高线一样一圈一圈的。这个问题出在 k-means 聚类数 K 值过小。K=4 的时候色带特别明显,因为颜色类别的区分度太大,过渡区没有中间色来缓冲。把 K 值往大了调,比如 8 或者 10,色带就会自然消失。还有一个办法,调完颜色量化之后,对结果再跑一次很轻的双边滤波,可以减少边缘处的条带感,这算是一个小 trick。
4.3 风格化方向调整:不同参数组合的效果差异
调参不只是为了修复问题,它还能制造完全不同的风格方向。我总结了三套比较有代表性的参数组合,打印成表给大家参考,都是踩过坑之后调出来的。
| 风格方向 | K值 | blockSize | C值 | 双边滤波sigmaColor | 对比度alpha | 效果描述 |
|---|---|---|---|---|---|---|
| 淡彩插画风 | 12 | 9 | 2 | 50 | 1.1 | 色彩丰富,线条细,接近水彩插画 |
| 粗颗粒漫画风 | 6 | 13 | 4 | 90 | 1.25 | 色块大而干净,线条粗犷,海报感强 |
| 日系柔和风 | 8 | 11 | 3 | 75 | 1.15 | 中性平衡,线条连贯,肤色自然 |
第三套就是我日常做头像的默认参数,算是综合效果最不容易翻车的组合。第一套偏细腻,适合风景图;第二套偏硬朗,适合人像特写。我建议你拿到代码后,先用这三套参数跑同一张图,把感觉找出来,然后再细调。
5. 常见问题与排查技巧实录
5.1 读图失败和保存失败
OpenCV 读取图片失败是最常见的问题。如果你在 Windows 下路径里带了中文,cv2.imread 大概率直接返回 None,程序报 ValueError。这是因为 OpenCV 的 imread 底层用 C++ 接口读文件,对中文路径支持非常差。我推荐一个稳妥的解决办法,用 numpy 配合 cv2.imdecode,代码可以照抄:
import numpy as np import cv2 def imread_unicode(path): data = np.fromfile(path, dtype=np.uint8) img = cv2.imdecode(data, cv2.IMREAD_COLOR) return img def imwrite_unicode(path, img): ext = path.split('.')[-1] result, encoded = cv2.imencode(f".{ext}", img) if result: encoded.tofile(path)保存的问题跟读取是对称的,直接使用 cv2.imwrite 保存到中文路径可能静默失败,没有任何报错,但文件就是没生成。用上面的 imwrite_unicode 函数就没这个问题,也是我文件操作的标配。
5.2 处理后的图像模糊或噪点密集
如果你输出的图像整体像蒙了一层雾,模糊得厉害,通常不是代码 bug,而是双边滤波过了头。d 值超过 15、sigmaColor 超过 100 之后,图像结构会被破坏,边缘模糊,整体发虚。解决办法很简单,把双边滤波次数从两次改回一次,效果还是不满意就把 sigmaColor 降回 60 左右。
反过来,如果输出图大量噪点,主要原因是中值滤波和双边滤波强度不够。提升第一处参数后,噪点基本能压住。但注意不要过度依赖滤波,比如图片本身分辨率就很低、只有 640x480,那么再强的滤波也救不了,反而会把本就不多的细节全抹掉。
5.3 图片过大导致内存溢出怎么办
处理 4000x3000 的图,运行 k-means 时内存可能会炸。因为每张图变成了一千二百万个三维点参与聚类,内存占用量轻松上 G,低配电脑直接卡死。我的经验是遇到超大图,先缩小再处理,最后把结果放大回原尺寸。
img = imread_unicode("large.jpg") h, w = img.shape[:2] scale = 0.5 small = cv2.resize(img, (int(w * scale), int(h * scale))) cartoon_small = photo_to_cartoon_pipeline(small) cartoon = cv2.resize(cartoon_small, (w, h), interpolation=cv2.INTER_CUBIC)缩小到 50% 处理后放大的效果,肉眼几乎看不出来差别,但内存占用直接降到原来的四分之一。这条经验在做批量处理时尤其值钱,我把整套流程封装成一个函数之后,给一百多张图批量跑完也没再出现卡死的问题。
5.4 批量处理时是否需要逐张调参
需要澄清一件事,批量处理时千万不要每张图都手工调参。正确做法是,先抽样三到五张有代表性的图片,把一套通用参数调好,然后让所有图片跑同一套参数。因为批量场景下一致性比单个最优更重要,如果每张图的参数不同,交付到客户手里或者发布到专栏里会有非常明显的风格漂移,看起来东一块西一块的,非常业余。
我的通用参数表里那套“日系柔和风”就是在二十多张照片上测试之后确定的,大部分生活照都能有不错的效果。个别特殊原因光线太差、或者红眼严重的图,单独拿出来再调,不要让它们影响主参数。
6. 项目扩展与后续优化方向
6.1 从单张图片扩展到批量处理
单张图跑通了,批量就很简单。只需要在 photo_to_cartoon 外层套一层文件遍历,读取一个文件夹里所有图片,将处理结果写到另一个文件夹。这里有一个容易忽略的细节,文件的输出命名不要直接拼在原文件名后面,建议加上一个统一的后缀,方便统一管理和清理,也避免处理中途出错时覆盖原图。
批量处理建议加一个日志输出,把处理成功和失败的图分别记录。OpenCV 遇到某些坏图会直接返回 None,如果你不检查返回值直接调用 shape,程序直接崩溃退出,前面的活都白干了。我的建议是每次读取都判断是否为空,失败就跳过并记录文件名,处理完一起查看。
6.2 卡通化效果从图片扩展到视频
图片做完了自然会想,能不能直接做成视频?是可以的,核心思路就是把视频拆成帧,逐帧做卡通化处理,再拼接回视频。但这里有一个现实问题,视频帧连续播放时,边缘检测的抖动会特别明显,因为相邻两帧的噪声不完全一致,边缘线条会闪来闪去。视频规格比图片要高。
我能给出的缓解方案有两种。第一种是在边缘检测前对帧做一次轻度的时域降噪,也就是把前后两帧做加权平均,降低噪声波动。第二种是固定边缘检测的参数,让抖动只来源于内容变化而不是参数变化,这个操作必须有。实测下来,固定参数后小幅抖动还是没法完全消除,但至少肉眼看起来是可接受的。
6.3 结合深度学习模型的进阶路线
最后说说如果想进阶到深度学习方案,可以从哪里入手。现在开源社区比较成熟的开源项目有 AnimeGAN、CartoonGAN、White-box-Cartoonization 这批。它们的共同特点是都需要预先下载训练好的模型权重文件,然后在推理阶段你只需要像普通调用函数一样使用模型。模型效果确实比本文的 OpenCV 方案好不少,特别是处理复杂光照和细节丰富的场景时。
但要注意的是,这些深度学习模型对输入分辨率敏感,建议的输入尺寸一般是 256x256 或 512x512,需要先做缩放到合适大小再送入模型。它们大概率也是基于 PyTorch 或者 TensorFlow 框架实现的,所以你电脑上需要提前装好对应框架。我自己的体会是,深度学习方案适合对画质要求高的场景,而 OpenCV 方案最适合日常快速出图和当作学习案例,两者并不冲突,反而可以相互补充。
6.4 缓存策略与工程化封装建议
整套流程跑熟之后,强烈建议你把代码封装成一个卡通化处理类,把参数和文件路径全部收敛到配置对象里。这样做的直接好处是后期调整参数非常方便,不用每个调用点都改一遍。
如果处理的图片数量很大,建议加入缓存机制。具体来说,就是计算每张输入图片的 hash 值,在输出目录里检查是否存在相同 hash 对应的输出图。如果存在,直接跳过处理。这样在重跑批量任务时,已经处理过的图片不会白白耗费 CPU 算力,任务从几十秒缩短到几秒,效率提升非常直观。这个做法在真实的工程任务里非常实用,自己写脚本或者接临时需求的时候都用得到。
本文还有配套的精品资源,点击获取
