图像主题颜色提取(Median cut)
前言
之前想对图片素材进行分类管理,除了打标签,还有一样是通过主题色进行分类。于是开始寻找能提取主主题色的工具,最后找到了大名鼎鼎的 Leptonica 库,其中就有中位切割算法的实现。下面附上中位切割算法的其它语言版本的实现。
- JavaScript版:quantize (此库有提取颜色数量不对的问题,见 issues/9)
- Java版:theme-color (我自己基于 quantize 实现的Java版)
中位切割算法(Median cut)
theme-color 项目的效果如下:

讲中位切分法之前,我们先聊聊颜色该如何描述。
颜色模型
常见的颜色模型有RGB,HSV等,中位切分法基于 RGB 模型。RBG 模型是一种加色模型,将红(Red)、绿(Green)、蓝(Blue)三原色的色光以不同的比例相加,以合成产生各种色彩光。每个像素由24位编码的RGB值表示,使用三个8位无符号整数(0到255)表示红色、绿色和蓝色的强度,所以RGB能表示1677万(256∗256∗256)万种颜色。如果将所有的颜色采用三维空间来进行描述,则如下图所示:
算法实现
中位切割算法(Median cut) 是Paul Heckbert于1979年提出来的算法。原理是将图像颜色映射成三维色彩空间中的长方体,沿着RGB中最长的一边从颜色数量统计的中位数一切为二,使得到的两个长方体所包含的像素数量相同,重复上述步骤,直到得到想要数量的长方体。
原理很简单,但是 Leptonica 的实现包含了很多细节。
压缩颜色总数
算法需要统计图像的每种颜色的数量(色彩分布图),也就是需要将三维的长方体映射到一维的数组中,RGB 总颜色数量达到1677万 (2^8 * 2^8 * 2^8),这在检索的时候会造成不小的性能开销。如果将8位无符号整数(0到255)压缩到5位无符号整数(0到31),那么总数量减少到 2^5 * 2^5 * 2^5 = 32768,而且可以使用 int 来表示数组下标了。
中位切分的优化
在原始的中位切分法中,是沿着颜色数量统计的中位数将长方体(vbox)一切为二的,Leptonica 中对此进行了优化,改成通过中位数将 vbox 分为左右两个vbox(只是分出左右,还未切割),然后从左右选出体积较大的vbox的中点进行切割。下面放上作者原话
Determine the cut planes, making sure that two vboxes are always produced. Generate the two vboxes and compute the sum in each of them. Choose the cut plane within the greater of the (left, right) sides of the bin in which the median pixel resides. Here’s the surprise: go halfway into that side. By doing that, you technically move away from “median cut,” but in the process a significant number of low-count vboxes are produced, allowing much better reproduction of low-count spot colors.
长方体体积大包含像素少问题
存在某些条件下 VBox 体积很大但只包含少量像素。解决的方法是,每次切分前先对所有 vbox 排序,再取出优先级最高的 vbox 进行中位切分。如果需要切割的 vbox 总数为 total,那前 total * FractByPopulation 个 vbox 以 vbox包含的像素数 排序,后 total * (1-FractByPopulation) 个 vbox 以 包含像素数 * vbox体积 排序。
FractByPopulation的值在 Leptonica 库中为 0.85,在 quantize 库中为 0.75
总结
本文介绍了中位切割算法以及在 Leptonica 库中的实现。
参考资料
三原色光模式 - 维基百科,自由的百科全书 (wikipedia.org)
中位切割算法 - 维基百科,自由的百科全书 (wikipedia.org)
图像主题色提取算法_mmcq算法_mingo_敏的博客-CSDN博客
相关文章:
图像主题颜色提取(Median cut)
前言 之前想对图片素材进行分类管理,除了打标签,还有一样是通过主题色进行分类。于是开始寻找能提取主主题色的工具,最后找到了大名鼎鼎的 Leptonica 库,其中就有中位切割算法的实现。下面附上中位切割算法的其它语言版本的实现。…...
Python 分支结构
Python 分支结构 应用场景 迄今为止,我们写的Python代码都是一条一条语句顺序执行,这种代码结构通常称之为顺序结构。然而仅有顺序结构并不能解决所有的问题,比如我们设计一个游戏,游戏第一关的通关条件是玩家获得1000分&#x…...
【C++知识点】文件操作
✍个人博客:https://blog.csdn.net/Newin2020?spm1011.2415.3001.5343 📚专栏地址:C/C知识点 📣专栏定位:整理一下 C 相关的知识点,供大家学习参考~ ❤️如果有收获的话,欢迎点赞👍…...
VBA小模板,跨表统计的2种写法
目标 1 统计一个excel 文件里,多个sheet里的内容2 有的统计需求是,每个表只单表统计,只是进行批量操作3 有的需求是,多个表得某些行列累加等造出来得文件 2 实现方法1 (可能只适合VBAEXCEL,不太干净的写法…...
部署问题 | 百度LAC安装部署清单
本项目实现基于LAC提供RESTAPI服务的最小化方案。 依赖: python-3.9.9 百度lac2.X fastAPI uvicorn 首先下载并安装python,本人选择3.9版本。 依次安装: 安装 vc vc_redist.x64.exe 64位:https://download.microsoft.com/…...
提高办公效率的免费网站有哪些
收藏一些免费好用的网站,在我们工作中需要用到的时候可以直接使用,提高我们的工作效率。小编就和大家分享10个可以提高我们办公效率的免费网站。 1.羽兔网软件下载-以设计类软件为主的免费软件下载网站 很多小白都不知道怎么下载软件,往往搜…...
前端开发者需要掌握的具体内容和步骤
第一部分:前端开发实践 前端的工作职称 下面是一个前端开发者在职业发展中各种职称的描述列表. 对于前端开发者最普遍的职称是 "前端开发者" 或者 "前端工程师", 可以根据任何包含 "前端", "客户端", "web UI", "CS…...
杨校老师课堂之基于File类的文件管理器
在日常工作中,经常会遇到批量操作系统文件的事情,通常情况下,只能手动重复的完成批量文件的操作,这样很是费时费力。 本案例要求编写一个文件管理器,实现文件的批量操作。 文件管理器具体功能要求如下: 用…...
java面试算法汇总-数组
数组 [程序一] 两数之和 :给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。 class Solution {public int[] twoSum(int[] nums, int target) {Map<Integer,…...
Docker-Mysql主从复制
步骤 1、新建主服务器容器实例3307 docker run -d -p 3307:3306 --privileged=true -v /tmp/mysql_master/log:/var/log/mysql -v /tmp/mysql_master/data:/var/lib/mysql -v /tmp/mysql_master/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=root --name mysql-master mys…...
(模拟)1241. 外卖店优先级
目录 题目链接 一些话 流程 套路 ac代码 题目链接 1241. 外卖店优先级 - AcWing题库 一些话 流程 // // 每经过 1 // 个时间单位,如果外卖店没有订单,则优先级会减少 1 // ,最低减到 0 // ;而如果外卖店有订单,则…...
Linux进程学习【进程地址】
✨个人主页: Yohifo 🎉所属专栏: Linux学习之旅 🎊每篇一句: 图片来源 🎃操作环境: CentOS 7.6 阿里云远程服务器 Perseverance is not a long race; it is many short races one after another…...
系统调用——文件操作相关函数
1.open open, creat - open and possibly create a file or device 打开一个文件,也可能创建一个文件,返回文件描述符 //头文件 #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> //接口 int open(const char *pa…...
做互联网自媒体创业的月薪收入真的能过万吗?
搞自媒体创业有前途吗?收入月薪过万是真的吗? 自媒体创业是一种新兴的创业方法,它的远景十分广阔。自媒体创业能够让人们在自己的兴趣爱好和专业范畴上发挥自己的才能,一起也能够获得不错的收入。可是,月薪过万并不是…...
Kubernetes (k8s) 污点(Taint)、容忍介绍、示例
Kubernetes (k8s) 污点(Taint) 是一种机制,用于标记一个节点(Node)不可被调度的状态。它可以将一个污点标记添加到节点上,以防止 Pod 被调度到该节点上。污点可以用于实现各种策略,例如分离故障…...
多团队协作构建可观测性
实施 SRE 工程,守护系统的可靠性是一个⻓期的工作,需要开发、测试、运维以及 SRE 整个团队的努力。而可观测性平台天生就是为 SRE 工程服务的,它致力于实现 SLO 目标。建立可观测性不仅仅是运维团队的事情,更是整个开发、测试以及…...
100种思维模型之认知资源思维模型-030
我们常说,一个人永远也赚不到自己认知以外的钱,这话的确很有道理,被无数人所推崇。 由此,不难看出,认知在我们的生活起着多么关键的作用。 你的认知层次越高,范围越广,就意味着你这个人所处的阶…...
c/cpp - 多线程/进程 基础
c/cpp - 多线程/进程 基础1. 概念1.1 程序1.2 任务1.3 多任务1.4 进程1.5 线程1.5 线程/进程应用程序/系统资源并发/并行/同步/异步1. 概念 1.1 程序 代码、指令,静态的 1.2 任务 具体要做的实景,可以是基于进程、或基于线程 1.3 多任务 例如࿱…...
第55章 头像图片的前端渲染显示
1 WebApi.Controllers.CustomerController.GetCustomerByToken /// <param name"token">1个指定的令牌字符串。</param> /// <summary> /// 【通过令牌获取用户-无需权限】 /// </summary> /// <remarks> /// 摘要: /// …...
vue2 使用 cesium 【第二篇-相机视角移动+添加模型】
vue2 使用 cesium 【第二篇-相机视角移动添加模型】 搞了一阵子 cesium,小白入门,这东西很牛逼,但是感觉这东西好费劲啊!网上资料不多,每个人的用法又不一样,操作起来真的是绝绝子。之前写了一篇 vue2 使用…...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...
React Native 导航系统实战(React Navigation)
导航系统实战(React Navigation) React Navigation 是 React Native 应用中最常用的导航库之一,它提供了多种导航模式,如堆栈导航(Stack Navigator)、标签导航(Tab Navigator)和抽屉…...
Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...
vscode(仍待补充)
写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...
PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...
什么是Ansible Jinja2
理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...
Go 语言并发编程基础:无缓冲与有缓冲通道
在上一章节中,我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道,它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好࿰…...
