深入了解Python和OpenCV:图像的卡通风格化
前言
当今数字时代,图像处理和美化已经变得非常普遍。从社交媒体到个人博客,人们都渴望分享独特且引人注目的图片。本文将介绍如何使用Python编程语言和OpenCV库创建令人印象深刻的卡通风格图像。卡通风格的图像具有艺术性和创意,它们可以用于图像编辑、创意表达以及增加娱乐价值。
文章目录
- 前言
- 1. 准备工作
- 2. 读取和显示图像
- 3. 创建边缘掩膜
- 4. 颜色量化
- 5. 图像处理和效果增强
- 6. 完整代码
- 总结
1. 准备工作
在开始之前,您需要安装以下必要的库:
- OpenCV (cv2)
- NumPy
如果您还没有安装这些库,可以使用pip进行安装。
pip install opencv-python numpy
2. 读取和显示图像
首先,我们将介绍如何使用OpenCV读取图像文件并在窗口中显示它们。这是我们处理图像的第一步。
# 读取文件
def read_file(filename: str) -> np.ndarray:try:img = cv2.imread(filename)if img is None:raise ValueError("Invalid file path or file format.")return imgexcept:raise ValueError("Invalid file path or file format.")# 显示图片
def display_image(img: np.ndarray, window_name: str) -> None:cv2.imshow(window_name, img)cv2.waitKey()
在这个步骤中,我们定义了一个名为read_file的函数,它接受一个文件名作为参数,并返回一个NumPy数组表示的图像。如果文件路径无效或图像格式不受支持,函数将引发异常。
我们定义了一个名为display_image的函数,它接受两个参数:要显示的图像和窗口的名称。函数将图像显示在指定的窗口中,并等待用户按下任意键后关闭窗口。这个简单的步骤允许我们在进行后续处理之前,查看原始照片的外观。
3. 创建边缘掩膜
接下来,我们将图像转化为卡通风格的第一步是创建边缘掩膜。我们将使用边缘检测技术来实现这一目标。
# 边缘掩膜
def edge_mask(image: np.ndarray, line_size: int, blur_value: int) -> np.ndarray:if not isinstance(line_size, int) or not isinstance(blur_value, int) or line_size < 1 or blur_value < 1:raise ValueError("Invalid value for 'line_size' or 'blur_value' parameter. Must be a positive integer.")gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)gray_blur = cv2.medianBlur(gray, blur_value)edges = cv2.adaptiveThreshold(gray_blur, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, line_size, blur_value)return edges
在这个步骤中,我们定义了一个名为edge_mask的函数,它接受三个参数:图像、线条大小(控制边缘粗细)和模糊程度。函数将图像转换为灰度图,然后应用中值模糊和自适应阈值处理,以创建边缘掩膜。
4. 颜色量化
卡通风格的图像通常具有较少的颜色。我们将使用K-Means聚类算法来减少图像中的颜色数量。
# 颜色量化
def color_quantization(image: np.ndarray, num_colors: int) -> np.ndarray:if not isinstance(num_colors, int) or num_colors < 1:raise ValueError("Invalid value for 'num_colors' parameter. Must be a positive integer.")# 转换图片data = np.float32(image).reshape((-1, 3))# 设置KMeans聚类参数kmeans_criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 20, 0.001)flags = cv2.KMEANS_RANDOM_CENTERS# 执行KMeans聚类_, labels, centers = cv2.kmeans(data, num_colors, None, kmeans_criteria, 10, flags)centers = np.uint8(centers)processed_image = centers[labels.flatten()]processed_image = processed_image.reshape(image.shape)# 应用颜色增强hsv_image = cv2.cvtColor(processed_image, cv2.COLOR_BGR2HSV)hsv_image[:, :, 1] = hsv_image[:, :, 1] * 1.5 # 增强饱和度enhanced_image = cv2.cvtColor(hsv_image, cv2.COLOR_HSV2BGR)return enhanced_image
在这个步骤中,我们定义了一个名为color_quantization的函数,它接受两个参数:图像和要使用的颜色数量。函数首先将图像转换为数据矩阵,然后使用K-Means聚类算法将图像颜色量化为指定数量的颜色。最后,我们增强了图像的饱和度,以使颜色更加生动。
5. 图像处理和效果增强
在这一步骤中,我们将应用一些图像处理技术,如双边滤波,以增强最终的卡通效果图像。
def resize_crop(image):h, w, c = np.shape(image)if min(h, w) > 720:if h > w:h, w = int(720 * h / w), 720else:h, w = 720, int(720 * w / h)image = cv2.resize(image, (w, h), interpolation=cv2.INTER_AREA)h, w = (h // 8) * 8, (w // 8) * 8image = image[:h, :w, :]return image# 图像处理和效果增强
def cartoonize(load_folder, save_folder):name_list = os.listdir(load_folder)for name in name_list:try:load_path = os.path.join(load_folder, name)save_path = os.path.join(save_folder, name)if not save_path.endswith('.jpg'):raise ValueError("Invalid file format. Must be a '.jpg' file.")image = cv2.imread(load_path)image = resize_crop(image)display_image(image, "Image")# 设置边缘掩膜参数并应用line_size = 7blur_value = 7edges = edge_mask(image, line_size, blur_value)display_image(edges, "Edges")# 执行颜色量化num_colors = 9processed_image = color_quantization(image, num_colors)display_image(processed_image, "Processed_image")# 应用双边滤波blurred = cv2.bilateralFilter(processed_image, d=9, sigmaColor=200, sigmaSpace=200)display_image(blurred, "Blurred")# 应用掩膜cartoonized_image = cv2.bitwise_and(blurred, blurred, mask=edges)display_image(cartoonized_image, "Cartoonized Image")cv2.imwrite(save_path, cartoonized_image)except:print('cartoonize {} failed'.format(load_path))
在这个步骤中,我们首先调整图像的大小和裁剪,以确保它符合处理的要求。然后,我们依次应用边缘掩膜、颜色量化、双边滤波和最后的掩膜应用,将图像转换成卡通画风。
这是整个卡通化过程的关键部分,通过这些步骤,您可以将任何普通照片转换成具有卡通风格的艺术品。在接下来的文章中,我们将展示如何使用这些代码来卡通化您自己的照片。
6. 完整代码
# -*- coding = utf-8 -*-
"""
# @Time : 2023/9/22 20:18
# @Author : FriK_log_ff 374591069
# @File : newmyway.py
# @Software: PyCharm
# @Function: 请输入项目功能
"""
import cv2
import numpy as np
import os# 读取文件
def read_file(filename: str) -> np.ndarray:try:img = cv2.imread(filename)if img is None:raise ValueError("Invalid file path or file format.")return imgexcept:raise ValueError("Invalid file path or file format.")# 显示图片
def display_image(img: np.ndarray, window_name: str) -> None:cv2.imshow(window_name, img)cv2.waitKey()# 边缘掩膜
def edge_mask(image: np.ndarray, line_size: int, blur_value: int) -> np.ndarray:if not isinstance(line_size, int) or not isinstance(blur_value, int) or line_size < 1 or blur_value < 1:raise ValueError("Invalid value for 'line_size' or 'blur_value' parameter. Must be a positive integer.")gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)gray_blur = cv2.medianBlur(gray, blur_value)edges = cv2.adaptiveThreshold(gray_blur, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, line_size, blur_value)return edges# 颜色量化
def color_quantization(image: np.ndarray, num_colors: int) -> np.ndarray:if not isinstance(num_colors, int) or num_colors < 1:raise ValueError("Invalid value for 'num_colors' parameter. Must be a positive integer.")# 转换图片data = np.float32(image).reshape((-1, 3))# 设置KMeans聚类参数kmeans_criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 20, 0.001)flags = cv2.KMEANS_RANDOM_CENTERS# 执行KMeans聚类_, labels, centers = cv2.kmeans(data, num_colors, None, kmeans_criteria, 10, flags)centers = np.uint8(centers)processed_image = centers[labels.flatten()]processed_image = processed_image.reshape(image.shape)# 应用颜色增强hsv_image = cv2.cvtColor(processed_image, cv2.COLOR_BGR2HSV)hsv_image[:, :, 1] = hsv_image[:, :, 1] * 1.5 # 增强饱和度enhanced_image = cv2.cvtColor(hsv_image, cv2.COLOR_HSV2BGR)return enhanced_imagedef resize_crop(image):h, w, c = np.shape(image)if min(h, w) > 720:if h > w:h, w = int(720 * h / w), 720else:h, w = 720, int(720 * w / h)image = cv2.resize(image, (w, h), interpolation=cv2.INTER_AREA)h, w = (h // 8) * 8, (w // 8) * 8image = image[:h, :w, :]return image# 上传文件
def cartoonize(load_folder, save_folder):name_list = os.listdir(load_folder)for name in name_list:try:load_path = os.path.join(load_folder, name)save_path = os.path.join(save_folder, name)if not save_path.endswith('.jpg'):raise ValueError("Invalid file format. Must be a '.jpg' file.")image = cv2.imread(load_path)image = resize_crop(image)display_image(image, "Image")# 设置边缘掩膜参数并应用line_size = 7blur_value = 7edges = edge_mask(image, line_size, blur_value)display_image(edges, "Edges")# 执行颜色量化num_colors = 9processed_image = color_quantization(image, num_colors)display_image(processed_image, "Processed_image")# 应用双边滤波blurred = cv2.bilateralFilter(processed_image, d=9, sigmaColor=200, sigmaSpace=200)display_image(blurred, "Blurred")# 应用掩膜cartoonized_image = cv2.bitwise_and(blurred, blurred, mask=edges)display_image(cartoonized_image, "Cartoonized Image")cv2.imwrite(save_path, cartoonized_image)except:print('cartoonize {} failed'.format(load_path))if __name__ == '__main__':load_folder = 'test_images'save_folder = 'cartoonized_images'if not os.path.exists(save_folder):os.mkdir(save_folder)cartoonize(load_folder, save_folder)
总结
在本文中,我们探讨了如何使用Python和OpenCV库创建卡通风格的图像。通过一系列图像处理步骤,我们将普通照片转化为有趣和具有创意的卡通风格图像。这个过程涵盖了图像读取、边缘检测、颜色量化、图像处理和效果增强等关键步骤。
卡通风格图像的制作涉及多个步骤,但通过掌握这些技巧,您可以自由发挥创造力,为照片增添新的趣味性。以下是本文中使用的一些关键技术的简要回顾:
-
图像读取和显示: 我们使用OpenCV库来读取图像文件并在窗口中显示它们。这是开始图像处理的第一步。
-
边缘掩膜: 为了创建卡通风格,我们使用了边缘检测技术,将图像中的边缘突出显示。
-
颜色量化: 卡通图像通常包含较少的颜色。我们使用K-Means聚类来减少图像中的颜色数量,从而实现卡通风格的色彩。
-
图像处理和效果增强: 我们应用了一些图像处理技术,例如双边滤波,以增强最终的卡通效果图像。
在完成所有处理步骤后,我们得到了有趣和独特的卡通风格图像。这个过程可以批量处理图像,使您能够轻松创建多个卡通化的照片。
希望本文对您有所帮助,能够启发您探索更多有趣的图像处理项目。 创造自己独特的卡通风格图像,让您的照片在社交媒体和网络上脱颖而出。
相关文章:
深入了解Python和OpenCV:图像的卡通风格化
前言 当今数字时代,图像处理和美化已经变得非常普遍。从社交媒体到个人博客,人们都渴望分享独特且引人注目的图片。本文将介绍如何使用Python编程语言和OpenCV库创建令人印象深刻的卡通风格图像。卡通风格的图像具有艺术性和创意,它们可以用…...
【算法挨揍日记】day06——1004. 最大连续1的个数 III、1658. 将 x 减到 0 的最小操作数
1004. 最大连续1的个数 III 1004. 最大连续1的个数 III 题目描述: 给定一个二进制数组 nums 和一个整数 k,如果可以翻转最多 k 个 0 ,则返回 数组中连续 1 的最大个数 。 解题思路: 首先题目要我们求出的最多翻转k个0后&#x…...
华为云HECS安装docker
1、运行安装指令 yum install docker都选择y,直到安装成功 2、查看是否安装成功 运行版本查看指令,显示docker版本,证明安装成功 docker --version 或者 docker -v 3、启用并运行docker 3.1启用docker 指令 systemctl enable docker …...
力扣669 补9.16
最近大三上四天有早八,真的是受不了了啊,欧嗨呦,早上困如狗,然后,下午困如狗,然后晚上困如狗,尤其我最近在晚上7点到10点这个时间段看力扣,看得我昏昏欲睡,不自觉就睡了1…...
2023-9-22 没有上司的舞会
题目链接:没有上司的舞会 #include <cstring> #include <iostream> #include <algorithm>using namespace std;const int N 6010;int n; int happy[N]; int h[N], e[N], ne[N], idx; bool has_father[N];// 两个状态,选该节点或不选该…...
【HDFS】cachingStrategy的设置
org.apache.hadoop.hdfs.client.impl.BlockReaderFactory#getRemoteBlockReader: private BlockReader getRemoteBlockReader(Peer peer) throws IOException {int networkDistance = clientContext.getNetworkDistance(datanode);return BlockReaderRemote...
性能测试 —— 性能测试常见的测试指标 !
一、什么是性能测试 先看下百度百科对它的定义,性能测试是通过自动化的测试工具模拟多种正常、峰值以及异常负载条件来对系统的各项性能指标进行测试。 我们可以认为性能测试是:通过在测试环境下对系统或构件的性能进行探测,用以验证在生产环…...
【学习草稿】背包问题
一、01背包问题 图解详细解析 (转载) https://blog.csdn.net/qq_37767455/article/details/99086678 :Vi表示第 i 个物品的价值,Wi表示第 i 个物品的体积,定义V(i,j):当前背包容量 j,前 i 个物…...
doxygen c++ 语法
c基本语法模板 以 /*! 开头, */ 结尾 /*!\关键字1\关键字2 */1 文件头部信息 /*! \file ClassA.h* \brief 文件说明 定义了类fatherA* \details This class is used to demonstrate a number of section commands.* \author John Doe* \author Jan Doe* \v…...
ChatGLM微调基于P-Tuning/LoRA/Full parameter(上)
1. 准备环境 首先必须有7个G的显存以上,torch >= 1.10 需要根据你的cuda版本 1.1 模型下载 $ git lfs install $ git clone https://huggingface.co/THUDM/chatglm-6b1.2 docker环境搭建 环境搭建 $ sudo docker pull slpcat/chatglm-6b:latest $ sudo docker run -it …...
BLE Mesh蓝牙mesh传输大数据包传输文件照片等大数据量通讯
1、BLE Mesh数据传输现状 BLE Mesh网络技术是低功耗蓝牙的一个进阶版,Mesh扩大了蓝牙在应用中的规模和范围,因为它同时支持超过三万个网络节点,可以跨越大型建筑物,不仅可以使得医疗健康应用更加方便快捷,还能监测像学…...
9.18 QT作业
mainwindow.h QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACEclass MainWindow : public QMainWindow {Q_OBJECTpublic:MainWindow(QWidget *parent nullptr);~MainWindow();signals:void jump(); //自定义跳转信号函数private slots:vo…...
【100天精通Python】Day67:Python可视化_Matplotlib 绘动画,2D、3D 动画 示例+代码
1 绘制2D动画(animation) Matplotlib是一个Python绘图库,它提供了丰富的绘图功能,包括绘制动画。要绘制动画,Matplotlib提供了FuncAnimation类,允许您创建基于函数的动画。下面是一个详细的Matplotlib动画示…...
Linux内核源码分析 (B.x)Linux页表的映射
Linux内核源码分析 (B.x)Linux页表的映射 文章目录 Linux内核源码分析 (B.x)Linux页表的映射一、ARM32页表1、页表术语2、虚拟地址到物理地址转换3、一级页表项4、二级页表项 二、ARM64页表1、ARMv8-A架构2、4KB大小页4级映射 三、Linux内核中关于页表的函数和宏1、查询页表2、…...
机器学习(15)---代价函数、损失函数和目标函数详解
文章目录 一、各自定义二、各自详解三、代价函数和损失函数区别四、例题理解 一、各自定义 1. 代价函数:代价函数(Cost Function)是定义在整个训练集上的,是所有样本误差的平均,也就是损失函数的平均。它用于衡量模型在…...
计算机专业大学规划之双非
亲爱的计算机专业大一学弟学妹们,欢迎来到充满挑战和机遇的大学校园!在经历了小半年的大学生活后,是否会对自己的未来感到一些迷茫,借着前几天给我大一的妹妹聊天的机会,我想发表一下关于我的建议(仅限个…...
2.策略模式
UML图 代码 main.cpp #include "Strategy.h" #include "Context.h"void test() {Context* pContext nullptr;/* StrategyA */pContext new Context(new StrategyA());pContext->contextInterface();/* StrategyB */pContext new Context(new Strat…...
算法通过村第七关-树(递归/二叉树遍历)黄金笔记|迭代遍历
文章目录 前言1. 迭代法实现前序遍历2. 迭代法实现中序遍历3. 迭代法实现后序遍历总结 前言 提示:在一个信息爆炸却多半无用的世界,清晰的见解就成了一种力量。 --尤瓦尔赫拉利《今日简史》 你是不是觉得上一关特别简单,代码少,背…...
MySQL数据库简介+库表管理操作+数据库用户管理
Mysql Part 1 一、数据库的基本概念1.1 使用数据库的必要性1.2 数据库基本概念1.2.1 数据(Data)1.2.2 表1.2.3 数据库1.2.4 数据库管理系统(DBMS)1.2.5 数据库系统 1.3 数据库的分类1.3.1 关系数据库 SQL1.3.2 非关系数据库 NoSQL…...
PyTorch实战:卷积神经网络详解+Python实现卷积神经网络Cifar10彩色图片分类
目录 前言 一、卷积神经网络概述 二、卷积神经网络特点 卷积运算 单通道,二维卷积运算示例 单通道,二维,带偏置的卷积示例 带填充的单通道,二维卷积运算示例 Valid卷积 Same卷积 多通道卷积计算 1.局部感知域 2.参数共…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...
04-初识css
一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...
什么是Ansible Jinja2
理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要: 近期,在使用较新版本的OpenSSH客户端连接老旧SSH服务器时,会遇到 "no matching key exchange method found", "n…...
Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
【C++进阶篇】智能指针
C内存管理终极指南:智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...
CSS | transition 和 transform的用处和区别
省流总结: transform用于变换/变形,transition是动画控制器 transform 用来对元素进行变形,常见的操作如下,它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...
解读《网络安全法》最新修订,把握网络安全新趋势
《网络安全法》自2017年施行以来,在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂,网络攻击、数据泄露等事件频发,现行法律已难以完全适应新的风险挑战。 2025年3月28日,国家网信办会同相关部门起草了《网络安全…...
Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析
Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析 一、第一轮基础概念问题 1. Spring框架的核心容器是什么?它的作用是什么? Spring框架的核心容器是IoC(控制反转)容器。它的主要作用是管理对…...
Python竞赛环境搭建全攻略
Python环境搭建竞赛技术文章大纲 竞赛背景与意义 竞赛的目的与价值Python在竞赛中的应用场景环境搭建对竞赛效率的影响 竞赛环境需求分析 常见竞赛类型(算法、数据分析、机器学习等)不同竞赛对Python版本及库的要求硬件与操作系统的兼容性问题 Pyth…...
